Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@selenight.nl>2017-08-23 12:31:17 +0300
committerDouwe Maan <douwe@selenight.nl>2017-08-23 12:31:17 +0300
commitfbe82e4cd9f4cda7264bb78eab9c5c55e6311518 (patch)
treede9444c1762fa43c336f595936878677aef8ce43
parent64820f9a6c17a348dc771a87618140a5c3c8874d (diff)
parent101d52b360a6a43f1633c5dd60b78e37bc8c4339 (diff)
Merge branch 'master' into issue-discussions-refactor
# Conflicts: # package.json
-rw-r--r--.eslintrc1
-rw-r--r--.gitlab-ci.yml6
-rw-r--r--CHANGELOG.md166
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile8
-rw-r--r--Gemfile.lock15
-rw-r--r--VERSION2
-rw-r--r--app/assets/javascripts/boards/components/issue_card_inner.js2
-rw-r--r--app/assets/javascripts/dispatcher.js4
-rw-r--r--app/assets/javascripts/groups_select.js3
-rw-r--r--app/assets/javascripts/helpers/user_feature_helper.js12
-rw-r--r--app/assets/javascripts/lib/utils/common_utils.js8
-rw-r--r--app/assets/javascripts/project_select_combo_button.js33
-rw-r--r--app/assets/javascripts/repo/components/repo_sidebar.vue9
-rw-r--r--app/assets/javascripts/repo/monaco_loader.js6
-rw-r--r--app/assets/javascripts/webpack.js2
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss27
-rw-r--r--app/assets/stylesheets/framework/filters.scss6
-rw-r--r--app/assets/stylesheets/framework/lists.scss2
-rw-r--r--app/assets/stylesheets/framework/selects.scss38
-rw-r--r--app/assets/stylesheets/framework/typography.scss6
-rw-r--r--app/assets/stylesheets/framework/variables.scss2
-rw-r--r--app/assets/stylesheets/new_sidebar.scss4
-rw-r--r--app/controllers/admin/logs_controller.rb9
-rw-r--r--app/controllers/groups_controller.rb7
-rw-r--r--app/controllers/projects/services_controller.rb9
-rw-r--r--app/helpers/application_settings_helper.rb1
-rw-r--r--app/helpers/events_helper.rb10
-rw-r--r--app/models/blob_viewer/composer_json.rb2
-rw-r--r--app/models/broadcast_message.rb32
-rw-r--r--app/models/ci/pipeline_schedule.rb2
-rw-r--r--app/models/ci/pipeline_schedule_variable.rb2
-rw-r--r--app/models/ci/stage.rb59
-rw-r--r--app/models/commit_status.rb9
-rw-r--r--app/models/concerns/has_status.rb2
-rw-r--r--app/models/concerns/storage/legacy_project.rb76
-rw-r--r--app/models/event.rb10
-rw-r--r--app/models/issue.rb3
-rw-r--r--app/models/merge_request.rb1
-rw-r--r--app/models/project.rb155
-rw-r--r--app/models/project_services/kubernetes_service.rb6
-rw-r--r--app/models/storage/hashed_project.rb42
-rw-r--r--app/models/storage/legacy_project.rb51
-rw-r--r--app/models/user.rb7
-rw-r--r--app/policies/group_policy.rb4
-rw-r--r--app/services/ci/create_pipeline_service.rb11
-rw-r--r--app/services/groups/create_service.rb4
-rw-r--r--app/services/groups/destroy_service.rb2
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb5
-rw-r--r--app/services/projects/housekeeping_service.rb3
-rw-r--r--app/services/users/destroy_service.rb6
-rw-r--r--app/views/admin/application_settings/_form.html.haml15
-rw-r--r--app/views/admin/logs/show.html.haml16
-rw-r--r--app/views/admin/users/_user.html.haml3
-rw-r--r--app/views/dashboard/issues.html.haml4
-rw-r--r--app/views/dashboard/merge_requests.html.haml4
-rw-r--r--app/views/dashboard/milestones/index.html.haml4
-rw-r--r--app/views/groups/issues.html.haml4
-rw-r--r--app/views/groups/merge_requests.html.haml4
-rw-r--r--app/views/import/gitlab_projects/new.html.haml3
-rw-r--r--app/views/profiles/accounts/show.html.haml37
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml2
-rw-r--r--app/views/projects/_activity.html.haml2
-rw-r--r--app/views/projects/_last_push.html.haml6
-rw-r--r--app/views/projects/activity.html.haml4
-rw-r--r--app/views/projects/commit/_signature_badge.html.haml2
-rw-r--r--app/views/projects/commits/_commit.html.haml2
-rw-r--r--app/views/projects/edit.html.haml2
-rw-r--r--app/views/shared/_event_filter.html.haml12
-rw-r--r--app/views/shared/_group_form.html.haml5
-rw-r--r--app/views/shared/_import_form.html.haml2
-rw-r--r--app/views/shared/_new_project_item_select.html.haml2
-rw-r--r--app/views/shared/empty_states/_issues.html.haml2
-rw-r--r--app/views/shared/empty_states/_merge_requests.html.haml2
-rw-r--r--app/views/shared/icons/_icon_arrow_circle_o_right.svg3
-rw-r--r--app/views/shared/icons/_icon_check_square_o.svg3
-rw-r--r--app/views/shared/icons/_icon_clock_o.svg2
-rw-r--r--app/views/shared/icons/_icon_clone.svg5
-rw-r--r--app/views/shared/icons/_icon_code_fork.svg3
-rw-r--r--app/views/shared/icons/_icon_comment_o.svg3
-rw-r--r--app/views/shared/icons/_icon_commit.svg3
-rw-r--r--app/views/shared/icons/_icon_edit.svg3
-rw-r--r--app/views/shared/icons/_icon_eye.svg3
-rw-r--r--app/views/shared/icons/_icon_eye_slash.svg3
-rw-r--r--app/views/shared/icons/_icon_merged.svg3
-rw-r--r--app/views/shared/icons/_icon_pencil.svg3
-rw-r--r--app/views/shared/icons/_icon_random.svg3
-rw-r--r--app/views/shared/icons/_icon_status_closed.svg2
-rw-r--r--app/views/shared/icons/_icon_tags.svg3
-rw-r--r--app/views/shared/icons/_icon_user.svg2
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml6
-rw-r--r--app/workers/authorized_projects_worker.rb13
-rw-r--r--app/workers/namespaceless_project_destroy_worker.rb3
-rw-r--r--app/workers/repository_fork_worker.rb16
-rw-r--r--app/workers/repository_import_worker.rb24
-rw-r--r--app/workers/stage_update_worker.rb10
-rw-r--r--app/workers/stuck_import_jobs_worker.rb50
-rw-r--r--changelogs/unreleased/10085-stop-encoding-user-name.yml4
-rw-r--r--changelogs/unreleased/13247-api_project_events_target_iid.yml4
-rw-r--r--changelogs/unreleased/13265-project_events_noteable_iid.yml4
-rw-r--r--changelogs/unreleased/13719-git-gc-timeout.yml3
-rw-r--r--changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml4
-rw-r--r--changelogs/unreleased/19629-remove-inactive-tokens-list.yml4
-rw-r--r--changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml4
-rw-r--r--changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml4
-rw-r--r--changelogs/unreleased/23036-replace-dashboard-spinach.yml4
-rw-r--r--changelogs/unreleased/26372-duplicate-issue-slash-command.yml4
-rw-r--r--changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml4
-rw-r--r--changelogs/unreleased/28202_decrease_abc_threshold_step2.yml4
-rw-r--r--changelogs/unreleased/28283-uuid-storage.yml4
-rw-r--r--changelogs/unreleased/28472-ignore-auto-generated-mails.yml4
-rw-r--r--changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml4
-rw-r--r--changelogs/unreleased/29385-add_shrug_command.yml4
-rw-r--r--changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml4
-rw-r--r--changelogs/unreleased/30634-protected-pipeline.yml5
-rw-r--r--changelogs/unreleased/31129-jira-project-key-elim.yml4
-rw-r--r--changelogs/unreleased/31207-clean-locked-merge-requests.yml4
-rw-r--r--changelogs/unreleased/31533-usage-data-projects-stats.yml4
-rw-r--r--changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml5
-rw-r--r--changelogs/unreleased/32483-jira-error.yml4
-rw-r--r--changelogs/unreleased/32844-issuables-performance.yml4
-rw-r--r--changelogs/unreleased/33095-mr-widget-ui.yml4
-rw-r--r--changelogs/unreleased/33097-issue-tracker.yml4
-rw-r--r--changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml4
-rw-r--r--changelogs/unreleased/33620-remove-events-from-notification_settings.yml4
-rw-r--r--changelogs/unreleased/33741-clarify-k8s-service-keys.yml5
-rw-r--r--changelogs/unreleased/33770-respect-blockquote-line-breaks.yml4
-rw-r--r--changelogs/unreleased/33874_confi.yml5
-rw-r--r--changelogs/unreleased/34027-add-icons-to-sidebar.yml4
-rw-r--r--changelogs/unreleased/34028-collapse-sidebar.yml4
-rw-r--r--changelogs/unreleased/34075-pipelines-count-mt.yml5
-rw-r--r--changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml4
-rw-r--r--changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml4
-rw-r--r--changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml4
-rw-r--r--changelogs/unreleased/34519-extend-api-group-secret-variable.yml4
-rw-r--r--changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml4
-rw-r--r--changelogs/unreleased/34533-speed-up-group-project-authorizations.yml5
-rw-r--r--changelogs/unreleased/34534-update-vue-resource.yml4
-rw-r--r--changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml4
-rw-r--r--changelogs/unreleased/34563-usage-ping-github.yml4
-rw-r--r--changelogs/unreleased/34764-rename-to-overview.yml4
-rw-r--r--changelogs/unreleased/34810-vue-pagination.yml4
-rw-r--r--changelogs/unreleased/34831-remove-coffee-rails-gem.yml4
-rw-r--r--changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml4
-rw-r--r--changelogs/unreleased/34867-remove-net-ssh-gem.yml4
-rw-r--r--changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml4
-rw-r--r--changelogs/unreleased/34921-global-dropdown-ui-improvement.yml4
-rw-r--r--changelogs/unreleased/34927-protect-manual-actions-on-tags.yml4
-rw-r--r--changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml4
-rw-r--r--changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml4
-rw-r--r--changelogs/unreleased/35072-fix-pages-delete.yml5
-rw-r--r--changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml4
-rw-r--r--changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml4
-rw-r--r--changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml4
-rw-r--r--changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml4
-rw-r--r--changelogs/unreleased/35164-cycle-analytics-firefox.yml4
-rw-r--r--changelogs/unreleased/35181-cannot-create-label-from-board-page.yml4
-rw-r--r--changelogs/unreleased/35191-prioritized-labels-for-non-member.yml4
-rw-r--r--changelogs/unreleased/35204-doc-api-ci-lint-typo.yml4
-rw-r--r--changelogs/unreleased/35225-transient-poll.yml4
-rw-r--r--changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml4
-rw-r--r--changelogs/unreleased/35343-inherit-milestones-and-labels.yml5
-rw-r--r--changelogs/unreleased/35391-fix-star-i18n-in-js.yml4
-rw-r--r--changelogs/unreleased/35408-group-auto-avatars.yml4
-rw-r--r--changelogs/unreleased/35483-improve-mobile-sidebar.yml4
-rw-r--r--changelogs/unreleased/35659-rename-pipeline.yml4
-rw-r--r--changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml4
-rw-r--r--changelogs/unreleased/35761-convdev-perc.yml4
-rw-r--r--changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml4
-rw-r--r--changelogs/unreleased/35815-webhook-log-encoding-error.yml4
-rw-r--r--changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml5
-rw-r--r--changelogs/unreleased/36041-notification-title.yml4
-rw-r--r--changelogs/unreleased/36087-users-cannot-delete-their-account.yml5
-rw-r--r--changelogs/unreleased/36185-or-separator.yml4
-rw-r--r--changelogs/unreleased/36611-error-in-getcomposer-link.yml5
-rw-r--r--changelogs/unreleased/3686_make_tarball_download_url.yml4
-rw-r--r--changelogs/unreleased/5971-webhook-testing.yml4
-rw-r--r--changelogs/unreleased/add-filtered-search-group-issues-ce.yml4
-rw-r--r--changelogs/unreleased/add-star-for-action-scope.yml4
-rw-r--r--changelogs/unreleased/appearances-caching-and-schema.yml4
-rw-r--r--changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml4
-rw-r--r--changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml4
-rw-r--r--changelogs/unreleased/broadcast-messages-cache.yml4
-rw-r--r--changelogs/unreleased/bump-omniauth-ldap-gem-version.yml4
-rw-r--r--changelogs/unreleased/bvl-add-all-settings-to-api.yml4
-rw-r--r--changelogs/unreleased/bvl-free-unused-names.yml5
-rw-r--r--changelogs/unreleased/bvl-nfs-circuitbreaker.yml4
-rw-r--r--changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml4
-rw-r--r--changelogs/unreleased/commits-list-page-limit.yml5
-rw-r--r--changelogs/unreleased/diff-changed-files-dropdown.yml4
-rw-r--r--changelogs/unreleased/dm-commit-cache-i18n.yml5
-rw-r--r--changelogs/unreleased/dm-large-push-performance.yml4
-rw-r--r--changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml4
-rw-r--r--changelogs/unreleased/dz-fix-calendar-today.yml4
-rw-r--r--changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-bang-format.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-declaration-order.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-import-path.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-property-spelling.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-space-after-comma.yml4
-rw-r--r--changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml4
-rw-r--r--changelogs/unreleased/ericy_ts-protected_branches_api.yml5
-rw-r--r--changelogs/unreleased/feature-backup-custom-path.yml4
-rw-r--r--changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml4
-rw-r--r--changelogs/unreleased/feature-gpg-signed-commits.yml4
-rw-r--r--changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml4
-rw-r--r--changelogs/unreleased/fix-broadcast-message-caching.yml5
-rw-r--r--changelogs/unreleased/fix-gb-fix-head-pipeline-when-pipeline-has-errors.yml5
-rw-r--r--changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml4
-rw-r--r--changelogs/unreleased/fix-import-fork-mr.yml5
-rw-r--r--changelogs/unreleased/fix-import-symbolink-links.yml4
-rw-r--r--changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml4
-rw-r--r--changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml4
-rw-r--r--changelogs/unreleased/fixes-for-internal-auth-disabled.yml4
-rw-r--r--changelogs/unreleased/forks-count-cache.yml5
-rw-r--r--changelogs/unreleased/gitaly_ref_exists.yml4
-rw-r--r--changelogs/unreleased/github.yml4
-rw-r--r--changelogs/unreleased/group-milestone-references-system-notes.yml4
-rw-r--r--changelogs/unreleased/group-new-issue.yml4
-rw-r--r--changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml4
-rw-r--r--changelogs/unreleased/issue_31790.yml4
-rw-r--r--changelogs/unreleased/issue_35580.yml4
-rw-r--r--changelogs/unreleased/memoize-user-personal-projects-count.yml4
-rw-r--r--changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml4
-rw-r--r--changelogs/unreleased/migrate-events-into-a-new-format.yml4
-rw-r--r--changelogs/unreleased/mk-fix-user-namespace-rename.yml5
-rw-r--r--changelogs/unreleased/mk-fix-wiki-backup.yml4
-rw-r--r--changelogs/unreleased/mr-branch-link-use-tree.yml4
-rw-r--r--changelogs/unreleased/only-limit-fetch-when-requested.yml5
-rw-r--r--changelogs/unreleased/pagination-projects-explore.yml4
-rw-r--r--changelogs/unreleased/pass-before-script-as-is.yml4
-rw-r--r--changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml4
-rw-r--r--changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml4
-rw-r--r--changelogs/unreleased/post-upload-pack-opt-out.yml4
-rw-r--r--changelogs/unreleased/rc-fix-branches-api-endpoint.yml5
-rw-r--r--changelogs/unreleased/rc-fix-commits-api.yml5
-rw-r--r--changelogs/unreleased/rc-fix-tags-api.yml5
-rw-r--r--changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml5
-rw-r--r--changelogs/unreleased/remove-nprogress-gleaning.yml4
-rw-r--r--changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml4
-rw-r--r--changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml4
-rw-r--r--changelogs/unreleased/replace_spinach_spec_browse_files.yml4
-rw-r--r--changelogs/unreleased/request-store-wrap.yml4
-rw-r--r--changelogs/unreleased/restrict-haml-javascript.yml4
-rw-r--r--changelogs/unreleased/rouge-2-2-0.yml5
-rw-r--r--changelogs/unreleased/rs-alphanumeric-ssh-params.yml5
-rw-r--r--changelogs/unreleased/sh-structured-logging.yml4
-rw-r--r--changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml4
-rw-r--r--changelogs/unreleased/tc-api-root-merge-requests.yml4
-rw-r--r--changelogs/unreleased/tc-issue-api-assignee.yml4
-rw-r--r--changelogs/unreleased/tc-no-todo-service-select.yml4
-rw-r--r--changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml5
-rw-r--r--changelogs/unreleased/toggle-new-project-import-description.yml4
-rw-r--r--changelogs/unreleased/use-a-specialized-class-for-querying-events.yml4
-rw-r--r--changelogs/unreleased/wiki_title.yml4
-rw-r--r--changelogs/unreleased/winh-derive-project-name.yml4
-rw-r--r--changelogs/unreleased/zj-delete-mm-team.yml4
-rw-r--r--changelogs/unreleased/zj-pipeline-badge-improvements.yml4
-rw-r--r--changelogs/unreleased/zj-project-templates.yml4
-rw-r--r--changelogs/unreleased/zj-remove-ci-api-v1.yml5
-rw-r--r--config/initializers/1_settings.rb10
-rw-r--r--config/initializers/workhorse_multipart.rb4
-rw-r--r--config/karma.config.js1
-rw-r--r--config/routes/ci.rb4
-rw-r--r--config/webpack.config.js10
-rw-r--r--db/migrate/20170711145320_add_status_to_ci_stages.rb9
-rw-r--r--db/migrate/20170720111708_add_lock_version_to_ci_stages.rb9
-rw-r--r--db/migrate/20170802013652_add_storage_fields_to_project.rb16
-rw-r--r--db/migrate/20170807071105_add_hashed_storage_to_settings.rb18
-rw-r--r--db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb35
-rw-r--r--db/post_migrate/20170711145558_migrate_stages_statuses.rb33
-rw-r--r--db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb54
-rw-r--r--db/schema.rb8
-rw-r--r--doc/README.md4
-rw-r--r--doc/api/README.md7
-rw-r--r--doc/api/ci/README.md24
-rw-r--r--doc/api/ci/builds.md147
-rw-r--r--doc/api/ci/runners.md59
-rw-r--r--doc/api/group_level_variables.md4
-rw-r--r--doc/api/lint.md (renamed from doc/api/ci/lint.md)3
-rw-r--r--doc/api/project_snippets.md2
-rw-r--r--doc/articles/index.md105
-rw-r--r--doc/articles/numerous_undo_possibilities_in_git/img/branching.pngbin0 -> 26245 bytes
-rw-r--r--doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.pngbin0 -> 43609 bytes
-rw-r--r--doc/articles/numerous_undo_possibilities_in_git/img/revert.pngbin0 -> 28112 bytes
-rw-r--r--doc/articles/numerous_undo_possibilities_in_git/index.md497
-rw-r--r--doc/ci/api/README.md1
-rw-r--r--doc/ci/api/builds.md1
-rw-r--r--doc/ci/api/runners.md1
-rw-r--r--doc/ci/docker/using_docker_images.md40
-rw-r--r--doc/gitlab-basics/create-project.md17
-rw-r--r--doc/gitlab-basics/img/create_new_project_info.pngbin20385 -> 82725 bytes
-rw-r--r--doc/install/kubernetes/gitlab_chart.md7
-rw-r--r--doc/install/kubernetes/gitlab_omnibus.md11
-rw-r--r--doc/install/kubernetes/gitlab_runner_chart.md7
-rw-r--r--doc/install/kubernetes/index.md6
-rw-r--r--doc/topics/authentication/index.md1
-rw-r--r--doc/topics/git/index.md1
-rw-r--r--doc/user/group/index.md6
-rw-r--r--doc/user/index.md4
-rw-r--r--doc/user/profile/img/profile_settings_dropdown.pngbin0 -> 4184 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png (renamed from doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png)bin24514 -> 24514 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.pngbin0 -> 4403 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.pngbin0 -> 41193 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png (renamed from doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png)bin9542 -> 9542 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png (renamed from doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png)bin14029 -> 14029 bytes
-rw-r--r--doc/user/project/gpg_signed_commits/index.md245
-rw-r--r--doc/user/project/import/bitbucket.md62
-rw-r--r--doc/user/project/import/clearcase.md47
-rw-r--r--doc/user/project/import/fogbugz.md28
-rw-r--r--doc/user/project/import/gitea.md77
-rw-r--r--doc/user/project/import/github.md122
-rw-r--r--doc/user/project/import/gitlab_com.md20
-rw-r--r--doc/user/project/import/img/bitbucket_import_grant_access.png (renamed from doc/workflow/importing/img/bitbucket_import_grant_access.png)bin7248 -> 7248 bytes
-rw-r--r--doc/user/project/import/img/bitbucket_import_new_project.png (renamed from doc/workflow/importing/img/bitbucket_import_new_project.png)bin1316 -> 1316 bytes
-rw-r--r--doc/user/project/import/img/bitbucket_import_select_project.png (renamed from doc/workflow/importing/img/bitbucket_import_select_project.png)bin8688 -> 8688 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_finished.png (renamed from doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png)bin17744 -> 17744 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_login.png (renamed from doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png)bin13751 -> 13751 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_select_fogbogz.png (renamed from doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png)bin12289 -> 12289 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_select_project.png (renamed from doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png)bin20905 -> 20905 bytes
-rw-r--r--doc/user/project/import/img/fogbugz_import_user_map.png (renamed from doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png)bin51238 -> 51238 bytes
-rw-r--r--doc/user/project/import/img/gitlab_importer.png (renamed from doc/workflow/importing/gitlab_importer/importer.png)bin12864 -> 12864 bytes
-rw-r--r--doc/user/project/import/img/gitlab_new_project_page.png (renamed from doc/workflow/importing/gitlab_importer/new_project_page.png)bin21251 -> 21251 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_gitea_new_import.png (renamed from doc/workflow/importing/img/import_projects_from_gitea_new_import.png)bin15561 -> 15561 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_github_importer.png (renamed from doc/workflow/importing/img/import_projects_from_github_importer.png)bin17953 -> 17953 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_github_select_auth_method.png (renamed from doc/workflow/importing/img/import_projects_from_github_select_auth_method.png)bin17612 -> 17612 bytes
-rw-r--r--doc/user/project/import/img/import_projects_from_new_project_page.png (renamed from doc/workflow/importing/img/import_projects_from_new_project_page.png)bin36821 -> 36821 bytes
-rw-r--r--doc/user/project/import/index.md21
-rw-r--r--doc/user/project/import/svn.md183
-rw-r--r--doc/user/project/index.md11
-rw-r--r--doc/user/project/issues/img/group_issues_list_view.pngbin0 -> 265130 bytes
-rwxr-xr-xdoc/user/project/issues/img/issue_tracker.pngbin37037 -> 0 bytes
-rw-r--r--doc/user/project/issues/img/project_issues_list_view.pngbin0 -> 309131 bytes
-rw-r--r--doc/user/project/issues/index.md30
-rw-r--r--doc/user/project/merge_requests/img/group_merge_requests_list_view.pngbin0 -> 283066 bytes
-rw-r--r--doc/user/project/merge_requests/img/merge_request_diff_file_navigation.pngbin0 -> 76052 bytes
-rw-r--r--doc/user/project/merge_requests/img/project_merge_requests_list_view.pngbin0 -> 325819 bytes
-rw-r--r--doc/user/project/merge_requests/index.md28
-rw-r--r--doc/user/search/index.md8
-rw-r--r--doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.pngbin32699 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.pngbin10331 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.pngbin112812 -> 0 bytes
-rw-r--r--doc/workflow/gpg_signed_commits/index.md84
-rw-r--r--doc/workflow/importing/README.md18
-rw-r--r--doc/workflow/importing/import_projects_from_bitbucket.md63
-rw-r--r--doc/workflow/importing/import_projects_from_fogbugz.md30
-rw-r--r--doc/workflow/importing/import_projects_from_gitea.md78
-rw-r--r--doc/workflow/importing/import_projects_from_github.md123
-rw-r--r--doc/workflow/importing/import_projects_from_gitlab_com.md22
-rw-r--r--doc/workflow/importing/migrating_from_svn.md184
-rw-r--r--lib/after_commit_queue.rb30
-rw-r--r--lib/api/helpers/pagination.rb17
-rw-r--r--lib/backup/repository.rb2
-rw-r--r--lib/ci/api/api.rb39
-rw-r--r--lib/ci/api/builds.rb219
-rw-r--r--lib/ci/api/entities.rb93
-rw-r--r--lib/ci/api/helpers.rb89
-rw-r--r--lib/ci/api/runners.rb50
-rw-r--r--lib/ci/api/triggers.rb39
-rw-r--r--lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb14
-rw-r--r--lib/gitlab/background_migration/migrate_stage_status.rb77
-rw-r--r--lib/gitlab/database/migration_helpers.rb5
-rw-r--r--lib/gitlab/git/repository.rb154
-rw-r--r--lib/gitlab/git_access.rb19
-rw-r--r--lib/gitlab/gitaly_client/blob_service.rb13
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb22
-rw-r--r--lib/gitlab/gitaly_client/ref_service.rb8
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb5
-rw-r--r--lib/gitlab/import_export/import_export.yml3
-rw-r--r--lib/gitlab/import_export/merge_request_parser.rb2
-rw-r--r--lib/gitlab/job_waiter.rb57
-rw-r--r--lib/gitlab/logger.rb8
-rw-r--r--lib/gitlab/regex.rb3
-rw-r--r--lib/gitlab/sidekiq_status.rb9
-rw-r--r--lib/gitlab/sidekiq_throttler.rb2
-rw-r--r--lib/gitlab/string_range_marker.rb34
-rw-r--r--lib/tasks/gitlab/import.rake6
-rw-r--r--locale/gitlab.pot156
-rw-r--r--package.json4
-rw-r--r--spec/controllers/projects/services_controller_spec.rb42
-rw-r--r--spec/factories/ci/stages.rb8
-rw-r--r--spec/factories/projects.rb4
-rw-r--r--spec/features/atom/users_spec.rb6
-rw-r--r--spec/features/explore/new_menu_spec.rb2
-rw-r--r--spec/features/groups_spec.rb17
-rw-r--r--spec/features/profile_spec.rb15
-rw-r--r--spec/features/projects/import_export/import_file_spec.rb82
-rw-r--r--spec/helpers/diff_helper_spec.rb8
-rw-r--r--spec/helpers/events_helper_spec.rb6
-rw-r--r--spec/initializers/settings_spec.rb25
-rw-r--r--spec/javascripts/boards/board_new_issue_spec.js8
-rw-r--r--spec/javascripts/boards/issue_card_spec.js19
-rw-r--r--spec/javascripts/fixtures/project_select_combo_button.html.haml2
-rw-r--r--spec/javascripts/lib/utils/common_utils_spec.js52
-rw-r--r--spec/javascripts/lib/utils/text_utility_spec.js1
-rw-r--r--spec/javascripts/project_select_combo_button_spec.js35
-rw-r--r--spec/javascripts/repo/monaco_loader_spec.js12
-rw-r--r--spec/lib/after_commit_queue_spec.rb15
-rw-r--r--spec/lib/api/helpers/pagination_spec.rb52
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb11
-rw-r--r--spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb21
-rw-r--r--spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb80
-rw-r--r--spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb6
-rw-r--r--spec/lib/gitlab/diff/inline_diff_marker_spec.rb14
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb59
-rw-r--r--spec/lib/gitlab/git/storage/forked_storage_check_spec.rb2
-rw-r--r--spec/lib/gitlab/git_access_spec.rb249
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb14
-rw-r--r--spec/lib/gitlab/gitaly_client/ref_service_spec.rb21
-rw-r--r--spec/lib/gitlab/gitaly_client/repository_service_spec.rb76
-rw-r--r--spec/lib/gitlab/import_export/project.json5
-rw-r--r--spec/lib/gitlab/import_export/project_tree_restorer_spec.rb7
-rw-r--r--spec/lib/gitlab/import_export/project_tree_saver_spec.rb10
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml2
-rw-r--r--spec/lib/gitlab/job_waiter_spec.rb41
-rw-r--r--spec/lib/gitlab/sidekiq_throttler_spec.rb50
-rw-r--r--spec/lib/gitlab/string_range_marker_spec.rb39
-rw-r--r--spec/migrations/README.md10
-rw-r--r--spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb2
-rw-r--r--spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb32
-rw-r--r--spec/migrations/migrate_stage_id_reference_in_background_spec.rb13
-rw-r--r--spec/migrations/migrate_stages_statuses_spec.rb67
-rw-r--r--spec/migrations/remove_dot_git_from_usernames_spec.rb3
-rw-r--r--spec/models/broadcast_message_spec.rb23
-rw-r--r--spec/models/ci/stage_spec.rb79
-rw-r--r--spec/models/commit_status_spec.rb6
-rw-r--r--spec/models/project_services/kubernetes_service_spec.rb3
-rw-r--r--spec/models/project_spec.rb258
-rw-r--r--spec/models/user_spec.rb61
-rw-r--r--spec/policies/group_policy_spec.rb36
-rw-r--r--spec/requests/ci/api/builds_spec.rb912
-rw-r--r--spec/requests/ci/api/runners_spec.rb127
-rw-r--r--spec/requests/ci/api/triggers_spec.rb90
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb58
-rw-r--r--spec/services/groups/create_service_spec.rb16
-rw-r--r--spec/services/groups/destroy_service_spec.rb26
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb20
-rw-r--r--spec/services/users/destroy_service_spec.rb27
-rw-r--r--spec/services/users/update_service_spec.rb15
-rw-r--r--spec/spec_helper.rb25
-rw-r--r--spec/support/background_migrations_matchers.rb13
-rw-r--r--spec/support/db_cleaner.rb2
-rw-r--r--spec/support/migrations_helpers.rb29
-rw-r--r--spec/workers/authorized_projects_worker_spec.rb16
-rw-r--r--spec/workers/namespaceless_project_destroy_worker_spec.rb16
-rw-r--r--spec/workers/repository_import_worker_spec.rb2
-rw-r--r--spec/workers/stage_update_worker_spec.rb22
-rw-r--r--spec/workers/stuck_import_jobs_worker_spec.rb34
-rw-r--r--yarn.lock894
450 files changed, 5232 insertions, 4538 deletions
diff --git a/.eslintrc b/.eslintrc
index 3e07edbccfe..44ad6a4896c 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -6,6 +6,7 @@
},
"extends": "airbnb-base",
"globals": {
+ "__webpack_public_path__": true,
"_": false,
"gl": false,
"gon": false,
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index df7244d5a2e..6f356a07576 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -259,7 +259,7 @@ setup-test-env:
<<: *default-cache
script:
- node --version
- - yarn install --pure-lockfile --cache-folder .yarn-cache
+ - yarn install --frozen-lockfile --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
- bundle exec ruby -Ispec -e 'require "spec_helper" ; TestEnv.init'
@@ -508,7 +508,7 @@ gitlab:assets:compile:
WEBPACK_REPORT: "true"
NO_COMPRESSION: "true"
script:
- - yarn install --pure-lockfile --production --cache-folder .yarn-cache
+ - yarn install --frozen-lockfile --production --cache-folder .yarn-cache
- bundle exec rake gettext:po_to_json
- bundle exec rake gitlab:assets:compile
artifacts:
@@ -522,7 +522,7 @@ karma:
<<: *dedicated-runner
<<: *except-docs
<<: *pull-cache
- image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-59.0-node-7.1-postgresql-9.6"
+ image: "dev.gitlab.org:5005/gitlab/gitlab-build-images:ruby-2.3.3-golang-1.8-git-2.13-chrome-60.0-node-7.1-postgresql-9.6"
stage: test
variables:
BABEL_ENV: "coverage"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3ecedd44c89..1d969164cfe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,172 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
+## 9.5.0 (2017-08-22)
+
+- [FIXED] Fix timeouts when creating projects in groups with many members. !13508
+- [FIXED] Improve API pagination headers when no record found. !13629 (Jordan Patterson)
+- [FIXED] Fix deleting GitLab Pages files when a project is removed. !13631
+- [FIXED] Fix commit list not loading the correct page when scrolling.
+- [OTHER] Cache the number of forks of a project. !13535
+- GPG signed commits integration. !9546 (Alexis Reigel)
+- Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes. !9707 (Hiroyuki Sato)
+- Add custom linter for inline JavaScript to haml_lint. !9742 (winniehell)
+- Add /shrug and /tableflip commands. !10068 (Alex Ives)
+- Allow wiki pages to be renamed in the UI. !10069 (wendy0402)
+- Insert user name directly without encoding. !10085 (Nathan Neulinger <nneul@neulinger.org>)
+- Avoid plucking Todo ids in TodoService. !10845
+- Handle errors while a project is being deleted asynchronously. !11088
+- Decrease ABC threshold to 56.96. !11227 (Maxim Rydkin)
+- Remove Mattermost team when deleting a group. !11362
+- Block access to failing repository storage. !11449
+- Add coordinator url to admin area runner page. !11603
+- Allow testing any events for project hooks and system hooks. !11728 (Alexander Randa (@randaalex))
+- Disallow running the pipeline if ref is protected and user cannot merge the branch or create the tag. !11910
+- Remove project_key from the Jira configuration. !12050
+- Add CSRF token verification to API. !12154 (Vitaliy @blackst0ne Klachkov)
+- Fixes needed when GitLab sign-in is not enabled. !12491 (Robin Bobbitt)
+- Lazy load images for better Frontend performance. !12503
+- Replaces dashboard/event_filters.feature spinach with rspec. !12651 (Alexander Randa (@randaalex))
+- Toggle import description with import_sources_enabled. !12691 (Brianna Kicia)
+- Bump scss-lint to 0.54.0. !12733 (Takuya Noguchi)
+- Enable SpaceAfterComma in scss-lint. !12734 (Takuya Noguchi)
+- Remove CSS for nprogress removed. !12737 (Takuya Noguchi)
+- Enable UnnecessaryParentReference in scss-lint. !12738 (Takuya Noguchi)
+- Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper. !12742 (Jacopo Beschi @jacopo-beschi)
+- Enable ImportPath in scss-lint. !12749 (Takuya Noguchi)
+- Enable PropertySpelling in scss-lint. !12752 (Takuya Noguchi)
+- Add API for protected branches to allow for wildcard matching and no access restrictions. !12756 (Eric Yu)
+- refactor initializations in dropzone_input.js. !12768 (Brandon Everett)
+- Improve CSS for global nav dropdown UI. !12772 (Takuya Noguchi)
+- Remove public/ci/favicon.ico. !12803 (Takuya Noguchi)
+- Enable DeclarationOrder in scss-lint. !12805 (Takuya Noguchi)
+- Increase width of dropdown menus automatically. !12809 (Thomas Wucher)
+- Enable BangFormat in scss-lint [ci skip]. !12815 (Takuya Noguchi)
+- Added /duplicate quick action to close a duplicate issue. !12845 (Ryan Scott)
+- Make all application-settings accessible through the API. !12851
+- Remove Inactive Personal Access Tokens list from Access Tokens page. !12866
+- Replaces dashboard/dashboard.feature spinach with rspec. !12876 (Alexander Randa (@randaalex))
+- Reduce memory usage of the GitHub importer. !12886
+- Bump fog-core to 1.44.3 and fog providers' plugins to latest. !12897 (Takuya Noguchi)
+- Use only CSS to truncate commit message in blame. !12900 (Takuya Noguchi)
+- Protect manual actions against protected tag too. !12908
+- Allow to configure automatic retry of a failed CI/CD job. !12909
+- Remove help message about prioritized labels for non-members. !12912 (Takuya Noguchi)
+- Add link to doc/api/ci/lint.md. !12914 (Takuya Noguchi)
+- Add RequestCache which makes caching with RequestStore easier. !12920
+- Free up some top level words, reject top level groups named like files in the public folder. !12932
+- Extend API for Group Secret Variable. !12936
+- Hide description about protected branches to non-member. !12945 (Takuya Noguchi)
+- Support custom directory in gitlab:backup:create task. !12984 (Markus Koller)
+- Raise guessed encoding confidence threshold to 50. !12990
+- Add author_id & assignee_id param to /issues API. !13004
+- Fix today day highlight in calendar. !13048
+- Prevent LDAP login callback from being called with a GET request. !13059
+- Add top-level merge_requests API endpoint. !13060
+- Handle maximum pages artifacts size correctly. !13072
+- Enable gitaly_post_upload_pack by default. !13078
+- Add Prometheus metrics exporter to Sidekiq. !13082
+- Fix improperly skipped backups of wikis. !13096
+- Projects can be created from templates. !13108
+- Fix the /projects/:id/repository/branches endpoint to handle dots in the branch name when the project full path contains a `/`. !13115
+- Fix project logos that are not centered vertically on list pages. !13124 (Florian Lemaitre)
+- Derive project path from import URL. !13131
+- Fix deletion of deploy keys linked to other projects. !13162
+- repository archive download url now ends with selected file extension. !13178 (haseebeqx)
+- Show auto-generated avatars for Groups without avatars. !13188
+- Allow any logged in users to read_users_list even if it's restricted. !13201
+- Unlock stuck merge request and set the proper state. !13207
+- Fix timezone inconsistencies in user contribution graph. !13208
+- Fix Issue board when using Ruby 2.4. !13220
+- Don't rename namespace called system when upgrading from 9.1.x to 9.5. !13228
+- Fix encoding error for WebHook logging. !13230 (Alexander Randa (@randaalex))
+- Uniquify reserved word usernames on OAuth user creation. !13244 (Robin Bobbitt)
+- Expose target_iid in Events API. !13247 (sue445)
+- Add star for action scope, in order to delete image from registry. !13248 (jean)
+- Make Delete Merged Branches handle wildcard protected branches correctly. !13251
+- Fix an order of operations for CI connection error message in merge request widget. !13252
+- Don't send rejection mails for all auto-generated mails. !13254
+- Expose noteable_iid in Note. !13265 (sue445)
+- Fix pipeline_schedules pages when active schedule has an abnormal state. !13286
+- Move some code from services to workers in order to improve performance. !13326
+- Fix destroy of case-insensitive conflicting redirects. !13357
+- Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name when the project full path contains a `/`. !13368
+- Fix the /projects/:id/repository/commits endpoint to handle dots in the ref name when the project full path contains a `/`. !13370
+- Project pending delete no longer return 500 error in admins projects view. !13389
+- Use full path of user's avatar in webhooks. !13401 (Vitaliy @blackst0ne Klachkov)
+- Make GPGME temporary directory handling thread safe. !13481 (Alexis Reigel)
+- Add support for kube_namespace in Metrics queries. !16169
+- Fix bar chart does not display label at 0 hour. !35136 (Jason Dai)
+- Use project_ref_path to create the link to a branch to fix links that 404.
+- Declare related resources into V4 API entities.
+- Add Slack and JIRA services counts to Usage Data.
+- Prevent web hook and project service background jobs from going to the dead jobs queue.
+- Display specific error message when JIRA test fails.
+- clean up merge request widget UI.
+- Associate Issues tab only with internal issues tracker.
+- Remove events column from notification settings table.
+- Clarifies and rearranges the input variables on the kubernetes integration page and adjusts the docs slightly to meet the same order.
+- Respect blockquote line breaks in markdown.
+- Update confidential issue UI - add confidential visibility and settings to sidebar.
+- Add icons to contextual sidebars.
+- Make contextual sidebar collapsible.
+- Update Pipeline's badge count in Merge Request and Commits view to match real-time content.
+- Added link to the MR widget that directs to the monitoring dashboard.
+- Use jQuery to control scroll behavior in job log for cross browser consistency.
+- move edit comment button outside of dropdown.
+- Updates vue resource and code according to breaking changes.
+- Add GitHub imported projects count to usage data.
+- Rename about to overview for group and project page.
+- Prevent disabled pagination button to be clicked.
+- Remove coffee-rails gem. (Takuya Noguchi)
+- Remove net-ssh gem. (Takuya Noguchi)
+- Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1. (Takuya Noguchi)
+- improve file upload/replace experience.
+- allow closing Cycle Analytics intro box in firefox.
+- Fix label creation from new list for subgroup projects.
+- fix transient js error in rspec tests.
+- fix jump to next discussion button.
+- Fix translations for Star/Unstar in JS file.
+- Improve mobile sidebar.
+- Rename Pipelines tab to CI / CD in new navigation.
+- Fix display of new diff comments after changing b between diff views.
+- Store & use ConvDev percentages returned by the Version app.
+- Fixes new issue button for failed job returning 404.
+- Align OR separator to center in new project page.
+- Add filtered search to group issue dashboard.
+- Cache Appearance instances in Redis.
+- Fixed breadcrumbs title aggressively collapsing.
+- Better caching and indexing of broadcast messages.
+- Moved diff changed files into a dropdown.
+- Improve performance of large (initial) push into default branch.
+- Improve performance of checking for projects on the projects dashboard.
+- Eager load project creators for project dashboards.
+- Modify if condition to be more readable.
+- Fix links to group milestones from issue and merge request sidebar.
+- Remove hidden symlinks from project import files.
+- Fixed sign-in restrictions buttons not toggling active state.
+- Fix replying to commit comments on merge requests created from forks.
+- Support Markdown references, autocomplete, and quick actions for group milestones.
+- Cache recent projects for group-level new resource creation.
+- Fix API responses when dealing with txt files.
+- Fix project milestones import when projects belongs to a group.
+- Fix Mattermost integration.
+- Memoize the number of personal projects a user has to reduce COUNT queries.
+- Merge issuable "reopened" state into "opened".
+- Migrate events into a new format to reduce the storage necessary and improve performance.
+- MR branch link now links to tree instead of commits.
+- Use Prev/Next pagination for exploring projects.
+- Pass before_script and script as-is preserving arrays.
+- Change project FK migration to skip existing FKs.
+- Remove redundant query when retrieving the most recent push of a user.
+- Re-organise "issues" indexes for faster ordering.
+- Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric character.
+- Fix search box losing focus when typing.
+- Add structured logging for Rails processes.
+- Skip oAuth authorization for trusted applications.
+- Use a specialized class for querying events to improve performance.
+- Update build badges to be pipeline badges and display passing instead of success.
+
## 9.4.5 (2017-08-14)
- Fix deletion of deploy keys linked to other projects. !13162
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index c25c8e5b741..be386c9ede3 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.30.0
+0.33.0
diff --git a/Gemfile b/Gemfile
index ab151e4171f..a0a9dddac10 100644
--- a/Gemfile
+++ b/Gemfile
@@ -144,8 +144,6 @@ end
# State machine
gem 'state_machines-activerecord', '~> 0.4.0'
-# Run events after state machine commits
-gem 'after_commit_queue', '~> 1.3.0'
# Issue tags
gem 'acts-as-taggable-on', '~> 4.0'
@@ -154,7 +152,7 @@ gem 'acts-as-taggable-on', '~> 4.0'
gem 'sidekiq', '~> 5.0'
gem 'sidekiq-cron', '~> 0.6.0'
gem 'redis-namespace', '~> 1.5.2'
-gem 'sidekiq-limit_fetch', '~> 3.4'
+gem 'sidekiq-limit_fetch', '~> 3.4', require: false
# Cron Parser
gem 'rufus-scheduler', '~> 3.4'
@@ -289,7 +287,7 @@ group :metrics do
gem 'influxdb', '~> 0.2', require: false
# Prometheus
- gem 'prometheus-client-mmap', '~>0.7.0.beta11'
+ gem 'prometheus-client-mmap', '~>0.7.0.beta12'
gem 'raindrops', '~> 0.18'
end
@@ -403,7 +401,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly', '~> 0.27.0'
+gem 'gitaly', '~> 0.29.0'
gem 'toml-rb', '~> 0.3.15', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 1554f314d1e..ec8349cd1df 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -46,8 +46,6 @@ GEM
ice_nine (~> 0.11.0)
memoizable (~> 0.4.0)
addressable (2.3.8)
- after_commit_queue (1.3.0)
- activerecord (>= 3.0)
akismet (2.0.0)
allocations (1.0.5)
arel (6.0.4)
@@ -277,7 +275,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
- gitaly (0.27.0)
+ gitaly (0.29.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
@@ -356,7 +354,7 @@ GEM
activesupport
grape (>= 0.16.0)
rake
- grpc (1.4.0)
+ grpc (1.4.5)
google-protobuf (~> 3.1)
googleauth (~> 0.5.1)
haml (4.0.7)
@@ -621,7 +619,7 @@ GEM
parser
unparser
procto (0.0.3)
- prometheus-client-mmap (0.7.0.beta11)
+ prometheus-client-mmap (0.7.0.beta12)
mmap2 (~> 2.2, >= 2.2.7)
pry (0.10.4)
coderay (~> 1.1.0)
@@ -724,7 +722,7 @@ GEM
retriable (1.4.1)
rinku (2.0.0)
rotp (2.1.2)
- rouge (2.1.0)
+ rouge (2.2.0)
rqrcode (0.7.0)
chunky_png
rqrcode-rails3 (0.1.7)
@@ -960,7 +958,6 @@ DEPENDENCIES
activerecord_sane_schema_dumper (= 0.2)
acts-as-taggable-on (~> 4.0)
addressable (~> 2.3.8)
- after_commit_queue (~> 1.3.0)
akismet (~> 2.0)
allocations (~> 1.0)
asana (~> 0.6.0)
@@ -1022,7 +1019,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
- gitaly (~> 0.27.0)
+ gitaly (~> 0.29.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.5.1)
@@ -1097,7 +1094,7 @@ DEPENDENCIES
pg (~> 0.18.2)
poltergeist (~> 1.9.0)
premailer-rails (~> 1.9.7)
- prometheus-client-mmap (~> 0.7.0.beta11)
+ prometheus-client-mmap (~> 0.7.0.beta12)
pry-byebug (~> 3.4.1)
pry-rails (~> 0.3.4)
rack-attack (~> 4.4.1)
diff --git a/VERSION b/VERSION
index 027fe8dd2cf..ddadd9f9c5a 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-9.5.0-pre
+9.6.0-pre
diff --git a/app/assets/javascripts/boards/components/issue_card_inner.js b/app/assets/javascripts/boards/components/issue_card_inner.js
index d3de1830895..9a5d87ede7e 100644
--- a/app/assets/javascripts/boards/components/issue_card_inner.js
+++ b/app/assets/javascripts/boards/components/issue_card_inner.js
@@ -97,7 +97,7 @@ gl.issueBoards.IssueCardInner = Vue.extend({
return `Avatar for ${assignee.name}`;
},
showLabel(label) {
- if (!this.list || !label) return true;
+ if (!label.id) return false;
return true;
},
filterByLabel(label, e) {
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 613a70f0a3a..e8ef8dcc0c5 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -413,7 +413,7 @@ import initChangesDropdown from './init_changes_dropdown';
case 'projects:tree:show':
shortcut_handler = new ShortcutsNavigation();
- if (UserFeatureHelper.isNewRepo()) break;
+ if (UserFeatureHelper.isNewRepoEnabled()) break;
new TreeView();
new BlobViewer();
@@ -433,7 +433,7 @@ import initChangesDropdown from './init_changes_dropdown';
shortcut_handler = true;
break;
case 'projects:blob:show':
- if (UserFeatureHelper.isNewRepo()) break;
+ if (UserFeatureHelper.isNewRepoEnabled()) break;
new BlobViewer();
initBlob();
break;
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index b5975295329..4d629bc6326 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -111,8 +111,7 @@ window.GroupsSelect = (function() {
};
GroupsSelect.prototype.forceOverflow = function (e) {
- const itemHeight = this.dropdown.querySelector('.select2-result:first-child').clientHeight;
- this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight - (itemHeight * 0.9))}px`;
+ this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight)}px`;
};
GroupsSelect.PER_PAGE = 20;
diff --git a/app/assets/javascripts/helpers/user_feature_helper.js b/app/assets/javascripts/helpers/user_feature_helper.js
index fcd8569819c..638118a5204 100644
--- a/app/assets/javascripts/helpers/user_feature_helper.js
+++ b/app/assets/javascripts/helpers/user_feature_helper.js
@@ -1,11 +1,7 @@
import Cookies from 'js-cookie';
-function isNewRepo() {
- return Cookies.get('new_repo') === 'true';
-}
-
-const UserFeatureHelper = {
- isNewRepo,
+export default {
+ isNewRepoEnabled() {
+ return Cookies.get('new_repo') === 'true';
+ },
};
-
-export default UserFeatureHelper;
diff --git a/app/assets/javascripts/lib/utils/common_utils.js b/app/assets/javascripts/lib/utils/common_utils.js
index dce5e76ecee..b8bebe1894f 100644
--- a/app/assets/javascripts/lib/utils/common_utils.js
+++ b/app/assets/javascripts/lib/utils/common_utils.js
@@ -386,15 +386,15 @@
w.gl.utils.backOff = (fn, timeout = 60000) => {
const maxInterval = 32000;
let nextInterval = 2000;
-
- const startTime = Date.now();
+ let timeElapsed = 0;
return new Promise((resolve, reject) => {
const stop = arg => ((arg instanceof Error) ? reject(arg) : resolve(arg));
const next = () => {
- if (Date.now() - startTime < timeout) {
- setTimeout(fn.bind(null, next, stop), nextInterval);
+ if (timeElapsed < timeout) {
+ setTimeout(() => fn(next, stop), nextInterval);
+ timeElapsed += nextInterval;
nextInterval = Math.min(nextInterval + nextInterval, maxInterval);
} else {
reject(new Error('BACKOFF_TIMEOUT'));
diff --git a/app/assets/javascripts/project_select_combo_button.js b/app/assets/javascripts/project_select_combo_button.js
index f799d9d619a..46a26fb91f4 100644
--- a/app/assets/javascripts/project_select_combo_button.js
+++ b/app/assets/javascripts/project_select_combo_button.js
@@ -4,10 +4,10 @@ export default class ProjectSelectComboButton {
constructor(select) {
this.projectSelectInput = $(select);
this.newItemBtn = $('.new-project-item-link');
- this.newItemBtnBaseText = this.newItemBtn.data('label');
- this.itemType = this.deriveItemTypeFromLabel();
+ this.resourceType = this.newItemBtn.data('type');
+ this.resourceLabel = this.newItemBtn.data('label');
+ this.formattedText = this.deriveTextVariants();
this.groupId = this.projectSelectInput.data('groupId');
-
this.bindEvents();
this.initLocalStorage();
}
@@ -23,9 +23,7 @@ export default class ProjectSelectComboButton {
const localStorageIsSafe = AccessorUtilities.isLocalStorageAccessSafe();
if (localStorageIsSafe) {
- const itemTypeKebabed = this.newItemBtnBaseText.toLowerCase().split(' ').join('-');
-
- this.localStorageKey = ['group', this.groupId, itemTypeKebabed, 'recent-project'].join('-');
+ this.localStorageKey = ['group', this.groupId, this.formattedText.localStorageItemType, 'recent-project'].join('-');
this.setBtnTextFromLocalStorage();
}
}
@@ -57,19 +55,14 @@ export default class ProjectSelectComboButton {
setNewItemBtnAttributes(project) {
if (project) {
this.newItemBtn.attr('href', project.url);
- this.newItemBtn.text(`${this.newItemBtnBaseText} in ${project.name}`);
+ this.newItemBtn.text(`${this.formattedText.defaultTextPrefix} in ${project.name}`);
this.newItemBtn.enable();
} else {
- this.newItemBtn.text(`Select project to create ${this.itemType}`);
+ this.newItemBtn.text(`Select project to create ${this.formattedText.presetTextSuffix}`);
this.newItemBtn.disable();
}
}
- deriveItemTypeFromLabel() {
- // label is either 'New issue' or 'New merge request'
- return this.newItemBtnBaseText.split(' ').slice(1).join(' ');
- }
-
getProjectFromLocalStorage() {
const projectString = localStorage.getItem(this.localStorageKey);
@@ -81,5 +74,19 @@ export default class ProjectSelectComboButton {
localStorage.setItem(this.localStorageKey, projectString);
}
+
+ deriveTextVariants() {
+ const defaultTextPrefix = this.resourceLabel;
+
+ // the trailing slice call depluralizes each of these strings (e.g. new-issues -> new-issue)
+ const localStorageItemType = `new-${this.resourceType.split('_').join('-').slice(0, -1)}`;
+ const presetTextSuffix = this.resourceType.split('_').join(' ').slice(0, -1);
+
+ return {
+ localStorageItemType, // new-issue / new-merge-request
+ defaultTextPrefix, // New issue / New merge request
+ presetTextSuffix, // issue / merge request
+ };
+ }
}
diff --git a/app/assets/javascripts/repo/components/repo_sidebar.vue b/app/assets/javascripts/repo/components/repo_sidebar.vue
index 72b40288566..3414128526d 100644
--- a/app/assets/javascripts/repo/components/repo_sidebar.vue
+++ b/app/assets/javascripts/repo/components/repo_sidebar.vue
@@ -74,7 +74,8 @@ export default {
<tbody>
<repo-file-options
:is-mini="isMini"
- :project-name="projectName"/>
+ :project-name="projectName"
+ />
<repo-previous-directory
v-if="isRoot"
:prev-url="prevURL"
@@ -84,7 +85,8 @@ export default {
:key="n"
:loading="loading"
:has-files="!!files.length"
- :is-mini="isMini"/>
+ :is-mini="isMini"
+ />
<repo-file
v-for="file in files"
:key="file.id"
@@ -93,7 +95,8 @@ export default {
@linkclicked="fileClicked(file)"
:is-tree="isTree"
:has-files="!!files.length"
- :active-file="activeFile"/>
+ :active-file="activeFile"
+ />
</tbody>
</table>
</div>
diff --git a/app/assets/javascripts/repo/monaco_loader.js b/app/assets/javascripts/repo/monaco_loader.js
index ad1370a7730..af83a1ec0b4 100644
--- a/app/assets/javascripts/repo/monaco_loader.js
+++ b/app/assets/javascripts/repo/monaco_loader.js
@@ -1,13 +1,11 @@
-/* eslint-disable no-underscore-dangle, camelcase */
-/* global __webpack_public_path__ */
-
import monacoContext from 'monaco-editor/dev/vs/loader';
monacoContext.require.config({
paths: {
- vs: `${__webpack_public_path__}monaco-editor/vs`,
+ vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
},
});
+// eslint-disable-next-line no-underscore-dangle
window.__monaco_context__ = monacoContext;
export default monacoContext.require;
diff --git a/app/assets/javascripts/webpack.js b/app/assets/javascripts/webpack.js
index 9a9cf395fb8..ced847294ae 100644
--- a/app/assets/javascripts/webpack.js
+++ b/app/assets/javascripts/webpack.js
@@ -5,5 +5,5 @@
*/
if (gon && gon.webpack_public_path) {
- __webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line
+ __webpack_public_path__ = gon.webpack_public_path; // eslint-disable-line camelcase
}
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 0abb5d7fd8a..7322aaae46c 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -732,26 +732,41 @@
@mixin new-style-dropdown($selector: '') {
#{$selector}.dropdown-menu,
#{$selector}.dropdown-menu-nav {
- .divider {
- margin: 6px 0;
- }
-
li {
padding: 0 1px;
+ &:hover {
+ background-color: transparent;
+ }
+
+ &.divider {
+ margin: 6px 0;
+
+ &:hover {
+ background-color: $dropdown-divider-color;
+ }
+ }
+
&.dropdown-header {
padding: 8px 16px;
}
- a {
+ a,
+ button {
border-radius: 0;
padding: 8px 16px;
+ // make sure the text color is not overriden
+ &.text-danger {
+ @extend .text-danger;
+ }
+
&.is-focused,
&:hover,
&:active,
&:focus {
- background-color: $gray-darker;
+ background-color: $dropdown-item-hover-bg;
+ color: $gl-text-color;
}
&.is-active {
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index ec13a86ccf7..8dcaa879b3f 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -50,6 +50,8 @@
}
.filtered-search-wrapper {
+ @include new-style-dropdown;
+
display: -webkit-flex;
display: flex;
@@ -411,8 +413,6 @@
}
%filter-dropdown-item-btn-hover {
- background-color: $dropdown-hover-color;
- color: $white-light;
text-decoration: none;
outline: 0;
@@ -422,8 +422,6 @@
}
.droplab-dropdown .dropdown-menu .filter-dropdown-item {
- padding: 0;
-
.btn {
border: none;
width: 100%;
diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss
index ab754f4a492..df2bf561194 100644
--- a/app/assets/stylesheets/framework/lists.scss
+++ b/app/assets/stylesheets/framework/lists.scss
@@ -132,6 +132,8 @@ ul.content-list {
}
.controls {
+ @include new-style-dropdown;
+
float: right;
> .control-text {
diff --git a/app/assets/stylesheets/framework/selects.scss b/app/assets/stylesheets/framework/selects.scss
index 40e654f4838..f7a0b355bf1 100644
--- a/app/assets/stylesheets/framework/selects.scss
+++ b/app/assets/stylesheets/framework/selects.scss
@@ -264,3 +264,41 @@
.ajax-users-dropdown {
min-width: 250px !important;
}
+
+// TODO: change global style
+.ajax-project-dropdown {
+ &.select2-drop {
+ color: $gl-text-color;
+ }
+
+ .select2-results {
+ .select2-no-results,
+ .select2-searching,
+ .select2-ajax-error,
+ .select2-selection-limit {
+ background: transparent;
+ }
+
+ .select2-result {
+ padding: 0 1px;
+
+ .select2-match {
+ font-weight: bold;
+ text-decoration: none;
+ }
+
+ .select2-result-label {
+ padding: #{$gl-padding / 2} $gl-padding;
+ }
+
+ &.select2-highlighted {
+ background-color: transparent !important;
+ color: $gl-text-color;
+
+ .select2-result-label {
+ background-color: $dropdown-item-hover-bg;
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss
index 96409b10b99..d13f9996518 100644
--- a/app/assets/stylesheets/framework/typography.scss
+++ b/app/assets/stylesheets/framework/typography.scss
@@ -13,12 +13,16 @@
img {
/*max-width: 100%;*/
margin: 0 0 8px;
+ }
+
+ img.lazy {
min-width: 200px;
min-height: 100px;
background-color: $gray-lightest;
}
- img.js-lazy-loaded {
+ img.js-lazy-loaded,
+ img.emoji {
min-width: inherit;
min-height: inherit;
background-color: inherit;
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 3c109a5a929..225d116e9c7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -294,7 +294,7 @@ $dropdown-input-focus-shadow: rgba($dropdown-input-focus-border, .4);
$dropdown-loading-bg: rgba(#fff, .6);
$dropdown-chevron-size: 10px;
$dropdown-toggle-active-border-color: darken($border-color, 14%);
-
+$dropdown-item-hover-bg: $gray-darker;
/*
* Filtered Search
diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss
index 840a4f07a34..cee5b22adb9 100644
--- a/app/assets/stylesheets/new_sidebar.scss
+++ b/app/assets/stylesheets/new_sidebar.scss
@@ -104,6 +104,10 @@ $new-sidebar-collapsed-width: 50px;
&.sidebar-icons-only {
width: $new-sidebar-collapsed-width;
+ .nav-sidebar-inner-scroll {
+ overflow-x: hidden;
+ }
+
.badge,
.project-title {
display: none;
diff --git a/app/controllers/admin/logs_controller.rb b/app/controllers/admin/logs_controller.rb
index b999018dde4..bdc4332ae69 100644
--- a/app/controllers/admin/logs_controller.rb
+++ b/app/controllers/admin/logs_controller.rb
@@ -1,2 +1,11 @@
class Admin::LogsController < Admin::ApplicationController
+ def show
+ @loggers = [
+ Gitlab::AppLogger,
+ Gitlab::GitLogger,
+ Gitlab::EnvironmentLogger,
+ Gitlab::SidekiqLogger,
+ Gitlab::RepositoryCheckLogger
+ ]
+ end
end
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index f76b3f69e9e..994e736d66e 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -26,6 +26,13 @@ class GroupsController < Groups::ApplicationController
def new
@group = Group.new
+
+ if params[:parent_id].present?
+ parent = Group.find_by(id: params[:parent_id])
+ if can?(current_user, :create_subgroup, parent)
+ @group.parent = parent
+ end
+ end
end
def create
diff --git a/app/controllers/projects/services_controller.rb b/app/controllers/projects/services_controller.rb
index d54a1111f11..daa5c88aae0 100644
--- a/app/controllers/projects/services_controller.rb
+++ b/app/controllers/projects/services_controller.rb
@@ -4,7 +4,6 @@ class Projects::ServicesController < Projects::ApplicationController
# Authorize
before_action :authorize_admin_project!
before_action :service, only: [:edit, :update, :test]
- before_action :update_service, only: [:update, :test]
respond_to :html
@@ -14,6 +13,8 @@ class Projects::ServicesController < Projects::ApplicationController
end
def update
+ @service.attributes = service_params[:service]
+
if @service.save(context: :manual_change)
redirect_to(project_settings_integrations_path(@project), notice: success_message)
else
@@ -24,7 +25,7 @@ class Projects::ServicesController < Projects::ApplicationController
def test
message = {}
- if @service.can_test?
+ if @service.can_test? && @service.update_attributes(service_params[:service])
data = @service.test_data(project, current_user)
outcome = @service.test(data)
@@ -50,10 +51,6 @@ class Projects::ServicesController < Projects::ApplicationController
end
end
- def update_service
- @service.assign_attributes(service_params[:service])
- end
-
def service
@service ||= @project.find_or_initialize_service(params[:id])
end
diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb
index 150188f0b65..3b76da238e0 100644
--- a/app/helpers/application_settings_helper.rb
+++ b/app/helpers/application_settings_helper.rb
@@ -116,6 +116,7 @@ module ApplicationSettingsHelper
:email_author_in_body,
:enabled_git_access_protocol,
:gravatar_enabled,
+ :hashed_storage_enabled,
:help_page_hide_commercial_content,
:help_page_support_url,
:help_page_text,
diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb
index 48c87dca217..c6f98e7e782 100644
--- a/app/helpers/events_helper.rb
+++ b/app/helpers/events_helper.rb
@@ -35,18 +35,18 @@ module EventsHelper
[event.action_name, target].join(" ")
end
- def event_filter_link(key, tooltip)
+ def event_filter_link(key, text, tooltip)
key = key.to_s
active = 'active' if @event_filter.active?(key)
link_opts = {
- class: "event-filter-link",
+ class: "event-filter-link has-tooltip",
id: "#{key}_event_filter",
- title: "Filter by #{tooltip.downcase}"
+ title: tooltip
}
content_tag :li, class: active do
link_to request.path, link_opts do
- content_tag(:span, ' ' + tooltip)
+ content_tag(:span, ' ' + text)
end
end
end
@@ -176,7 +176,7 @@ module EventsHelper
sanitize(
text,
tags: %w(a img gl-emoji b pre code p span),
- attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-name', 'data-unicode-version']
+ attributes: Rails::Html::WhiteListSanitizer.allowed_attributes + ['style', 'data-src', 'data-name', 'data-unicode-version']
)
end
diff --git a/app/models/blob_viewer/composer_json.rb b/app/models/blob_viewer/composer_json.rb
index ef8b4aef8e8..def4879fbb5 100644
--- a/app/models/blob_viewer/composer_json.rb
+++ b/app/models/blob_viewer/composer_json.rb
@@ -9,7 +9,7 @@ module BlobViewer
end
def manager_url
- 'https://getcomposer.com/'
+ 'https://getcomposer.org/'
end
def package_name
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 3692bcc680d..fdc5a2adea0 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -19,11 +19,21 @@ class BroadcastMessage < ActiveRecord::Base
after_commit :flush_redis_cache
def self.current
- Rails.cache.fetch(CACHE_KEY) do
- where('ends_at > :now AND starts_at <= :now', now: Time.zone.now)
- .reorder(id: :asc)
- .to_a
- end
+ messages = Rails.cache.fetch(CACHE_KEY) { current_and_future_messages.to_a }
+
+ return messages if messages.empty?
+
+ now_or_future = messages.select(&:now_or_future?)
+
+ # If there are cached entries but none are to be displayed we'll purge the
+ # cache so we don't keep running this code all the time.
+ Rails.cache.delete(CACHE_KEY) if now_or_future.empty?
+
+ now_or_future.select(&:now?)
+ end
+
+ def self.current_and_future_messages
+ where('ends_at > :now', now: Time.zone.now).reorder(id: :asc)
end
def active?
@@ -38,6 +48,18 @@ class BroadcastMessage < ActiveRecord::Base
ends_at < Time.zone.now
end
+ def now?
+ (starts_at..ends_at).cover?(Time.zone.now)
+ end
+
+ def future?
+ starts_at > Time.zone.now
+ end
+
+ def now_or_future?
+ now? || future?
+ end
+
def flush_redis_cache
Rails.cache.delete(CACHE_KEY)
end
diff --git a/app/models/ci/pipeline_schedule.rb b/app/models/ci/pipeline_schedule.rb
index 085eeeae157..e7e02587759 100644
--- a/app/models/ci/pipeline_schedule.rb
+++ b/app/models/ci/pipeline_schedule.rb
@@ -9,7 +9,7 @@ module Ci
belongs_to :owner, class_name: 'User'
has_one :last_pipeline, -> { order(id: :desc) }, class_name: 'Ci::Pipeline'
has_many :pipelines
- has_many :variables, class_name: 'Ci::PipelineScheduleVariable'
+ has_many :variables, class_name: 'Ci::PipelineScheduleVariable', validate: false
validates :cron, unless: :importing?, cron: true, presence: { unless: :importing? }
validates :cron_timezone, cron_timezone: true, presence: { unless: :importing? }
diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb
index 1ff177616e8..ee5b8733fac 100644
--- a/app/models/ci/pipeline_schedule_variable.rb
+++ b/app/models/ci/pipeline_schedule_variable.rb
@@ -4,5 +4,7 @@ module Ci
include HasVariable
belongs_to :pipeline_schedule
+
+ validates :key, uniqueness: { scope: :pipeline_schedule_id }
end
end
diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb
index 59570924c8d..4ee972fa68d 100644
--- a/app/models/ci/stage.rb
+++ b/app/models/ci/stage.rb
@@ -1,11 +1,66 @@
module Ci
class Stage < ActiveRecord::Base
extend Ci::Model
+ include Importable
+ include HasStatus
+ include Gitlab::OptimisticLocking
+
+ enum status: HasStatus::STATUSES_ENUM
belongs_to :project
belongs_to :pipeline
- has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
- has_many :builds, foreign_key: :commit_id
+ has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id
+ has_many :builds, foreign_key: :stage_id
+
+ validates :project, presence: true, unless: :importing?
+ validates :pipeline, presence: true, unless: :importing?
+ validates :name, presence: true, unless: :importing?
+
+ state_machine :status, initial: :created do
+ event :enqueue do
+ transition created: :pending
+ transition [:success, :failed, :canceled, :skipped] => :running
+ end
+
+ event :run do
+ transition any - [:running] => :running
+ end
+
+ event :skip do
+ transition any - [:skipped] => :skipped
+ end
+
+ event :drop do
+ transition any - [:failed] => :failed
+ end
+
+ event :succeed do
+ transition any - [:success] => :success
+ end
+
+ event :cancel do
+ transition any - [:canceled] => :canceled
+ end
+
+ event :block do
+ transition any - [:manual] => :manual
+ end
+ end
+
+ def update_status
+ retry_optimistic_lock(self) do
+ case statuses.latest.status
+ when 'pending' then enqueue
+ when 'running' then run
+ when 'success' then succeed
+ when 'failed' then drop
+ when 'canceled' then cancel
+ when 'manual' then block
+ when 'skipped' then skip
+ else skip
+ end
+ end
+ end
end
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 07cec63b939..842c6e5cb50 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -39,14 +39,14 @@ class CommitStatus < ActiveRecord::Base
scope :after_stage, -> (index) { where('stage_idx > ?', index) }
state_machine :status do
- event :enqueue do
- transition [:created, :skipped, :manual] => :pending
- end
-
event :process do
transition [:skipped, :manual] => :created
end
+ event :enqueue do
+ transition [:created, :skipped, :manual] => :pending
+ end
+
event :run do
transition pending: :running
end
@@ -91,6 +91,7 @@ class CommitStatus < ActiveRecord::Base
end
end
+ StageUpdateWorker.perform_async(commit_status.stage_id)
ExpireJobCacheWorker.perform_async(commit_status.id)
end
end
diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb
index 32af5566135..3803e18a96e 100644
--- a/app/models/concerns/has_status.rb
+++ b/app/models/concerns/has_status.rb
@@ -8,6 +8,8 @@ module HasStatus
ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze
+ STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
class_methods do
def status_sql
diff --git a/app/models/concerns/storage/legacy_project.rb b/app/models/concerns/storage/legacy_project.rb
deleted file mode 100644
index 815db712285..00000000000
--- a/app/models/concerns/storage/legacy_project.rb
+++ /dev/null
@@ -1,76 +0,0 @@
-module Storage
- module LegacyProject
- extend ActiveSupport::Concern
-
- def disk_path
- full_path
- end
-
- def ensure_storage_path_exist
- gitlab_shell.add_namespace(repository_storage_path, namespace.full_path)
- end
-
- def rename_repo
- path_was = previous_changes['path'].first
- old_path_with_namespace = File.join(namespace.full_path, path_was)
- new_path_with_namespace = File.join(namespace.full_path, path)
-
- Rails.logger.error "Attempting to rename #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- if has_container_registry_tags?
- Rails.logger.error "Project #{old_path_with_namespace} cannot be renamed because container registry tags are present!"
-
- # we currently doesn't support renaming repository if it contains images in container registry
- raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
- end
-
- expire_caches_before_rename(old_path_with_namespace)
-
- if gitlab_shell.mv_repository(repository_storage_path, old_path_with_namespace, new_path_with_namespace)
- # If repository moved successfully we need to send update instructions to users.
- # However we cannot allow rollback since we moved repository
- # So we basically we mute exceptions in next actions
- begin
- gitlab_shell.mv_repository(repository_storage_path, "#{old_path_with_namespace}.wiki", "#{new_path_with_namespace}.wiki")
- send_move_instructions(old_path_with_namespace)
- expires_full_path_cache
-
- @old_path_with_namespace = old_path_with_namespace
-
- SystemHooksService.new.execute_hooks_for(self, :rename)
-
- @repository = nil
- rescue => e
- Rails.logger.error "Exception renaming #{old_path_with_namespace} -> #{new_path_with_namespace}: #{e}"
- # Returning false does not rollback after_* transaction but gives
- # us information about failing some of tasks
- false
- end
- else
- Rails.logger.error "Repository could not be renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- # if we cannot move namespace directory we should rollback
- # db changes in order to prevent out of sync between db and fs
- raise StandardError.new('repository cannot be renamed')
- end
-
- Gitlab::AppLogger.info "Project was renamed: #{old_path_with_namespace} -> #{new_path_with_namespace}"
-
- Gitlab::UploadsTransfer.new.rename_project(path_was, path, namespace.full_path)
- Gitlab::PagesTransfer.new.rename_project(path_was, path, namespace.full_path)
- end
-
- def create_repository(force: false)
- # Forked import is handled asynchronously
- return if forked? && !force
-
- if gitlab_shell.add_repository(repository_storage_path, path_with_namespace)
- repository.after_create
- true
- else
- errors.add(:base, 'Failed to create repository via gitlab-shell')
- false
- end
- end
- end
-end
diff --git a/app/models/event.rb b/app/models/event.rb
index f2a560a6b56..15ee170ca75 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -83,6 +83,10 @@ class Event < ActiveRecord::Base
self.inheritance_column = 'action'
class << self
+ def model_name
+ ActiveModel::Name.new(self, nil, 'event')
+ end
+
def find_sti_class(action)
if action.to_i == PUSHED
PushEvent
@@ -438,6 +442,12 @@ class Event < ActiveRecord::Base
EventForMigration.create!(new_attributes)
end
+ def to_partial_path
+ # We are intentionally using `Event` rather than `self.class` so that
+ # subclasses also use the `Event` implementation.
+ Event._to_partial_path
+ end
+
private
def recent_update?
diff --git a/app/models/issue.rb b/app/models/issue.rb
index 2f7624ae2bb..4cd30dfeb94 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -9,11 +9,8 @@ class Issue < ActiveRecord::Base
include Spammable
include FasterCacheKeys
include RelativePositioning
- include IgnorableColumn
include CreatedAtFilterable
- ignore_column :position
-
DueDateStruct = Struct.new(:title, :name).freeze
NoDueDate = DueDateStruct.new('No Due Date', '0').freeze
AnyDueDate = DueDateStruct.new('Any Due Date', '').freeze
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index ac08dc0ee1f..f028d2395c1 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -7,7 +7,6 @@ class MergeRequest < ActiveRecord::Base
include IgnorableColumn
include CreatedAtFilterable
- ignore_column :position
ignore_column :locked_at
belongs_to :target_project, class_name: "Project"
diff --git a/app/models/project.rb b/app/models/project.rb
index 89b4debcd42..37f4dd08355 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -17,7 +17,6 @@ class Project < ActiveRecord::Base
include ProjectFeaturesCompatibility
include SelectForProjectAuthorization
include Routable
- include Storage::LegacyProject
extend Gitlab::ConfigHelper
@@ -25,6 +24,7 @@ class Project < ActiveRecord::Base
NUMBER_OF_PERMITTED_BOARDS = 1
UNKNOWN_IMPORT_URL = 'http://unknown.git'.freeze
+ LATEST_STORAGE_VERSION = 1
cache_markdown_field :description, pipeline: :description
@@ -32,6 +32,8 @@ class Project < ActiveRecord::Base
:merge_requests_enabled?, :issues_enabled?, to: :project_feature,
allow_nil: true
+ delegate :base_dir, :disk_path, :ensure_storage_path_exists, to: :storage
+
default_value_for :archived, false
default_value_for :visibility_level, gitlab_config_features.visibility_level
default_value_for :container_registry_enabled, gitlab_config_features.container_registry
@@ -44,32 +46,24 @@ class Project < ActiveRecord::Base
default_value_for :snippets_enabled, gitlab_config_features.snippets
default_value_for :only_allow_merge_if_all_discussions_are_resolved, false
- after_create :ensure_storage_path_exist
- after_create :create_project_feature, unless: :project_feature
- after_save :update_project_statistics, if: :namespace_id_changed?
+ add_authentication_token_field :runners_token
+ before_save :ensure_runners_token
- # set last_activity_at to the same as created_at
+ after_save :update_project_statistics, if: :namespace_id_changed?
+ after_create :create_project_feature, unless: :project_feature
after_create :set_last_activity_at
- def set_last_activity_at
- update_column(:last_activity_at, self.created_at)
- end
-
after_create :set_last_repository_updated_at
- def set_last_repository_updated_at
- update_column(:last_repository_updated_at, self.created_at)
- end
+ after_update :update_forks_visibility_level
before_destroy :remove_private_deploy_keys
after_destroy -> { run_after_commit { remove_pages } }
- # update visibility_level of forks
- after_update :update_forks_visibility_level
-
after_validation :check_pending_delete
- # Legacy Storage specific hooks
-
- after_save :ensure_storage_path_exist, if: :namespace_id_changed?
+ # Storage specific hooks
+ after_initialize :use_hashed_storage
+ after_create :ensure_storage_path_exists
+ after_save :ensure_storage_path_exists, if: :namespace_id_changed?
acts_as_taggable
@@ -238,9 +232,6 @@ class Project < ActiveRecord::Base
presence: true,
inclusion: { in: ->(_object) { Gitlab.config.repositories.storages.keys } }
- add_authentication_token_field :runners_token
- before_save :ensure_runners_token
-
mount_uploader :avatar, AvatarUploader
has_many :uploads, as: :model, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
@@ -369,7 +360,10 @@ class Project < ActiveRecord::Base
state :failed
after_transition [:none, :finished, :failed] => :scheduled do |project, _|
- project.run_after_commit { add_import_job }
+ project.run_after_commit do
+ job_id = add_import_job
+ update(import_jid: job_id) if job_id
+ end
end
after_transition started: :finished do |project, _|
@@ -484,6 +478,10 @@ class Project < ActiveRecord::Base
@repository ||= Repository.new(full_path, self, disk_path: disk_path)
end
+ def reload_repository!
+ @repository = nil
+ end
+
def container_registry_url
if Gitlab.config.registry.enabled
"#{Gitlab.config.registry.host_port}/#{full_path.downcase}"
@@ -524,17 +522,26 @@ class Project < ActiveRecord::Base
def add_import_job
job_id =
if forked?
- RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path,
- forked_from_project.full_path,
- self.namespace.full_path)
+ RepositoryForkWorker.perform_async(id,
+ forked_from_project.repository_storage_path,
+ forked_from_project.full_path,
+ self.namespace.full_path)
else
RepositoryImportWorker.perform_async(self.id)
end
+ log_import_activity(job_id)
+
+ job_id
+ end
+
+ def log_import_activity(job_id, type: :import)
+ job_type = type.to_s.capitalize
+
if job_id
- Rails.logger.info "Import job started for #{full_path} with job ID #{job_id}"
+ Rails.logger.info("#{job_type} job scheduled for #{full_path} with job ID #{job_id}.")
else
- Rails.logger.error "Import job failed to start for #{full_path}"
+ Rails.logger.error("#{job_type} job failed to create for #{full_path}.")
end
end
@@ -543,6 +550,7 @@ class Project < ActiveRecord::Base
ProjectCacheWorker.perform_async(self.id)
end
+ update(import_error: nil)
remove_import_data
end
@@ -991,6 +999,19 @@ class Project < ActiveRecord::Base
end
end
+ def create_repository(force: false)
+ # Forked import is handled asynchronously
+ return if forked? && !force
+
+ if gitlab_shell.add_repository(repository_storage_path, disk_path)
+ repository.after_create
+ true
+ else
+ errors.add(:base, 'Failed to create repository via gitlab-shell')
+ false
+ end
+ end
+
def hook_attrs(backward: true)
attrs = {
name: name,
@@ -1073,6 +1094,7 @@ class Project < ActiveRecord::Base
!!repository.exists?
end
+ # update visibility_level of forks
def update_forks_visibility_level
return unless visibility_level < visibility_level_was
@@ -1200,7 +1222,8 @@ class Project < ActiveRecord::Base
end
def pages_path
- File.join(Settings.pages.path, disk_path)
+ # TODO: when we migrate Pages to work with new storage types, change here to use disk_path
+ File.join(Settings.pages.path, full_path)
end
def public_pages_path
@@ -1239,6 +1262,50 @@ class Project < ActiveRecord::Base
end
end
+ def rename_repo
+ new_full_path = build_full_path
+
+ Rails.logger.error "Attempting to rename #{full_path_was} -> #{new_full_path}"
+
+ if has_container_registry_tags?
+ Rails.logger.error "Project #{full_path_was} cannot be renamed because container registry tags are present!"
+
+ # we currently doesn't support renaming repository if it contains images in container registry
+ raise StandardError.new('Project cannot be renamed, because images are present in its container registry')
+ end
+
+ expire_caches_before_rename(full_path_was)
+
+ if storage.rename_repo
+ Gitlab::AppLogger.info "Project was renamed: #{full_path_was} -> #{new_full_path}"
+ rename_repo_notify!
+ after_rename_repo
+ else
+ Rails.logger.error "Repository could not be renamed: #{full_path_was} -> #{new_full_path}"
+
+ # if we cannot move namespace directory we should rollback
+ # db changes in order to prevent out of sync between db and fs
+ raise StandardError.new('repository cannot be renamed')
+ end
+ end
+
+ def rename_repo_notify!
+ send_move_instructions(full_path_was)
+ expires_full_path_cache
+
+ self.old_path_with_namespace = full_path_was
+ SystemHooksService.new.execute_hooks_for(self, :rename)
+
+ reload_repository!
+ end
+
+ def after_rename_repo
+ path_before_change = previous_changes['path'].first
+
+ Gitlab::UploadsTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
+ Gitlab::PagesTransfer.new.rename_project(path_before_change, self.path, namespace.full_path)
+ end
+
def running_or_pending_build_count(force: false)
Rails.cache.fetch(['projects', id, 'running_or_pending_build_count'], force: force) do
builds.running_or_pending.count(:all)
@@ -1397,6 +1464,10 @@ class Project < ActiveRecord::Base
end
end
+ def full_path_was
+ File.join(namespace.full_path, previous_changes['path'].first)
+ end
+
alias_method :name_with_namespace, :full_name
alias_method :human_name, :full_name
# @deprecated cannot remove yet because it has an index with its name in elasticsearch
@@ -1406,8 +1477,36 @@ class Project < ActiveRecord::Base
Projects::ForksCountService.new(self).count
end
+ def legacy_storage?
+ self.storage_version.nil?
+ end
+
private
+ def storage
+ @storage ||=
+ if self.storage_version && self.storage_version >= 1
+ Storage::HashedProject.new(self)
+ else
+ Storage::LegacyProject.new(self)
+ end
+ end
+
+ def use_hashed_storage
+ if self.new_record? && current_application_settings.hashed_storage_enabled
+ self.storage_version = LATEST_STORAGE_VERSION
+ end
+ end
+
+ # set last_activity_at to the same as created_at
+ def set_last_activity_at
+ update_column(:last_activity_at, self.created_at)
+ end
+
+ def set_last_repository_updated_at
+ update_column(:last_repository_updated_at, self.created_at)
+ end
+
def cross_namespace_reference?(from)
case from
when Project
diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb
index dee99bbb859..8ba07173c74 100644
--- a/app/models/project_services/kubernetes_service.rb
+++ b/app/models/project_services/kubernetes_service.rb
@@ -24,6 +24,8 @@ class KubernetesService < DeploymentService
validates :token
end
+ before_validation :enforce_namespace_to_lower_case
+
validates :namespace,
allow_blank: true,
length: 1..63,
@@ -207,4 +209,8 @@ class KubernetesService < DeploymentService
max_session_time: current_application_settings.terminal_max_session_time
}
end
+
+ def enforce_namespace_to_lower_case
+ self.namespace = self.namespace&.downcase
+ end
end
diff --git a/app/models/storage/hashed_project.rb b/app/models/storage/hashed_project.rb
new file mode 100644
index 00000000000..fae1b64961a
--- /dev/null
+++ b/app/models/storage/hashed_project.rb
@@ -0,0 +1,42 @@
+module Storage
+ class HashedProject
+ attr_accessor :project
+ delegate :gitlab_shell, :repository_storage_path, to: :project
+
+ ROOT_PATH_PREFIX = '@hashed'.freeze
+
+ def initialize(project)
+ @project = project
+ end
+
+ # Base directory
+ #
+ # @return [String] directory where repository is stored
+ def base_dir
+ "#{ROOT_PATH_PREFIX}/#{disk_hash[0..1]}/#{disk_hash[2..3]}" if disk_hash
+ end
+
+ # Disk path is used to build repository and project's wiki path on disk
+ #
+ # @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
+ def disk_path
+ "#{base_dir}/#{disk_hash}" if disk_hash
+ end
+
+ def ensure_storage_path_exists
+ gitlab_shell.add_namespace(repository_storage_path, base_dir)
+ end
+
+ def rename_repo
+ true
+ end
+
+ private
+
+ # Generates the hash for the project path and name on disk
+ # If you need to refer to the repository on disk, use the `#disk_path`
+ def disk_hash
+ @disk_hash ||= Digest::SHA2.hexdigest(project.id.to_s) if project.id
+ end
+ end
+end
diff --git a/app/models/storage/legacy_project.rb b/app/models/storage/legacy_project.rb
new file mode 100644
index 00000000000..9d9e5e1d352
--- /dev/null
+++ b/app/models/storage/legacy_project.rb
@@ -0,0 +1,51 @@
+module Storage
+ class LegacyProject
+ attr_accessor :project
+ delegate :namespace, :gitlab_shell, :repository_storage_path, to: :project
+
+ def initialize(project)
+ @project = project
+ end
+
+ # Base directory
+ #
+ # @return [String] directory where repository is stored
+ def base_dir
+ namespace.full_path
+ end
+
+ # Disk path is used to build repository and project's wiki path on disk
+ #
+ # @return [String] combination of base_dir and the repository own name without `.git` or `.wiki.git` extensions
+ def disk_path
+ project.full_path
+ end
+
+ def ensure_storage_path_exists
+ return unless namespace
+
+ gitlab_shell.add_namespace(repository_storage_path, base_dir)
+ end
+
+ def rename_repo
+ new_full_path = project.build_full_path
+
+ if gitlab_shell.mv_repository(repository_storage_path, project.full_path_was, new_full_path)
+ # If repository moved successfully we need to send update instructions to users.
+ # However we cannot allow rollback since we moved repository
+ # So we basically we mute exceptions in next actions
+ begin
+ gitlab_shell.mv_repository(repository_storage_path, "#{project.full_path_was}.wiki", "#{new_full_path}.wiki")
+ return true
+ rescue => e
+ Rails.logger.error "Exception renaming #{project.full_path_was} -> #{new_full_path}: #{e}"
+ # Returning false does not rollback after_* transaction but gives
+ # us information about failing some of tasks
+ return false
+ end
+ end
+
+ false
+ end
+ end
+end
diff --git a/app/models/user.rb b/app/models/user.rb
index 02c3ab6654b..fbd08bc4d0a 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -837,7 +837,12 @@ class User < ActiveRecord::Base
create_namespace!(path: username, name: username) unless namespace
if username_changed?
- namespace.update_attributes(path: username, name: username)
+ unless namespace.update_attributes(path: username, name: username)
+ namespace.errors.each do |attribute, message|
+ self.errors.add(:"namespace_#{attribute}", message)
+ end
+ raise ActiveRecord::RecordInvalid.new(namespace)
+ end
end
end
diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb
index 6defab75fce..8ada661e571 100644
--- a/app/policies/group_policy.rb
+++ b/app/policies/group_policy.rb
@@ -13,6 +13,8 @@ class GroupPolicy < BasePolicy
condition(:master) { access_level >= GroupMember::MASTER }
condition(:reporter) { access_level >= GroupMember::REPORTER }
+ condition(:nested_groups_supported, scope: :global) { Group.supports_nested_groups? }
+
condition(:has_projects) do
GroupProjectsFinder.new(group: @subject, current_user: @user).execute.any?
end
@@ -42,7 +44,7 @@ class GroupPolicy < BasePolicy
enable :change_visibility_level
end
- rule { owner & can_create_group }.enable :create_subgroup
+ rule { owner & can_create_group & nested_groups_supported }.enable :create_subgroup
rule { public_group | logged_in_viewable }.enable :view_globally
diff --git a/app/services/ci/create_pipeline_service.rb b/app/services/ci/create_pipeline_service.rb
index 884b681ff81..d0ba9f89460 100644
--- a/app/services/ci/create_pipeline_service.rb
+++ b/app/services/ci/create_pipeline_service.rb
@@ -176,9 +176,14 @@ module Ci
end
def error(message, save: false)
- pipeline.errors.add(:base, message)
- pipeline.drop if save
- pipeline
+ pipeline.tap do
+ pipeline.errors.add(:base, message)
+
+ if save
+ pipeline.drop
+ update_merge_requests_head_pipeline
+ end
+ end
end
def pipeline_created_counter
diff --git a/app/services/groups/create_service.rb b/app/services/groups/create_service.rb
index c4e9b8fd8e0..c7c27621085 100644
--- a/app/services/groups/create_service.rb
+++ b/app/services/groups/create_service.rb
@@ -13,9 +13,9 @@ module Groups
return @group
end
- if @group.parent && !can?(current_user, :admin_group, @group.parent)
+ if @group.parent && !can?(current_user, :create_subgroup, @group.parent)
@group.parent = nil
- @group.errors.add(:parent_id, 'manage access required to create subgroup')
+ @group.errors.add(:parent_id, 'You don’t have permission to create a subgroup in this group.')
return @group
end
diff --git a/app/services/groups/destroy_service.rb b/app/services/groups/destroy_service.rb
index f565612a89d..e3f9d9ee95d 100644
--- a/app/services/groups/destroy_service.rb
+++ b/app/services/groups/destroy_service.rb
@@ -13,7 +13,7 @@ module Groups
# Execute the destruction of the models immediately to ensure atomic cleanup.
# Skip repository removal because we remove directory with namespace
# that contain all these repositories
- ::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
+ ::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
end
group.children.each do |group|
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 738cedbaed7..da39a380451 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -3,6 +3,8 @@ module MergeRequests
def execute
return error('Invalid issue iid') unless issue_iid.present? && issue.present?
+ params[:label_ids] = issue.label_ids if issue.label_ids.any?
+
result = CreateBranchService.new(project, current_user).execute(branch_name, ref)
return result if result[:status] == :error
@@ -43,7 +45,8 @@ module MergeRequests
{
source_project_id: project.id,
source_branch: branch_name,
- target_project_id: project.id
+ target_project_id: project.id,
+ milestone_id: issue.milestone_id
}
end
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index 4b8946f8ee2..d66ef676088 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -9,7 +9,8 @@ module Projects
class HousekeepingService < BaseService
include Gitlab::CurrentSettings
- LEASE_TIMEOUT = 3600
+ # Timeout set to 24h
+ LEASE_TIMEOUT = 86400
class LeaseTaken < StandardError
def to_s
diff --git a/app/services/users/destroy_service.rb b/app/services/users/destroy_service.rb
index 9d7237c2fbb..8e20de8dfa5 100644
--- a/app/services/users/destroy_service.rb
+++ b/app/services/users/destroy_service.rb
@@ -35,16 +35,18 @@ module Users
Groups::DestroyService.new(group, current_user).execute
end
+ namespace = user.namespace
+ namespace.prepare_for_destroy
+
user.personal_projects.each do |project|
# Skip repository removal because we remove directory with namespace
# that contain all this repositories
- ::Projects::DestroyService.new(project, current_user, skip_repo: true).execute
+ ::Projects::DestroyService.new(project, current_user, skip_repo: project.legacy_storage?).execute
end
MigrateToGhostUserService.new(user).execute unless options[:hard_delete]
# Destroy the namespace after destroying the user since certain methods may depend on the namespace existing
- namespace = user.namespace
user_data = user.destroy
namespace.really_destroy!
diff --git a/app/views/admin/application_settings/_form.html.haml b/app/views/admin/application_settings/_form.html.haml
index 8bf6556079b..959af5c0d13 100644
--- a/app/views/admin/application_settings/_form.html.haml
+++ b/app/views/admin/application_settings/_form.html.haml
@@ -362,7 +362,9 @@
%fieldset
%legend Background Jobs
%p
- These settings require a restart to take effect.
+ These settings require a
+ = link_to 'restart', help_page_path('administration/restart_gitlab')
+ to take effect.
.form-group
.col-sm-offset-2.col-sm-10
.checkbox
@@ -491,6 +493,16 @@
%fieldset
%legend Repository Storage
.form-group
+ .col-sm-offset-2.col-sm-10
+ .checkbox
+ = f.label :hashed_storage_enabled do
+ = f.check_box :hashed_storage_enabled
+ Create new projects using hashed storage paths
+ .help-block
+ Enable immutable, hash-based paths and repository names to store repositories on disk. This prevents
+ repositories from having to be moved or renamed when the Project URL changes and may improve disk I/O performance.
+ %em (EXPERIMENTAL)
+ .form-group
= f.label :repository_storages, 'Storage paths for new projects', class: 'control-label col-sm-2'
.col-sm-10
= f.select :repository_storages, repository_storages_options_for_select, {include_hidden: false}, multiple: true, class: 'form-control'
@@ -499,6 +511,7 @@
= succeed "." do
= link_to "repository storages documentation", help_page_path("administration/repository_storages")
+
%fieldset
%legend Repository Checks
.form-group
diff --git a/app/views/admin/logs/show.html.haml b/app/views/admin/logs/show.html.haml
index 487f1cf5c4f..ee87f25a225 100644
--- a/app/views/admin/logs/show.html.haml
+++ b/app/views/admin/logs/show.html.haml
@@ -1,25 +1,21 @@
- @no_container = true
- page_title "Logs"
-- loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
- Gitlab::EnvironmentLogger, Gitlab::SidekiqLogger,
- Gitlab::RepositoryCheckLogger]
= render 'admin/monitoring/head'
%div{ class: container_class }
%ul.nav-links.log-tabs
- - loggers.each do |klass|
- %li{ class: active_when(klass == Gitlab::GitLogger) }>
- = link_to klass::file_name, "##{klass::file_name_noext}",
- 'data-toggle' => 'tab'
+ - @loggers.each do |klass|
+ %li{ class: active_when(klass == @loggers.first) }>
+ = link_to klass.file_name, "##{klass.file_name_noext}", data: { toggle: 'tab' }
.row-content-block
To prevent performance issues admin logs output the last 2000 lines
.tab-content
- - loggers.each do |klass|
- .tab-pane{ class: active_when(klass == Gitlab::GitLogger), id: klass::file_name_noext }
+ - @loggers.each do |klass|
+ .tab-pane{ class: active_when(klass == @loggers.first), id: klass.file_name_noext }
.file-holder#README
.js-file-title.file-title
%i.fa.fa-file
- = klass::file_name
+ = klass.file_name
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml
index 4cf4a57ba18..ca6e43e091c 100644
--- a/app/views/admin/users/_user.html.haml
+++ b/app/views/admin/users/_user.html.haml
@@ -40,9 +40,10 @@
%li
= link_to 'Remove user', admin_user_path(user),
data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" },
+ class: 'text-danger',
method: :delete
%li
= link_to 'Remove user and contributions', admin_user_path(user, hard_delete: true),
data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and comments authored by this user, and groups owned solely by them, will also be removed! Are you sure?" },
- class: 'btn btn-remove btn-block',
+ class: 'text-danger',
method: :delete
diff --git a/app/views/dashboard/issues.html.haml b/app/views/dashboard/issues.html.haml
index 52e0012fd7d..9ac44674b73 100644
--- a/app/views/dashboard/issues.html.haml
+++ b/app/views/dashboard/issues.html.haml
@@ -8,14 +8,14 @@
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn has-tooltip append-right-10', title: 'Subscribe' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
.top-area
= render 'shared/issuable/nav', type: :issues
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
= link_to params.merge(rss_url_options), class: 'btn has-tooltip', title: 'Subscribe' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", with_feature_enabled: 'issues', type: :issues
= render 'shared/issuable/filter', type: :issues
= render 'shared/issues'
diff --git a/app/views/dashboard/merge_requests.html.haml b/app/views/dashboard/merge_requests.html.haml
index c3fe14da2b2..960e1e55f36 100644
--- a/app/views/dashboard/merge_requests.html.haml
+++ b/app/views/dashboard/merge_requests.html.haml
@@ -4,12 +4,12 @@
- if show_new_nav?
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
.top-area
= render 'shared/issuable/nav', type: :merge_requests
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", with_feature_enabled: 'merge_requests', type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests
= render 'shared/merge_requests'
diff --git a/app/views/dashboard/milestones/index.html.haml b/app/views/dashboard/milestones/index.html.haml
index 37dbcaf5cb8..cb8bf57cba1 100644
--- a/app/views/dashboard/milestones/index.html.haml
+++ b/app/views/dashboard/milestones/index.html.haml
@@ -4,13 +4,13 @@
- if show_new_nav?
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
+ = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.top-area
= render 'shared/milestones_filter', counts: @milestone_states
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true
+ = render 'shared/new_project_item_select', path: 'milestones/new', label: 'New milestone', include_groups: true, type: :milestones
.milestones
%ul.content-list
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index f83ebbf09ef..12bc092d216 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -12,7 +12,7 @@
- content_for :breadcrumbs_extra do
= link_to params.merge(rss_url_options), class: 'btn btn-default append-right-10' do
= icon('rss')
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
- if group_issues_exists
.top-area
@@ -22,7 +22,7 @@
= icon('rss')
%span.icon-label
Subscribe
- = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue"
+ = render 'shared/new_project_item_select', path: 'issues/new', label: "New issue", type: :issues
= render 'shared/issuable/search_bar', type: :issues
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 997c82c77d9..569eef46e6e 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -2,7 +2,7 @@
- if show_new_nav? && current_user
- content_for :breadcrumbs_extra do
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
- if @group_merge_requests.empty?
= render 'shared/empty_states/merge_requests', project_select_button: true
@@ -11,7 +11,7 @@
= render 'shared/issuable/nav', type: :merge_requests
- if current_user
.nav-controls{ class: ("visible-xs" if show_new_nav?) }
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request"
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: "New merge request", type: :merge_requests
= render 'shared/issuable/filter', type: :merge_requests
diff --git a/app/views/import/gitlab_projects/new.html.haml b/app/views/import/gitlab_projects/new.html.haml
index 008e8287aa3..5d68e1e2156 100644
--- a/app/views/import/gitlab_projects/new.html.haml
+++ b/app/views/import/gitlab_projects/new.html.haml
@@ -25,7 +25,7 @@
= hidden_field_tag :namespace_id, value: current_user.namespace_id
.form-group.col-xs-12.col-sm-6.project-path
= label_tag :path, 'Project name', class: 'label-light'
- = text_field_tag :path, nil, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
+ = text_field_tag :path, @path, placeholder: "my-awesome-project", class: "js-path-name form-control", tabindex: 2, autofocus: true, required: true
.row
.form-group.col-md-12
@@ -33,7 +33,6 @@
.row
.form-group.col-sm-12
= hidden_field_tag :namespace_id, @namespace.id
- = hidden_field_tag :path, @path
= label_tag :file, 'GitLab project export', class: 'label-light'
.form-group
= file_field_tag :file, class: ''
diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml
index ed079ed7dfb..5d778d67ae7 100644
--- a/app/views/profiles/accounts/show.html.haml
+++ b/app/views/profiles/accounts/show.html.haml
@@ -92,25 +92,24 @@
Update username
%hr
-- if signup_enabled?
- .row.prepend-top-default
- .col-lg-4.profile-settings-sidebar
- %h4.prepend-top-0.danger-title
- Remove account
- .col-lg-8
- - if @user.can_be_removed? && can?(current_user, :destroy_user, @user)
+.row.prepend-top-default
+ .col-lg-4.profile-settings-sidebar
+ %h4.prepend-top-0.danger-title
+ Remove account
+ .col-lg-8
+ - if @user.can_be_removed? && can?(current_user, :destroy_user, @user)
+ %p
+ Deleting an account has the following effects:
+ = render 'users/deletion_guidance', user: current_user
+ = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
+ - else
+ - if @user.solo_owned_groups.present?
%p
- Deleting an account has the following effects:
- = render 'users/deletion_guidance', user: current_user
- = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove"
+ Your account is currently an owner in these groups:
+ %strong= @user.solo_owned_groups.map(&:name).join(', ')
+ %p
+ You must transfer ownership or delete these groups before you can delete your account.
- else
- - if @user.solo_owned_groups.present?
- %p
- Your account is currently an owner in these groups:
- %strong= @user.solo_owned_groups.map(&:name).join(', ')
- %p
- You must transfer ownership or delete these groups before you can delete your account.
- - else
- %p
- You don't have access to delete this user.
+ %p
+ You don't have access to delete this user.
.append-bottom-default
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 8331daeeb75..720a97cddb7 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -12,7 +12,7 @@
Add a GPG key
%p.profile-settings-content
Before you can add a GPG key you need to
- = link_to 'generate it.', help_page_path('workflow/gpg_signed_commits/index.md')
+ = link_to 'generate it.', help_page_path('user/project/gpg_signed_commits/index.md')
= render 'form'
%hr
%h5
diff --git a/app/views/projects/_activity.html.haml b/app/views/projects/_activity.html.haml
index ad63f5e73ae..1f701f2aa1b 100644
--- a/app/views/projects/_activity.html.haml
+++ b/app/views/projects/_activity.html.haml
@@ -1,7 +1,7 @@
%div{ class: container_class }
.nav-block.activity-filter-block.activities
.controls
- = link_to project_path(@project, rss_url_options), title: "Subscribe", class: 'btn rss-btn has-tooltip' do
+ = link_to project_path(@project, rss_url_options), title: s_("ProjectActivityRSS|Subscribe"), class: 'btn rss-btn has-tooltip' do
= icon('rss')
= render 'shared/event_filter'
diff --git a/app/views/projects/_last_push.html.haml b/app/views/projects/_last_push.html.haml
index 1a71bfca2e2..56eecece54c 100644
--- a/app/views/projects/_last_push.html.haml
+++ b/app/views/projects/_last_push.html.haml
@@ -3,16 +3,16 @@
.row-content-block.top-block.hidden-xs.white
.event-last-push
.event-last-push-text
- %span You pushed to
+ %span= s_("LastPushEvent|You pushed to")
%strong
= link_to event.ref_name, project_commits_path(event.project, event.ref_name), class: 'ref-name'
- if event.project != @project
- %span at
+ %span= s_("LastPushEvent|at")
%strong= link_to_project event.project
#{time_ago_with_tooltip(event.created_at)}
.pull-right
- = link_to new_mr_path_from_push_event(event), title: "New merge request", class: "btn btn-info btn-sm" do
+ = link_to new_mr_path_from_push_event(event), title: _("New merge request"), class: "btn btn-info btn-sm" do
#{ _('Create merge request') }
diff --git a/app/views/projects/activity.html.haml b/app/views/projects/activity.html.haml
index 9e2688e492e..5452c6db6a6 100644
--- a/app/views/projects/activity.html.haml
+++ b/app/views/projects/activity.html.haml
@@ -1,9 +1,9 @@
- @no_container = true
- if show_new_nav?
- - add_to_breadcrumbs("Project", project_path(@project))
+ - add_to_breadcrumbs(_("Project"), project_path(@project))
-- page_title "Activity"
+- page_title _("Activity")
= render "projects/head"
= render 'projects/last_push'
diff --git a/app/views/projects/commit/_signature_badge.html.haml b/app/views/projects/commit/_signature_badge.html.haml
index 66f00eb5507..a3783b31b86 100644
--- a/app/views/projects/commit/_signature_badge.html.haml
+++ b/app/views/projects/commit/_signature_badge.html.haml
@@ -12,7 +12,7 @@
%span.monospace= signature.gpg_key_primary_keyid
- = link_to('Learn more about signing commits', help_page_path('workflow/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
+ = link_to('Learn more about signing commits', help_page_path('user/project/gpg_signed_commits/index.md'), class: 'gpg-popover-help-link')
%button{ class: css_classes, data: { toggle: 'popover', html: 'true', placement: 'auto top', title: title, content: content } }
= label
diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml
index e7da47032be..7e8a5a38086 100644
--- a/app/views/projects/commits/_commit.html.haml
+++ b/app/views/projects/commits/_commit.html.haml
@@ -5,7 +5,7 @@
- notes = commit.notes
- note_count = notes.user.count
-- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits)]
+- cache_key = [project.full_path, commit.id, current_application_settings, note_count, @path.presence, current_controller?(:commits), I18n.locale]
- cache_key.push(commit.status(ref)) if commit.status(ref)
= cache(cache_key, expires_in: 1.day) do
diff --git a/app/views/projects/edit.html.haml b/app/views/projects/edit.html.haml
index 6178abe9160..9e26bdecd31 100644
--- a/app/views/projects/edit.html.haml
+++ b/app/views/projects/edit.html.haml
@@ -202,8 +202,6 @@
.sub-section.rename-respository
%h4.warning-title
Rename repository
- %p
- Export this project with all its related data in order to move your project to a new GitLab instance. Once the export is finished, you can import the file from the "New Project" page.
= render 'projects/errors'
= form_for([@project.namespace.becomes(Namespace), @project]) do |f|
.form-group.project_name_holder
diff --git a/app/views/shared/_event_filter.html.haml b/app/views/shared/_event_filter.html.haml
index e50ab5fea09..151aad306a0 100644
--- a/app/views/shared/_event_filter.html.haml
+++ b/app/views/shared/_event_filter.html.haml
@@ -1,11 +1,11 @@
%ul.nav-links.event-filter.scrolling-tabs
- = event_filter_link EventFilter.all, 'All'
+ = event_filter_link EventFilter.all, _('All'), s_('EventFilterBy|Filter by all')
- if event_filter_visible(:repository)
- = event_filter_link EventFilter.push, 'Push events'
+ = event_filter_link EventFilter.push, _('Push events'), s_('EventFilterBy|Filter by push events')
- if event_filter_visible(:merge_requests)
- = event_filter_link EventFilter.merged, 'Merge events'
+ = event_filter_link EventFilter.merged, _('Merge events'), s_('EventFilterBy|Filter by merge events')
- if event_filter_visible(:issues)
- = event_filter_link EventFilter.issue, 'Issue events'
+ = event_filter_link EventFilter.issue, _('Issue events'), s_('EventFilterBy|Filter by issue events')
- if comments_visible?
- = event_filter_link EventFilter.comments, 'Comments'
- = event_filter_link EventFilter.team, 'Team'
+ = event_filter_link EventFilter.comments, _('Comments'), s_('EventFilterBy|Filter by comments')
+ = event_filter_link EventFilter.team, _('Team'), s_('EventFilterBy|Filter by team')
diff --git a/app/views/shared/_group_form.html.haml b/app/views/shared/_group_form.html.haml
index 8d5b5129454..2e1bd5a088c 100644
--- a/app/views/shared/_group_form.html.haml
+++ b/app/views/shared/_group_form.html.haml
@@ -1,6 +1,6 @@
- content_for :page_specific_javascripts do
= page_specific_javascript_bundle_tag('group')
-- parent = GroupFinder.new(current_user).execute(id: params[:parent_id] || @group.parent_id)
+- parent = @group.parent
- group_path = root_url
- group_path << parent.full_path + '/' if parent
@@ -13,13 +13,12 @@
%span>= root_url
- if parent
%strong= parent.full_path + '/'
+ = f.hidden_field :parent_id
= f.text_field :path, placeholder: 'open-source', class: 'form-control',
autofocus: local_assigns[:autofocus] || false, required: true,
pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS,
title: 'Please choose a group path with no special characters.',
"data-bind-in" => "#{'create_chat_team' if Gitlab.config.mattermost.enabled}"
- - if parent
- = f.hidden_field :parent_id, value: parent.id
- if @group.persisted?
.alert.alert-warning.prepend-top-10
diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml
index 873179339dc..233d8c95eda 100644
--- a/app/views/shared/_import_form.html.haml
+++ b/app/views/shared/_import_form.html.haml
@@ -13,4 +13,4 @@
%li
The import will time out after 15 minutes. For repositories that take longer, use a clone/push combination.
%li
- To migrate an SVN repository, check out #{link_to "this document", help_page_path('workflow/importing/migrating_from_svn')}.
+ To migrate an SVN repository, check out #{link_to "this document", help_page_path('user/project/import/svn')}.
diff --git a/app/views/shared/_new_project_item_select.html.haml b/app/views/shared/_new_project_item_select.html.haml
index 96502d7ce93..dc912d800cf 100644
--- a/app/views/shared/_new_project_item_select.html.haml
+++ b/app/views/shared/_new_project_item_select.html.haml
@@ -1,6 +1,6 @@
- if any_projects?(@projects)
.project-item-select-holder.btn-group.pull-right
- %a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label] } }
+ %a.btn.btn-new.new-project-item-link{ href: '', data: { label: local_assigns[:label], type: local_assigns[:type] } }
= icon('spinner spin')
= project_select_tag :project_path, class: "project-item-select", data: { include_groups: local_assigns[:include_groups], order_by: 'last_activity_at', relative_path: local_assigns[:path] }, with_feature_enabled: local_assigns[:with_feature_enabled]
%button.btn.btn-new.new-project-item-select-button
diff --git a/app/views/shared/empty_states/_issues.html.haml b/app/views/shared/empty_states/_issues.html.haml
index b0c0ab523c7..68737e8da66 100644
--- a/app/views/shared/empty_states/_issues.html.haml
+++ b/app/views/shared/empty_states/_issues.html.haml
@@ -15,7 +15,7 @@
Issues can be bugs, tasks or ideas to be discussed.
Also, issues are searchable and filterable.
- if project_select_button
- = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue'
+ = render 'shared/new_project_item_select', path: 'issues/new', label: 'New issue', type: :issues
- else
= link_to 'New issue', button_path, class: 'btn btn-new', title: 'New issue', id: 'new_issue_link'
- else
diff --git a/app/views/shared/empty_states/_merge_requests.html.haml b/app/views/shared/empty_states/_merge_requests.html.haml
index 3e64f403b8b..ff5741b6d61 100644
--- a/app/views/shared/empty_states/_merge_requests.html.haml
+++ b/app/views/shared/empty_states/_merge_requests.html.haml
@@ -14,7 +14,7 @@
%p
Interested parties can even contribute by pushing commits if they want to.
- if project_select_button
- = render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request'
+ = render 'shared/new_project_item_select', path: 'merge_requests/new', label: 'New merge request', type: :merge_requests
- else
= link_to 'New merge request', button_path, class: 'btn btn-new', title: 'New merge request', id: 'new_merge_request_link'
- else
diff --git a/app/views/shared/icons/_icon_arrow_circle_o_right.svg b/app/views/shared/icons/_icon_arrow_circle_o_right.svg
index 5e45c6c15ce..29bdc8e5754 100644
--- a/app/views/shared/icons/_icon_arrow_circle_o_right.svg
+++ b/app/views/shared/icons/_icon_arrow_circle_o_right.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><g fill-rule="evenodd"><path fill-rule="nonzero" d="m0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7m1 0c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6"/><path d="m7 6h-2.702c-.154 0-.298.132-.298.295v1.41c0 .164.133.295.298.295h2.702v1.694c0 .18.095.209.213.09l2.539-2.568c.115-.116.118-.312 0-.432l-2.539-2.568c-.115-.116-.213-.079-.213.09v1.694"/></g></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m9 6h-7a2 2 0 1 0 0 4h7v2.586a1 1 0 0 0 1.707.707l4.586-4.586a1 1 0 0 0 0-1.414l-4.586-4.586a1 1 0 0 0 -1.707.707z" fill-rule="evenodd"/></svg>
+
diff --git a/app/views/shared/icons/_icon_check_square_o.svg b/app/views/shared/icons/_icon_check_square_o.svg
index 3dfbfc8c0e9..05ed4d715d5 100644
--- a/app/views/shared/icons/_icon_check_square_o.svg
+++ b/app/views/shared/icons/_icon_check_square_o.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1472 930v318q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-10 10-23 10-3 0-9-2-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-254q0-13 9-22l64-64q10-10 23-10 6 0 12 3 20 8 20 29zm231-489l-814 814q-24 24-57 24t-57-24l-430-430q-24-24-24-57t24-57l110-110q24-24 57-24t57 24l263 263 647-647q24-24 57-24t57 24l110 110q24 24 24 57t-24 57z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M7.536 8.657l2.828-2.829a1 1 0 0 1 1.414 1.415l-3.535 3.535a.997.997 0 0 1-1.415 0l-2.12-2.121A1 1 0 0 1 6.12 7.243l1.415 1.414zM3 0h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H3a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h10a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_clock_o.svg b/app/views/shared/icons/_icon_clock_o.svg
index 8ddce62614c..9787ff6cb9e 100644
--- a/app/views/shared/icons/_icon_clock_o.svg
+++ b/app/views/shared/icons/_icon_clock_o.svg
@@ -1 +1 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1024 544v448q0 14-9 23t-23 9h-320q-14 0-23-9t-9-23v-64q0-14 9-23t23-9h224v-352q0-14 9-23t23-9h64q14 0 23 9t9 23zm416 352q0-148-73-273t-198-198-273-73-273 73-198 198-73 273 73 273 198 198 273 73 273-73 198-198 73-273zm224 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M9 7h1c.552 0 1 .448 1 1s-.448 1-1 1H8c-.276 0-.526-.112-.707-.293S7 8.277 7 8V5c0-.552.448-1 1-1s1 .448 1 1zm-1 9c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_clone.svg b/app/views/shared/icons/_icon_clone.svg
index ccc897aa98f..faba51b5797 100644
--- a/app/views/shared/icons/_icon_clone.svg
+++ b/app/views/shared/icons/_icon_clone.svg
@@ -1,3 +1,2 @@
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="14" height="14" viewBox="0 0 14 14">
-<path d="M13 12.75v-8.5q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h8.5q0.102 0 0.176-0.074t0.074-0.176zM14 4.25v8.5q0 0.516-0.367 0.883t-0.883 0.367h-8.5q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883zM11 1.25v1.25h-1v-1.25q0-0.102-0.074-0.176t-0.176-0.074h-8.5q-0.102 0-0.176 0.074t-0.074 0.176v8.5q0 0.102 0.074 0.176t0.176 0.074h1.25v1h-1.25q-0.516 0-0.883-0.367t-0.367-0.883v-8.5q0-0.516 0.367-0.883t0.883-0.367h8.5q0.516 0 0.883 0.367t0.367 0.883z"></path>
-</svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M10.874 2H12a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3h-2c-.918 0-1.74-.413-2.29-1.063a3.987 3.987 0 0 0 1.988-.984A1 1 0 0 0 10 14h2a1 1 0 0 0 1-1V5a1 1 0 0 0-1-1h-1V3c0-.345-.044-.68-.126-1zM4 0h3a3 3 0 0 1 3 3v8a3 3 0 0 1-3 3H4a3 3 0 0 1-3-3V3a3 3 0 0 1 3-3zm0 2a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H4z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_code_fork.svg b/app/views/shared/icons/_icon_code_fork.svg
index 5a0df2eee19..968e0ad3b2b 100644
--- a/app/views/shared/icons/_icon_code_fork.svg
+++ b/app/views/shared/icons/_icon_code_fork.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M672 1472q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm0-1152q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm640 128q0-40-28-68t-68-28-68 28-28 68 28 68 68 28 68-28 28-68zm96 0q0 52-26 96.5t-70 69.5q-2 287-226 414-68 38-203 81-128 40-169.5 71t-41.5 100v26q44 25 70 69.5t26 96.5q0 80-56 136t-136 56-136-56-56-136q0-52 26-96.5t70-69.5v-820q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136q0 52-26 96.5t-70 69.5v497q54-26 154-57 55-17 87.5-29.5t70.5-31 59-39.5 40.5-51 28-69.5 8.5-91.5q-44-25-70-69.5t-26-96.5q0-80 56-136t136-56 136 56 56 136z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M6 11.978v.29a2 2 0 1 1-2 0V3.732a2 2 0 1 1 2 0v3.849c.592-.491 1.31-.854 2.15-1.081 1.308-.353 1.875-.882 1.893-1.743a2 2 0 1 1 2.002-.051C12.053 6.54 10.857 7.84 8.67 8.43 7.056 8.867 6.195 9.98 6 11.978zM5 3a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm6 1a1 1 0 1 0 0-2 1 1 0 0 0 0 2zM5 15a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_comment_o.svg b/app/views/shared/icons/_icon_comment_o.svg
index b99bd5f42c8..050d7356f54 100644
--- a/app/views/shared/icons/_icon_comment_o.svg
+++ b/app/views/shared/icons/_icon_comment_o.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M896 384q-204 0-381.5 69.5t-282 187.5-104.5 255q0 112 71.5 213.5t201.5 175.5l87 50-27 96q-24 91-70 172 152-63 275-171l43-38 57 6q69 8 130 8 204 0 381.5-69.5t282-187.5 104.5-255-104.5-255-282-187.5-381.5-69.5zm896 512q0 174-120 321.5t-326 233-450 85.5q-70 0-145-8-198 175-460 242-49 14-114 22h-5q-15 0-27-10.5t-16-27.5v-1q-3-4-.5-12t2-10 4.5-9.5l6-9 7-8.5 8-9q7-8 31-34.5t34.5-38 31-39.5 32.5-51 27-59 26-76q-157-89-247.5-220t-90.5-281q0-174 120-321.5t326-233 450-85.5 450 85.5 326 233 120 321.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m1.707 15.707c-.63.63-1.707.184-1.707-.707v-12a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1 -3 3h-7.586zm.293-3.121 2.293-2.293a1 1 0 0 1 .707-.293h8a1 1 0 0 0 1-1v-6a1 1 0 0 0 -1-1h-10a1 1 0 0 0 -1 1z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_commit.svg b/app/views/shared/icons/_icon_commit.svg
index 7e9c0ded04e..6060d2e2aa4 100644
--- a/app/views/shared/icons/_icon_commit.svg
+++ b/app/views/shared/icons/_icon_commit.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 18" enable-background="new 0 0 36 18"><path d="m34 7h-7.2c-.9-4-4.5-7-8.8-7s-7.9 3-8.8 7h-7.2c-1.1 0-2 .9-2 2 0 1.1.9 2 2 2h7.2c.9 4 4.5 7 8.8 7s7.9-3 8.8-7h7.2c1.1 0 2-.9 2-2 0-1.1-.9-2-2-2m-16 7c-2.8 0-5-2.2-5-5s2.2-5 5-5 5 2.2 5 5-2.2 5-5 5"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3.876-1.008a4.002 4.002 0 0 1-7.752 0A1.01 1.01 0 0 1 4 9H1a1 1 0 1 1 0-2h3c.042 0 .083.003.124.008a4.002 4.002 0 0 1 7.752 0A1.01 1.01 0 0 1 12 7h3a1 1 0 0 1 0 2h-3a1.01 1.01 0 0 1-.124-.008z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_edit.svg b/app/views/shared/icons/_icon_edit.svg
index cd4e34147e1..1c10ef138b5 100644
--- a/app/views/shared/icons/_icon_edit.svg
+++ b/app/views/shared/icons/_icon_edit.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M888 1184l116-116-152-152-116 116v56h96v96h56zm440-720q-16-16-33 1l-350 350q-17 17-1 33t33-1l350-350q17-17 1-33zm80 594v190q0 119-84.5 203.5t-203.5 84.5h-832q-119 0-203.5-84.5t-84.5-203.5v-832q0-119 84.5-203.5t203.5-84.5h832q63 0 117 25 15 7 18 23 3 17-9 29l-49 49q-14 14-32 8-23-6-45-6h-832q-66 0-113 47t-47 113v832q0 66 47 113t113 47h832q66 0 113-47t47-113v-126q0-13 9-22l64-64q15-15 35-7t20 29zm-96-738l288 288-672 672h-288v-288zm444 132l-92 92-288-288 92-92q28-28 68-28t68 28l152 152q28 28 28 68t-28 68z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m13.436 1.413 1.415 1.414a1 1 0 0 1 0 1.414l-10.316 10.315a1 1 0 0 1 -.703.293l-2.407.008-.008-2.421a1 1 0 0 1 .293-.71l10.312-10.314a1 1 0 0 1 1.414 0zm-9.608 12.436 10.315-10.315-1.413-1.414-10.313 10.312.005 1.422zm7.486-10.313 1.414 1.414-7.778 7.778-1.407.007-.007-1.421zm1.414-1.415 1.414 1.415-.707.707-1.414-1.415z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_eye.svg b/app/views/shared/icons/_icon_eye.svg
index 2e2ae67142f..9fea9841eb3 100644
--- a/app/views/shared/icons/_icon_eye.svg
+++ b/app/views/shared/icons/_icon_eye.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1664 960q-152-236-381-353 61 104 61 225 0 185-131.5 316.5t-316.5 131.5-316.5-131.5-131.5-316.5q0-121 61-225-229 117-381 353 133 205 333.5 326.5t434.5 121.5 434.5-121.5 333.5-326.5zm-720-384q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm848 384q0 34-20 69-140 230-376.5 368.5t-499.5 138.5-499.5-139-376.5-368q-20-35-20-69t20-69q140-229 376.5-368t499.5-139 499.5 139 376.5 368q20 35 20 69z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M8 14C4.816 14 2.253 12.284.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2s5.747 1.716 7.607 5.019a2 2 0 0 1 0 1.962C13.747 12.284 11.184 14 8 14zm0-2c2.41 0 4.338-1.29 5.864-4C12.338 5.29 10.411 4 8 4 5.59 4 3.662 5.29 2.136 8 3.662 10.71 5.589 12 8 12zm0-1a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm1-3a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_eye_slash.svg b/app/views/shared/icons/_icon_eye_slash.svg
index a16c5dcb24b..45c06b3495d 100644
--- a/app/views/shared/icons/_icon_eye_slash.svg
+++ b/app/views/shared/icons/_icon_eye_slash.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M555 1335l78-141q-87-63-136-159t-49-203q0-121 61-225-229 117-381 353 167 258 427 375zm389-759q0-20-14-34t-34-14q-125 0-214.5 89.5t-89.5 214.5q0 20 14 34t34 14 34-14 14-34q0-86 61-147t147-61q20 0 34-14t14-34zm363-191q0 7-1 9-105 188-315 566t-316 567l-49 89q-10 16-28 16-12 0-134-70-16-10-16-28 0-12 44-87-143-65-263.5-173t-208.5-245q-20-31-20-69t20-69q153-235 380-371t496-136q89 0 180 17l54-97q10-16 28-16 5 0 18 6t31 15.5 33 18.5 31.5 18.5 19.5 11.5q16 10 16 27zm37 447q0 139-79 253.5t-209 164.5l280-502q8 45 8 84zm448 128q0 35-20 69-39 64-109 145-150 172-347.5 267t-419.5 95l74-132q212-18 392.5-137t301.5-307q-115-179-282-294l63-112q95 64 182.5 153t144.5 184q20 34 20 69z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.618 2.62L1.62 14.619a1 1 0 0 1-.985-1.668l1.525-1.526C1.516 10.742.926 9.927.393 8.981a2 2 0 0 1 0-1.962C2.253 3.716 4.816 2 8 2c1.074 0 2.076.195 3.006.58l.944-.944a1 1 0 0 1 1.668.985zM8.068 11a3 3 0 0 0 2.931-2.932l-2.931 2.931zm-3.02-2.462a3 3 0 0 1 3.49-3.49l.884-.884A6.044 6.044 0 0 0 8 4C5.59 4 3.662 5.29 2.136 8c.445.79.924 1.46 1.439 2.011l1.473-1.473zm.421 5.06l1.658-1.658c.283.04.575.06.873.06 2.41 0 4.338-1.29 5.864-4a11.023 11.023 0 0 0-1.133-1.664l1.418-1.418a12.799 12.799 0 0 1 1.458 2.1 2 2 0 0 1 0 1.963C13.747 12.284 11.184 14 8 14a7.883 7.883 0 0 1-2.53-.402z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_merged.svg b/app/views/shared/icons/_icon_merged.svg
index 43d591daefa..77d170b2491 100644
--- a/app/views/shared/icons/_icon_merged.svg
+++ b/app/views/shared/icons/_icon_merged.svg
@@ -1 +1,2 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="m2 3c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m.761.85c.154 2.556 1.987 4.692 4.45 5.255.328-.655 1.01-1.105 1.789-1.105 1.105 0 2 .895 2 2 0 1.105-.895 2-2 2-.89 0-1.645-.582-1.904-1.386-1.916-.376-3.548-1.5-4.596-3.044v4.493c.863.222 1.5 1.01 1.5 1.937 0 1.105-.895 2-2 2-1.105 0-2-.895-2-2 0-.74.402-1.387 1-1.732v-8.535c-.598-.346-1-.992-1-1.732 0-1.105.895-2 2-2 1.105 0 2 .895 2 2 0 .835-.512 1.551-1.239 1.85m6.239 7.15c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1m-7 4c.552 0 1-.448 1-1 0-.552-.448-1-1-1-.552 0-1 .448-1 1 0 .552.448 1 1 1" transform="translate(3)"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M11 12.268V5a1 1 0 0 0-1-1v1a.5.5 0 0 1-.8.4l-2.667-2a.5.5 0 0 1 0-.8L9.2.6a.5.5 0 0 1 .8.4v1a3 3 0 0 1 3 3v7.268a2 2 0 1 1-2 0zm-6 0a2 2 0 1 1-2 0V4.732a2 2 0 1 1 2 0v7.536zM4 4a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm0 11a1 1 0 1 0 0-2 1 1 0 0 0 0 2zm8 0a1 1 0 1 0 0-2 1 1 0 0 0 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_pencil.svg b/app/views/shared/icons/_icon_pencil.svg
index a3b48404f87..bcde54bd1e1 100644
--- a/app/views/shared/icons/_icon_pencil.svg
+++ b/app/views/shared/icons/_icon_pencil.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M491 1536l91-91-235-235-91 91v107h128v128h107zm523-928q0-22-22-22-10 0-17 7l-542 542q-7 7-7 17 0 22 22 22 10 0 17-7l542-542q7-7 7-17zm-54-192l416 416-832 832h-416v-416zm683 96q0 53-37 90l-166 166-416-416 166-165q36-38 90-38 53 0 91 38l235 234q37 39 37 91z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M13.02 1.293l1.414 1.414a1 1 0 0 1 0 1.414L4.119 14.436a1 1 0 0 1-.704.293l-2.407.008L1 12.316a1 1 0 0 1 .293-.71L11.605 1.292a1 1 0 0 1 1.414 0zm-1.416 1.415l-.707.707L12.31 4.83l.707-.707-1.414-1.415zM3.411 13.73l1.123-1.122H3.12v-1.415L2 12.312l.005 1.422 1.406-.005z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_random.svg b/app/views/shared/icons/_icon_random.svg
index 763bd2d3dd8..74c1c903657 100644
--- a/app/views/shared/icons/_icon_random.svg
+++ b/app/views/shared/icons/_icon_random.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M666 481q-60 92-137 273-22-45-37-72.5t-40.5-63.5-51-56.5-63-35-81.5-14.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q250 0 410 225zm1126 799q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192q-32 0-85 .5t-81 1-73-1-71-5-64-10.5-63-18.5-58-28.5-59-40-55-53.5-56-69.5q59-93 136-273 22 45 37 72.5t40.5 63.5 51 56.5 63 35 81.5 14.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23zm0-896q0 14-9 23l-320 320q-9 9-23 9-13 0-22.5-9.5t-9.5-22.5v-192h-256q-48 0-87 15t-69 45-51 61.5-45 77.5q-32 62-78 171-29 66-49.5 111t-54 105-64 100-74 83-90 68.5-106.5 42-128 16.5h-224q-14 0-23-9t-9-23v-192q0-14 9-23t23-9h224q48 0 87-15t69-45 51-61.5 45-77.5q32-62 78-171 29-66 49.5-111t54-105 64-100 74-83 90-68.5 106.5-42 128-16.5h256v-192q0-14 9-23t23-9q12 0 24 10l319 319q9 9 9 23z"/></svg>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16"><path d="M1.707 15.707C1.077 16.337 0 15.891 0 15V3a3 3 0 0 1 3-3h10a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H5.414l-3.707 3.707zM2 12.586l2.293-2.293A1 1 0 0 1 5 10h8a1 1 0 0 0 1-1V3a1 1 0 0 0-1-1H3a1 1 0 0 0-1 1v9.586zM5 7a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm3 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>
+
diff --git a/app/views/shared/icons/_icon_status_closed.svg b/app/views/shared/icons/_icon_status_closed.svg
index de448ee1194..dc39223e721 100644
--- a/app/views/shared/icons/_icon_status_closed.svg
+++ b/app/views/shared/icons/_icon_status_closed.svg
@@ -1 +1 @@
-<svg width="14" height="14" viewBox="0 0 14 14" xmlns="http://www.w3.org/2000/svg"><path d="M0 7c0-3.866 3.142-7 7-7 3.866 0 7 3.142 7 7 0 3.866-3.142 7-7 7-3.866 0-7-3.142-7-7z"/><path d="M1 7c0 3.309 2.69 6 6 6 3.309 0 6-2.69 6-6 0-3.309-2.69-6-6-6-3.309 0-6 2.69-6 6z" fill="#FFF"/><rect x="3.36" y="6.16" width="7.28" height="1.68" rx=".84"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M7.536 8.657l2.828-2.83c.39-.39 1.024-.39 1.414 0 .39.392.39 1.025 0 1.416l-3.535 3.535c-.196.195-.452.293-.707.293-.256 0-.512-.097-.708-.292l-2.12-2.12c-.39-.392-.39-1.025 0-1.415s1.023-.39 1.413 0zM8 16c-4.418 0-8-3.582-8-8s3.582-8 8-8 8 3.582 8 8-3.582 8-8 8zm0-2c3.314 0 6-2.686 6-6s-2.686-6-6-6-6 2.686-6 6 2.686 6 6 6z"/></svg>
diff --git a/app/views/shared/icons/_icon_tags.svg b/app/views/shared/icons/_icon_tags.svg
index fc5acc89c5e..d36ea022f92 100644
--- a/app/views/shared/icons/_icon_tags.svg
+++ b/app/views/shared/icons/_icon_tags.svg
@@ -1 +1,2 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M384 448q0-53-37.5-90.5t-90.5-37.5-90.5 37.5-37.5 90.5 37.5 90.5 90.5 37.5 90.5-37.5 37.5-90.5zm1067 576q0 53-37 90l-491 492q-39 37-91 37-53 0-90-37l-715-716q-38-37-64.5-101t-26.5-117v-416q0-52 38-90t90-38h416q53 0 117 26.5t102 64.5l715 714q37 39 37 91zm384 0q0 53-37 90l-491 492q-39 37-91 37-36 0-59-14t-53-45l470-470q37-37 37-90 0-52-37-91l-715-714q-38-38-102-64.5t-117-26.5h224q53 0 117 26.5t102 64.5l715 714q37 39 37 91z"/></svg>
+<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="m7.222.222c1.657 0 3 1.343 3 3v8.327c0 .631-.298 1.226-.805 1.603l-3 2.237c-.709.529-1.682.529-2.391 0l-3-2.237c-.506-.377-.805-.972-.805-1.603v-8.327c0-1.657 1.343-3 3-3h4m-5 3v8.08c0 .158.075.306.201.401l2.5 1.864c.177.132.42.132.598 0l2.5-1.864c.127-.094.201-.243.201-.401v-8.08c0-.552-.448-1-1-1h-4c-.552 0-1 .448-1 1m2.778 7.778c-.552 0-1-.448-1-1s .448-1 1-1 1 .448 1 1-.448 1-1 1" transform="matrix(-.70711 .70711 -.70711 -.70711 17.05 9.767)"/></svg>
+
diff --git a/app/views/shared/icons/_icon_user.svg b/app/views/shared/icons/_icon_user.svg
index 9b8cd74d62b..6e7406f7eac 100644
--- a/app/views/shared/icons/_icon_user.svg
+++ b/app/views/shared/icons/_icon_user.svg
@@ -1 +1 @@
-<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1600 1405q0 120-73 189.5t-194 69.5h-874q-121 0-194-69.5t-73-189.5q0-53 3.5-103.5t14-109 26.5-108.5 43-97.5 62-81 85.5-53.5 111.5-20q9 0 42 21.5t74.5 48 108 48 133.5 21.5 133.5-21.5 108-48 74.5-48 42-21.5q61 0 111.5 20t85.5 53.5 62 81 43 97.5 26.5 108.5 14 109 3.5 103.5zm-320-893q0 159-112.5 271.5t-271.5 112.5-271.5-112.5-112.5-271.5 112.5-271.5 271.5-112.5 271.5 112.5 112.5 271.5z"/></svg>
+<svg height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="M8 7C6.343 7 5 5.657 5 4s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3zm0 8c-6.888 0-6.976-.78-6.976-2.52S2.144 8 8 8s6.976 2.692 6.976 4.48S14.888 15 8 15z" fill-rule="evenodd"/></svg>
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index 1ad00461d76..f63b9698408 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -57,7 +57,7 @@
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link
No Assignee
- %li.divider
+ %li.divider.droplab-item-ignore
- if current_user
= render 'shared/issuable/user_dropdown_item',
user: current_user
@@ -76,7 +76,7 @@
%li.filter-dropdown-item{ 'data-value' => 'started' }
%button.btn.btn-link
Started
- %li.divider
+ %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.btn.btn-link.js-data-value
@@ -86,7 +86,7 @@
%li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link
No Label
- %li.divider
+ %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item
%button.btn.btn-link
diff --git a/app/workers/authorized_projects_worker.rb b/app/workers/authorized_projects_worker.rb
index 13207a8bc71..be4c77503bb 100644
--- a/app/workers/authorized_projects_worker.rb
+++ b/app/workers/authorized_projects_worker.rb
@@ -4,18 +4,25 @@ class AuthorizedProjectsWorker
# Schedules multiple jobs and waits for them to be completed.
def self.bulk_perform_and_wait(args_list)
- job_ids = bulk_perform_async(args_list)
+ waiter = Gitlab::JobWaiter.new(args_list.size)
- Gitlab::JobWaiter.new(job_ids).wait
+ # Point all the bulk jobs at the same JobWaiter. Converts, [[1], [2], [3]]
+ # into [[1, "key"], [2, "key"], [3, "key"]]
+ waiting_args_list = args_list.map { |args| args << waiter.key }
+ bulk_perform_async(waiting_args_list)
+
+ waiter.wait
end
def self.bulk_perform_async(args_list)
Sidekiq::Client.push_bulk('class' => self, 'queue' => sidekiq_options['queue'], 'args' => args_list)
end
- def perform(user_id)
+ def perform(user_id, notify_key = nil)
user = User.find_by(id: user_id)
user&.refresh_authorized_projects
+ ensure
+ Gitlab::JobWaiter.notify(notify_key, jid) if notify_key
end
end
diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb
index a9073742ff7..1cfb0be759e 100644
--- a/app/workers/namespaceless_project_destroy_worker.rb
+++ b/app/workers/namespaceless_project_destroy_worker.rb
@@ -18,7 +18,8 @@ class NamespacelessProjectDestroyWorker
rescue ActiveRecord::RecordNotFound
return
end
- return unless project.namespace_id.nil? # Reject doing anything for projects that *do* have a namespace
+
+ return if project.namespace # Reject doing anything for projects that *do* have a namespace
project.team.truncate
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index a338523dc6b..cde5b45ad41 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -5,14 +5,17 @@ class RepositoryForkWorker
include Gitlab::ShellAdapter
include DedicatedSidekiqQueue
+ sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION
+
def perform(project_id, forked_from_repository_storage_path, source_path, target_path)
+ project = Project.find(project_id)
+
+ return unless start_fork(project)
+
Gitlab::Metrics.add_event(:fork_repository,
source_path: source_path,
target_path: target_path)
- project = Project.find(project_id)
- project.import_start
-
result = gitlab_shell.fork_repository(forked_from_repository_storage_path, source_path,
project.repository_storage_path, target_path)
raise ForkError, "Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}" unless result
@@ -33,6 +36,13 @@ class RepositoryForkWorker
private
+ def start_fork(project)
+ return true if project.import_start
+
+ Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while forking.")
+ false
+ end
+
def fail_fork(project, message)
Rails.logger.error(message)
project.mark_import_as_failed(message)
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 6be541abd3e..2c2d1e8b91f 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -4,23 +4,18 @@ class RepositoryImportWorker
include Sidekiq::Worker
include DedicatedSidekiqQueue
- sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_EXPIRATION
-
- attr_accessor :project, :current_user
+ sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION
def perform(project_id)
- @project = Project.find(project_id)
- @current_user = @project.creator
+ project = Project.find(project_id)
- project.import_start
+ return unless start_import(project)
Gitlab::Metrics.add_event(:import_repository,
- import_url: @project.import_url,
- path: @project.full_path)
-
- project.update_columns(import_jid: self.jid, import_error: nil)
+ import_url: project.import_url,
+ path: project.full_path)
- result = Projects::ImportService.new(project, current_user).execute
+ result = Projects::ImportService.new(project, project.creator).execute
raise ImportError, result[:message] if result[:status] == :error
project.repository.after_import
@@ -37,6 +32,13 @@ class RepositoryImportWorker
private
+ def start_import(project)
+ return true if project.import_start
+
+ Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while importing.")
+ false
+ end
+
def fail_import(project, message)
project.mark_import_as_failed(message)
end
diff --git a/app/workers/stage_update_worker.rb b/app/workers/stage_update_worker.rb
new file mode 100644
index 00000000000..eef0b11e70b
--- /dev/null
+++ b/app/workers/stage_update_worker.rb
@@ -0,0 +1,10 @@
+class StageUpdateWorker
+ include Sidekiq::Worker
+ include PipelineQueue
+
+ def perform(stage_id)
+ Ci::Stage.find_by(id: stage_id).try do |stage|
+ stage.update_status
+ end
+ end
+end
diff --git a/app/workers/stuck_import_jobs_worker.rb b/app/workers/stuck_import_jobs_worker.rb
index bfc5e667bb6..f850e459cd9 100644
--- a/app/workers/stuck_import_jobs_worker.rb
+++ b/app/workers/stuck_import_jobs_worker.rb
@@ -2,36 +2,60 @@ class StuckImportJobsWorker
include Sidekiq::Worker
include CronjobQueue
- IMPORT_EXPIRATION = 15.hours.to_i
+ IMPORT_JOBS_EXPIRATION = 15.hours.to_i
def perform
- stuck_projects.find_in_batches(batch_size: 500) do |group|
+ projects_without_jid_count = mark_projects_without_jid_as_failed!
+ projects_with_jid_count = mark_projects_with_jid_as_failed!
+
+ Gitlab::Metrics.add_event(:stuck_import_jobs,
+ projects_without_jid_count: projects_without_jid_count,
+ projects_with_jid_count: projects_with_jid_count)
+ end
+
+ private
+
+ def mark_projects_without_jid_as_failed!
+ started_projects_without_jid.each do |project|
+ project.mark_import_as_failed(error_message)
+ end.count
+ end
+
+ def mark_projects_with_jid_as_failed!
+ completed_jids_count = 0
+
+ started_projects_with_jid.find_in_batches(batch_size: 500) do |group|
jids = group.map(&:import_jid)
# Find the jobs that aren't currently running or that exceeded the threshold.
- completed_jids = Gitlab::SidekiqStatus.completed_jids(jids)
+ completed_jids = Gitlab::SidekiqStatus.completed_jids(jids).to_set
if completed_jids.any?
- completed_ids = group.select { |project| completed_jids.include?(project.import_jid) }.map(&:id)
+ completed_jids_count += completed_jids.count
+ group.each do |project|
+ project.mark_import_as_failed(error_message) if completed_jids.include?(project.import_jid)
+ end
- fail_batch!(completed_jids, completed_ids)
+ Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_jids.to_a.join(', ')}")
end
end
- end
- private
+ completed_jids_count
+ end
- def stuck_projects
- Project.select('id, import_jid').with_import_status(:started).where.not(import_jid: nil)
+ def started_projects
+ Project.with_import_status(:started)
end
- def fail_batch!(completed_jids, completed_ids)
- Project.where(id: completed_ids).update_all(import_status: 'failed', import_error: error_message)
+ def started_projects_with_jid
+ started_projects.where.not(import_jid: nil)
+ end
- Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_jids.join(', ')}")
+ def started_projects_without_jid
+ started_projects.where(import_jid: nil)
end
def error_message
- "Import timed out. Import took longer than #{IMPORT_EXPIRATION} seconds"
+ "Import timed out. Import took longer than #{IMPORT_JOBS_EXPIRATION} seconds"
end
end
diff --git a/changelogs/unreleased/10085-stop-encoding-user-name.yml b/changelogs/unreleased/10085-stop-encoding-user-name.yml
deleted file mode 100644
index 8fab474e047..00000000000
--- a/changelogs/unreleased/10085-stop-encoding-user-name.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Insert user name directly without encoding"
-merge_request: 10085
-author: Nathan Neulinger <nneul@neulinger.org>
diff --git a/changelogs/unreleased/13247-api_project_events_target_iid.yml b/changelogs/unreleased/13247-api_project_events_target_iid.yml
deleted file mode 100644
index 08a31039f77..00000000000
--- a/changelogs/unreleased/13247-api_project_events_target_iid.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose target_iid in Events API
-merge_request: 13247
-author: sue445
diff --git a/changelogs/unreleased/13265-project_events_noteable_iid.yml b/changelogs/unreleased/13265-project_events_noteable_iid.yml
deleted file mode 100644
index 54d538bb548..00000000000
--- a/changelogs/unreleased/13265-project_events_noteable_iid.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Expose noteable_iid in Note
-merge_request: 13265
-author: sue445
diff --git a/changelogs/unreleased/13719-git-gc-timeout.yml b/changelogs/unreleased/13719-git-gc-timeout.yml
new file mode 100644
index 00000000000..13cf97ec764
--- /dev/null
+++ b/changelogs/unreleased/13719-git-gc-timeout.yml
@@ -0,0 +1,3 @@
+---
+title: "Raise Housekeeping timeout to 24 hours"
+merge_request: 13719
diff --git a/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml b/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml
deleted file mode 100644
index c8c2bb3eb4c..00000000000
--- a/changelogs/unreleased/1827-prevent-concurrent-editing-wiki.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Alert the user if a Wiki page changed while they were editing it in order to prevent overwriting changes.
-merge_request: 9707
-author: Hiroyuki Sato
diff --git a/changelogs/unreleased/19629-remove-inactive-tokens-list.yml b/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
deleted file mode 100644
index 414e3d49e29..00000000000
--- a/changelogs/unreleased/19629-remove-inactive-tokens-list.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove Inactive Personal Access Tokens list from Access Tokens page
-merge_request: 12866
-author:
diff --git a/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml b/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml
deleted file mode 100644
index c4c3fc7ceb2..00000000000
--- a/changelogs/unreleased/20817-please-add-coordinator-url-to-admin-area-runner-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add coordinator url to admin area runner page
-merge_request: 11603
-author:
diff --git a/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml b/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml
deleted file mode 100644
index 837a34bd067..00000000000
--- a/changelogs/unreleased/22600-related-resources-uris-using-grape-source-helpers.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Declare related resources into V4 API entities
-merge_request:
-author:
diff --git a/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml
deleted file mode 100644
index 807cd097178..00000000000
--- a/changelogs/unreleased/23036-replace-dashboard-event-filters-spinach.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replaces dashboard/event_filters.feature spinach with rspec
-merge_request: 12651
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/23036-replace-dashboard-spinach.yml b/changelogs/unreleased/23036-replace-dashboard-spinach.yml
deleted file mode 100644
index b3197c4cfa6..00000000000
--- a/changelogs/unreleased/23036-replace-dashboard-spinach.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replaces dashboard/dashboard.feature spinach with rspec
-merge_request: 12876
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/26372-duplicate-issue-slash-command.yml b/changelogs/unreleased/26372-duplicate-issue-slash-command.yml
deleted file mode 100644
index 3108344e0bf..00000000000
--- a/changelogs/unreleased/26372-duplicate-issue-slash-command.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added /duplicate quick action to close a duplicate issue
-merge_request: 12845
-author: Ryan Scott
diff --git a/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml b/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml
deleted file mode 100644
index 1b3c3b8538d..00000000000
--- a/changelogs/unreleased/27616-fix-contributions-graph-utc-offset-mysql.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix timezone inconsistencies in user contribution graph
-merge_request: 13208
-author:
diff --git a/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml b/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml
deleted file mode 100644
index b8f30b52b18..00000000000
--- a/changelogs/unreleased/28202_decrease_abc_threshold_step2.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Decrease ABC threshold to 56.96
-merge_request: 11227
-author: Maxim Rydkin
diff --git a/changelogs/unreleased/28283-uuid-storage.yml b/changelogs/unreleased/28283-uuid-storage.yml
new file mode 100644
index 00000000000..283e06d4b7f
--- /dev/null
+++ b/changelogs/unreleased/28283-uuid-storage.yml
@@ -0,0 +1,4 @@
+---
+title: Hashed Storage support for Repositories (EXPERIMENTAL)
+merge_request: 13246
+author:
diff --git a/changelogs/unreleased/28472-ignore-auto-generated-mails.yml b/changelogs/unreleased/28472-ignore-auto-generated-mails.yml
deleted file mode 100644
index af63b43e62e..00000000000
--- a/changelogs/unreleased/28472-ignore-auto-generated-mails.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't send rejection mails for all auto-generated mails
-merge_request: 13254
-author:
diff --git a/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml b/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml
deleted file mode 100644
index 488b37ac37f..00000000000
--- a/changelogs/unreleased/29289-project-destroy-clean-up-after-failure.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle errors while a project is being deleted asynchronously.
-merge_request: 11088
-author:
diff --git a/changelogs/unreleased/29385-add_shrug_command.yml b/changelogs/unreleased/29385-add_shrug_command.yml
deleted file mode 100644
index 14b8f486d5c..00000000000
--- a/changelogs/unreleased/29385-add_shrug_command.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add /shrug and /tableflip commands
-merge_request: 10068
-author: Alex Ives
diff --git a/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml b/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml
deleted file mode 100644
index 8850422fc88..00000000000
--- a/changelogs/unreleased/29901-refactor-initialization-dropzone_input-js.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: refactor initializations in dropzone_input.js
-merge_request: 12768
-author: Brandon Everett
diff --git a/changelogs/unreleased/30634-protected-pipeline.yml b/changelogs/unreleased/30634-protected-pipeline.yml
deleted file mode 100644
index e46538e5b46..00000000000
--- a/changelogs/unreleased/30634-protected-pipeline.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow running the pipeline if ref is protected and user cannot merge the
- branch or create the tag
-merge_request: 11910
-author:
diff --git a/changelogs/unreleased/31129-jira-project-key-elim.yml b/changelogs/unreleased/31129-jira-project-key-elim.yml
deleted file mode 100644
index bfa0e99f250..00000000000
--- a/changelogs/unreleased/31129-jira-project-key-elim.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove project_key from the Jira configuration
-merge_request: 12050
-author:
diff --git a/changelogs/unreleased/31207-clean-locked-merge-requests.yml b/changelogs/unreleased/31207-clean-locked-merge-requests.yml
deleted file mode 100644
index 1f52987baef..00000000000
--- a/changelogs/unreleased/31207-clean-locked-merge-requests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Unlock stuck merge request and set the proper state
-merge_request: 13207
-author:
diff --git a/changelogs/unreleased/31533-usage-data-projects-stats.yml b/changelogs/unreleased/31533-usage-data-projects-stats.yml
deleted file mode 100644
index 11bb6118337..00000000000
--- a/changelogs/unreleased/31533-usage-data-projects-stats.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Slack and JIRA services counts to Usage Data
-merge_request:
-author:
diff --git a/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml b/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml
deleted file mode 100644
index 69900f0b314..00000000000
--- a/changelogs/unreleased/31571-don-t-let-webhooks-jobs-go-to-the-dead-jobs-queue.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Prevent web hook and project service background jobs from going to the dead
- jobs queue
-merge_request:
-author:
diff --git a/changelogs/unreleased/32483-jira-error.yml b/changelogs/unreleased/32483-jira-error.yml
deleted file mode 100644
index 1c530ca5e0f..00000000000
--- a/changelogs/unreleased/32483-jira-error.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Display specific error message when JIRA test fails
-merge_request:
-author:
diff --git a/changelogs/unreleased/32844-issuables-performance.yml b/changelogs/unreleased/32844-issuables-performance.yml
deleted file mode 100644
index e9b21c1aa45..00000000000
--- a/changelogs/unreleased/32844-issuables-performance.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Move some code from services to workers in order to improve performance
-merge_request: 13326
-author:
diff --git a/changelogs/unreleased/33095-mr-widget-ui.yml b/changelogs/unreleased/33095-mr-widget-ui.yml
deleted file mode 100644
index 9ce3086df27..00000000000
--- a/changelogs/unreleased/33095-mr-widget-ui.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: clean up merge request widget UI
-merge_request:
-author:
diff --git a/changelogs/unreleased/33097-issue-tracker.yml b/changelogs/unreleased/33097-issue-tracker.yml
deleted file mode 100644
index 0b13f7165db..00000000000
--- a/changelogs/unreleased/33097-issue-tracker.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Associate Issues tab only with internal issues tracker
-merge_request:
-author:
diff --git a/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml b/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
deleted file mode 100644
index 88cfb99a73e..00000000000
--- a/changelogs/unreleased/33601-add-csrf-token-verification-to-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add CSRF token verification to API
-merge_request: 12154
-author: Vitaliy @blackst0ne Klachkov
diff --git a/changelogs/unreleased/33620-remove-events-from-notification_settings.yml b/changelogs/unreleased/33620-remove-events-from-notification_settings.yml
deleted file mode 100644
index f5f3ef3fb82..00000000000
--- a/changelogs/unreleased/33620-remove-events-from-notification_settings.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove events column from notification settings table
-merge_request:
-author:
diff --git a/changelogs/unreleased/33741-clarify-k8s-service-keys.yml b/changelogs/unreleased/33741-clarify-k8s-service-keys.yml
deleted file mode 100644
index 91142a0d580..00000000000
--- a/changelogs/unreleased/33741-clarify-k8s-service-keys.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Clarifies and rearranges the input variables on the kubernetes integration
- page and adjusts the docs slightly to meet the same order
-merge_request: !12188
-author:
diff --git a/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml b/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml
deleted file mode 100644
index 3a45ad88270..00000000000
--- a/changelogs/unreleased/33770-respect-blockquote-line-breaks.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Respect blockquote line breaks in markdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/33874_confi.yml b/changelogs/unreleased/33874_confi.yml
deleted file mode 100644
index 940753d9aaa..00000000000
--- a/changelogs/unreleased/33874_confi.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update confidential issue UI - add confidential visibility and settings to
- sidebar
-merge_request:
-author:
diff --git a/changelogs/unreleased/34027-add-icons-to-sidebar.yml b/changelogs/unreleased/34027-add-icons-to-sidebar.yml
deleted file mode 100644
index f5b50ca1dee..00000000000
--- a/changelogs/unreleased/34027-add-icons-to-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add icons to contextual sidebars
-merge_request:
-author:
diff --git a/changelogs/unreleased/34028-collapse-sidebar.yml b/changelogs/unreleased/34028-collapse-sidebar.yml
deleted file mode 100644
index 468212240ac..00000000000
--- a/changelogs/unreleased/34028-collapse-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make contextual sidebar collapsible
-merge_request:
-author:
diff --git a/changelogs/unreleased/34075-pipelines-count-mt.yml b/changelogs/unreleased/34075-pipelines-count-mt.yml
deleted file mode 100644
index 3846e7b06a4..00000000000
--- a/changelogs/unreleased/34075-pipelines-count-mt.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Update Pipeline's badge count in Merge Request and Commits view to match real-time
- content
-merge_request:
-author:
diff --git a/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml b/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml
deleted file mode 100644
index 1911705dd2b..00000000000
--- a/changelogs/unreleased/34110-memory-usage-notice-doesn-t-link-anywhere.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Added link to the MR widget that directs to the monitoring dashboard
-merge_request:
-author:
diff --git a/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml b/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml
deleted file mode 100644
index 13f28da8577..00000000000
--- a/changelogs/unreleased/34339-user_avatar-url-in-push-event-webhook-json-payload-is-relative-should-be-absolute.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use full path of user's avatar in webhooks
-merge_request: 13401
-author: Vitaliy @blackst0ne Klachkov
diff --git a/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml b/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml
deleted file mode 100644
index d188a558d38..00000000000
--- a/changelogs/unreleased/34361-lazy-load-images-on-the-frontend.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Lazy load images for better Frontend performance
-merge_request: 12503
-author:
diff --git a/changelogs/unreleased/34519-extend-api-group-secret-variable.yml b/changelogs/unreleased/34519-extend-api-group-secret-variable.yml
deleted file mode 100644
index e0b625c392f..00000000000
--- a/changelogs/unreleased/34519-extend-api-group-secret-variable.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Extend API for Group Secret Variable
-merge_request: 12936
-author:
diff --git a/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml b/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml
deleted file mode 100644
index 08171f6bcec..00000000000
--- a/changelogs/unreleased/34527-make-edit-comment-button-always-available-outside-of-dropdown.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: move edit comment button outside of dropdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml b/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml
deleted file mode 100644
index ddaaf4a2507..00000000000
--- a/changelogs/unreleased/34533-speed-up-group-project-authorizations.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix timeouts when creating projects in groups with many members
-merge_request: 13508
-author:
-type: fixed
diff --git a/changelogs/unreleased/34534-update-vue-resource.yml b/changelogs/unreleased/34534-update-vue-resource.yml
deleted file mode 100644
index 2d0af0c9bfe..00000000000
--- a/changelogs/unreleased/34534-update-vue-resource.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Updates vue resource and code according to breaking changes
-merge_request:
-author:
diff --git a/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml b/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml
deleted file mode 100644
index e843bbac239..00000000000
--- a/changelogs/unreleased/34549-extract-devise-mappings-into-helper.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Extract "@request.env[devise.mapping] = Devise.mappings[:user]" to a test helper
-merge_request: 12742
-author: Jacopo Beschi @jacopo-beschi
diff --git a/changelogs/unreleased/34563-usage-ping-github.yml b/changelogs/unreleased/34563-usage-ping-github.yml
deleted file mode 100644
index 3ab982beea3..00000000000
--- a/changelogs/unreleased/34563-usage-ping-github.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add GitHub imported projects count to usage data
-merge_request:
-author:
diff --git a/changelogs/unreleased/34764-rename-to-overview.yml b/changelogs/unreleased/34764-rename-to-overview.yml
deleted file mode 100644
index 5b9643285b7..00000000000
--- a/changelogs/unreleased/34764-rename-to-overview.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename about to overview for group and project page
-merge_request:
-author:
diff --git a/changelogs/unreleased/34810-vue-pagination.yml b/changelogs/unreleased/34810-vue-pagination.yml
deleted file mode 100644
index 5cd03518a98..00000000000
--- a/changelogs/unreleased/34810-vue-pagination.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent disabled pagination button to be clicked
-merge_request:
-author:
diff --git a/changelogs/unreleased/34831-remove-coffee-rails-gem.yml b/changelogs/unreleased/34831-remove-coffee-rails-gem.yml
deleted file mode 100644
index b555f112b8d..00000000000
--- a/changelogs/unreleased/34831-remove-coffee-rails-gem.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove coffee-rails gem
-merge_request:
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml b/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml
deleted file mode 100644
index e6cd834aed2..00000000000
--- a/changelogs/unreleased/34858-bump-scss-lint-to-0-54-0.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Bump scss-lint to 0.54.0
-merge_request: 12733
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34867-remove-net-ssh-gem.yml b/changelogs/unreleased/34867-remove-net-ssh-gem.yml
deleted file mode 100644
index f5648d62467..00000000000
--- a/changelogs/unreleased/34867-remove-net-ssh-gem.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove net-ssh gem
-merge_request:
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml b/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml
deleted file mode 100644
index 0eb2d069719..00000000000
--- a/changelogs/unreleased/34869-bump-rubocop-to-0-49-1-and-rubocop-rspec-to-1-15-1.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Bump rubocop to 0.49.1 and rubocop-rspec to 1.15.1
-merge_request:
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml b/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml
deleted file mode 100644
index 6a17353ba3f..00000000000
--- a/changelogs/unreleased/34921-global-dropdown-ui-improvement.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve CSS for global nav dropdown UI
-merge_request: 12772
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml b/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml
deleted file mode 100644
index d996ae2826a..00000000000
--- a/changelogs/unreleased/34927-protect-manual-actions-on-tags.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Protect manual actions against protected tag too
-merge_request: 12908
-author:
diff --git a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml b/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
deleted file mode 100644
index 25cc8b5e45f..00000000000
--- a/changelogs/unreleased/34978-remove-public-ci-favicon-ico.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove public/ci/favicon.ico
-merge_request: 12803
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml b/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
deleted file mode 100644
index 9de4dbefd35..00000000000
--- a/changelogs/unreleased/35044-projects-logo-are-not-centered-vertically-on-projects-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix project logos that are not centered vertically on list pages
-merge_request: 13124
-author: Florian Lemaitre
diff --git a/changelogs/unreleased/35072-fix-pages-delete.yml b/changelogs/unreleased/35072-fix-pages-delete.yml
deleted file mode 100644
index 21af2bde201..00000000000
--- a/changelogs/unreleased/35072-fix-pages-delete.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix deleting GitLab Pages files when a project is removed
-merge_request: 13631
-author:
-type: fixed
diff --git a/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml b/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml
deleted file mode 100644
index 3cdb3011f5b..00000000000
--- a/changelogs/unreleased/35098-raise-encoding-confidence-threshold.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Raise guessed encoding confidence threshold to 50
-merge_request: 12990
-author:
diff --git a/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml b/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml
deleted file mode 100644
index ea8f31cca9d..00000000000
--- a/changelogs/unreleased/35136-barchart-not-display-label-at-0-hour.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix bar chart does not display label at 0 hour
-merge_request: 35136
-author: Jason Dai
diff --git a/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml b/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml
deleted file mode 100644
index 9d9558347ba..00000000000
--- a/changelogs/unreleased/35155-upgrade-fog-core-to-1-44-3-and-its-providers-to-the-latest.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Bump fog-core to 1.44.3 and fog providers' plugins to latest
-merge_request: 12897
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml b/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml
deleted file mode 100644
index 4fd60a79782..00000000000
--- a/changelogs/unreleased/35163-url-in-commit-message-can-be-broken-in-blame.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use only CSS to truncate commit message in blame
-merge_request: 12900
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35164-cycle-analytics-firefox.yml b/changelogs/unreleased/35164-cycle-analytics-firefox.yml
deleted file mode 100644
index 0b7115136ca..00000000000
--- a/changelogs/unreleased/35164-cycle-analytics-firefox.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: allow closing Cycle Analytics intro box in firefox
-merge_request:
-author:
diff --git a/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml b/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml
deleted file mode 100644
index 4afe603720d..00000000000
--- a/changelogs/unreleased/35181-cannot-create-label-from-board-page.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix label creation from new list for subgroup projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml b/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml
deleted file mode 100644
index fbe55d4c2b0..00000000000
--- a/changelogs/unreleased/35191-prioritized-labels-for-non-member.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove help message about prioritized labels for non-members
-merge_request: 12912
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml b/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
deleted file mode 100644
index 45b6c57579b..00000000000
--- a/changelogs/unreleased/35204-doc-api-ci-lint-typo.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add link to doc/api/ci/lint.md
-merge_request: 12914
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35225-transient-poll.yml b/changelogs/unreleased/35225-transient-poll.yml
deleted file mode 100644
index 59e2e738c7b..00000000000
--- a/changelogs/unreleased/35225-transient-poll.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: fix transient js error in rspec tests
-merge_request:
-author:
diff --git a/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml b/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml
deleted file mode 100644
index 9b2a66da1c3..00000000000
--- a/changelogs/unreleased/35253-desc-protected-branches-for-non-member.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Hide description about protected branches to non-member
-merge_request: 12945
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/35343-inherit-milestones-and-labels.yml b/changelogs/unreleased/35343-inherit-milestones-and-labels.yml
new file mode 100644
index 00000000000..ce737a67356
--- /dev/null
+++ b/changelogs/unreleased/35343-inherit-milestones-and-labels.yml
@@ -0,0 +1,5 @@
+---
+title: inherits milestone and labels when a merge request is created from issue
+merge_request: 13461
+author: haseebeqx
+type: added
diff --git a/changelogs/unreleased/35391-fix-star-i18n-in-js.yml b/changelogs/unreleased/35391-fix-star-i18n-in-js.yml
deleted file mode 100644
index a6fd4dc89fd..00000000000
--- a/changelogs/unreleased/35391-fix-star-i18n-in-js.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix translations for Star/Unstar in JS file
-merge_request:
-author:
diff --git a/changelogs/unreleased/35408-group-auto-avatars.yml b/changelogs/unreleased/35408-group-auto-avatars.yml
deleted file mode 100644
index 77b644a7f94..00000000000
--- a/changelogs/unreleased/35408-group-auto-avatars.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Show auto-generated avatars for Groups without avatars
-merge_request: 13188
-author:
diff --git a/changelogs/unreleased/35483-improve-mobile-sidebar.yml b/changelogs/unreleased/35483-improve-mobile-sidebar.yml
deleted file mode 100644
index eb3dab1da9e..00000000000
--- a/changelogs/unreleased/35483-improve-mobile-sidebar.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve mobile sidebar
-merge_request:
-author:
diff --git a/changelogs/unreleased/35659-rename-pipeline.yml b/changelogs/unreleased/35659-rename-pipeline.yml
deleted file mode 100644
index 0fe211868e4..00000000000
--- a/changelogs/unreleased/35659-rename-pipeline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Rename Pipelines tab to CI / CD in new navigation
-merge_request:
-author:
diff --git a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml b/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
deleted file mode 100644
index 1c9ad20bc95..00000000000
--- a/changelogs/unreleased/35695-comment-appears-in-a-wrong-place-after-changing-diff-view-to-inline.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix display of new diff comments after changing b between diff views
-merge_request:
-author:
diff --git a/changelogs/unreleased/35761-convdev-perc.yml b/changelogs/unreleased/35761-convdev-perc.yml
deleted file mode 100644
index 319c4d18219..00000000000
--- a/changelogs/unreleased/35761-convdev-perc.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Store & use ConvDev percentages returned by the Version app
-merge_request:
-author:
diff --git a/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml b/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml
deleted file mode 100644
index ac480993d85..00000000000
--- a/changelogs/unreleased/35769-fix-ruby-2-4-compatibility.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix Issue board when using Ruby 2.4
-merge_request: 13220
-author:
diff --git a/changelogs/unreleased/35815-webhook-log-encoding-error.yml b/changelogs/unreleased/35815-webhook-log-encoding-error.yml
deleted file mode 100644
index 76ec235086c..00000000000
--- a/changelogs/unreleased/35815-webhook-log-encoding-error.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix encoding error for WebHook logging
-merge_request: 13230
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml b/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml
new file mode 100644
index 00000000000..eac8dbe23c2
--- /dev/null
+++ b/changelogs/unreleased/35845-improve-subgroup-creation-permissions.yml
@@ -0,0 +1,5 @@
+---
+title: Improves subgroup creation permissions
+merge_request: 13418
+author:
+type: bugifx
diff --git a/changelogs/unreleased/36041-notification-title.yml b/changelogs/unreleased/36041-notification-title.yml
new file mode 100644
index 00000000000..7c5e0a0cd0d
--- /dev/null
+++ b/changelogs/unreleased/36041-notification-title.yml
@@ -0,0 +1,4 @@
+---
+title: Don't escape html entities in InlineDiffMarkdownMarker
+merge_request:
+author:
diff --git a/changelogs/unreleased/36087-users-cannot-delete-their-account.yml b/changelogs/unreleased/36087-users-cannot-delete-their-account.yml
new file mode 100644
index 00000000000..9ba75d8b1d0
--- /dev/null
+++ b/changelogs/unreleased/36087-users-cannot-delete-their-account.yml
@@ -0,0 +1,5 @@
+---
+title: allow all users to delete their account
+merge_request: 13636
+author: Jacopo Beschi @jacopo-beschi
+type: changed
diff --git a/changelogs/unreleased/36185-or-separator.yml b/changelogs/unreleased/36185-or-separator.yml
deleted file mode 100644
index 4e46e60ea1b..00000000000
--- a/changelogs/unreleased/36185-or-separator.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Align OR separator to center in new project page
-merge_request:
-author:
diff --git a/changelogs/unreleased/36611-error-in-getcomposer-link.yml b/changelogs/unreleased/36611-error-in-getcomposer-link.yml
new file mode 100644
index 00000000000..1ff6ec01684
--- /dev/null
+++ b/changelogs/unreleased/36611-error-in-getcomposer-link.yml
@@ -0,0 +1,5 @@
+---
+title: Fix external link to Composer website
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/3686_make_tarball_download_url.yml b/changelogs/unreleased/3686_make_tarball_download_url.yml
deleted file mode 100644
index 4e75e52e3ac..00000000000
--- a/changelogs/unreleased/3686_make_tarball_download_url.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: repository archive download url now ends with selected file extension
-merge_request: 13178
-author: haseebeqx
diff --git a/changelogs/unreleased/5971-webhook-testing.yml b/changelogs/unreleased/5971-webhook-testing.yml
deleted file mode 100644
index 58233091977..00000000000
--- a/changelogs/unreleased/5971-webhook-testing.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow testing any events for project hooks and system hooks
-merge_request: 11728
-author: Alexander Randa (@randaalex)
diff --git a/changelogs/unreleased/add-filtered-search-group-issues-ce.yml b/changelogs/unreleased/add-filtered-search-group-issues-ce.yml
deleted file mode 100644
index f83f4173890..00000000000
--- a/changelogs/unreleased/add-filtered-search-group-issues-ce.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add filtered search to group issue dashboard
-merge_request:
-author:
diff --git a/changelogs/unreleased/add-star-for-action-scope.yml b/changelogs/unreleased/add-star-for-action-scope.yml
deleted file mode 100644
index a8119a01ec4..00000000000
--- a/changelogs/unreleased/add-star-for-action-scope.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add star for action scope, in order to delete image from registry
-merge_request: 13248
-author: jean
diff --git a/changelogs/unreleased/appearances-caching-and-schema.yml b/changelogs/unreleased/appearances-caching-and-schema.yml
deleted file mode 100644
index 5743f6e0f2d..00000000000
--- a/changelogs/unreleased/appearances-caching-and-schema.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cache Appearance instances in Redis
-merge_request:
-author:
diff --git a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml b/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
deleted file mode 100644
index 7d47c60e262..00000000000
--- a/changelogs/unreleased/artifacts-download-dropdown-menu-is-too-narrow.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Increase width of dropdown menus automatically
-merge_request: 12809
-author: Thomas Wucher
diff --git a/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml b/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml
deleted file mode 100644
index 988fdacb5fd..00000000000
--- a/changelogs/unreleased/breadcrumbs-collapsed-title-width-fix.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixed breadcrumbs title aggressively collapsing
-merge_request:
-author:
diff --git a/changelogs/unreleased/broadcast-messages-cache.yml b/changelogs/unreleased/broadcast-messages-cache.yml
deleted file mode 100644
index a3c9e1ff465..00000000000
--- a/changelogs/unreleased/broadcast-messages-cache.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Better caching and indexing of broadcast messages
-merge_request:
-author:
diff --git a/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml b/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
deleted file mode 100644
index 42e1c9e8f83..00000000000
--- a/changelogs/unreleased/bump-omniauth-ldap-gem-version.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Prevent LDAP login callback from being called with a GET request
-merge_request: 13059
-author:
diff --git a/changelogs/unreleased/bvl-add-all-settings-to-api.yml b/changelogs/unreleased/bvl-add-all-settings-to-api.yml
deleted file mode 100644
index bfaf237a21c..00000000000
--- a/changelogs/unreleased/bvl-add-all-settings-to-api.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make all application-settings accessible through the API
-merge_request: 12851
-author:
diff --git a/changelogs/unreleased/bvl-free-unused-names.yml b/changelogs/unreleased/bvl-free-unused-names.yml
deleted file mode 100644
index 53acb95e5bb..00000000000
--- a/changelogs/unreleased/bvl-free-unused-names.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Free up some top level words, reject top level groups named like files in the
- public folder
-merge_request: 12932
-author:
diff --git a/changelogs/unreleased/bvl-nfs-circuitbreaker.yml b/changelogs/unreleased/bvl-nfs-circuitbreaker.yml
deleted file mode 100644
index 151854ed31f..00000000000
--- a/changelogs/unreleased/bvl-nfs-circuitbreaker.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Block access to failing repository storage
-merge_request: 11449
-author:
diff --git a/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml b/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml
deleted file mode 100644
index a24cc7a1c43..00000000000
--- a/changelogs/unreleased/bvl-rollback-renamed-system-namespace.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Don't rename namespace called system when upgrading from 9.1.x to 9.5
-merge_request: 13228
-author:
diff --git a/changelogs/unreleased/commits-list-page-limit.yml b/changelogs/unreleased/commits-list-page-limit.yml
deleted file mode 100644
index 2fd54c5960a..00000000000
--- a/changelogs/unreleased/commits-list-page-limit.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix commit list not loading the correct page when scrolling
-merge_request:
-author:
-type: fixed
diff --git a/changelogs/unreleased/diff-changed-files-dropdown.yml b/changelogs/unreleased/diff-changed-files-dropdown.yml
deleted file mode 100644
index 2d2a26ffea2..00000000000
--- a/changelogs/unreleased/diff-changed-files-dropdown.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Moved diff changed files into a dropdown
-merge_request:
-author:
diff --git a/changelogs/unreleased/dm-commit-cache-i18n.yml b/changelogs/unreleased/dm-commit-cache-i18n.yml
new file mode 100644
index 00000000000..d47226fd408
--- /dev/null
+++ b/changelogs/unreleased/dm-commit-cache-i18n.yml
@@ -0,0 +1,5 @@
+---
+title: Commit rows would occasionally render with the wrong language
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/dm-large-push-performance.yml b/changelogs/unreleased/dm-large-push-performance.yml
deleted file mode 100644
index f5fe1bd3b28..00000000000
--- a/changelogs/unreleased/dm-large-push-performance.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Improve performance of large (initial) push into default branch
-merge_request:
-author:
diff --git a/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml b/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml
deleted file mode 100644
index 8ecea635ce5..00000000000
--- a/changelogs/unreleased/dont-use-limit-offset-when-counting-projects.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: "Improve performance of checking for projects on the projects dashboard"
-merge_request:
-author:
diff --git a/changelogs/unreleased/dz-fix-calendar-today.yml b/changelogs/unreleased/dz-fix-calendar-today.yml
deleted file mode 100644
index 5320d8b26b5..00000000000
--- a/changelogs/unreleased/dz-fix-calendar-today.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix today day highlight in calendar
-merge_request: 13048
-author:
diff --git a/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml b/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml
deleted file mode 100644
index e550e0b2f44..00000000000
--- a/changelogs/unreleased/eager-load-project-creators-for-project-dashboards.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Eager load project creators for project dashboards
-merge_request:
-author:
diff --git a/changelogs/unreleased/enable-scss-lint-bang-format.yml b/changelogs/unreleased/enable-scss-lint-bang-format.yml
deleted file mode 100644
index 0b73760198e..00000000000
--- a/changelogs/unreleased/enable-scss-lint-bang-format.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable BangFormat in scss-lint [ci skip]
-merge_request: 12815
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-declaration-order.yml b/changelogs/unreleased/enable-scss-lint-declaration-order.yml
deleted file mode 100644
index 7ac2f55592e..00000000000
--- a/changelogs/unreleased/enable-scss-lint-declaration-order.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable DeclarationOrder in scss-lint
-merge_request: 12805
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-import-path.yml b/changelogs/unreleased/enable-scss-lint-import-path.yml
deleted file mode 100644
index d158cf5b5f3..00000000000
--- a/changelogs/unreleased/enable-scss-lint-import-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable ImportPath in scss-lint
-merge_request: 12749
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-property-spelling.yml b/changelogs/unreleased/enable-scss-lint-property-spelling.yml
deleted file mode 100644
index c5a5a4dddb6..00000000000
--- a/changelogs/unreleased/enable-scss-lint-property-spelling.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable PropertySpelling in scss-lint
-merge_request: 12752
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-space-after-comma.yml b/changelogs/unreleased/enable-scss-lint-space-after-comma.yml
deleted file mode 100644
index 210f34fbb87..00000000000
--- a/changelogs/unreleased/enable-scss-lint-space-after-comma.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable SpaceAfterComma in scss-lint
-merge_request: 12734
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml b/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml
deleted file mode 100644
index 59d5df56525..00000000000
--- a/changelogs/unreleased/enable-scss-lint-unnecessary-parent-reference.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable UnnecessaryParentReference in scss-lint
-merge_request: 12738
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/ericy_ts-protected_branches_api.yml b/changelogs/unreleased/ericy_ts-protected_branches_api.yml
deleted file mode 100644
index 4cd275c5e8f..00000000000
--- a/changelogs/unreleased/ericy_ts-protected_branches_api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Add API for protected branches to allow for wildcard matching and no access
- restrictions
-merge_request: 12756
-author: Eric Yu
diff --git a/changelogs/unreleased/feature-backup-custom-path.yml b/changelogs/unreleased/feature-backup-custom-path.yml
deleted file mode 100644
index 1c5f25b3ee5..00000000000
--- a/changelogs/unreleased/feature-backup-custom-path.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support custom directory in gitlab:backup:create task
-merge_request: 12984
-author: Markus Koller
diff --git a/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml b/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml
deleted file mode 100644
index bdafc5929c0..00000000000
--- a/changelogs/unreleased/feature-gb-auto-retry-failed-ci-job.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow to configure automatic retry of a failed CI/CD job
-merge_request: 12909
-author:
diff --git a/changelogs/unreleased/feature-gpg-signed-commits.yml b/changelogs/unreleased/feature-gpg-signed-commits.yml
deleted file mode 100644
index 99bc5a309ef..00000000000
--- a/changelogs/unreleased/feature-gpg-signed-commits.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: GPG signed commits integration
-merge_request: 9546
-author: Alexis Reigel
diff --git a/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml b/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml
deleted file mode 100644
index be6f1ea00fb..00000000000
--- a/changelogs/unreleased/fix-500-error-when-rendering-avatar-for-deleted-project-creator.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Modify if condition to be more readable
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-broadcast-message-caching.yml b/changelogs/unreleased/fix-broadcast-message-caching.yml
new file mode 100644
index 00000000000..58ec1766cfd
--- /dev/null
+++ b/changelogs/unreleased/fix-broadcast-message-caching.yml
@@ -0,0 +1,5 @@
+---
+title: Fix caching of future broadcast messages
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gb-fix-head-pipeline-when-pipeline-has-errors.yml b/changelogs/unreleased/fix-gb-fix-head-pipeline-when-pipeline-has-errors.yml
new file mode 100644
index 00000000000..ede8031a501
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-fix-head-pipeline-when-pipeline-has-errors.yml
@@ -0,0 +1,5 @@
+---
+title: Fix merge request pipeline status when pipeline has errors
+merge_request: 13664
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml b/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml
deleted file mode 100644
index 3d9592bbf2a..00000000000
--- a/changelogs/unreleased/fix-gb-handle-max-pages-artifacts-size-correctly.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Handle maximum pages artifacts size correctly
-merge_request: 13072
-author:
diff --git a/changelogs/unreleased/fix-import-fork-mr.yml b/changelogs/unreleased/fix-import-fork-mr.yml
new file mode 100644
index 00000000000..4e9cf7faae8
--- /dev/null
+++ b/changelogs/unreleased/fix-import-fork-mr.yml
@@ -0,0 +1,5 @@
+---
+title: Fix Import/Export issue to do with fork merge requests
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-import-symbolink-links.yml b/changelogs/unreleased/fix-import-symbolink-links.yml
deleted file mode 100644
index 36e73821bdc..00000000000
--- a/changelogs/unreleased/fix-import-symbolink-links.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove hidden symlinks from project import files
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml b/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
deleted file mode 100644
index f4136460626..00000000000
--- a/changelogs/unreleased/fix-replying-to-commit-comment-in-mr-from-fork.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix replying to commit comments on merge requests created from forks
-merge_request:
-author:
diff --git a/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml b/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml
deleted file mode 100644
index 66b5b6b4f47..00000000000
--- a/changelogs/unreleased/fix-thread-safe-gpgme-tmp-directory.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Make GPGME temporary directory handling thread safe
-merge_request: 13481
-author: Alexis Reigel
diff --git a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml b/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
deleted file mode 100644
index 188d2770455..00000000000
--- a/changelogs/unreleased/fixes-for-internal-auth-disabled.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fixes needed when GitLab sign-in is not enabled
-merge_request: 12491
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/forks-count-cache.yml b/changelogs/unreleased/forks-count-cache.yml
deleted file mode 100644
index da8c53c2abd..00000000000
--- a/changelogs/unreleased/forks-count-cache.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Cache the number of forks of a project
-merge_request: 13535
-author:
-type: other
diff --git a/changelogs/unreleased/gitaly_ref_exists.yml b/changelogs/unreleased/gitaly_ref_exists.yml
new file mode 100644
index 00000000000..f62b646e406
--- /dev/null
+++ b/changelogs/unreleased/gitaly_ref_exists.yml
@@ -0,0 +1,4 @@
+---
+title: Implement the Gitaly RefService::RefExists endpoint
+merge_request: 13528
+author: Andrew Newdigate
diff --git a/changelogs/unreleased/github.yml b/changelogs/unreleased/github.yml
deleted file mode 100644
index 585b9b13b65..00000000000
--- a/changelogs/unreleased/github.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Reduce memory usage of the GitHub importer
-merge_request: 12886
-author:
diff --git a/changelogs/unreleased/group-milestone-references-system-notes.yml b/changelogs/unreleased/group-milestone-references-system-notes.yml
deleted file mode 100644
index 58215352305..00000000000
--- a/changelogs/unreleased/group-milestone-references-system-notes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Support Markdown references, autocomplete, and quick actions for group milestones
-merge_request:
-author:
diff --git a/changelogs/unreleased/group-new-issue.yml b/changelogs/unreleased/group-new-issue.yml
deleted file mode 100644
index 5480a44526b..00000000000
--- a/changelogs/unreleased/group-new-issue.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Cache recent projects for group-level new resource creation.
-merge_request: !13058
-author:
diff --git a/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml b/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml
deleted file mode 100644
index 0d64844a2b8..00000000000
--- a/changelogs/unreleased/handle-reserved-words-for-oauth-usernames.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Uniquify reserved word usernames on OAuth user creation
-merge_request: 13244
-author: Robin Bobbitt
diff --git a/changelogs/unreleased/issue_31790.yml b/changelogs/unreleased/issue_31790.yml
deleted file mode 100644
index df02cad423a..00000000000
--- a/changelogs/unreleased/issue_31790.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix API responses when dealing with txt files
-merge_request:
-author:
diff --git a/changelogs/unreleased/issue_35580.yml b/changelogs/unreleased/issue_35580.yml
deleted file mode 100644
index 3a94e771e25..00000000000
--- a/changelogs/unreleased/issue_35580.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix project milestones import when projects belongs to a group
-merge_request:
-author:
diff --git a/changelogs/unreleased/memoize-user-personal-projects-count.yml b/changelogs/unreleased/memoize-user-personal-projects-count.yml
deleted file mode 100644
index 3839a97f185..00000000000
--- a/changelogs/unreleased/memoize-user-personal-projects-count.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Memoize the number of personal projects a user has to reduce COUNT queries
-merge_request:
-author:
diff --git a/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml b/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml
deleted file mode 100644
index 5d7af8971e5..00000000000
--- a/changelogs/unreleased/merge-issuable-reopened-into-opened-state.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Merge issuable "reopened" state into "opened"
-merge_request:
-author:
diff --git a/changelogs/unreleased/migrate-events-into-a-new-format.yml b/changelogs/unreleased/migrate-events-into-a-new-format.yml
deleted file mode 100644
index 8a29f75323f..00000000000
--- a/changelogs/unreleased/migrate-events-into-a-new-format.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Migrate events into a new format to reduce the storage necessary and improve performance
-merge_request:
-author:
diff --git a/changelogs/unreleased/mk-fix-user-namespace-rename.yml b/changelogs/unreleased/mk-fix-user-namespace-rename.yml
new file mode 100644
index 00000000000..bb43b21f708
--- /dev/null
+++ b/changelogs/unreleased/mk-fix-user-namespace-rename.yml
@@ -0,0 +1,5 @@
+---
+title: Make username update fail if the namespace update fails
+merge_request: 13642
+author:
+type: fixed
diff --git a/changelogs/unreleased/mk-fix-wiki-backup.yml b/changelogs/unreleased/mk-fix-wiki-backup.yml
deleted file mode 100644
index ba9c1e85955..00000000000
--- a/changelogs/unreleased/mk-fix-wiki-backup.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Fix improperly skipped backups of wikis.
-merge_request: 13096
-author:
diff --git a/changelogs/unreleased/mr-branch-link-use-tree.yml b/changelogs/unreleased/mr-branch-link-use-tree.yml
deleted file mode 100644
index f4c4d9f5082..00000000000
--- a/changelogs/unreleased/mr-branch-link-use-tree.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: MR branch link now links to tree instead of commits
-merge_request:
-author:
diff --git a/changelogs/unreleased/only-limit-fetch-when-requested.yml b/changelogs/unreleased/only-limit-fetch-when-requested.yml
new file mode 100644
index 00000000000..d9acdf56511
--- /dev/null
+++ b/changelogs/unreleased/only-limit-fetch-when-requested.yml
@@ -0,0 +1,5 @@
+---
+title: Only require Sidekiq throttling library when enabled, to reduce cache misses
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/pagination-projects-explore.yml b/changelogs/unreleased/pagination-projects-explore.yml
deleted file mode 100644
index dc9c4218793..00000000000
--- a/changelogs/unreleased/pagination-projects-explore.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use Prev/Next pagination for exploring projects
-merge_request:
-author:
diff --git a/changelogs/unreleased/pass-before-script-as-is.yml b/changelogs/unreleased/pass-before-script-as-is.yml
deleted file mode 100644
index ac6513dcff6..00000000000
--- a/changelogs/unreleased/pass-before-script-as-is.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Pass before_script and script as-is preserving arrays
-merge_request:
-author:
diff --git a/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml b/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml
deleted file mode 100644
index 71eabdc16d2..00000000000
--- a/changelogs/unreleased/pawel-add-sidekiq-metrics-endpoint-32145.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add Prometheus metrics exporter to Sidekiq
-merge_request: 13082
-author:
diff --git a/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml b/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml
deleted file mode 100644
index c1e831306df..00000000000
--- a/changelogs/unreleased/pawel-add_more_variables_to_additional_metrics-35267.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add support for kube_namespace in Metrics queries
-merge_request: 16169
-author:
diff --git a/changelogs/unreleased/post-upload-pack-opt-out.yml b/changelogs/unreleased/post-upload-pack-opt-out.yml
deleted file mode 100644
index 302a99795a0..00000000000
--- a/changelogs/unreleased/post-upload-pack-opt-out.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Enable gitaly_post_upload_pack by default
-merge_request: 13078
-author:
diff --git a/changelogs/unreleased/rc-fix-branches-api-endpoint.yml b/changelogs/unreleased/rc-fix-branches-api-endpoint.yml
deleted file mode 100644
index b36663bbe91..00000000000
--- a/changelogs/unreleased/rc-fix-branches-api-endpoint.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/branches endpoint to handle dots in the branch
- name when the project full path contains a `/`
-merge_request: 13115
-author:
diff --git a/changelogs/unreleased/rc-fix-commits-api.yml b/changelogs/unreleased/rc-fix-commits-api.yml
deleted file mode 100644
index 215429eaf6b..00000000000
--- a/changelogs/unreleased/rc-fix-commits-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/commits endpoint to handle dots in the ref
- name when the project full path contains a `/`
-merge_request: 13370
-author:
diff --git a/changelogs/unreleased/rc-fix-tags-api.yml b/changelogs/unreleased/rc-fix-tags-api.yml
deleted file mode 100644
index 0a7dd5ca6ab..00000000000
--- a/changelogs/unreleased/rc-fix-tags-api.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Fix the /projects/:id/repository/tags endpoint to handle dots in the tag name
- when the project full path contains a `/`
-merge_request: 13368
-author:
diff --git a/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml b/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml
new file mode 100644
index 00000000000..00528397d64
--- /dev/null
+++ b/changelogs/unreleased/rd-fix-broken-configuration-for-some-integrations.yml
@@ -0,0 +1,5 @@
+---
+title: Testing of some integrations were broken due to missing ServiceHook record.
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/remove-nprogress-gleaning.yml b/changelogs/unreleased/remove-nprogress-gleaning.yml
deleted file mode 100644
index 78e4dc82dd4..00000000000
--- a/changelogs/unreleased/remove-nprogress-gleaning.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove CSS for nprogress removed
-merge_request: 12737
-author: Takuya Noguchi
diff --git a/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml b/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml
deleted file mode 100644
index 83934217e6a..00000000000
--- a/changelogs/unreleased/remove-redundant-query-when-retrieving-recent-pushes.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove redundant query when retrieving the most recent push of a user
-merge_request:
-author:
diff --git a/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml b/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml
deleted file mode 100644
index 5bfe55e562f..00000000000
--- a/changelogs/unreleased/reorganise-issues-indexes-for-sorting.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Re-organise "issues" indexes for faster ordering
-merge_request:
-author:
diff --git a/changelogs/unreleased/replace_spinach_spec_browse_files.yml b/changelogs/unreleased/replace_spinach_spec_browse_files.yml
deleted file mode 100644
index 7380d39fa9f..00000000000
--- a/changelogs/unreleased/replace_spinach_spec_browse_files.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Replace 'browse_files.feature' spinach test with an rspec analog
-merge_request: 12251
-author: @blackst0ne
diff --git a/changelogs/unreleased/request-store-wrap.yml b/changelogs/unreleased/request-store-wrap.yml
deleted file mode 100644
index 8017054b77b..00000000000
--- a/changelogs/unreleased/request-store-wrap.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add RequestCache which makes caching with RequestStore easier
-merge_request: 12920
-author:
diff --git a/changelogs/unreleased/restrict-haml-javascript.yml b/changelogs/unreleased/restrict-haml-javascript.yml
deleted file mode 100644
index 3d0a52f416d..00000000000
--- a/changelogs/unreleased/restrict-haml-javascript.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add custom linter for inline JavaScript to haml_lint
-merge_request: 9742
-author: winniehell
diff --git a/changelogs/unreleased/rouge-2-2-0.yml b/changelogs/unreleased/rouge-2-2-0.yml
new file mode 100644
index 00000000000..0b53cd14628
--- /dev/null
+++ b/changelogs/unreleased/rouge-2-2-0.yml
@@ -0,0 +1,5 @@
+---
+title: Bump rouge to v2.2.0
+merge_request: 13633
+author:
+type: other
diff --git a/changelogs/unreleased/rs-alphanumeric-ssh-params.yml b/changelogs/unreleased/rs-alphanumeric-ssh-params.yml
deleted file mode 100644
index 426b01cafad..00000000000
--- a/changelogs/unreleased/rs-alphanumeric-ssh-params.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Disallow Git URLs that include a username or hostname beginning with a non-alphanumeric
- character
-merge_request:
-author:
diff --git a/changelogs/unreleased/sh-structured-logging.yml b/changelogs/unreleased/sh-structured-logging.yml
deleted file mode 100644
index d89eb93f689..00000000000
--- a/changelogs/unreleased/sh-structured-logging.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add structured logging for Rails processes
-merge_request:
-author:
diff --git a/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml b/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml
deleted file mode 100644
index 7b4ae355978..00000000000
--- a/changelogs/unreleased/skip-oauth-authorization-for-trusted-applications.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Skip oAuth authorization for trusted applications
-merge_request:
-author:
diff --git a/changelogs/unreleased/tc-api-root-merge-requests.yml b/changelogs/unreleased/tc-api-root-merge-requests.yml
deleted file mode 100644
index 17456f943eb..00000000000
--- a/changelogs/unreleased/tc-api-root-merge-requests.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add top-level merge_requests API endpoint
-merge_request: 13060
-author:
diff --git a/changelogs/unreleased/tc-issue-api-assignee.yml b/changelogs/unreleased/tc-issue-api-assignee.yml
deleted file mode 100644
index 8d6360d5baf..00000000000
--- a/changelogs/unreleased/tc-issue-api-assignee.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Add author_id & assignee_id param to /issues API
-merge_request: 13004
-author:
diff --git a/changelogs/unreleased/tc-no-todo-service-select.yml b/changelogs/unreleased/tc-no-todo-service-select.yml
deleted file mode 100644
index ddcae334aa7..00000000000
--- a/changelogs/unreleased/tc-no-todo-service-select.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Avoid plucking Todo ids in TodoService
-merge_request: 10845
-author:
diff --git a/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml b/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml
new file mode 100644
index 00000000000..218336df5d2
--- /dev/null
+++ b/changelogs/unreleased/tc-remove-nonexisting-namespace-pending-delete-projects.yml
@@ -0,0 +1,5 @@
+---
+title: Migration to remove pending delete projects with non-existing namespace
+merge_request: 13598
+author:
+type: other
diff --git a/changelogs/unreleased/toggle-new-project-import-description.yml b/changelogs/unreleased/toggle-new-project-import-description.yml
deleted file mode 100644
index 8f0d09e0540..00000000000
--- a/changelogs/unreleased/toggle-new-project-import-description.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Toggle import description with import_sources_enabled
-merge_request: 12691
-author: Brianna Kicia \ No newline at end of file
diff --git a/changelogs/unreleased/use-a-specialized-class-for-querying-events.yml b/changelogs/unreleased/use-a-specialized-class-for-querying-events.yml
deleted file mode 100644
index 6c1ec10aa12..00000000000
--- a/changelogs/unreleased/use-a-specialized-class-for-querying-events.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Use a specialized class for querying events to improve performance
-merge_request:
-author:
diff --git a/changelogs/unreleased/wiki_title.yml b/changelogs/unreleased/wiki_title.yml
deleted file mode 100644
index 3ef5fa2969b..00000000000
--- a/changelogs/unreleased/wiki_title.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Allow wiki pages to be renamed in the UI
-merge_request: 10069
-author: wendy0402
diff --git a/changelogs/unreleased/winh-derive-project-name.yml b/changelogs/unreleased/winh-derive-project-name.yml
deleted file mode 100644
index 2244d21d768..00000000000
--- a/changelogs/unreleased/winh-derive-project-name.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Derive project path from import URL
-merge_request: 13131
-author:
diff --git a/changelogs/unreleased/zj-delete-mm-team.yml b/changelogs/unreleased/zj-delete-mm-team.yml
deleted file mode 100644
index f0c782c4566..00000000000
--- a/changelogs/unreleased/zj-delete-mm-team.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Remove Mattermost team when deleting a group
-merge_request: 11362
-author:
diff --git a/changelogs/unreleased/zj-pipeline-badge-improvements.yml b/changelogs/unreleased/zj-pipeline-badge-improvements.yml
deleted file mode 100644
index 735192ede2d..00000000000
--- a/changelogs/unreleased/zj-pipeline-badge-improvements.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Update build badges to be pipeline badges and display passing instead of success
-merge_request:
-author:
diff --git a/changelogs/unreleased/zj-project-templates.yml b/changelogs/unreleased/zj-project-templates.yml
deleted file mode 100644
index ab6e0f2d5f2..00000000000
--- a/changelogs/unreleased/zj-project-templates.yml
+++ /dev/null
@@ -1,4 +0,0 @@
----
-title: Projects can be created from templates
-merge_request: 13108
-author:
diff --git a/changelogs/unreleased/zj-remove-ci-api-v1.yml b/changelogs/unreleased/zj-remove-ci-api-v1.yml
new file mode 100644
index 00000000000..8f2dc321b36
--- /dev/null
+++ b/changelogs/unreleased/zj-remove-ci-api-v1.yml
@@ -0,0 +1,5 @@
+---
+title: Remove CI API v1
+merge_request:
+author:
+type: removed
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index 38ade18bdc0..abaabad5d65 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -139,6 +139,8 @@ if Settings.ldap['enabled'] || Rails.env.test?
end
Settings.ldap['servers'].each do |key, server|
+ server = Settingslogic.new(server)
+
server['label'] ||= 'LDAP'
server['timeout'] ||= 10.seconds
server['block_auto_created_users'] = false if server['block_auto_created_users'].nil?
@@ -165,6 +167,8 @@ if Settings.ldap['enabled'] || Rails.env.test?
MSG
Rails.logger.warn(message)
end
+
+ Settings.ldap['servers'][key] = server
end
end
@@ -436,7 +440,9 @@ unless Settings.repositories.storages['default']
Settings.repositories.storages['default']['path'] ||= Settings.gitlab['user_home'] + '/repositories/'
end
-Settings.repositories.storages.values.each do |storage|
+Settings.repositories.storages.each do |key, storage|
+ storage = Settingslogic.new(storage)
+
# Expand relative paths
storage['path'] = Settings.absolute(storage['path'])
# Set failure defaults
@@ -450,6 +456,8 @@ Settings.repositories.storages.values.each do |storage|
storage['failure_reset_time'] = storage['failure_reset_time'].to_i
# We might want to have a timeout shorter than 1 second.
storage['storage_timeout'] = storage['storage_timeout'].to_f
+
+ Settings.repositories.storages[key] = storage
end
#
diff --git a/config/initializers/workhorse_multipart.rb b/config/initializers/workhorse_multipart.rb
index 064e5964f09..4196e3a8f61 100644
--- a/config/initializers/workhorse_multipart.rb
+++ b/config/initializers/workhorse_multipart.rb
@@ -10,10 +10,8 @@ end
#
module Gitlab
module StrongParameterScalars
- GITLAB_PERMITTED_SCALAR_TYPES = [::UploadedFile].freeze
-
def permitted_scalar?(value)
- super || GITLAB_PERMITTED_SCALAR_TYPES.any? { |type| value.is_a?(type) }
+ super || value.is_a?(::UploadedFile)
end
end
end
diff --git a/config/karma.config.js b/config/karma.config.js
index 2f571978e08..e459f5cdac3 100644
--- a/config/karma.config.js
+++ b/config/karma.config.js
@@ -8,6 +8,7 @@ if (webpackConfig.plugins) {
webpackConfig.plugins = webpackConfig.plugins.filter(function (plugin) {
return !(
plugin instanceof webpack.optimize.CommonsChunkPlugin ||
+ plugin instanceof webpack.optimize.ModuleConcatenationPlugin ||
plugin instanceof webpack.DefinePlugin
);
});
diff --git a/config/routes/ci.rb b/config/routes/ci.rb
index 8d23aa8fbf6..cbd4c2db852 100644
--- a/config/routes/ci.rb
+++ b/config/routes/ci.rb
@@ -1,8 +1,4 @@
namespace :ci do
- # CI API
- Ci::API::API.logger Rails.logger
- mount Ci::API::API => '/api'
-
resource :lint, only: [:show, :create]
root to: redirect('/')
diff --git a/config/webpack.config.js b/config/webpack.config.js
index 1b2af3cdf14..d5487bf0a02 100644
--- a/config/webpack.config.js
+++ b/config/webpack.config.js
@@ -77,7 +77,6 @@ var config = {
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
ui_development_kit: './ui_development_kit.js',
- users: './users/index.js',
raven: './raven/index.js',
vue_merge_request_widget: './vue_merge_request_widget/index.js',
test: './test.js',
@@ -279,14 +278,9 @@ if (IS_PRODUCTION) {
})
);
- // zopfli requires a lot of compute time and is disabled in CI
+ // compression can require a lot of compute time and is disabled in CI
if (!NO_COMPRESSION) {
- // gracefully fall back to gzip if `node-zopfli` is unavailable (e.g. in CentOS 6)
- try {
- config.plugins.push(new CompressionPlugin({ algorithm: 'zopfli' }));
- } catch(err) {
- config.plugins.push(new CompressionPlugin({ algorithm: 'gzip' }));
- }
+ config.plugins.push(new CompressionPlugin());
}
}
diff --git a/db/migrate/20170711145320_add_status_to_ci_stages.rb b/db/migrate/20170711145320_add_status_to_ci_stages.rb
new file mode 100644
index 00000000000..d497a61a959
--- /dev/null
+++ b/db/migrate/20170711145320_add_status_to_ci_stages.rb
@@ -0,0 +1,9 @@
+class AddStatusToCiStages < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_stages, :status, :integer
+ end
+end
diff --git a/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
new file mode 100644
index 00000000000..e1c4f033286
--- /dev/null
+++ b/db/migrate/20170720111708_add_lock_version_to_ci_stages.rb
@@ -0,0 +1,9 @@
+class AddLockVersionToCiStages < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def change
+ add_column :ci_stages, :lock_version, :integer
+ end
+end
diff --git a/db/migrate/20170802013652_add_storage_fields_to_project.rb b/db/migrate/20170802013652_add_storage_fields_to_project.rb
new file mode 100644
index 00000000000..c2381a9d0b2
--- /dev/null
+++ b/db/migrate/20170802013652_add_storage_fields_to_project.rb
@@ -0,0 +1,16 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddStorageFieldsToProject < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ def up
+ add_column :projects, :storage_version, :integer, limit: 2
+ end
+
+ def down
+ remove_column :projects, :storage_version
+ end
+end
diff --git a/db/migrate/20170807071105_add_hashed_storage_to_settings.rb b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
new file mode 100644
index 00000000000..0846557add8
--- /dev/null
+++ b/db/migrate/20170807071105_add_hashed_storage_to_settings.rb
@@ -0,0 +1,18 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class AddHashedStorageToSettings < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_column_with_default :application_settings, :hashed_storage_enabled, :boolean, default: false
+ end
+
+ def down
+ remove_columns :application_settings, :hashed_storage_enabled
+ end
+end
diff --git a/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
new file mode 100644
index 00000000000..229298e1946
--- /dev/null
+++ b/db/migrate/20170820100558_correct_protected_tags_foreign_keys.rb
@@ -0,0 +1,35 @@
+# See http://doc.gitlab.com/ce/development/migration_style_guide.html
+# for more information on how to write migrations for GitLab.
+
+class CorrectProtectedTagsForeignKeys < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ # Set this constant to true if this migration requires downtime.
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ remove_foreign_key_without_error(:protected_tag_create_access_levels,
+ column: :protected_tag_id)
+
+ execute <<-EOF
+ DELETE FROM protected_tag_create_access_levels
+ WHERE NOT EXISTS (
+ SELECT true
+ FROM protected_tags
+ WHERE protected_tag_create_access_levels.protected_tag_id = protected_tags.id
+ )
+ AND protected_tag_id IS NOT NULL
+ EOF
+
+ add_concurrent_foreign_key(:protected_tag_create_access_levels,
+ :protected_tags,
+ column: :protected_tag_id)
+ end
+
+ def down
+ # Previously there was a foreign key without a CASCADING DELETE, so we'll
+ # just leave the foreign key in place.
+ end
+end
diff --git a/db/post_migrate/20170711145558_migrate_stages_statuses.rb b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
new file mode 100644
index 00000000000..5a24fb1307f
--- /dev/null
+++ b/db/post_migrate/20170711145558_migrate_stages_statuses.rb
@@ -0,0 +1,33 @@
+class MigrateStagesStatuses < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ BATCH_SIZE = 10000
+ RANGE_SIZE = 1000
+ MIGRATION = 'MigrateStageStatus'.freeze
+
+ class Stage < ActiveRecord::Base
+ self.table_name = 'ci_stages'
+ include ::EachBatch
+ end
+
+ def up
+ Stage.where(status: nil).each_batch(of: BATCH_SIZE) do |relation, index|
+ relation.each_batch(of: RANGE_SIZE) do |batch|
+ range = relation.pluck('MIN(id)', 'MAX(id)').first
+ schedule = index * 5.minutes
+
+ BackgroundMigrationWorker.perform_in(schedule, MIGRATION, range)
+ end
+ end
+ end
+
+ def down
+ disable_statement_timeout
+
+ update_column_in_batches(:ci_stages, :status, nil)
+ end
+end
diff --git a/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
new file mode 100644
index 00000000000..3f085c17133
--- /dev/null
+++ b/db/post_migrate/20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb
@@ -0,0 +1,54 @@
+# Follow up of CleanupNamespacelessPendingDeleteProjects and it cleans
+# all projects with `pending_delete = true` and for which the
+# namespace no longer exists.
+class CleanupNonexistingNamespacePendingDeleteProjects < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ class Project < ActiveRecord::Base
+ self.table_name = 'projects'
+
+ include ::EachBatch
+ end
+
+ class Namespace < ActiveRecord::Base
+ self.table_name = 'namespaces'
+ end
+
+ def up
+ find_projects.each_batch do |batch|
+ args = batch.pluck(:id).map { |id| [id] }
+
+ NamespacelessProjectDestroyWorker.bulk_perform_async(args)
+ end
+ end
+
+ def down
+ # NOOP
+ end
+
+ private
+
+ def find_projects
+ projects = Project.arel_table
+ namespaces = Namespace.arel_table
+
+ namespace_query = namespaces.project(1)
+ .where(namespaces[:id].eq(projects[:namespace_id]))
+ .exists.not
+
+ # SELECT "projects"."id"
+ # FROM "projects"
+ # WHERE "projects"."pending_delete" = 't'
+ # AND (NOT (EXISTS
+ # (SELECT 1
+ # FROM "namespaces"
+ # WHERE "namespaces"."id" = "projects"."namespace_id")))
+ Project.where(projects[:pending_delete].eq(true))
+ .where(namespace_query)
+ .select(:id)
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 2ea6ae29dc7..cd488630237 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: 20170815060945) do
+ActiveRecord::Schema.define(version: 20170820100558) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -128,6 +128,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.integer "performance_bar_allowed_group_id"
t.boolean "password_authentication_enabled"
t.boolean "project_export_enabled", default: true, null: false
+ t.boolean "hashed_storage_enabled", default: false, null: false
end
create_table "audit_events", force: :cascade do |t|
@@ -379,6 +380,8 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
+ t.integer "status"
+ t.integer "lock_version"
end
add_index "ci_stages", ["pipeline_id", "name"], name: "index_ci_stages_on_pipeline_id_and_name", using: :btree
@@ -1206,6 +1209,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
t.datetime "last_repository_updated_at"
t.string "ci_config_path"
t.text "delete_error"
+ t.integer "storage_version", limit: 2
end
add_index "projects", ["ci_id"], name: "index_projects_on_ci_id", using: :btree
@@ -1726,7 +1730,7 @@ ActiveRecord::Schema.define(version: 20170815060945) do
add_foreign_key "protected_branch_push_access_levels", "protected_branches", name: "fk_9ffc86a3d9", on_delete: :cascade
add_foreign_key "protected_branches", "projects", name: "fk_7a9c6d93e7", on_delete: :cascade
add_foreign_key "protected_tag_create_access_levels", "namespaces", column: "group_id"
- add_foreign_key "protected_tag_create_access_levels", "protected_tags"
+ add_foreign_key "protected_tag_create_access_levels", "protected_tags", name: "fk_f7dfda8c51", on_delete: :cascade
add_foreign_key "protected_tag_create_access_levels", "users"
add_foreign_key "protected_tags", "projects", name: "fk_8e4af87648", on_delete: :cascade
add_foreign_key "push_event_payloads", "events_for_migration", column: "event_id", name: "fk_36c74129da", on_delete: :cascade
diff --git a/doc/README.md b/doc/README.md
index 547541c4876..76d4c3e51fe 100644
--- a/doc/README.md
+++ b/doc/README.md
@@ -98,11 +98,11 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i
- [Git](topics/git/index.md): Getting started with Git, branching strategies, Git LFS, advanced use.
- [Git cheatsheet](https://gitlab.com/gitlab-com/marketing/raw/master/design/print/git-cheatsheet/print-pdf/git-cheatsheet.pdf): Download a PDF describing the most used Git operations.
- [GitLab Flow](workflow/gitlab_flow.md): explore the best of Git with the GitLab Flow strategy.
-- [Signing commits](workflow/gpg_signed_commits/index.md): use GPG to sign your commits.
+- [Signing commits](user/project/gpg_signed_commits/index.md): use GPG to sign your commits.
### Migrate and import your projects from other platforms
-- [Importing to GitLab](workflow/importing/README.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab.
+- [Importing to GitLab](user/project/import/index.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab.
- [Migrating from SVN](workflow/importing/migrating_from_svn.md): Convert a SVN repository to Git and GitLab.
### Continuous Integration, Delivery, and Deployment
diff --git a/doc/api/README.md b/doc/api/README.md
index 8acb2145f1a..266b5f018d9 100644
--- a/doc/api/README.md
+++ b/doc/api/README.md
@@ -55,15 +55,10 @@ following locations:
- [Tags](tags.md)
- [Todos](todos.md)
- [Users](users.md)
-- [Validate CI configuration](ci/lint.md)
+- [Validate CI configuration](lint.md)
- [V3 to V4](v3_to_v4.md)
- [Version](version.md)
-The following documentation is for the [internal CI API](ci/README.md):
-
-- [Builds](ci/builds.md)
-- [Runners](ci/runners.md)
-
## Road to GraphQL
Going forward, we will start on moving to
diff --git a/doc/api/ci/README.md b/doc/api/ci/README.md
deleted file mode 100644
index 96a281e27c8..00000000000
--- a/doc/api/ci/README.md
+++ /dev/null
@@ -1,24 +0,0 @@
-# GitLab CI API
-
-## Purpose
-
-The main purpose of GitLab CI API is to provide the necessary data and context
-for GitLab CI Runners.
-
-All relevant information about the consumer API can be found in a
-[separate document](../../api/README.md).
-
-## API Prefix
-
-The current CI API prefix is `/ci/api/v1`.
-
-You need to prepend this prefix to all examples in this documentation, like:
-
-```bash
-GET /ci/api/v1/builds/:id/artifacts
-```
-
-## Resources
-
-- [Builds](builds.md)
-- [Runners](runners.md)
diff --git a/doc/api/ci/builds.md b/doc/api/ci/builds.md
deleted file mode 100644
index c8374d94716..00000000000
--- a/doc/api/ci/builds.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# Builds API
-
-API used by runners to receive and update builds.
-
->**Note:**
-This API is intended to be used only by Runners as their own
-communication channel. For the consumer API see the
-[Jobs API](../jobs.md).
-
-## Authentication
-
-This API uses two types of authentication:
-
-1. Unique Runner's token which is the token assigned to the Runner after it
- has been registered.
-
-2. Using the build authorization token.
- This is project's CI token that can be found under the **Builds** section of
- a project's settings. The build authorization token can be passed as a
- parameter or a value of `BUILD-TOKEN` header.
-
-These two methods of authentication are interchangeable.
-
-## Builds
-
-### Runs oldest pending build by runner
-
-```
-POST /ci/api/v1/builds/register
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|---------------------|
-| `token` | string | yes | Unique runner token |
-
-
-```
-curl --request POST "https://gitlab.example.com/ci/api/v1/builds/register" --form "token=t0k3n"
-```
-
-**Responses:**
-
-| Status | Data |Description |
-|--------|------|---------------------------------------------------------------------------|
-| `201` | yes | When a build is scheduled for a runner |
-| `204` | no | When no builds are scheduled for a runner (for GitLab Runner >= `v1.3.0`) |
-| `403` | no | When invalid token is used or no token is sent |
-| `404` | no | When no builds are scheduled for a runner (for GitLab Runner < `v1.3.0`) **or** when the runner is set to `paused` in GitLab runner's configuration page |
-
-### Update details of an existing build
-
-```
-PUT /ci/api/v1/builds/:id
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|----------------------|
-| `id` | integer | yes | The ID of a project |
-| `token` | string | yes | Unique runner token |
-| `state` | string | no | The state of a build |
-| `trace` | string | no | The trace of a build |
-
-```
-curl --request PUT "https://gitlab.example.com/ci/api/v1/builds/1234" --form "token=t0k3n" --form "state=running" --form "trace=Running git clone...\n"
-```
-
-### Incremental build trace update
-
-Using this method you need to send trace content as a request body. You also need to provide the `Content-Range` header
-with a range of sent trace part. Note that you need to send parts in the proper order, so the begining of the part
-must start just after the end of the previous part. If you provide the wrong part, then GitLab CI API will return `416
-Range Not Satisfiable` response with a header `Range: 0-X`, where `X` is the current trace length.
-
-For example, if you receive `Range: 0-11` in the response, then your next part must contain a `Content-Range: 11-...`
-header and a trace part covered by this range.
-
-For a valid update API will return `202` response with:
-* `Build-Status: {status}` header containing current status of the build,
-* `Range: 0-{length}` header with the current trace length.
-
-```
-PATCH /ci/api/v1/builds/:id/trace.txt
-```
-
-Parameters:
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|----------------------|
-| `id` | integer | yes | The ID of a build |
-
-Headers:
-
-| Attribute | Type | Required | Description |
-|-----------------|---------|----------|-----------------------------------|
-| `BUILD-TOKEN` | string | yes | The build authorization token |
-| `Content-Range` | string | yes | Bytes range of trace that is sent |
-
-```
-curl --request PATCH "https://gitlab.example.com/ci/api/v1/builds/1234/trace.txt" --header "BUILD-TOKEN=build_t0k3n" --header "Content-Range=0-21" --data "Running git clone...\n"
-```
-
-
-### Upload artifacts to build
-
-```
-POST /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| `id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-| `file` | mixed | yes | Artifacts file |
-
-```
-curl --request POST "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n" --form "file=@/path/to/file"
-```
-
-### Download the artifacts file from build
-
-```
-GET /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| `id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-
-```
-curl "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n"
-```
-
-### Remove the artifacts file from build
-
-```
-DELETE /ci/api/v1/builds/:id/artifacts
-```
-
-| Attribute | Type | Required | Description |
-|-----------|---------|----------|-------------------------------|
-| ` id` | integer | yes | The ID of a build |
-| `token` | string | yes | The build authorization token |
-
-```
-curl --request DELETE "https://gitlab.example.com/ci/api/v1/builds/1234/artifacts" --form "token=build_t0k3n"
-```
diff --git a/doc/api/ci/runners.md b/doc/api/ci/runners.md
deleted file mode 100644
index 342c039dad8..00000000000
--- a/doc/api/ci/runners.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Register and Delete Runners API
-
-API used by Runners to register and delete themselves.
-
->**Note:**
-This API is intended to be used only by Runners as their own
-communication channel. For the consumer API see the
-[new Runners API](../runners.md).
-
-## Authentication
-
-This API uses two types of authentication:
-
-1. Unique Runner's token, which is the token assigned to the Runner after it
- has been registered. This token can be found on the Runner's edit page (go to
- **Project > Runners**, select one of the Runners listed under **Runners activated for
- this project**).
-
-2. Using Runners' registration token.
- This is a token that can be found in project's settings.
- It can also be found in the **Admin > Runners** settings area.
- There are two types of tokens you can pass: shared Runner registration
- token or project specific registration token.
-
-## Register a new runner
-
-Used to make GitLab CI aware of available runners.
-
-```sh
-POST /ci/api/v1/runners/register
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ------- | --------- | ----------- |
-| `token` | string | yes | Runner's registration token |
-
-Example request:
-
-```sh
-curl --request POST "https://gitlab.example.com/ci/api/v1/runners/register" --form "token=t0k3n"
-```
-
-## Delete a Runner
-
-Used to remove a Runner.
-
-```sh
-DELETE /ci/api/v1/runners/delete
-```
-
-| Attribute | Type | Required | Description |
-| --------- | ------- | --------- | ----------- |
-| `token` | string | yes | Unique Runner's token |
-
-Example request:
-
-```sh
-curl --request DELETE "https://gitlab.example.com/ci/api/v1/runners/delete" --form "token=t0k3n"
-```
diff --git a/doc/api/group_level_variables.md b/doc/api/group_level_variables.md
index e19be7b35c4..33c6da08018 100644
--- a/doc/api/group_level_variables.md
+++ b/doc/api/group_level_variables.md
@@ -1,5 +1,7 @@
# Group-level Variables API
+> [Introduced][ce-34519] in GitLab 9.5
+
## List group variables
Get list of a group's variables.
@@ -123,3 +125,5 @@ DELETE /groups/:id/variables/:key
```
curl --request DELETE --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/1/variables/VARIABLE_1"
```
+
+[ce-34519]: https://gitlab.com/gitlab-org/gitlab-ce/issues/34519
diff --git a/doc/api/ci/lint.md b/doc/api/lint.md
index e4a6dc809b1..bd5a216a99d 100644
--- a/doc/api/ci/lint.md
+++ b/doc/api/lint.md
@@ -5,7 +5,7 @@
Checks if your .gitlab-ci.yml file is valid.
```
-POST ci/lint
+POST /lint
```
| Attribute | Type | Required | Description |
@@ -49,3 +49,4 @@ Example responses:
```
[ce-5953]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/5953
+
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index d74398c6e65..24c8ff5fa7a 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -150,4 +150,4 @@ Example response:
}
```
-[ce-[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
+[ce-29508]: https://gitlab.com/gitlab-org/gitlab-ce/issues/29508
diff --git a/doc/articles/index.md b/doc/articles/index.md
index 3039faca411..1aa65504852 100644
--- a/doc/articles/index.md
+++ b/doc/articles/index.md
@@ -17,8 +17,8 @@ Explore GitLab's supported [authentications methods](../topics/authentication/in
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
| **LDAP** |
-| [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)| Admin guide | 2017/05/03 |
-| [How to configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) | Admin guide | 2017/05/03 |
+| [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)| Admin guide | 2017-05-03 |
+| [How to configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) | Admin guide | 2017-05-03 |
## Build, test, and deploy with GitLab CI/CD
@@ -27,17 +27,17 @@ Build, test, and deploy the software you develop with [GitLab CI/CD](../ci/READM
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
| [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md) | Tutorial | 2017-08-15 |
-| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017/07/13 |
-| [Dockerizing GitLab Review Apps](https://about.gitlab.com/2017/07/11/dockerizing-review-apps/) | Concepts | 2017/07/11 |
-| [Continuous Integration: From Jenkins to GitLab Using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/) | Concepts | 2017/07/27 |
-| [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) | Tutorial | 2016/12/14 |
-| [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/) | Tutorial | 2016/11/30 |
-| [Automated Debian Package Build with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/) | Tutorial | 2016/10/12 |
-| [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/) | Tutorial | 2016/08/11 |
-| [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/) | Technical overview | 2016/06/09 |
-| [GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/) | Technical overview | 2016/05/23 |
-| [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) | Technical overview | 2017/05/15 |
-| [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) | Tutorial | 2016/03/10 |
+| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017-07-13 |
+| [Dockerizing GitLab Review Apps](https://about.gitlab.com/2017/07/11/dockerizing-review-apps/) | Concepts | 2017-07-11 |
+| [Continuous Integration: From Jenkins to GitLab Using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/) | Concepts | 2017-07-27 |
+| [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) | Tutorial | 2016-12-14 |
+| [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/) | Tutorial | 2016-11-30 |
+| [Automated Debian Package Build with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/) | Tutorial | 2016-10-12 |
+| [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/) | Tutorial | 2016-08-11 |
+| [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/) | Technical overview | 2016-06-09 |
+| [GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/) | Technical overview | 2016-05-23 |
+| [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) | Technical overview | 2017-05-15 |
+| [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) | Tutorial | 2016-03-10 |
## Git
@@ -45,10 +45,11 @@ Learn how to use [Git with GitLab](../topics/git/index.md):
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
-| [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) | Concepts | 2017/05/17 |
-| [How to install Git](how_to_install_git/index.md) | Tutorial | 2017/05/15 |
-| [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) | Tutorial | 2017/01/30 |
-| [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) | Technical overview | 2016/12/08 |
+| [Numerous _undo_ possibilities in Git](numerous_undo_possibilities_in_git/index.md) | Tutorial | 2017-08-17 |
+| [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) | Concepts | 2017-05-17 |
+| [How to install Git](how_to_install_git/index.md) | Tutorial | 2017-05-15 |
+| [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) | Tutorial | 2017-01-30 |
+| [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) | Technical overview | 2016-12-08 |
## GitLab Pages
@@ -57,21 +58,21 @@ Learn how to deploy a static website with [GitLab Pages](../user/project/pages/i
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
| **Series: GitLab Pages from A to Z:** |
-| [- Part 1: Static sites and GitLab Pages domains](../user/project/pages/getting_started_part_one.md)| User guide | 2017/02/22 |
-| [- Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)| User guide | 2017/02/22 |
-| [- Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)| User guide | 2017/02/22 |
-| [- Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)| User guide | 2017/02/22 |
-| [Setting up GitLab Pages with CloudFlare Certificates](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | Tutorial | 2017/02/07 |
-| [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) | Tutorial | 2016/12/07 |
-| [Publish Code Coverage Report with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/) | Tutorial | 2016/11/03 |
-| [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) | Tutorial | 2016/08/26 |
-| [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) | Tutorial | 2016/08/19 |
+| [- Part 1: Static sites and GitLab Pages domains](../user/project/pages/getting_started_part_one.md)| User guide | 2017-02-22 |
+| [- Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)| User guide | 2017-02-22 |
+| [- Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)| User guide | 2017-02-22 |
+| [- Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)| User guide | 2017-02-22 |
+| [Setting up GitLab Pages with CloudFlare Certificates](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | Tutorial | 2017-02-07 |
+| [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) | Tutorial | 2016-12-07 |
+| [Publish Code Coverage Report with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/) | Tutorial | 2016-11-03 |
+| [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) | Tutorial | 2016-08-26 |
+| [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) | Tutorial | 2016-08-19 |
| **Series: Static Site Generator:** |
-| [- Part 1: Dynamic vs Static Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | Tutorial | 2016/06/03 |
-| [- Part 2: Modern Static Site Generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) | Tutorial | 2016/06/10 |
-| [- Part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | Tutorial | 2016/06/17 |
-| [Securing your GitLab Pages with TLS and Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) | Tutorial | 2016/04/11 |
-| [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) | Tutorial | 2016/04/07 |
+| [- Part 1: Dynamic vs Static Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | Tutorial | 2016-06-03 |
+| [- Part 2: Modern Static Site Generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) | Tutorial | 2016-06-10 |
+| [- Part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | Tutorial | 2016-06-17 |
+| [Securing your GitLab Pages with TLS and Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) | Tutorial | 2016-04-11 |
+| [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) | Tutorial | 2016-04-07 |
## Install and maintain GitLab
@@ -79,10 +80,10 @@ Install, upgrade, integrate, migrate to GitLab:
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
-| [Video Tutorial: Idea to Production on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/) | Tutorial | 2017/01/23 |
-| [How to Setup a GitLab Instance on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) | Tutorial | 2016/07/13 |
-| [Get started with OpenShift Origin 3 and GitLab](openshift_and_gitlab/index.md) | Tutorial | 2016/06/28 |
-| [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) | Tutorial | 2016/04/27 |
+| [Video Tutorial: Idea to Production on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/) | Tutorial | 2017-01-23 |
+| [How to Setup a GitLab Instance on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) | Tutorial | 2016-07-13 |
+| [Get started with OpenShift Origin 3 and GitLab](openshift_and_gitlab/index.md) | Tutorial | 2016-06-28 |
+| [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) | Tutorial | 2016-04-27 |
## Software development
@@ -90,25 +91,25 @@ Explore the best of GitLab's software development's capabilities:
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
-| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017/07/13 |
-| [From 2/3 of the Self-Hosted Git Market, to the Next-Generation CI System, to Auto DevOps](https://about.gitlab.com/2017/06/29/whats-next-for-gitlab-ci/)| Concepts | 2017/06/29 |
-| [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) | Concepts | 2017/05/22 |
-| [Demo: Auto-Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/) | Technical overview | 2017/05/16 |
-| [Demo: GitLab Service Desk](https://about.gitlab.com/2017/05/09/demo-service-desk/) | Feature highlight | 2017/05/09 |
-| [Demo: Mapping Work Versus Time, With Burndown Charts](https://about.gitlab.com/2017/04/25/mapping-work-to-do-versus-time-with-burndown-charts/) | Feature highlight | 2017/04/25 |
-| [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/) | Feature highlight | 2017/04/18 |
-| [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/) | Feature highlight | 2017/03/17 |
-| [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/) | Technical overview | 2016/11/14 |
-| [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Technical overview | 2016/10/25 |
-| [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/) | Concepts | 2016/08/16 |
-| [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) | Concepts | 2016/08/05 |
-| [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/) | Concepts | 2016/07/07 |
-| [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/) | Technical overview | 2016/03/08 |
+| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017-07-13 |
+| [From 2/3 of the Self-Hosted Git Market, to the Next-Generation CI System, to Auto DevOps](https://about.gitlab.com/2017/06/29/whats-next-for-gitlab-ci/)| Concepts | 2017-06-29 |
+| [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) | Concepts | 2017-05-22 |
+| [Demo: Auto-Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/) | Technical overview | 2017-05-16 |
+| [Demo: GitLab Service Desk](https://about.gitlab.com/2017/05/09/demo-service-desk/) | Feature highlight | 2017-05-09 |
+| [Demo: Mapping Work Versus Time, With Burndown Charts](https://about.gitlab.com/2017/04/25/mapping-work-to-do-versus-time-with-burndown-charts/) | Feature highlight | 2017-04-25 |
+| [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/) | Feature highlight | 2017-04-18 |
+| [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/) | Feature highlight | 2017-03-17 |
+| [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/) | Technical overview | 2016-11-14 |
+| [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Technical overview | 2016-10-25 |
+| [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/) | Concepts | 2016-08-16 |
+| [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) | Concepts | 2016-08-05 |
+| [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/) | Concepts | 2016-07-07 |
+| [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/) | Technical overview | 2016-03-08 |
## Technologies
| Article title | Category | Publishing date |
| :------------ | :------: | --------------: |
-| [Why we are not leaving the cloud](https://about.gitlab.com/2017/03/02/why-we-are-not-leaving-the-cloud/) | Concepts | 2017/03/02 |
-| [Why We Chose Vue.js](https://about.gitlab.com/2016/10/20/why-we-chose-vue/) | Concepts | 2016/10/20 |
-| [Markdown Kramdown Tips & Tricks](https://about.gitlab.com/2016/07/19/markdown-kramdown-tips-and-tricks/) | Technical overview | 2016/07/19 |
+| [Why we are not leaving the cloud](https://about.gitlab.com/2017/03/02/why-we-are-not-leaving-the-cloud/) | Concepts | 2017-03-02 |
+| [Why We Chose Vue.js](https://about.gitlab.com/2016/10/20/why-we-chose-vue/) | Concepts | 2016-10-20 |
+| [Markdown Kramdown Tips & Tricks](https://about.gitlab.com/2016/07/19/markdown-kramdown-tips-and-tricks/) | Technical overview | 2016-07-19 |
diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/branching.png b/doc/articles/numerous_undo_possibilities_in_git/img/branching.png
new file mode 100644
index 00000000000..9a80c211c99
--- /dev/null
+++ b/doc/articles/numerous_undo_possibilities_in_git/img/branching.png
Binary files differ
diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png b/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png
new file mode 100644
index 00000000000..ac7ea9ecddc
--- /dev/null
+++ b/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png
Binary files differ
diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/revert.png b/doc/articles/numerous_undo_possibilities_in_git/img/revert.png
new file mode 100644
index 00000000000..13b3a35ca45
--- /dev/null
+++ b/doc/articles/numerous_undo_possibilities_in_git/img/revert.png
Binary files differ
diff --git a/doc/articles/numerous_undo_possibilities_in_git/index.md b/doc/articles/numerous_undo_possibilities_in_git/index.md
new file mode 100644
index 00000000000..9f1239b8f88
--- /dev/null
+++ b/doc/articles/numerous_undo_possibilities_in_git/index.md
@@ -0,0 +1,497 @@
+# Numerous undo possibilities in Git
+
+> **Article [Type](../../development/writing_documentation.md#types-of-technical-articles):** tutorial ||
+> **Level:** intermediary ||
+> **Author:** [Crt Mori](https://gitlab.com/Letme) ||
+> **Publication date:** 2017/08/17
+
+## Introduction
+
+In this tutorial, we will show you different ways of undoing your work in Git, for which
+we will assume you have a basic working knowledge of. Check GitLab's
+[Git documentation](../../topics/git/index.md#git-documentation) for reference.
+Also, we will only provide some general info of the commands, which is enough
+to get you started for the easy cases/examples, but for anything more advanced please refer to the [Git book](https://git-scm.com/book/en/v2).
+
+We will explain a few different techniques to undo your changes based on the stage
+of the change in your current development. Also, keep in mind that [nothing in
+Git is really deleted.][git-autoclean-ref]
+This means that until Git automatically cleans detached commits (which cannot be
+accessed by branch or tag) it will be possible to view them with `git reflog` command
+and access them with direct commit-id. Read more about _[redoing the undo](#redoing-the-undo)_ on the section below.
+
+This guide is organized depending on the [stage of development][git-basics]
+where you want to undo your changes from and if they were shared with other developers
+or not. Because Git is tracking changes a created or edited file is in the unstaged state
+(if created it is untracked by Git). After you add it to a repository (`git add`) you put
+a file into the **staged** state, which is then committed (`git commit`) to your
+local repository. After that, file can be shared with other developers (`git push`).
+Here's what we'll cover in this tutorial:
+
+ - [Undo local changes](#undo-local-changes) which were not pushed to remote repository
+
+ - Before you commit, in both unstaged and staged state
+ - After you committed
+
+ - Undo changes after they are pushed to remote repository
+
+ - [Without history modification](#undo-remote-changes-without-changing-history) (preferred way)
+ - [With history modification](#undo-remote-changes-with-modifying-history) (requires
+ coordination with team and force pushes).
+
+ - [Usecases when modifying history is generally acceptable](#where-modifying-history-is-generally-acceptable)
+ - [How to modify history](#how-modifying-history-is-done)
+ - [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits)
+
+
+### Branching strategy
+
+[Git][git-official] is a de-centralized version control system, which means that beside regular
+versioning of the whole repository, it has possibilities to exchange changes
+with other repositories. To avoid chaos with
+[multiple sources of truth][git-distributed], various
+development workflows have to be followed, and it depends on your internal
+workflow how certain changes or commits can be undone or changed.
+[GitLab Flow][gitlab-flow] provides a good
+balance between developers clashing with each other while
+developing the same feature and cooperating seamlessly, but it does not enable
+joined development of the same feature by multiple developers by default.
+When multiple developers develop the same feature on the same branch, clashing
+with every synchronization is unavoidable, but a proper or chosen Git Workflow will
+prevent that anything is lost or out of sync when feature is complete. You can also
+read through this blog post on [Git Tips & Tricks][gitlab-git-tips-n-tricks]
+to learn how to easily **do** things in Git.
+
+
+## Undo local changes
+
+Until you push your changes to any remote repository, they will only affect you.
+That broadens your options on how to handle undoing them. Still, local changes
+can be on various stages and each stage has a different approach on how to tackle them.
+
+
+### Unstaged local changes (before you commit)
+
+When a change is made, but it is not added to the staged tree, Git itself
+proposes a solution to discard changes to certain file.
+
+Suppose you edited a file to change the content using your favorite editor:
+
+```shell
+vim <file>
+```
+
+Since you did not `git add <file>` to staging, it should be under unstaged files (or
+untracked if file was created). You can confirm that with:
+
+```shell
+$ git status
+On branch master
+Your branch is up-to-date with 'origin/master'.
+Changes not staged for commit:
+ (use "git add <file>..." to update what will be committed)
+ (use "git checkout -- <file>..." to discard changes in working directory)
+
+ modified: <file>
+no changes added to commit (use "git add" and/or "git commit -a")
+```
+
+At this point there are 3 options to undo the local changes you have:
+
+ - Discard all local changes, but save them for possible re-use [later](#quickly-save-local-changes)
+
+ ```shell
+ git stash
+ ```
+
+ - Discarding local changes (permanently) to a file
+
+ ```shell
+ git checkout -- <file>
+ ```
+
+ - Discard all local changes to all files permanently
+
+ ```shell
+ git reset --hard
+ ```
+
+
+Before executing `git reset --hard`, keep in mind that there is also a way to
+just temporary store the changes without committing them using `git stash`.
+This command resets the changes to all files, but it also saves them in case
+you would like to apply them at some later time. You can read more about it in
+[section below](#quickly-save-local-changes).
+
+### Quickly save local changes
+
+You are working on a feature when a boss drops by with an urgent task. Since your
+feature is not complete, but you need to swap to another branch, you can use
+`git stash` to save what you had done, swap to another branch, commit, push,
+test, then get back to previous feature branch, do `git stash pop` and continue
+where you left.
+
+The example above shows that discarding all changes is not always a preferred option,
+but Git provides a way to save them for later, while resetting the repository to state without
+them. This is achieved by Git stashing command `git stash`, which in fact saves your
+current work and runs `git reset --hard`, but it also has various
+additional options like:
+
+ - `git stash save`, which enables including temporary commit message, which will help you identify changes, among with other options
+ - `git stash list`, which lists all previously stashed commits (yes, there can be more) that were not `pop`ed
+ - `git stash pop`, which redoes previously stashed changes and removes them from stashed list
+ - `git stash apply`, which redoes previously stashed changes, but keeps them on stashed list
+
+### Staged local changes (before you commit)
+
+Let's say you have added some files to staging, but you want to remove them from the
+current commit, yet you want to retain those changes - just move them outside
+of the staging tree. You also have an option to discard all changes with
+`git reset --hard` or think about `git stash` [as described earlier.](#quickly-save-local-changes)
+
+Lets start the example by editing a file, with your favorite editor, to change the
+content and add it to staging
+
+```
+vim <file>
+git add <file>
+```
+
+The file is now added to staging as confirmed by `git status` command:
+
+```shell
+$ git status
+On branch master
+Your branch is up-to-date with 'origin/master'.
+Changes to be committed:
+ (use "git reset HEAD <file>..." to unstage)
+
+ new file: <file>
+```
+
+Now you have 4 options to undo your changes:
+
+ - Unstage the file to current commit (HEAD)
+
+ ```shell
+ git reset HEAD <file>
+ ```
+
+ - Unstage everything - retain changes
+
+ ```shell
+ git reset
+ ```
+
+ - Discard all local changes, but save them for [later](#quickly-save-local-changes)
+
+ ```shell
+ git stash
+ ```
+
+ - Discard everything permanently
+
+ ```shell
+ git reset --hard
+ ```
+
+## Committed local changes
+
+Once you commit, your changes are recorded by the version control system.
+Because you haven't pushed to your remote repository yet, your changes are
+still not public (or shared with other developers). At this point, undoing
+things is a lot easier, we have quite some workaround options. Once you push
+your code, you'll have less options to troubleshoot your work.
+
+### Without modifying history
+
+Through the development process some of the previously committed changes do not
+fit anymore in the end solution, or are source of the bugs. Once you find the
+commit which triggered bug, or once you have a faulty commit, you can simply
+revert it with `git revert commit-id`. This command inverts (swaps) the additions and
+deletions in that commit, so that it does not modify history. Retaining history
+can be helpful in future to notice that some changes have been tried
+unsuccessfully in the past.
+
+In our example we will assume there are commits `A`,`B`,`C`,`D`,`E` committed in this order: `A-B-C-D-E`,
+and `B` is the commit you want to undo. There are many different ways to identify commit
+`B` as bad, one of them is to pass a range to `git bisect` command. The provided range includes
+last known good commit (we assume `A`) and first known bad commit (where bug was detected - we will assume `E`).
+
+```shell
+git bisect A..E
+```
+
+Bisect will provide us with commit-id of the middle commit to test, and then guide us
+through simple bisection process. You can read more about it [in official Git Tools][git-debug]
+In our example we will end up with commit `B`, that introduced bug/error. We have
+4 options on how to remove it (or part of it) from our repository.
+
+- Undo (swap additions and deletions) changes introduced by commit `B`.
+
+ ```shell
+ git revert commit-B-id
+ ```
+
+- Undo changes on a single file or directory from commit `B`, but retain them in the staged state
+
+ ```shell
+ git checkout commit-B-id <file>
+ ```
+
+- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state
+
+ ```shell
+ git reset commit-B-id <file>
+ ```
+
+ - There is one command we also must not forget: **creating a new branch**
+ from the point where changes are not applicable or where the development has hit a
+ dead end. For example you have done commits `A-B-C-D` on your feature-branch
+ and then you figure `C` and `D` are wrong. At this point you either reset to `B`
+ and do commit `F` (which will cause problems with pushing and if forced pushed also with other developers)
+ since branch now looks `A-B-F`, which clashes with what other developers have locally (you will
+ [change history](#with-history-modification)), or you simply checkout commit `B` create
+ a new branch and do commit `F`. In the last case, everyone else can still do their work while you
+ have your new way to get it right and merge it back in later. Alternatively, with GitLab,
+ you can [cherry-pick](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
+ that commit into a new merge request.
+
+ ![Create a new branch to avoid clashing](img/branching.png)
+
+ ```shell
+ git checkout commit-B-id
+ git checkout -b new-path-of-feature
+ # Create <commit F>
+ git commit -a
+ ```
+
+### With history modification
+
+There is one command for history modification and that is `git rebase`. Command
+provides interactive mode (`-i` flag) which enables you to:
+
+ - **reword** commit messages (there is also `git commit --amend` for editing
+ last commit message)
+ - **edit** the commit content (changes introduced by commit) and message
+ - **squash** multiple commits into a single one, and have a custom or aggregated
+ commit message
+ - **drop** commits - simply delete them
+ - and few more options
+
+Let us check few examples. Again there are commits `A-B-C-D` where you want to
+delete commit `B`.
+
+- Rebase the range from current commit D to A:
+
+ ```shell
+ git rebase -i A
+ ```
+
+- Command opens your favorite editor where you write `drop` in front of commit
+ `B`, but you leave default `pick` with all other commits. Save and exit the
+ editor to perform a rebase. Remember: if you want to cancel delete whole
+ file content before saving and exiting the editor
+
+In case you want to modify something introduced in commit `B`.
+
+- Rebase the range from current commit D to A:
+
+ ```shell
+ git rebase -i A
+ ```
+
+- Command opens your favorite text editor where you write `edit` in front of commit
+ `B`, but leave default `pick` with all other commits. Save and exit the editor to
+ perform a rebase
+
+- Now do your edits and commit changes:
+
+ ```shell
+ git commit -a
+ ```
+
+You can find some more examples in [below section where we explain how to modify
+history](#how-modifying-history-is-done)
+
+
+### Redoing the Undo
+
+Sometimes you realize that the changes you undid were useful and you want them
+back. Well because of first paragraph you are in luck. Command `git reflog`
+enables you to *recall* detached local commits by referencing or applying them
+via commit-id. Although, do not expect to see really old commits in reflog, because
+Git regularly [cleans the commits which are *unreachable* by branches or tags][git-autoclean-ref].
+
+To view repository history and to track older commits you can use below command:
+
+```shell
+$ git reflog show
+
+# Example output:
+b673187 HEAD@{4}: merge 6e43d5987921bde189640cc1e37661f7f75c9c0b: Merge made by the 'recursive' strategy.
+eb37e74 HEAD@{5}: rebase -i (finish): returning to refs/heads/master
+eb37e74 HEAD@{6}: rebase -i (pick): Commit C
+97436c6 HEAD@{7}: rebase -i (start): checkout 97436c6eec6396c63856c19b6a96372705b08b1b
+...
+88f1867 HEAD@{12}: commit: Commit D
+97436c6 HEAD@{13}: checkout: moving from 97436c6eec6396c63856c19b6a96372705b08b1b to test
+97436c6 HEAD@{14}: checkout: moving from master to 97436c6
+05cc326 HEAD@{15}: commit: Commit C
+6e43d59 HEAD@{16}: commit: Commit B
+```
+
+Output of command shows repository history. In first column there is commit-id,
+in following column, number next to `HEAD` indicates how many commits ago something
+was made, after that indicator of action that was made (commit, rebase, merge, ...)
+and then on end description of that action.
+
+## Undo remote changes without changing history
+
+This topic is roughly same as modifying committed local changes without modifying
+history. **It should be the preferred way of undoing changes on any remote repository
+or public branch.** Keep in mind that branching is the best solution when you want
+to retain the history of faulty development, yet start anew from certain point. Branching
+enables you to include the existing changes in new development (by merging) and
+it also provides a clear timeline and development structure.
+
+![Use revert to keep branch flowing](img/revert.png)
+
+If you want to revert changes introduced in certain `commit-id` you can simply
+revert that `commit-id` (swap additions and deletions) in newly created commit:
+You can do this with
+
+```shell
+git revert commit-id
+```
+
+or creating a new branch:
+
+```shell
+git checkout commit-id
+git checkout -b new-path-of-feature
+```
+
+## Undo remote changes with modifying history
+
+This is useful when you want to *hide* certain things - like secret keys,
+passwords, SSH keys, etc. It is and should not be used to hide mistakes, as
+it will make it harder to debug in case there are some other bugs. The main
+reason for this is that you loose the real development progress. **Also keep in
+mind that, even with modified history, commits are just detached and can still be
+accessed through commit-id** - at least until all repositories perform
+the cleanup of detached commits (happens automatically).
+
+![Modifying history causes problems on remote branch](img/rebase_reset.png)
+
+### Where modifying history is generally acceptable
+
+Modified history breaks the development chain of other developers, as changed
+history does not have matching commits'ids. For that reason it should not
+be used on any public branch or on branch that *might* be used by other
+developers. When contributing to big open source repositories (e.g. [GitLab CE][gitlab-ce]),
+it is acceptable to *squash* commits into a single one, to present
+a nicer history of your contribution.
+Keep in mind that this also removes the comments attached to certain commits
+in merge requests, so if you need to retain traceability in GitLab, then
+modifying history is not acceptable.
+A feature-branch of a merge request is a public branch and might be used by
+other developers, but project process and rules might allow or require
+you to use `git rebase` (command that changes history) to reduce number of
+displayed commits on target branch after reviews are done (for example
+GitLab). There is a `git merge --squash` command which does exactly that
+(squashes commits on feature-branch to a single commit on target branch
+at merge).
+
+>**Note:**
+Never modify the commit history of `master` or shared branch
+
+### How modifying history is done
+
+After you know what you want to modify (how far in history or how which range of
+old commits), use `git rebase -i commit-id`. This command will then display all the commits from
+current version to chosen commit-id and allow modification, squashing, deletion
+of that commits.
+
+```shell
+$ git rebase -i commit1-id..commit3-id
+pick <commit1-id> <commit1-commit-message>
+pick <commit2-id> <commit2-commit-message>
+pick <commit3-id> <commit3-commit-message>
+
+# Rebase commit1-id..commit3-id onto <commit4-id> (3 command(s))
+#
+# Commands:
+# p, pick = use commit
+# r, reword = use commit, but edit the commit message
+# e, edit = use commit, but stop for amending
+# s, squash = use commit, but meld into previous commit
+# f, fixup = like "squash", but discard this commit's log message
+# x, exec = run command (the rest of the line) using shell
+# d, drop = remove commit
+#
+# These lines can be re-ordered; they are executed from top to bottom.
+#
+# If you remove a line here THAT COMMIT WILL BE LOST.
+#
+# However, if you remove everything, the rebase will be aborted.
+#
+# Note that empty commits are commented out
+```
+
+>**Note:**
+It is important to notice that comment from the output clearly states that, if
+you decide to abort, then do not just close your editor (as that will in-fact
+modify history), but remove all uncommented lines and save.
+
+That is one of the reasons why `git rebase` should be used carefully on
+shared and remote branches. But don't worry, there will be nothing broken until
+you push back to the remote repository (so you can freely explore the
+different outcomes locally).
+
+```shell
+# Modify history from commit-id to HEAD (current commit)
+git rebase -i commit-id
+```
+
+### Deleting sensitive information from commits
+
+Git also enables you to delete sensitive information from your past commits and
+it does modify history in the progress. That is why we have included it in this
+section and not as a standalone topic. To do so, you should run the
+`git filter-branch`, which enables you to rewrite history with
+[certain filters][git-filters-manual].
+This command uses rebase to modify history and if you want to remove certain
+file from history altogether use:
+
+```shell
+git filter-branch --tree-filter 'rm filename' HEAD
+```
+
+Since `git filter-branch` command might be slow on big repositories, there are
+tools that can use some of Git specifics to enable faster execution of common
+tasks (which is exactly what removing sensitive information file is about).
+An alternative is [BFG Repo-cleaner][bfg-repo-cleaner]. Keep in mind that these
+tools are faster because they do not provide a same fully feature set as `git filter-branch`
+does, but focus on specific usecases.
+
+## Conclusion
+
+There are various options of undoing your work with any version control system, but
+because of de-centralized nature of Git, these options are multiplied (or limited)
+depending on the stage of your process. Git also enables rewriting history, but that
+should be avoided as it might cause problems when multiple developers are
+contributing to the same codebase.
+
+<!-- Identifiers, in alphabetical order -->
+
+[bfg-repo-cleaner]: https://rtyley.github.io/bfg-repo-cleaner/
+[git-autoclean-ref]: https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery
+[git-basics]: https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository
+[git-debug]: https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git
+[git-distributed]: https://git-scm.com/about/distributed
+[git-filters-manual]: https://git-scm.com/docs/git-filter-branch#_options
+[git-official]: https://git-scm.com/
+[gitlab-ce]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria
+[gitlab-flow]: https://about.gitlab.com/2014/09/29/gitlab-flow/
+[gitlab-git-tips-n-tricks]: https://about.gitlab.com/2016/12/08/git-tips-and-tricks/
diff --git a/doc/ci/api/README.md b/doc/ci/api/README.md
deleted file mode 100644
index 98f37935427..00000000000
--- a/doc/ci/api/README.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/README.md).
diff --git a/doc/ci/api/builds.md b/doc/ci/api/builds.md
deleted file mode 100644
index 0563a367609..00000000000
--- a/doc/ci/api/builds.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/builds.md).
diff --git a/doc/ci/api/runners.md b/doc/ci/api/runners.md
deleted file mode 100644
index 1027363851c..00000000000
--- a/doc/ci/api/runners.md
+++ /dev/null
@@ -1 +0,0 @@
-This document was moved to a [new location](../../api/ci/runners.md).
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index d3433594eb7..dc5313c5597 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -117,7 +117,7 @@ following these rules:
created (requires GitLab Runner v1.1.0 or higher)
To override the default behavior, you can
-[specify a service alias](#available-settings-for-services-entry).
+[specify a service alias](#available-settings-for-services).
## Define `image` and `services` from `.gitlab-ci.yml`
@@ -183,8 +183,7 @@ test:
## Extended Docker configuration options
-> **Note:**
-This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher.
+> Introduced in GitLab and GitLab Runner 9.4.
When configuring the `image` or `services` entries, you can use a string or a map as
options:
@@ -221,28 +220,29 @@ For example, the following two definitions are equal:
### Available settings for `image`
-> **Note:**
-This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher.
+> Introduced in GitLab and GitLab Runner 9.4.
-| Setting | Required | Description |
-|------------|----------|-------------|
-| `name` | yes, when used with any other option | Full name of the image that should be used. It should contain the Registry part if needed. |
-| `entrypoint` | no | Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. |
+| Setting | Required | GitLab version | Description |
+|------------|----------|----------------| ----------- |
+| `name` | yes, when used with any other option | 9.4 |Full name of the image that should be used. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. |
### Available settings for `services`
-> **Note:**
-This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher.
+> Introduced in GitLab and GitLab Runner 9.4.
-| Setting | Required | Description |
-|------------|----------|-------------|
-| `name` | yes, when used with any other option | Full name of the image that should be used. It should contain the Registry part if needed. |
-| `entrypoint` | no | Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. |
-| `command` | no | Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`][cmd] directive, where each shell token is a separate string in the array. |
-| `alias` | no | Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
+| Setting | Required | GitLab version | Description |
+|------------|----------|----------------| ----------- |
+| `name` | yes, when used with any other option | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. |
+| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. |
+| `command` | no | 9.4 |Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`][cmd] directive, where each shell token is a separate string in the array. |
+| `alias` | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. |
### Starting multiple services from the same image
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended
+configuration options](#extended-docker-configuration-options).
+
Before the new extended Docker configuration options, the following configuration
would not work properly:
@@ -274,6 +274,9 @@ in `.gitlab-ci.yml` file.
### Setting a command for the service
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended
+configuration options](#extended-docker-configuration-options).
+
Let's assume you have a `super/sql:latest` image with some SQL database
inside it and you would like to use it as a service for your job. Let's also
assume that this image doesn't start the database process while starting
@@ -313,6 +316,9 @@ As you can see, the syntax of `command` is similar to [Dockerfile's `CMD`][cmd].
### Overriding the entrypoint of an image
+> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended
+configuration options](#extended-docker-configuration-options).
+
Let's assume you have a `super/sql:experimental` image with some SQL database
inside it and you would like to use it as a base image for your job because you
want to execute some tests with this database binary. Let's also assume that
diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md
index b4b77a2f94b..67ef189fee9 100644
--- a/doc/gitlab-basics/create-project.md
+++ b/doc/gitlab-basics/create-project.md
@@ -13,13 +13,17 @@
![Project information](img/create_new_project_info.png)
+1. Choose if you want start a blank project, or with one of the predefined
+ [Project Templates](https://gitlab.com/gitlab-org/project-templates):
+ this will kickstart your repository code and CI automatically.
+ Otherwise, if you have a project in a different repository, you can [import it] by
+ clicking an **Import project from** button provided this is enabled in
+ your GitLab instance. Ask your administrator if not.
+
1. Provide the following information:
- Enter the name of your project in the **Project name** field. You can't use
special characters, but you can use spaces, hyphens, underscores or even
emoji.
- - If you have a project in a different repository, you can [import it] by
- clicking an **Import project from** button provided this is enabled in
- your GitLab instance. Ask your administrator if not.
- The **Project description (optional)** field enables you to enter a
description for your project's dashboard, which will help others
understand what your project is about. Though it's not required, it's a good
@@ -29,12 +33,5 @@
1. Click **Create project**.
-## From a template
-
-To kickstart your development GitLab projects can be started from a template.
-For example, one of the templates included is Ruby on Rails. When filling out the
-form for new projects, click the 'Ruby on Rails' button. During project creation,
-this will import a Ruby on Rails template with GitLab CI preconfigured.
-
[import it]: ../workflow/importing/README.md
[reserved]: ../user/reserved_names.md
diff --git a/doc/gitlab-basics/img/create_new_project_info.png b/doc/gitlab-basics/img/create_new_project_info.png
index fcfbca87b91..ef8753e224b 100644
--- a/doc/gitlab-basics/img/create_new_project_info.png
+++ b/doc/gitlab-basics/img/create_new_project_info.png
Binary files differ
diff --git a/doc/install/kubernetes/gitlab_chart.md b/doc/install/kubernetes/gitlab_chart.md
index 0fad181f59e..81057736e3a 100644
--- a/doc/install/kubernetes/gitlab_chart.md
+++ b/doc/install/kubernetes/gitlab_chart.md
@@ -428,6 +428,13 @@ ingress:
## Installing GitLab using the Helm Chart
> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
Once you [have configured](#configuration) GitLab in your `values.yml` file,
run the following:
diff --git a/doc/install/kubernetes/gitlab_omnibus.md b/doc/install/kubernetes/gitlab_omnibus.md
index bd3a85272d0..05e0a59ffeb 100644
--- a/doc/install/kubernetes/gitlab_omnibus.md
+++ b/doc/install/kubernetes/gitlab_omnibus.md
@@ -126,14 +126,23 @@ Let's Encrypt limits a single TLD to five certificate requests within a single w
## Installing GitLab using the Helm Chart
> You may see a temporary error message `SchedulerPredicates failed due to PersistentVolumeClaim is not bound` while storage provisions. Once the storage provisions, the pods will automatically restart. This may take a couple minutes depending on your cloud provider. If the error persists, please review the [prerequisites](#prerequisites) to ensure you have enough RAM, CPU, and storage.
-Once you have reviewed the [configuration settings](#configuring-and-installing-gitlab) and [added the Helm repository](index.md#add-the-gitlab-helm-repository), you can install the chart. We recommending saving your configuration options in a `values.yaml` file for easier upgrades in the future.
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
+Once you have reviewed the [configuration settings](#configuring-and-installing-gitlab) you can install the chart. We recommending saving your configuration options in a `values.yaml` file for easier upgrades in the future.
For example:
+
```bash
helm install --name gitlab -f values.yaml gitlab/gitlab-omnibus
```
or passing them on the command line:
+
```bash
helm install --name gitlab --set baseDomain=gitlab.io,baseIP=1.1.1.1,gitlab=ee,gitlabEELicense=$LICENSE,legoEmail=email@gitlab.com gitlab/gitlab-omnibus
```
diff --git a/doc/install/kubernetes/gitlab_runner_chart.md b/doc/install/kubernetes/gitlab_runner_chart.md
index b0fe91d6337..51f94a33109 100644
--- a/doc/install/kubernetes/gitlab_runner_chart.md
+++ b/doc/install/kubernetes/gitlab_runner_chart.md
@@ -190,6 +190,13 @@ certsSecretName: <SECRET NAME>
## Installing GitLab Runner using the Helm Chart
+Ensure the GitLab repo has been added and re-initialize Helm:
+
+```bash
+helm repo add gitlab https://charts.gitlab.io
+helm init
+```
+
Once you [have configured](#configuration) GitLab Runner in your `values.yml` file,
run the following:
diff --git a/doc/install/kubernetes/index.md b/doc/install/kubernetes/index.md
index 3608aa6b2d6..eb98dc06a18 100644
--- a/doc/install/kubernetes/index.md
+++ b/doc/install/kubernetes/index.md
@@ -35,12 +35,14 @@ helm init
## Using the GitLab Helm Charts
-GitLab makes available three Helm Charts: an easy to use bundled chart, and a specific chart for GitLab itself and the Runner.
+GitLab makes available three Helm Charts.
-- [gitlab-omnibus](gitlab_omnibus.md): The easiest way to get started. Includes everything needed to run GitLab, including: a Runner, Container Registry, automatic SSL, and an Ingress.
+- [gitlab-omnibus](gitlab_omnibus.md): **Recommended** and the easiest way to get started. Includes everything needed to run GitLab, including: a [Runner](https://docs.gitlab.com/runner/), [Container Registry](https://docs.gitlab.com/ee/user/project/container_registry.html#gitlab-container-registry), [automatic SSL](https://github.com/kubernetes/charts/tree/master/stable/kube-lego), and an [Ingress](https://github.com/kubernetes/ingress/tree/master/controllers/nginx).
- [gitlab](gitlab_chart.md): Just the GitLab service, with optional Postgres and Redis.
- [gitlab-runner](gitlab_runner_chart.md): GitLab Runner, to process CI jobs.
+We are also working on a new set of [cloud native Charts](https://gitlab.com/charts/helm.gitlab.io) which will eventually replace these.
+
[chart]: https://github.com/kubernetes/charts
[helm-quick]: https://github.com/kubernetes/helm/blob/master/docs/quickstart.md
[helm]: https://github.com/kubernetes/helm/blob/master/README.md
diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md
index 0c0d482499a..fac91935a45 100644
--- a/doc/topics/authentication/index.md
+++ b/doc/topics/authentication/index.md
@@ -37,7 +37,6 @@ This page gathers all the resources for the topic **Authentication** within GitL
- [Private Tokens](../../api/README.md#private-tokens)
- [Impersonation tokens](../../api/README.md#impersonation-tokens)
- [GitLab as an OAuth2 provider](../../api/oauth2.md#gitlab-as-an-oauth2-provider)
-- [GitLab Runner API - Authentication](../../api/ci/runners.md#authentication)
## Third-party resources
diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md
index 604f9375714..df56f031970 100644
--- a/doc/topics/git/index.md
+++ b/doc/topics/git/index.md
@@ -22,6 +22,7 @@ We've gathered some resources to help you to get the best from Git with GitLab.
- [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit)
- [Squashing commits](../../workflow/gitlab_flow.md#squashing-commits-with-rebase)
- **Articles:**
+ - [Numerous _undo_ possibilities in Git](../../articles/numerous_undo_possibilities_in_git/index.md)
- [How to install Git](../../articles/how_to_install_git/index.md)
- [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/)
- [Eight Tips to help you work better with Git](https://about.gitlab.com/2015/02/19/8-tips-to-help-you-work-better-with-git/)
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index 9e168e830e5..fbc05261a32 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -55,6 +55,12 @@ By doing so:
- John mentions everyone from his team with `@john-team`
- John mentions only his marketing team with `@john-team/marketing`
+## Issues and merge requests within a group
+
+Issues and merge requests are part of projects. For a given group, view all the
+[issues](../project/issues/index.md#issues-per-group) and [merge requests](../project/merge_requests/index.md#merge-requests-per-group) across all the projects in that group,
+together in a single list view.
+
## Create a new group
> **Notes:**
diff --git a/doc/user/index.md b/doc/user/index.md
index d664fd62754..e9ec603f2f1 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -126,6 +126,10 @@ are a tool for working faster and more effectively with your team,
by listing all user or group mentions, as well as issues and merge
requests you're assigned to.
+## Search
+
+[Search and filter](search/index.md) through groups, projects, issues, merge requests, files, code, and more.
+
## Snippets
[Snippets](snippets.md) are code blocks that you want to store in GitLab, from which
diff --git a/doc/user/profile/img/profile_settings_dropdown.png b/doc/user/profile/img/profile_settings_dropdown.png
new file mode 100644
index 00000000000..a2c620642e2
--- /dev/null
+++ b/doc/user/profile/img/profile_settings_dropdown.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
index 8e26d98f1b0..8e26d98f1b0 100644
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
+++ b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_paste_pub.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
new file mode 100644
index 00000000000..5c14df36d73
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png b/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
new file mode 100644
index 00000000000..33936a7d6d7
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png b/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
index 22565cf7c7e..22565cf7c7e 100644
--- a/doc/workflow/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_commit_unverified_signature.png
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png b/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png
index 1778b2ddf2b..1778b2ddf2b 100644
--- a/doc/workflow/gpg_signed_commits/img/project_signed_commit_verified_signature.png
+++ b/doc/user/project/gpg_signed_commits/img/project_signed_commit_verified_signature.png
Binary files differ
diff --git a/doc/user/project/gpg_signed_commits/index.md b/doc/user/project/gpg_signed_commits/index.md
new file mode 100644
index 00000000000..3ea2203c895
--- /dev/null
+++ b/doc/user/project/gpg_signed_commits/index.md
@@ -0,0 +1,245 @@
+# Signing commits with GPG
+
+> [Introduced][ce-9546] in GitLab 9.5.
+
+GitLab can show whether a commit is verified or not when signed with a GPG key.
+All you need to do is upload the public GPG key in your profile settings.
+
+GPG verified tags are not supported yet.
+
+## Getting started with GPG
+
+Here are a few guides to get you started with GPG:
+
+- [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)
+- [Managing OpenPGP Keys](https://riseup.net/en/security/message-security/openpgp/gpg-keys)
+- [OpenPGP Best Practices](https://riseup.net/en/security/message-security/openpgp/best-practices)
+- [Creating a new GPG key with subkeys](https://www.void.gr/kargig/blog/2013/12/02/creating-a-new-gpg-key-with-subkeys/) (advanced)
+
+## How GitLab handles GPG
+
+GitLab uses its own keyring to verify the GPG signature. It does not access any
+public key server.
+
+In order to have a commit verified on GitLab the corresponding public key needs
+to be uploaded to GitLab. For a signature to be verified two prerequisites need
+to be met:
+
+1. The public key needs to be added your GitLab account
+1. One of the emails in the GPG key matches your **primary** email
+
+## Generating a GPG key
+
+If you don't already have a GPG key, the following steps will help you get
+started:
+
+1. [Install GPG](https://www.gnupg.org/download/index.html) for your operating system
+1. Generate the private/public key pair with the following command:
+
+ ```sh
+ gpg --full-gen-key
+ ```
+
+ This will spawn a series of questions.
+
+1. The first question is which algorithm can be used. Select the kind you want
+ or press <kbd>Enter</kbd> to choose the default (RSA and RSA):
+
+ ```
+ Please select what kind of key you want:
+ (1) RSA and RSA (default)
+ (2) DSA and Elgamal
+ (3) DSA (sign only)
+ (4) RSA (sign only)
+ Your selection? 1
+ ```
+
+1. The next question is key length. We recommend to choose the highest value
+ which is `4096`:
+
+ ```
+ RSA keys may be between 1024 and 4096 bits long.
+ What keysize do you want? (2048) 4096
+ Requested keysize is 4096 bits
+ ```
+1. Next, you need to specify the validity period of your key. This is something
+ subjective, and you can use the default value which is to never expire:
+
+ ```
+ Please specify how long the key should be valid.
+ 0 = key does not expire
+ <n> = key expires in n days
+ <n>w = key expires in n weeks
+ <n>m = key expires in n months
+ <n>y = key expires in n years
+ Key is valid for? (0) 0
+ Key does not expire at all
+ ```
+
+1. Confirm that the answers you gave were correct by typing `y`:
+
+ ```
+ Is this correct? (y/N) y
+ ```
+
+1. Enter you real name, the email address to be associated with this key (should
+ match the primary email address you use in GitLab) and an optional comment
+ (press <kbd>Enter</kbd> to skip):
+
+ ```
+ GnuPG needs to construct a user ID to identify your key.
+
+ Real name: Mr. Robot
+ Email address: mr@robot.sh
+ Comment:
+ You selected this USER-ID:
+ "Mr. Robot <mr@robot.sh>"
+
+ Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
+ ```
+
+1. Pick a strong password when asked and type it twice to confirm.
+1. Use the following command to list the private GPG key you just created:
+
+ ```
+ gpg --list-secret-keys mr@robot.sh
+ ```
+
+ Replace `mr@robot.sh` with the email address you entered above.
+
+1. Copy the GPG key ID that starts with `sec`. In the following example, that's
+ `0x30F2B65B9246B6CA`:
+
+ ```
+ sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC]
+ D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
+ uid [ultimate] Mr. Robot <mr@robot.sh>
+ ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E]
+ ```
+
+1. Export the public key of that ID (replace your key ID from the previous step):
+
+ ```
+ gpg --armor --export 0x30F2B65B9246B6CA
+ ```
+
+1. Finally, copy the public key and [add it in your profile settings](#adding-a-gpg-key-to-your-account)
+
+## Adding a GPG key to your account
+
+>**Note:**
+Once you add a key, you cannot edit it, only remove it. In case the paste
+didn't work, you'll have to remove the offending key and re-add it.
+
+You can add a GPG key in your profile's settings:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+
+ ![Settings dropdown](../../profile/img/profile_settings_dropdown.png)
+
+1. Navigate to the **GPG keys** tab and paste your _public_ key in the 'Key'
+ box.
+
+ ![Paste GPG public key](img/profile_settings_gpg_keys_paste_pub.png)
+
+1. Finally, click on **Add key** to add it to GitLab. You will be able to see
+ its fingerprint, the corresponding email address and creation date.
+
+ ![GPG key single page](img/profile_settings_gpg_keys_single_key.png)
+
+## Associating your GPG key with Git
+
+After you have [created your GPG key](#generating-a-gpg-key) and [added it to
+your account](#adding-a-gpg-key-to-your-account), it's time to tell Git which
+key to use.
+
+1. Use the following command to list the private GPG key you just created:
+
+ ```
+ gpg --list-secret-keys mr@robot.sh
+ ```
+
+ Replace `mr@robot.sh` with the email address you entered above.
+
+1. Copy the GPG key ID that starts with `sec`. In the following example, that's
+ `0x30F2B65B9246B6CA`:
+
+ ```
+ sec rsa4096/0x30F2B65B9246B6CA 2017-08-18 [SC]
+ D5E4F29F3275DC0CDA8FFC8730F2B65B9246B6CA
+ uid [ultimate] Mr. Robot <mr@robot.sh>
+ ssb rsa4096/0xB7ABC0813E4028C0 2017-08-18 [E]
+ ```
+
+1. Tell Git to use that key to sign the commits:
+
+ ```
+ git config --global user.signingkey 0x30F2B65B9246B6CA
+ ```
+
+ Replace `0x30F2B65B9246B6CA` with your GPG key ID.
+
+## Signing commits
+
+After you have [created your GPG key](#generating-a-gpg-key) and [added it to
+your account](#adding-a-gpg-key-to-your-account), you can start signing your
+commits:
+
+1. Commit like you used to, the only difference is the addition of the `-S` flag:
+
+ ```
+ git commit -S -m "My commit msg"
+ ```
+
+1. Enter the passphrase of your GPG key when asked.
+1. Push to GitLab and check that your commits [are verified](#verifying-commits).
+
+If you don't want to type the `-S` flag every time you commit, you can tell Git
+to sign your commits automatically:
+
+```
+git config --global commit.gpgsign true
+```
+
+## Verifying commits
+
+1. Within a project or [merge request](../merge_requests/index.md), navigate to
+ the **Commits** tab. Signed commits will show a badge containing either
+ "Verified" or "Unverified", depending on the verification status of the GPG
+ signature.
+
+ ![Signed and unsigned commits](img/project_signed_and_unsigned_commits.png)
+
+1. By clicking on the GPG badge, details of the signature are displayed.
+
+ ![Signed commit with verified signature](img/project_signed_commit_verified_signature.png)
+
+ ![Signed commit with verified signature](img/project_signed_commit_unverified_signature.png)
+
+## Revoking a GPG key
+
+Revoking a key **unverifies** already signed commits. Commits that were
+verified by using this key will change to an unverified state. Future commits
+will also stay unverified once you revoke this key. This action should be used
+in case your key has been compromised.
+
+To revoke a GPG key:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+1. Navigate to the **GPG keys** tab.
+1. Click on **Revoke** besides the GPG key you want to delete.
+
+## Removing a GPG key
+
+Removing a key **does not unverify** already signed commits. Commits that were
+verified by using this key will stay verified. Only unpushed commits will stay
+unverified once you remove this key. To unverify already signed commits, you need
+to [revoke the associated GPG key](#revoking-a-gpg-key) from your account.
+
+To remove a GPG key from your account:
+
+1. On the upper right corner, click on your avatar and go to your **Settings**.
+1. Navigate to the **GPG keys** tab.
+1. Click on the trash icon besides the GPG key you want to delete.
+
+[ce-9546]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/9546
diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md
new file mode 100644
index 00000000000..b22c7db0047
--- /dev/null
+++ b/doc/user/project/import/bitbucket.md
@@ -0,0 +1,62 @@
+# Import your project from Bitbucket to GitLab
+
+Import your projects from Bitbucket to GitLab with minimal effort.
+
+## Overview
+
+>**Note:**
+The [Bitbucket integration][bb-import] must be first enabled in order to be
+able to import your projects from Bitbucket. Ask your GitLab administrator
+to enable this if not already.
+
+- At its current state, the Bitbucket importer can import:
+ - the repository description (GitLab 7.7+)
+ - the Git repository data (GitLab 7.7+)
+ - the issues (GitLab 7.7+)
+ - the issue comments (GitLab 8.15+)
+ - the pull requests (GitLab 8.4+)
+ - the pull request comments (GitLab 8.15+)
+ - the milestones (GitLab 8.15+)
+ - the wiki (GitLab 8.15+)
+- References to pull requests and issues are preserved (GitLab 8.7+)
+- Repository public access is retained. If a repository is private in Bitbucket
+ it will be created as private in GitLab as well.
+
+
+## How it works
+
+When issues/pull requests are being imported, the Bitbucket importer tries to find
+the Bitbucket author/assignee in GitLab's database using the Bitbucket ID. For this
+to work, the Bitbucket author/assignee should have signed in beforehand in GitLab
+and **associated their Bitbucket account**. If the user is not
+found in GitLab's database, the project creator (most of the times the current
+user that started the import process) is set as the author, but a reference on
+the issue about the original Bitbucket author is kept.
+
+The importer will create any new namespaces (groups) if they don't exist or in
+the case the namespace is taken, the repository will be imported under the user's
+namespace that started the import process.
+
+## Importing your Bitbucket repositories
+
+1. Sign in to GitLab and go to your dashboard.
+1. Click on **New project**.
+
+ ![New project in GitLab](img/bitbucket_import_new_project.png)
+
+1. Click on the "Bitbucket" button
+
+ ![Bitbucket](img/import_projects_from_new_project_page.png)
+
+1. Grant GitLab access to your Bitbucket account
+
+ ![Grant access](img/bitbucket_import_grant_access.png)
+
+1. Click on the projects that you'd like to import or **Import all projects**.
+ You can also select the namespace under which each project will be
+ imported.
+
+ ![Import projects](img/bitbucket_import_select_project.png)
+
+[bb-import]: ../../../integration/bitbucket.md
+[social sign-in]: ../../profile/account/social_sign_in.md
diff --git a/doc/user/project/import/clearcase.md b/doc/user/project/import/clearcase.md
new file mode 100644
index 00000000000..f23623ed485
--- /dev/null
+++ b/doc/user/project/import/clearcase.md
@@ -0,0 +1,47 @@
+# Migrating from ClearCase
+
+[ClearCase](https://www-03.ibm.com/software/products/en/clearcase/) is a set of
+tools developed by IBM which also include a centralized version control system
+similar to Git.
+
+A good read of ClearCase's basic concepts is can be found in this [StackOverflow
+post](https://stackoverflow.com/a/645771/974710).
+
+The following table illustrates the main differences between ClearCase and Git:
+
+| Aspect | ClearCase | Git |
+| ------ | --------- | --- |
+| Repository model | Client-server | Distributed |
+| Revision IDs | Branch + number | Global alphanumeric ID |
+| Scope of Change | File | Directory tree snapshot |
+| Concurrency model | Merge | Merge |
+| Storage Method | Deltas | Full content |
+| Client | CLI, Eclipse, CC Client | CLI, Eclipse, Git client/GUIs |
+| Server | UNIX, Windows legacy systems | UNIX, macOS |
+| License | Proprietary | GPL |
+
+_Taken from the slides [ClearCase and the journey to Git](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf) provided by collab.net_
+
+## Why migrate
+
+ClearCase can be difficult to manage both from a user and an admin perspective.
+Migrating to Git/GitLab there is:
+
+- **No licensing costs**, Git is GPL while ClearCase is proprietary.
+- **Shorter learning curve**, Git has a big community and a vast number of
+ tutorials to get you started.
+- **Integration with modern tools**, migrating to Git and GitLab you can have
+ an open source end-to-end software development platform with built-in version
+ control, issue tracking, code review, CI/CD, and more.
+
+## How to migrate
+
+While there doesn't exist a tool to fully migrate from ClearCase to Git, here
+are some useful links to get you started:
+
+- [Bridge for Git and ClearCase](https://github.com/charleso/git-cc)
+- [Slides "ClearCase and the journey to Git"](https://www.open.collab.net/media/pdfs/ClearCase-and-the-journey-to-Git.pdf)
+- [ClearCase to Git](https://therub.org/2013/07/19/clearcase-to-git/)
+- [Dual syncing ClearCase to Git](https://therub.org/2013/10/22/dual-syncing-clearcase-and-git/)
+- [Moving to Git from ClearCase](https://sateeshkumarb.wordpress.com/2011/01/15/moving-to-git-from-clearcase/)
+- [ClearCase to Git webinar](https://www.brighttalk.com/webcast/11817/162473/clearcase-to-git)
diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md
new file mode 100644
index 00000000000..17222c53675
--- /dev/null
+++ b/doc/user/project/import/fogbugz.md
@@ -0,0 +1,28 @@
+# Import your project from FogBugz to GitLab
+
+It only takes a few simple steps to import your project from FogBugz.
+The importer will import all of your cases and comments with original case
+numbers and timestamps. You will also have the opportunity to map FogBugz
+users to GitLab users.
+
+1. From your GitLab dashboard click 'New project'
+1. Click on the 'FogBugz' button
+
+ ![FogBugz](img/fogbugz_import_select_fogbogz.png)
+
+1. Enter your FogBugz URL, email address, and password.
+
+ ![Login](img/fogbugz_import_login.png)
+
+1. Create mapping from FogBugz users to GitLab users.
+
+ ![User Map](img/fogbugz_import_user_map.png)
+
+1. Select the projects you wish to import by clicking the Import buttons
+
+ ![Import Project](img/fogbugz_import_select_project.png)
+
+1. Once the import has finished click the link to take you to the project
+dashboard. Follow the directions to push your existing repository.
+
+ ![Finished](img/fogbugz_import_finished.png)
diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md
new file mode 100644
index 00000000000..f5746a0fb31
--- /dev/null
+++ b/doc/user/project/import/gitea.md
@@ -0,0 +1,77 @@
+# Import your project from Gitea to GitLab
+
+Import your projects from Gitea to GitLab with minimal effort.
+
+## Overview
+
+>**Note:**
+This requires Gitea `v1.0.0` or newer.
+
+- At its current state, Gitea importer can import:
+ - the repository description (GitLab 8.15+)
+ - the Git repository data (GitLab 8.15+)
+ - the issues (GitLab 8.15+)
+ - the pull requests (GitLab 8.15+)
+ - the milestones (GitLab 8.15+)
+ - the labels (GitLab 8.15+)
+- Repository public access is retained. If a repository is private in Gitea
+ it will be created as private in GitLab as well.
+
+## How it works
+
+Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped
+to users in your GitLab's instance. This means that the project creator (most of
+the times the current user that started the import process) is set as the author,
+but a reference on the issue about the original Gitea author is kept.
+
+The importer will create any new namespaces (groups) if they don't exist or in
+the case the namespace is taken, the repository will be imported under the user's
+namespace that started the import process.
+
+## Importing your Gitea repositories
+
+The importer page is visible when you create a new project.
+
+![New project page on GitLab](img/import_projects_from_new_project_page.png)
+
+Click on the **Gitea** link and the import authorization process will start.
+
+![New Gitea project import](img/import_projects_from_gitea_new_import.png)
+
+### Authorize access to your repositories using a personal access token
+
+With this method, you will perform a one-off authorization with Gitea to grant
+GitLab access your repositories:
+
+1. Go to <https://you-gitea-instance/user/settings/applications> (replace
+ `you-gitea-instance` with the host of your Gitea instance).
+1. Click **Generate New Token**.
+1. Enter a token description.
+1. Click **Generate Token**.
+1. Copy the token hash.
+1. Go back to GitLab and provide the token to the Gitea importer.
+1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads
+ your repositories' information. Once done, you'll be taken to the importer
+ page to select the repositories to import.
+
+### Select which repositories to import
+
+After you've authorized access to your Gitea repositories, you will be
+redirected to the Gitea importer page.
+
+From there, you can see the import statuses of your Gitea repositories.
+
+- Those that are being imported will show a _started_ status,
+- those already successfully imported will be green with a _done_ status,
+- whereas those that are not yet imported will have an **Import** button on the
+ right side of the table.
+
+If you want, you can import all your Gitea projects in one go by hitting
+**Import all projects** in the upper left corner.
+
+![Gitea importer page](img/import_projects_from_github_importer.png)
+
+---
+
+You can also choose a different name for the project and a different namespace,
+if you have the privileges to do so.
diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md
new file mode 100644
index 00000000000..016f98966e3
--- /dev/null
+++ b/doc/user/project/import/github.md
@@ -0,0 +1,122 @@
+# Import your project from GitHub to GitLab
+
+Import your projects from GitHub to GitLab with minimal effort.
+
+## Overview
+
+>**Note:**
+If you are an administrator you can enable the [GitHub integration][gh-import]
+in your GitLab instance sitewide. This configuration is optional, users will
+still be able to import their GitHub repositories with a
+[personal access token][gh-token].
+
+>**Note:**
+Administrators of a GitLab instance (Community or Enterprise Edition) can also
+use the [GitHub rake task][gh-rake] to import projects from GitHub without the
+constrains of a Sidekiq worker.
+
+- At its current state, GitHub importer can import:
+ - the repository description (GitLab 7.7+)
+ - the Git repository data (GitLab 7.7+)
+ - the issues (GitLab 7.7+)
+ - the pull requests (GitLab 8.4+)
+ - the wiki pages (GitLab 8.4+)
+ - the milestones (GitLab 8.7+)
+ - the labels (GitLab 8.7+)
+ - the release note descriptions (GitLab 8.12+)
+- References to pull requests and issues are preserved (GitLab 8.7+)
+- Repository public access is retained. If a repository is private in GitHub
+ it will be created as private in GitLab as well.
+
+## How it works
+
+When issues/pull requests are being imported, the GitHub importer tries to find
+the GitHub author/assignee in GitLab's database using the GitHub ID. For this
+to work, the GitHub author/assignee should have signed in beforehand in GitLab
+and **associated their GitHub account**. If the user is not
+found in GitLab's database, the project creator (most of the times the current
+user that started the import process) is set as the author, but a reference on
+the issue about the original GitHub author is kept.
+
+The importer will create any new namespaces (groups) if they don't exist or in
+the case the namespace is taken, the repository will be imported under the user's
+namespace that started the import process.
+
+## Importing your GitHub repositories
+
+The importer page is visible when you create a new project.
+
+![New project page on GitLab](img/import_projects_from_new_project_page.png)
+
+Click on the **GitHub** link and the import authorization process will start.
+There are two ways to authorize access to your GitHub repositories:
+
+1. [Using the GitHub integration][gh-integration] (if it's enabled by your
+ GitLab administrator). This is the preferred way as it's possible to
+ preserve the GitHub authors/assignees. Read more in the [How it works](#how-it-works)
+ section.
+1. [Using a personal access token][gh-token] provided by GitHub.
+
+![Select authentication method](img/import_projects_from_github_select_auth_method.png)
+
+### Authorize access to your repositories using the GitHub integration
+
+If the [GitHub integration][gh-import] is enabled by your GitLab administrator,
+you can use it instead of the personal access token.
+
+1. First you may want to connect your GitHub account to GitLab in order for
+ the username mapping to be correct.
+1. Once you connect GitHub, click the **List your GitHub repositories** button
+ and you will be redirected to GitHub for permission to access your projects.
+1. After accepting, you'll be automatically redirected to the importer.
+
+You can now go on and [select which repositories to import](#select-which-repositories-to-import).
+
+### Authorize access to your repositories using a personal access token
+
+>**Note:**
+For a proper author/assignee mapping for issues and pull requests, the
+[GitHub integration][gh-integration] should be used instead of the
+[personal access token][gh-token]. If the GitHub integration is enabled by your
+GitLab administrator, it should be the preferred method to import your repositories.
+Read more in the [How it works](#how-it-works) section.
+
+If you are not using the GitHub integration, you can still perform a one-off
+authorization with GitHub to grant GitLab access your repositories:
+
+1. Go to <https://github.com/settings/tokens/new>.
+1. Enter a token description.
+1. Check the `repo` scope.
+1. Click **Generate token**.
+1. Copy the token hash.
+1. Go back to GitLab and provide the token to the GitHub importer.
+1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads
+ your repositories' information. Once done, you'll be taken to the importer
+ page to select the repositories to import.
+
+### Select which repositories to import
+
+After you've authorized access to your GitHub repositories, you will be
+redirected to the GitHub importer page.
+
+From there, you can see the import statuses of your GitHub repositories.
+
+- Those that are being imported will show a _started_ status,
+- those already successfully imported will be green with a _done_ status,
+- whereas those that are not yet imported will have an **Import** button on the
+ right side of the table.
+
+If you want, you can import all your GitHub projects in one go by hitting
+**Import all projects** in the upper left corner.
+
+![GitHub importer page](img/import_projects_from_github_importer.png)
+
+---
+
+You can also choose a different name for the project and a different namespace,
+if you have the privileges to do so.
+
+[gh-import]: ../../../integration/github.md "GitHub integration"
+[gh-rake]: ../../../administration/raketasks/github_import.md "GitHub rake task"
+[gh-integration]: #authorize-access-to-your-repositories-using-the-github-integration
+[gh-token]: #authorize-access-to-your-repositories-using-a-personal-access-token
diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md
new file mode 100644
index 00000000000..3b37da67a5b
--- /dev/null
+++ b/doc/user/project/import/gitlab_com.md
@@ -0,0 +1,20 @@
+# Project importing from GitLab.com to your private GitLab instance
+
+You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if
+GitLab support is enabled on your GitLab instance.
+You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html)
+To get to the importer page you need to go to "New project" page.
+
+>**Note:**
+If you are interested in importing Wiki and Merge Request data to your new
+instance, you'll need to follow the instructions for [project export](../settings/import_export.md)
+
+![New project page](img/gitlab_new_project_page.png)
+
+Click on the "Import projects from GitLab.com" link and you will be redirected to GitLab.com
+for permission to access your projects. After accepting, you'll be automatically redirected to the importer.
+
+![Importer page](img/gitlab_importer.png)
+
+To import a project, you can simple click "Import". The importer will import your repository and issues.
+Once the importer is done, a new GitLab project will be created with your imported data.
diff --git a/doc/workflow/importing/img/bitbucket_import_grant_access.png b/doc/user/project/import/img/bitbucket_import_grant_access.png
index 429904e621d..429904e621d 100644
--- a/doc/workflow/importing/img/bitbucket_import_grant_access.png
+++ b/doc/user/project/import/img/bitbucket_import_grant_access.png
Binary files differ
diff --git a/doc/workflow/importing/img/bitbucket_import_new_project.png b/doc/user/project/import/img/bitbucket_import_new_project.png
index 8ed528c2f09..8ed528c2f09 100644
--- a/doc/workflow/importing/img/bitbucket_import_new_project.png
+++ b/doc/user/project/import/img/bitbucket_import_new_project.png
Binary files differ
diff --git a/doc/workflow/importing/img/bitbucket_import_select_project.png b/doc/user/project/import/img/bitbucket_import_select_project.png
index 1bca6166ec8..1bca6166ec8 100644
--- a/doc/workflow/importing/img/bitbucket_import_select_project.png
+++ b/doc/user/project/import/img/bitbucket_import_select_project.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png b/doc/user/project/import/img/fogbugz_import_finished.png
index 62c5c86c9b3..62c5c86c9b3 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png
+++ b/doc/user/project/import/img/fogbugz_import_finished.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png b/doc/user/project/import/img/fogbugz_import_login.png
index 96bce70b74d..96bce70b74d 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png
+++ b/doc/user/project/import/img/fogbugz_import_login.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png b/doc/user/project/import/img/fogbugz_import_select_fogbogz.png
index b26c652e382..b26c652e382 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png
+++ b/doc/user/project/import/img/fogbugz_import_select_fogbogz.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png b/doc/user/project/import/img/fogbugz_import_select_project.png
index ccc82f9d4cd..ccc82f9d4cd 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png
+++ b/doc/user/project/import/img/fogbugz_import_select_project.png
Binary files differ
diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png b/doc/user/project/import/img/fogbugz_import_user_map.png
index 28ff55a8d89..28ff55a8d89 100644
--- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png
+++ b/doc/user/project/import/img/fogbugz_import_user_map.png
Binary files differ
diff --git a/doc/workflow/importing/gitlab_importer/importer.png b/doc/user/project/import/img/gitlab_importer.png
index 27d42eb492e..27d42eb492e 100644
--- a/doc/workflow/importing/gitlab_importer/importer.png
+++ b/doc/user/project/import/img/gitlab_importer.png
Binary files differ
diff --git a/doc/workflow/importing/gitlab_importer/new_project_page.png b/doc/user/project/import/img/gitlab_new_project_page.png
index c673724f436..c673724f436 100644
--- a/doc/workflow/importing/gitlab_importer/new_project_page.png
+++ b/doc/user/project/import/img/gitlab_new_project_page.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_gitea_new_import.png b/doc/user/project/import/img/import_projects_from_gitea_new_import.png
index a3f603cbd0a..a3f603cbd0a 100644
--- a/doc/workflow/importing/img/import_projects_from_gitea_new_import.png
+++ b/doc/user/project/import/img/import_projects_from_gitea_new_import.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_github_importer.png b/doc/user/project/import/img/import_projects_from_github_importer.png
index d8effaf6075..d8effaf6075 100644
--- a/doc/workflow/importing/img/import_projects_from_github_importer.png
+++ b/doc/user/project/import/img/import_projects_from_github_importer.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png b/doc/user/project/import/img/import_projects_from_github_select_auth_method.png
index 1ccb38a815e..1ccb38a815e 100644
--- a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png
+++ b/doc/user/project/import/img/import_projects_from_github_select_auth_method.png
Binary files differ
diff --git a/doc/workflow/importing/img/import_projects_from_new_project_page.png b/doc/user/project/import/img/import_projects_from_new_project_page.png
index 97ca30b2087..97ca30b2087 100644
--- a/doc/workflow/importing/img/import_projects_from_new_project_page.png
+++ b/doc/user/project/import/img/import_projects_from_new_project_page.png
Binary files differ
diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md
new file mode 100644
index 00000000000..2a8728ed96e
--- /dev/null
+++ b/doc/user/project/import/index.md
@@ -0,0 +1,21 @@
+# Migrating projects to a GitLab instance
+
+1. [From Bitbucket.org](bitbucket.md)
+1. [From GitHub.com of GitHub Enterprise](github.md)
+1. [From GitLab.com](gitlab_com.md)
+1. [From FogBugz](fogbugz.md)
+1. [From Gitea](gitea.md)
+1. [From SVN](svn.md)
+1. [From ClearCase](clearcase.md)
+
+In addition to the specific migration documentation above, you can import any
+Git repository via HTTP from the New Project page. Be aware that if the
+repository is too large the import can timeout.
+
+## Migrating from self-hosted GitLab to GitLab.com
+
+You can copy your repos by changing the remote and pushing to the new server,
+but issues and merge requests can't be imported.
+
+If you want to retain all metadata like issues and merge requests, you can use
+the [import/export feature](../settings/import_export.md).
diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md
new file mode 100644
index 00000000000..7a3628a39d7
--- /dev/null
+++ b/doc/user/project/import/svn.md
@@ -0,0 +1,183 @@
+# Migrating from SVN to GitLab
+
+Subversion (SVN) is a central version control system (VCS) while
+Git is a distributed version control system. There are some major differences
+between the two, for more information consult your favorite search engine.
+
+## Overview
+
+There are two approaches to SVN to Git migration:
+
+1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
+ - Makes the GitLab repository to mirror the SVN project.
+ - Git and SVN repositories are kept in sync; you can use either one.
+ - Smoothens the migration process and allows to manage migration risks.
+
+1. [Cut over migration](#cut-over-migration-with-svn2git) which:
+ - Translates and imports the existing data and history from SVN to Git.
+ - Is a fire and forget approach, good for smaller teams.
+
+## Smooth migration with a Git/SVN mirror using SubGit
+
+[SubGit](https://subgit.com) is a tool for a smooth, stress-free SVN to Git
+migration. It creates a writable Git mirror of a local or remote Subversion
+repository and that way you can use both Subversion and Git as long as you like.
+It requires access to your GitLab server as it talks with the Git repositories
+directly in a filesystem level.
+
+### SubGit prerequisites
+
+1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can
+ follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html).
+1. Download SubGit from https://subgit.com/download/.
+1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit`
+ command will be available at `/opt/subgit-VERSION/bin/subgit`.
+
+### SubGit configuration
+
+The first step to mirror you SVN repository in GitLab is to create a new empty
+project which will be used as a mirror. For Omnibus installations the path to
+the repository will be located at
+`/var/opt/gitlab/git-data/repositories/USER/REPO.git` by default. For
+installations from source, the default repository directory will be
+`/home/git/repositories/USER/REPO.git`. For convenience, assign this path to a
+variable:
+
+```
+GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git
+```
+
+SubGit will keep this repository in sync with a remote SVN project. For
+convenience, assign your remote SVN project URL to a variable:
+
+```
+SVN_PROJECT_URL=http://svn.company.com/repos/project
+```
+
+Next you need to run SubGit to set up a Git/SVN mirror. Make sure the following
+`subgit` command is ran on behalf of the same user that keeps ownership of
+GitLab Git repositories (by default `git`):
+
+```
+subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH
+```
+
+Adjust authors and branches mappings, if necessary. Open with your favorite
+text editor:
+
+```
+edit $GIT_REPO_PATH/subgit/authors.txt
+edit $GIT_REPO_PATH/subgit/config
+```
+
+For more information regarding the SubGit configuration options, refer to
+[SubGit's documentation](https://subgit.com/documentation.html) website.
+
+### Initial translation
+
+Now that SubGit has configured the Git/SVN repos, run `subgit` to perform the
+initial translation of existing SVN revisions into the Git repository:
+
+```
+subgit install $GIT_REPO_PATH
+```
+
+After the initial translation is completed, the Git repository and the SVN
+project will be kept in sync by `subgit` - new Git commits will be translated to
+SVN revisions and new SVN revisions will be translated to Git commits. Mirror
+works transparently and does not require any special commands.
+
+If you would prefer to perform one-time cut over migration with `subgit`, use
+the `import` command instead of `install`:
+
+```
+subgit import $GIT_REPO_PATH
+```
+
+### SubGit licensing
+
+Running SubGit in a mirror mode requires a
+[registration](https://subgit.com/pricing.html). Registration is free for open
+source, academic and startup projects.
+
+We're currently working on deeper GitLab/SubGit integration. You may track our
+progress at [this issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/990).
+
+### SubGit support
+
+For any questions related to SVN to GitLab migration with SubGit, you can
+contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.com).
+
+## Cut over migration with svn2git
+
+If you are currently using an SVN repository, you can migrate the repository
+to Git and GitLab. We recommend a hard cut over - run the migration command once
+and then have all developers start using the new GitLab repository immediately.
+Otherwise, it's hard to keep changing in sync in both directions. The conversion
+process should be run on a local workstation.
+
+Install `svn2git`. On all systems you can install as a Ruby gem if you already
+have Ruby and Git installed.
+
+```bash
+sudo gem install svn2git
+```
+
+On Debian-based Linux distributions you can install the native packages:
+
+```bash
+sudo apt-get install git-core git-svn ruby
+```
+
+Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors.
+If you choose not to create the authors file then commits will not be attributed
+to the correct GitLab user. Some users may not consider this a big issue while
+others will want to ensure they complete this step. If you choose to map authors
+you will be required to map every author that is present on changes in the SVN
+repository. If you don't, the conversion will fail and you will have to update
+the author file accordingly. The following command will search through the
+repository and output a list of authors.
+
+```bash
+svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq
+```
+
+Use the output from the last command to construct the authors file.
+Create a file called `authors.txt` and add one mapping per line.
+
+```
+janedoe = Jane Doe <janedoe@example.com>
+johndoe = John Doe <johndoe@example.com>
+```
+
+If your SVN repository is in the standard format (trunk, branches, tags,
+not nested) the conversion is simple. For a non-standard repository see
+[svn2git documentation](https://github.com/nirvdrum/svn2git). The following
+command will checkout the repository and do the conversion in the current
+working directory. Be sure to create a new directory for each repository before
+running the `svn2git` command. The conversion process will take some time.
+
+```bash
+svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt
+```
+
+If your SVN repository requires a username and password add the
+`--username <username>` and `--password <password` flags to the above command.
+`svn2git` also supports excluding certain file paths, branches, tags, etc. See
+[svn2git documentation](https://github.com/nirvdrum/svn2git) or run
+`svn2git --help` for full documentation on all of the available options.
+
+Create a new GitLab project, where you will eventually push your converted code.
+Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab
+repository as a Git remote and push all the changes. This will push all commits,
+branches and tags.
+
+```bash
+git remote add origin git@gitlab.com:<group>/<project>.git
+git push --all origin
+git push --tags origin
+```
+
+## Contribute to this guide
+We welcome all contributions that would expand this guide with instructions on
+how to migrate from SVN and other version control systems.
diff --git a/doc/user/project/index.md b/doc/user/project/index.md
index 0dd0faf35e9..41a96246292 100644
--- a/doc/user/project/index.md
+++ b/doc/user/project/index.md
@@ -24,6 +24,7 @@ integrated platform
from messing with history or pushing code without review
- [Protected tags](protected_tags.md): Control over who has
permission to create tags, and prevent accidental update or deletion
+ - [Signing commits](gpg_signed_commits/index.md): use GPG to sign your commits
- [Merge Requests](merge_requests/index.md): Apply your branching
strategy and get reviewed by your team
- [Merge Request Approvals](https://docs.gitlab.com/ee/user/project/merge_requests/merge_request_approvals.html) (**EES/EEP**): Ask for approval before
@@ -90,11 +91,11 @@ from your fork to the upstream project
## Import or export a project
-- Import a project from:
- - [GitHub to GitLab](../../workflow/importing/import_projects_from_github.md)
- - [BitBucket to GitLab](../../workflow/importing/import_projects_from_bitbucket.md)
- - [Gitea to GitLab](../../workflow/importing/import_projects_from_gitea.md)
- - [FogBugz to GitLab](../../workflow/importing/import_projects_from_fogbugz.md)
+- [Import a project](import/index.md) from:
+ - [GitHub to GitLab](import/github.md)
+ - [BitBucket to GitLab](import/bitbucket.md)
+ - [Gitea to GitLab](import/gitea.md)
+ - [FogBugz to GitLab](import/fogbugz.md)
- [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data)
- [Importing and exporting projects between GitLab instances](settings/import_export.md)
diff --git a/doc/user/project/issues/img/group_issues_list_view.png b/doc/user/project/issues/img/group_issues_list_view.png
new file mode 100644
index 00000000000..5d20e8cbc89
--- /dev/null
+++ b/doc/user/project/issues/img/group_issues_list_view.png
Binary files differ
diff --git a/doc/user/project/issues/img/issue_tracker.png b/doc/user/project/issues/img/issue_tracker.png
deleted file mode 100755
index ab25cb64d13..00000000000
--- a/doc/user/project/issues/img/issue_tracker.png
+++ /dev/null
Binary files differ
diff --git a/doc/user/project/issues/img/project_issues_list_view.png b/doc/user/project/issues/img/project_issues_list_view.png
new file mode 100644
index 00000000000..2fcc9e8d9da
--- /dev/null
+++ b/doc/user/project/issues/img/project_issues_list_view.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index 1f78849a92c..20901e01f6e 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -7,7 +7,7 @@ of solving a problem.
It allows you, your team, and your collaborators to share
and discuss proposals before and while implementing them.
-Issues and the GitLab Issue Tracker are available in all
+GitLab Issues and the GitLab Issue Tracker are available in all
[GitLab Products](https://about.gitlab.com/products/) as
part of the [GitLab Workflow](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/).
@@ -48,11 +48,27 @@ for feature proposals and another one for bug reports.
## Issue Tracker
-The issue tracker is the collection of opened and closed issues created in a project.
+The Issue Tracker is the collection of opened and closed issues created in a project.
+It is available for all projects, from the moment the project is created.
-![Issue tracker](img/issue_tracker.png)
+Find the issue tracker by navigating to your **Project's homepage** > **Issues**.
-Find the issue tracker by navigating to your **Project's Dashboard** > **Issues**.
+### Issues per project
+
+When you access your project's issues, GitLab will present them in a list,
+and you can use the tabs available to quickly filter by open and closed issues.
+
+![Project issues list view](img/project_issues_list_view.png)
+
+You can also [search and filter](../../search/index.md#issues-and-merge-requests-per-project) the results more deeply with GitLab's search capacities.
+
+### Issues per group
+
+View all the issues in a group (that is, all the issues across all projects in that
+group) by navigating to **Group > Issues**. This view also has the open and closed
+issue tabs.
+
+![Group Issues list view](img/group_issues_list_view.png)
## GitLab Issues Functionalities
@@ -120,6 +136,12 @@ to find out more about this feature.
With [GitLab Enterprise Edition Starter](https://about.gitlab.com/gitlab-ee/), you can also
create various boards per project with [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.html#multiple-issue-boards).
+### External Issue Tracker
+
+Alternatively to GitLab's built-in Issue Tracker, you can also use an [external
+tracker](../../../integration/external-issue-tracker.md) such as Jira, Redmine,
+or Bugzilla.
+
### Issue's API
Read through the [API documentation](../../../api/issues.md).
diff --git a/doc/user/project/merge_requests/img/group_merge_requests_list_view.png b/doc/user/project/merge_requests/img/group_merge_requests_list_view.png
new file mode 100644
index 00000000000..02a88d0112f
--- /dev/null
+++ b/doc/user/project/merge_requests/img/group_merge_requests_list_view.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
new file mode 100644
index 00000000000..9b8aee47411
--- /dev/null
+++ b/doc/user/project/merge_requests/img/merge_request_diff_file_navigation.png
Binary files differ
diff --git a/doc/user/project/merge_requests/img/project_merge_requests_list_view.png b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
new file mode 100644
index 00000000000..702ec1a2949
--- /dev/null
+++ b/doc/user/project/merge_requests/img/project_merge_requests_list_view.png
Binary files differ
diff --git a/doc/user/project/merge_requests/index.md b/doc/user/project/merge_requests/index.md
index 9bdf2a998d3..26c6277d33a 100644
--- a/doc/user/project/merge_requests/index.md
+++ b/doc/user/project/merge_requests/index.md
@@ -56,6 +56,23 @@ B. Consider you're a web developer writing a webpage for your company's:
1. Once approved, your merge request is [squashed and merged](https://docs.gitlab.com/ee/user/project/merge_requests/squash_and_merge.html), and [deployed to staging with GitLab Pages](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) (Squash and Merge is available in GitLab Enterprise Edition Starter)
1. Your production team [cherry picks](#cherry-pick-changes) the merge commit into production
+## Merge requests per project
+
+View all the merge requests within a project by navigating to **Project > Merge Requests**.
+
+When you access your project's merge requests, GitLab will present them in a list,
+and you can use the tabs available to quickly filter by open and closed. You can also [search and filter the results](../../search/index.md#issues-and-merge-requests-per-project).
+
+![Project merge requests list view](img/project_merge_requests_list_view.png)
+
+## Merge requests per group
+
+View all the merge requests in a group (that is, all the merge requests across all projects in that
+group) by navigating to **Group > Merge Requests**. This view also has the open, merged, and closed
+merge request tabs, from which you can [search and filter the results](../../search/index.md#issues-and-merge-requests-per-group).
+
+![Group Issues list view](img/group_merge_requests_list_view.png)
+
## Authorization for merge requests
There are two main ways to have a merge request flow with GitLab:
@@ -120,6 +137,14 @@ have been marked as a **Work In Progress**.
[Learn more about settings a merge request as "Work In Progress".](work_in_progress_merge_requests.md)
+## Merge request diff file navigation
+
+The diff view has a persistent dropdown for file navigation. As you scroll through
+diffs with a large number of files and/or many changes in those files, you can
+easily jump to any changed file through the dropdown navigation.
+
+![Merge request diff file navigation](img/merge_request_diff_file_navigation.png)
+
## Ignore whitespace changes in Merge Request diff view
If you click the **Hide whitespace changes** button, you can see the diff
@@ -141,7 +166,6 @@ all your changes will be available to preview by anyone with the Review Apps lin
[Read more about Review Apps.](../../../ci/review_apps/index.md)
-
## Tips
Here are some tips that will help you be more efficient with merge requests in
@@ -230,4 +254,4 @@ git checkout origin/merge-requests/1
```
[protected branches]: ../protected_branches.md
-[ee]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition"
+[ee]: https://about.gitlab.com/gitlab-ee/ "GitLab Enterprise Edition" \ No newline at end of file
diff --git a/doc/user/search/index.md b/doc/user/search/index.md
index 79f34fd29ba..f5c7ce49e8e 100644
--- a/doc/user/search/index.md
+++ b/doc/user/search/index.md
@@ -27,7 +27,7 @@ on the search field on the top-right of your screen:
![shortcut to your issues and mrs](img/issues_mrs_shortcut.png)
-## Issues and merge requests per project
+### Issues and merge requests per project
If you want to search for issues present in a specific project, navigate to
a project's **Issues** tab, and click on the field **Search or filter results...**. It will
@@ -40,7 +40,7 @@ The same process is valid for merge requests. Navigate to your project's **Merge
and click **Search or filter results...**. Merge requests can be filtered by author, assignee,
milestone, and label.
-## Issues and merge requests per group
+### Issues and merge requests per group
Similar to **Issues and merge requests per project**, you can also search for issues
within a group. Navigate to a group's **Issues** tab and query search results in
@@ -48,6 +48,10 @@ the same way as you do for projects.
![filter issues in a group](img/group_issues_filter.png)
+The same process is valid for merge requests. Navigate to your project's **Merge Requests** tab.
+The search and filter UI currently uses dropdowns. In a future release, the same
+dynamic UI as above will be carried over here.
+
## Search history
You can view recent searches by clicking on the little arrow-clock icon, which is to the left of the search input. Click the search entry to run that search again. This feature is available for issues and merge requests. Searches are stored locally in your browser.
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png b/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png
deleted file mode 100644
index e525083918b..00000000000
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png b/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
deleted file mode 100644
index f715c46adc3..00000000000
--- a/doc/workflow/gpg_signed_commits/img/profile_settings_gpg_keys_single_key.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png b/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
deleted file mode 100644
index 16ec2d031ae..00000000000
--- a/doc/workflow/gpg_signed_commits/img/project_signed_and_unsigned_commits.png
+++ /dev/null
Binary files differ
diff --git a/doc/workflow/gpg_signed_commits/index.md b/doc/workflow/gpg_signed_commits/index.md
deleted file mode 100644
index 7d5762d2b9d..00000000000
--- a/doc/workflow/gpg_signed_commits/index.md
+++ /dev/null
@@ -1,84 +0,0 @@
-# Signing commits with GPG
-
-## Getting started
-
-- [Git Tools - Signing Your Work](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work)
-- [Git Tools - Signing Your Work: GPG introduction](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work#_gpg_introduction)
-- [Git Tools - Signing Your Work: Signing commits](https://git-scm.com/book/en/v2/Git-Tools-Signing-Your-Work#_signing_commits)
-
-## How GitLab handles GPG
-
-GitLab uses its own keyring to verify the GPG signature. It does not access any
-public key server.
-
-In order to have a commit verified on GitLab the corresponding public key needs
-to be uploaded to GitLab.
-
-For a signature to be verified two prerequisites need to be met:
-
-1. The public key needs to be added to GitLab
-1. One of the emails in the GPG key matches your **primary** email
-
-## Add a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
- ![Settings dropdown](../../gitlab-basics/img/profile_settings.png)
-
-1. Navigate to the **GPG keys** tab.
-
- ![GPG Keys](img/profile_settings_gpg_keys.png)
-
-1. Paste your **public** key in the 'Key' box.
-
- ![Paste GPG public key](img/profile_settings_gpg_keys_paste_pub.png)
-
-1. Finally, click on **Add key** to add it to GitLab. You will be able to see
- its fingerprint, the corresponding email address and creation date.
-
- ![GPG key single page](img/profile_settings_gpg_keys_single_key.png)
-
->**Note:**
-Once you add a key, you cannot edit it, only remove it. In case the paste
-didn't work, you will have to remove the offending key and re-add it.
-
-## Remove a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
-1. Navigate to the **GPG keys** tab.
-
-1. Click on the trash icon besides the GPG key you want to delete.
-
->**Note:**
-Removing a key **does not unverify** already signed commits. Commits that were
-verified by using this key will stay verified. Only unpushed commits will stay
-unverified once you remove this key.
-
-## Revoke a GPG key
-
-1. On the upper right corner, click on your avatar and go to your **Settings**.
-
-1. Navigate to the **GPG keys** tab.
-
-1. Click on **Revoke** besides the GPG key you want to delete.
-
->**Note:**
-Revoking a key **unverifies** already signed commits. Commits that were
-verified by using this key will change to an unverified state. Future commits
-will also stay unverified once you revoke this key. This action should be used
-in case your key has been compromised.
-
-## Verifying commits
-
-1. Within a project navigate to the **Commits** tag. Signed commits will show a
- badge containing either "Verified" or "Unverified", depending on the
- verification status of the GPG signature.
-
- ![Signed and unsigned commits](img/project_signed_and_unsigned_commits.png)
-
-1. By clicking on the GPG badge details of the signature are displayed.
-
- ![Signed commit with verified signature](img/project_signed_commit_verified_signature.png)
-
- ![Signed commit with verified signature](img/project_signed_commit_unverified_signature.png)
diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md
index 2d91bee0e94..f753708ad89 100644
--- a/doc/workflow/importing/README.md
+++ b/doc/workflow/importing/README.md
@@ -1,17 +1 @@
-# Migrating projects to a GitLab instance
-
-1. [Bitbucket](import_projects_from_bitbucket.md)
-1. [GitHub](import_projects_from_github.md)
-1. [GitLab.com](import_projects_from_gitlab_com.md)
-1. [FogBugz](import_projects_from_fogbugz.md)
-1. [Gitea](import_projects_from_gitea.md)
-1. [SVN](migrating_from_svn.md)
-
-In addition to the specific migration documentation above, you can import any
-Git repository via HTTP from the New Project page. Be aware that if the
-repository is too large the import can timeout.
-
-### Migrating from self-hosted GitLab to GitLab.com
-
-You can copy your repos by changing the remote and pushing to the new server;
-but issues and merge requests can't be imported.
+This document was moved to a [new location](../../user/project/import/index.md).
diff --git a/doc/workflow/importing/import_projects_from_bitbucket.md b/doc/workflow/importing/import_projects_from_bitbucket.md
index f3c636ed1d5..248c3990372 100644
--- a/doc/workflow/importing/import_projects_from_bitbucket.md
+++ b/doc/workflow/importing/import_projects_from_bitbucket.md
@@ -1,62 +1 @@
-# Import your project from Bitbucket to GitLab
-
-Import your projects from Bitbucket to GitLab with minimal effort.
-
-## Overview
-
->**Note:**
-The [Bitbucket integration][bb-import] must be first enabled in order to be
-able to import your projects from Bitbucket. Ask your GitLab administrator
-to enable this if not already.
-
-- At its current state, the Bitbucket importer can import:
- - the repository description (GitLab 7.7+)
- - the Git repository data (GitLab 7.7+)
- - the issues (GitLab 7.7+)
- - the issue comments (GitLab 8.15+)
- - the pull requests (GitLab 8.4+)
- - the pull request comments (GitLab 8.15+)
- - the milestones (GitLab 8.15+)
- - the wiki (GitLab 8.15+)
-- References to pull requests and issues are preserved (GitLab 8.7+)
-- Repository public access is retained. If a repository is private in Bitbucket
- it will be created as private in GitLab as well.
-
-
-## How it works
-
-When issues/pull requests are being imported, the Bitbucket importer tries to find
-the Bitbucket author/assignee in GitLab's database using the Bitbucket ID. For this
-to work, the Bitbucket author/assignee should have signed in beforehand in GitLab
-and **associated their Bitbucket account**. If the user is not
-found in GitLab's database, the project creator (most of the times the current
-user that started the import process) is set as the author, but a reference on
-the issue about the original Bitbucket author is kept.
-
-The importer will create any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository will be imported under the user's
-namespace that started the import process.
-
-## Importing your Bitbucket repositories
-
-1. Sign in to GitLab and go to your dashboard.
-1. Click on **New project**.
-
- ![New project in GitLab](img/bitbucket_import_new_project.png)
-
-1. Click on the "Bitbucket" button
-
- ![Bitbucket](img/import_projects_from_new_project_page.png)
-
-1. Grant GitLab access to your Bitbucket account
-
- ![Grant access](img/bitbucket_import_grant_access.png)
-
-1. Click on the projects that you'd like to import or **Import all projects**.
- You can also select the namespace under which each project will be
- imported.
-
- ![Import projects](img/bitbucket_import_select_project.png)
-
-[bb-import]: ../../integration/bitbucket.md
-[social sign-in]: ../../user/profile/account/social_sign_in.md
+This document was moved to a [new location](../../user/project/import/bitbucket.md).
diff --git a/doc/workflow/importing/import_projects_from_fogbugz.md b/doc/workflow/importing/import_projects_from_fogbugz.md
index 71af0f9ea44..050746e2b4d 100644
--- a/doc/workflow/importing/import_projects_from_fogbugz.md
+++ b/doc/workflow/importing/import_projects_from_fogbugz.md
@@ -1,29 +1 @@
-# Import your project from FogBugz to GitLab
-
-It only takes a few simple steps to import your project from FogBugz.
-The importer will import all of your cases and comments with original case
-numbers and timestamps. You will also have the opportunity to map FogBugz
-users to GitLab users.
-
-* From your GitLab dashboard click 'New project'
-
-* Click on the 'FogBugz' button
-
-![FogBugz](fogbugz_importer/fogbugz_import_select_fogbogz.png)
-
-* Enter your FogBugz URL, email address, and password.
-
-![Login](fogbugz_importer/fogbugz_import_login.png)
-
-* Create mapping from FogBugz users to GitLab users.
-
-![User Map](fogbugz_importer/fogbugz_import_user_map.png)
-
-* Select the projects you wish to import by clicking the Import buttons
-
-![Import Project](fogbugz_importer/fogbugz_import_select_project.png)
-
-* Once the import has finished click the link to take you to the project
-dashboard. Follow the directions to push your existing repository.
-
-![Finished](fogbugz_importer/fogbugz_import_finished.png)
+This document was moved to a [new location](../../user/project/import/fogbugz.md).
diff --git a/doc/workflow/importing/import_projects_from_gitea.md b/doc/workflow/importing/import_projects_from_gitea.md
index f5746a0fb31..cb90c490b0f 100644
--- a/doc/workflow/importing/import_projects_from_gitea.md
+++ b/doc/workflow/importing/import_projects_from_gitea.md
@@ -1,77 +1 @@
-# Import your project from Gitea to GitLab
-
-Import your projects from Gitea to GitLab with minimal effort.
-
-## Overview
-
->**Note:**
-This requires Gitea `v1.0.0` or newer.
-
-- At its current state, Gitea importer can import:
- - the repository description (GitLab 8.15+)
- - the Git repository data (GitLab 8.15+)
- - the issues (GitLab 8.15+)
- - the pull requests (GitLab 8.15+)
- - the milestones (GitLab 8.15+)
- - the labels (GitLab 8.15+)
-- Repository public access is retained. If a repository is private in Gitea
- it will be created as private in GitLab as well.
-
-## How it works
-
-Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped
-to users in your GitLab's instance. This means that the project creator (most of
-the times the current user that started the import process) is set as the author,
-but a reference on the issue about the original Gitea author is kept.
-
-The importer will create any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository will be imported under the user's
-namespace that started the import process.
-
-## Importing your Gitea repositories
-
-The importer page is visible when you create a new project.
-
-![New project page on GitLab](img/import_projects_from_new_project_page.png)
-
-Click on the **Gitea** link and the import authorization process will start.
-
-![New Gitea project import](img/import_projects_from_gitea_new_import.png)
-
-### Authorize access to your repositories using a personal access token
-
-With this method, you will perform a one-off authorization with Gitea to grant
-GitLab access your repositories:
-
-1. Go to <https://you-gitea-instance/user/settings/applications> (replace
- `you-gitea-instance` with the host of your Gitea instance).
-1. Click **Generate New Token**.
-1. Enter a token description.
-1. Click **Generate Token**.
-1. Copy the token hash.
-1. Go back to GitLab and provide the token to the Gitea importer.
-1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads
- your repositories' information. Once done, you'll be taken to the importer
- page to select the repositories to import.
-
-### Select which repositories to import
-
-After you've authorized access to your Gitea repositories, you will be
-redirected to the Gitea importer page.
-
-From there, you can see the import statuses of your Gitea repositories.
-
-- Those that are being imported will show a _started_ status,
-- those already successfully imported will be green with a _done_ status,
-- whereas those that are not yet imported will have an **Import** button on the
- right side of the table.
-
-If you want, you can import all your Gitea projects in one go by hitting
-**Import all projects** in the upper left corner.
-
-![Gitea importer page](img/import_projects_from_github_importer.png)
-
----
-
-You can also choose a different name for the project and a different namespace,
-if you have the privileges to do so.
+This document was moved to a [new location](../../user/project/import/gitea.md).
diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md
index 8ed1d98d05b..13639feaa04 100644
--- a/doc/workflow/importing/import_projects_from_github.md
+++ b/doc/workflow/importing/import_projects_from_github.md
@@ -1,122 +1 @@
-# Import your project from GitHub to GitLab
-
-Import your projects from GitHub to GitLab with minimal effort.
-
-## Overview
-
->**Note:**
-If you are an administrator you can enable the [GitHub integration][gh-import]
-in your GitLab instance sitewide. This configuration is optional, users will
-still be able to import their GitHub repositories with a
-[personal access token][gh-token].
-
->**Note:**
-Administrators of a GitLab instance (Community or Enterprise Edition) can also
-use the [GitHub rake task][gh-rake] to import projects from GitHub without the
-constrains of a Sidekiq worker.
-
-- At its current state, GitHub importer can import:
- - the repository description (GitLab 7.7+)
- - the Git repository data (GitLab 7.7+)
- - the issues (GitLab 7.7+)
- - the pull requests (GitLab 8.4+)
- - the wiki pages (GitLab 8.4+)
- - the milestones (GitLab 8.7+)
- - the labels (GitLab 8.7+)
- - the release note descriptions (GitLab 8.12+)
-- References to pull requests and issues are preserved (GitLab 8.7+)
-- Repository public access is retained. If a repository is private in GitHub
- it will be created as private in GitLab as well.
-
-## How it works
-
-When issues/pull requests are being imported, the GitHub importer tries to find
-the GitHub author/assignee in GitLab's database using the GitHub ID. For this
-to work, the GitHub author/assignee should have signed in beforehand in GitLab
-and **associated their GitHub account**. If the user is not
-found in GitLab's database, the project creator (most of the times the current
-user that started the import process) is set as the author, but a reference on
-the issue about the original GitHub author is kept.
-
-The importer will create any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository will be imported under the user's
-namespace that started the import process.
-
-## Importing your GitHub repositories
-
-The importer page is visible when you create a new project.
-
-![New project page on GitLab](img/import_projects_from_new_project_page.png)
-
-Click on the **GitHub** link and the import authorization process will start.
-There are two ways to authorize access to your GitHub repositories:
-
-1. [Using the GitHub integration][gh-integration] (if it's enabled by your
- GitLab administrator). This is the preferred way as it's possible to
- preserve the GitHub authors/assignees. Read more in the [How it works](#how-it-works)
- section.
-1. [Using a personal access token][gh-token] provided by GitHub.
-
-![Select authentication method](img/import_projects_from_github_select_auth_method.png)
-
-### Authorize access to your repositories using the GitHub integration
-
-If the [GitHub integration][gh-import] is enabled by your GitLab administrator,
-you can use it instead of the personal access token.
-
-1. First you may want to connect your GitHub account to GitLab in order for
- the username mapping to be correct.
-1. Once you connect GitHub, click the **List your GitHub repositories** button
- and you will be redirected to GitHub for permission to access your projects.
-1. After accepting, you'll be automatically redirected to the importer.
-
-You can now go on and [select which repositories to import](#select-which-repositories-to-import).
-
-### Authorize access to your repositories using a personal access token
-
->**Note:**
-For a proper author/assignee mapping for issues and pull requests, the
-[GitHub integration][gh-integration] should be used instead of the
-[personal access token][gh-token]. If the GitHub integration is enabled by your
-GitLab administrator, it should be the preferred method to import your repositories.
-Read more in the [How it works](#how-it-works) section.
-
-If you are not using the GitHub integration, you can still perform a one-off
-authorization with GitHub to grant GitLab access your repositories:
-
-1. Go to <https://github.com/settings/tokens/new>.
-1. Enter a token description.
-1. Check the `repo` scope.
-1. Click **Generate token**.
-1. Copy the token hash.
-1. Go back to GitLab and provide the token to the GitHub importer.
-1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads
- your repositories' information. Once done, you'll be taken to the importer
- page to select the repositories to import.
-
-### Select which repositories to import
-
-After you've authorized access to your GitHub repositories, you will be
-redirected to the GitHub importer page.
-
-From there, you can see the import statuses of your GitHub repositories.
-
-- Those that are being imported will show a _started_ status,
-- those already successfully imported will be green with a _done_ status,
-- whereas those that are not yet imported will have an **Import** button on the
- right side of the table.
-
-If you want, you can import all your GitHub projects in one go by hitting
-**Import all projects** in the upper left corner.
-
-![GitHub importer page](img/import_projects_from_github_importer.png)
-
----
-
-You can also choose a different name for the project and a different namespace,
-if you have the privileges to do so.
-
-[gh-import]: ../../integration/github.md "GitHub integration"
-[gh-rake]: ../../administration/raketasks/github_import.md "GitHub rake task"
-[gh-integration]: #authorize-access-to-your-repositories-using-the-github-integration
-[gh-token]: #authorize-access-to-your-repositories-using-a-personal-access-token
+This document was moved to a [new location](../../user/project/import/github.md).
diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md
index b27125a44de..df4c180919a 100644
--- a/doc/workflow/importing/import_projects_from_gitlab_com.md
+++ b/doc/workflow/importing/import_projects_from_gitlab_com.md
@@ -1,21 +1 @@
-# Project importing from GitLab.com to your private GitLab instance
-
-You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if
-GitLab support is enabled on your GitLab instance.
-You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html)
-To get to the importer page you need to go to "New project" page.
-
->**Note:**
-If you are interested in importing Wiki and Merge Request data to your new instance, you'll need to follow the instructions for [project export](../../user/project/settings/import_export.md)
-
-![New project page](gitlab_importer/new_project_page.png)
-
-Click on the "Import projects from GitLab.com" link and you will be redirected to GitLab.com
-for permission to access your projects. After accepting, you'll be automatically redirected to the importer.
-
-
-![Importer page](gitlab_importer/importer.png)
-
-
-To import a project, you can simple click "Import". The importer will import your repository and issues.
-Once the importer is done, a new GitLab project will be created with your imported data. \ No newline at end of file
+This document was moved to a [new location](../../user/project/import/gitlab_com.md).
diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md
index 7a3628a39d7..81df3fbcdbb 100644
--- a/doc/workflow/importing/migrating_from_svn.md
+++ b/doc/workflow/importing/migrating_from_svn.md
@@ -1,183 +1 @@
-# Migrating from SVN to GitLab
-
-Subversion (SVN) is a central version control system (VCS) while
-Git is a distributed version control system. There are some major differences
-between the two, for more information consult your favorite search engine.
-
-## Overview
-
-There are two approaches to SVN to Git migration:
-
-1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which:
- - Makes the GitLab repository to mirror the SVN project.
- - Git and SVN repositories are kept in sync; you can use either one.
- - Smoothens the migration process and allows to manage migration risks.
-
-1. [Cut over migration](#cut-over-migration-with-svn2git) which:
- - Translates and imports the existing data and history from SVN to Git.
- - Is a fire and forget approach, good for smaller teams.
-
-## Smooth migration with a Git/SVN mirror using SubGit
-
-[SubGit](https://subgit.com) is a tool for a smooth, stress-free SVN to Git
-migration. It creates a writable Git mirror of a local or remote Subversion
-repository and that way you can use both Subversion and Git as long as you like.
-It requires access to your GitLab server as it talks with the Git repositories
-directly in a filesystem level.
-
-### SubGit prerequisites
-
-1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can
- follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html).
-1. Download SubGit from https://subgit.com/download/.
-1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit`
- command will be available at `/opt/subgit-VERSION/bin/subgit`.
-
-### SubGit configuration
-
-The first step to mirror you SVN repository in GitLab is to create a new empty
-project which will be used as a mirror. For Omnibus installations the path to
-the repository will be located at
-`/var/opt/gitlab/git-data/repositories/USER/REPO.git` by default. For
-installations from source, the default repository directory will be
-`/home/git/repositories/USER/REPO.git`. For convenience, assign this path to a
-variable:
-
-```
-GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git
-```
-
-SubGit will keep this repository in sync with a remote SVN project. For
-convenience, assign your remote SVN project URL to a variable:
-
-```
-SVN_PROJECT_URL=http://svn.company.com/repos/project
-```
-
-Next you need to run SubGit to set up a Git/SVN mirror. Make sure the following
-`subgit` command is ran on behalf of the same user that keeps ownership of
-GitLab Git repositories (by default `git`):
-
-```
-subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH
-```
-
-Adjust authors and branches mappings, if necessary. Open with your favorite
-text editor:
-
-```
-edit $GIT_REPO_PATH/subgit/authors.txt
-edit $GIT_REPO_PATH/subgit/config
-```
-
-For more information regarding the SubGit configuration options, refer to
-[SubGit's documentation](https://subgit.com/documentation.html) website.
-
-### Initial translation
-
-Now that SubGit has configured the Git/SVN repos, run `subgit` to perform the
-initial translation of existing SVN revisions into the Git repository:
-
-```
-subgit install $GIT_REPO_PATH
-```
-
-After the initial translation is completed, the Git repository and the SVN
-project will be kept in sync by `subgit` - new Git commits will be translated to
-SVN revisions and new SVN revisions will be translated to Git commits. Mirror
-works transparently and does not require any special commands.
-
-If you would prefer to perform one-time cut over migration with `subgit`, use
-the `import` command instead of `install`:
-
-```
-subgit import $GIT_REPO_PATH
-```
-
-### SubGit licensing
-
-Running SubGit in a mirror mode requires a
-[registration](https://subgit.com/pricing.html). Registration is free for open
-source, academic and startup projects.
-
-We're currently working on deeper GitLab/SubGit integration. You may track our
-progress at [this issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/990).
-
-### SubGit support
-
-For any questions related to SVN to GitLab migration with SubGit, you can
-contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.com).
-
-## Cut over migration with svn2git
-
-If you are currently using an SVN repository, you can migrate the repository
-to Git and GitLab. We recommend a hard cut over - run the migration command once
-and then have all developers start using the new GitLab repository immediately.
-Otherwise, it's hard to keep changing in sync in both directions. The conversion
-process should be run on a local workstation.
-
-Install `svn2git`. On all systems you can install as a Ruby gem if you already
-have Ruby and Git installed.
-
-```bash
-sudo gem install svn2git
-```
-
-On Debian-based Linux distributions you can install the native packages:
-
-```bash
-sudo apt-get install git-core git-svn ruby
-```
-
-Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors.
-If you choose not to create the authors file then commits will not be attributed
-to the correct GitLab user. Some users may not consider this a big issue while
-others will want to ensure they complete this step. If you choose to map authors
-you will be required to map every author that is present on changes in the SVN
-repository. If you don't, the conversion will fail and you will have to update
-the author file accordingly. The following command will search through the
-repository and output a list of authors.
-
-```bash
-svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq
-```
-
-Use the output from the last command to construct the authors file.
-Create a file called `authors.txt` and add one mapping per line.
-
-```
-janedoe = Jane Doe <janedoe@example.com>
-johndoe = John Doe <johndoe@example.com>
-```
-
-If your SVN repository is in the standard format (trunk, branches, tags,
-not nested) the conversion is simple. For a non-standard repository see
-[svn2git documentation](https://github.com/nirvdrum/svn2git). The following
-command will checkout the repository and do the conversion in the current
-working directory. Be sure to create a new directory for each repository before
-running the `svn2git` command. The conversion process will take some time.
-
-```bash
-svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt
-```
-
-If your SVN repository requires a username and password add the
-`--username <username>` and `--password <password` flags to the above command.
-`svn2git` also supports excluding certain file paths, branches, tags, etc. See
-[svn2git documentation](https://github.com/nirvdrum/svn2git) or run
-`svn2git --help` for full documentation on all of the available options.
-
-Create a new GitLab project, where you will eventually push your converted code.
-Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab
-repository as a Git remote and push all the changes. This will push all commits,
-branches and tags.
-
-```bash
-git remote add origin git@gitlab.com:<group>/<project>.git
-git push --all origin
-git push --tags origin
-```
-
-## Contribute to this guide
-We welcome all contributions that would expand this guide with instructions on
-how to migrate from SVN and other version control systems.
+This document was moved to a [new location](../../user/project/import/svn.md).
diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb
new file mode 100644
index 00000000000..b67575a3ac2
--- /dev/null
+++ b/lib/after_commit_queue.rb
@@ -0,0 +1,30 @@
+module AfterCommitQueue
+ extend ActiveSupport::Concern
+
+ included do
+ after_commit :_run_after_commit_queue
+ after_rollback :_clear_after_commit_queue
+ end
+
+ def run_after_commit(method = nil, &block)
+ _after_commit_queue << proc { self.send(method) } if method
+ _after_commit_queue << block if block
+ true
+ end
+
+ protected
+
+ def _run_after_commit_queue
+ while action = _after_commit_queue.pop
+ self.instance_eval(&action)
+ end
+ end
+
+ def _after_commit_queue
+ @after_commit_queue ||= []
+ end
+
+ def _clear_after_commit_queue
+ _after_commit_queue.clear
+ end
+end
diff --git a/lib/api/helpers/pagination.rb b/lib/api/helpers/pagination.rb
index 0764b58fb4c..95108292aac 100644
--- a/lib/api/helpers/pagination.rb
+++ b/lib/api/helpers/pagination.rb
@@ -11,7 +11,7 @@ module API
def add_pagination_headers(paginated_data)
header 'X-Total', paginated_data.total_count.to_s
- header 'X-Total-Pages', paginated_data.total_pages.to_s
+ header 'X-Total-Pages', total_pages(paginated_data).to_s
header 'X-Per-Page', paginated_data.limit_value.to_s
header 'X-Page', paginated_data.current_page.to_s
header 'X-Next-Page', paginated_data.next_page.to_s
@@ -26,20 +26,25 @@ module API
links = []
- request_params[:page] = paginated_data.current_page - 1
- links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") unless paginated_data.first_page?
+ request_params[:page] = paginated_data.prev_page
+ links << %(<#{request_url}?#{request_params.to_query}>; rel="prev") if request_params[:page]
- request_params[:page] = paginated_data.current_page + 1
- links << %(<#{request_url}?#{request_params.to_query}>; rel="next") unless paginated_data.last_page?
+ request_params[:page] = paginated_data.next_page
+ links << %(<#{request_url}?#{request_params.to_query}>; rel="next") if request_params[:page]
request_params[:page] = 1
links << %(<#{request_url}?#{request_params.to_query}>; rel="first")
- request_params[:page] = paginated_data.total_pages
+ request_params[:page] = total_pages(paginated_data)
links << %(<#{request_url}?#{request_params.to_query}>; rel="last")
links.join(', ')
end
+
+ def total_pages(paginated_data)
+ # Ensure there is in total at least 1 page
+ [paginated_data.total_pages, 1].max
+ end
end
end
end
diff --git a/lib/backup/repository.rb b/lib/backup/repository.rb
index 88821ae56e0..4e92be85110 100644
--- a/lib/backup/repository.rb
+++ b/lib/backup/repository.rb
@@ -75,7 +75,7 @@ module Backup
path_to_project_repo = path_to_repo(project)
path_to_project_bundle = path_to_bundle(project)
- project.ensure_storage_path_exist
+ project.ensure_storage_path_exists
cmd = if File.exist?(path_to_project_bundle)
%W(#{Gitlab.config.git.bin_path} clone --bare #{path_to_project_bundle} #{path_to_project_repo})
diff --git a/lib/ci/api/api.rb b/lib/ci/api/api.rb
deleted file mode 100644
index 24bb3649a76..00000000000
--- a/lib/ci/api/api.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Ci
- module API
- class API < Grape::API
- include ::API::APIGuard
- version 'v1', using: :path
-
- rescue_from ActiveRecord::RecordNotFound do
- rack_response({ 'message' => '404 Not found' }.to_json, 404)
- end
-
- # Retain 405 error rather than a 500 error for Grape 0.15.0+.
- # https://github.com/ruby-grape/grape/blob/a3a28f5b5dfbb2797442e006dbffd750b27f2a76/UPGRADING.md#changes-to-method-not-allowed-routes
- rescue_from Grape::Exceptions::MethodNotAllowed do |e|
- error! e.message, e.status, e.headers
- end
-
- rescue_from Grape::Exceptions::Base do |e|
- error! e.message, e.status, e.headers
- end
-
- rescue_from :all do |exception|
- handle_api_exception(exception)
- end
-
- content_type :txt, 'text/plain'
- content_type :json, 'application/json'
- format :json
-
- helpers ::SentryHelper
- helpers ::Ci::API::Helpers
- helpers ::API::Helpers
- helpers Gitlab::CurrentSettings
-
- mount ::Ci::API::Builds
- mount ::Ci::API::Runners
- mount ::Ci::API::Triggers
- end
- end
-end
diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb
deleted file mode 100644
index 79058c02ce5..00000000000
--- a/lib/ci/api/builds.rb
+++ /dev/null
@@ -1,219 +0,0 @@
-module Ci
- module API
- # Builds API
- class Builds < Grape::API
- resource :builds do
- # Runs oldest pending build by runner - Runners only
- #
- # Parameters:
- # token (required) - The uniq token of runner
- #
- # Example Request:
- # POST /builds/register
- post "register" do
- authenticate_runner!
- required_attributes! [:token]
- not_found! unless current_runner.active?
- update_runner_info
-
- if current_runner.is_runner_queue_value_latest?(params[:last_update])
- header 'X-GitLab-Last-Update', params[:last_update]
- Gitlab::Metrics.add_event(:build_not_found_cached)
- return build_not_found!
- end
-
- new_update = current_runner.ensure_runner_queue_value
-
- result = Ci::RegisterJobService.new(current_runner).execute
-
- if result.valid?
- if result.build
- Gitlab::Metrics.add_event(:build_found,
- project: result.build.project.full_path)
-
- present result.build, with: Entities::BuildDetails
- else
- Gitlab::Metrics.add_event(:build_not_found)
-
- header 'X-GitLab-Last-Update', new_update
-
- build_not_found!
- end
- else
- # We received build that is invalid due to concurrency conflict
- Gitlab::Metrics.add_event(:build_invalid)
- conflict!
- end
- end
-
- # Update an existing build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a project
- # state (optional) - The state of a build
- # trace (optional) - The trace of a build
- # Example Request:
- # PUT /builds/:id
- put ":id" do
- authenticate_runner!
- build = Ci::Build.where(runner_id: current_runner.id).running.find(params[:id])
- validate_build!(build)
-
- update_runner_info
-
- build.trace.set(params[:trace]) if params[:trace]
-
- Gitlab::Metrics.add_event(:update_build,
- project: build.project.full_path)
-
- case params[:state].to_s
- when 'success'
- build.success
- when 'failed'
- build.drop
- end
- end
-
- # Send incremental log update - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # Body:
- # content of logs to append
- # Headers:
- # Content-Range (required) - range of content that was sent
- # BUILD-TOKEN (required) - The build authorization token
- # Example Request:
- # PATCH /builds/:id/trace.txt
- patch ":id/trace.txt" do
- build = authenticate_build!
-
- error!('400 Missing header Content-Range', 400) unless request.headers.key?('Content-Range')
- content_range = request.headers['Content-Range']
- content_range = content_range.split('-')
-
- stream_size = build.trace.append(request.body.read, content_range[0].to_i)
- if stream_size < 0
- return error!('416 Range Not Satisfiable', 416, { 'Range' => "0-#{-stream_size}" })
- end
-
- status 202
- header 'Build-Status', build.status
- header 'Range', "0-#{stream_size}"
- end
-
- # Authorize artifacts uploading for build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # filesize (optional) - the size of uploaded file
- # Example Request:
- # POST /builds/:id/artifacts/authorize
- post ":id/artifacts/authorize" do
- require_gitlab_workhorse!
- Gitlab::Workhorse.verify_api_request!(headers)
- not_allowed! unless Gitlab.config.artifacts.enabled
- build = authenticate_build!
- forbidden!('build is not running') unless build.running?
-
- if params[:filesize]
- file_size = params[:filesize].to_i
- file_to_large! unless file_size < max_artifacts_size
- end
-
- status 200
- content_type Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE
- Gitlab::Workhorse.artifact_upload_ok
- end
-
- # Upload artifacts to build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # file (required) - Artifacts file
- # expire_in (optional) - Specify when artifacts should expire (ex. 7d)
- # Parameters (accelerated by GitLab Workhorse):
- # file.path - path to locally stored body (generated by Workhorse)
- # file.name - real filename as send in Content-Disposition
- # file.type - real content type as send in Content-Type
- # metadata.path - path to locally stored body (generated by Workhorse)
- # metadata.name - filename (generated by Workhorse)
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Body:
- # The file content
- #
- # Example Request:
- # POST /builds/:id/artifacts
- post ":id/artifacts" do
- require_gitlab_workhorse!
- not_allowed! unless Gitlab.config.artifacts.enabled
- build = authenticate_build!
- forbidden!('Build is not running!') unless build.running?
-
- artifacts_upload_path = ArtifactUploader.artifacts_upload_path
- artifacts = uploaded_file(:file, artifacts_upload_path)
- metadata = uploaded_file(:metadata, artifacts_upload_path)
-
- bad_request!('Missing artifacts file!') unless artifacts
- file_to_large! unless artifacts.size < max_artifacts_size
-
- build.artifacts_file = artifacts
- build.artifacts_metadata = metadata
- build.artifacts_expire_in =
- params['expire_in'] ||
- Gitlab::CurrentSettings.current_application_settings
- .default_artifacts_expire_in
-
- if build.save
- present(build, with: Entities::BuildDetails)
- else
- render_validation_error!(build)
- end
- end
-
- # Download the artifacts file from build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Example Request:
- # GET /builds/:id/artifacts
- get ":id/artifacts" do
- build = authenticate_build!
- artifacts_file = build.artifacts_file
-
- unless artifacts_file.exists?
- not_found!
- end
-
- unless artifacts_file.file_storage?
- return redirect_to build.artifacts_file.url
- end
-
- present_file!(artifacts_file.path, artifacts_file.filename)
- end
-
- # Remove the artifacts file from build - Runners only
- #
- # Parameters:
- # id (required) - The ID of a build
- # token (required) - The build authorization token
- # Headers:
- # BUILD-TOKEN (required) - The build authorization token, the same as token
- # Example Request:
- # DELETE /builds/:id/artifacts
- delete ":id/artifacts" do
- build = authenticate_build!
-
- status(200)
- build.erase_artifacts!
- end
- end
- end
- end
-end
diff --git a/lib/ci/api/entities.rb b/lib/ci/api/entities.rb
deleted file mode 100644
index 31f66dd5a58..00000000000
--- a/lib/ci/api/entities.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-module Ci
- module API
- module Entities
- class Commit < Grape::Entity
- expose :id, :sha, :project_id, :created_at
- expose :status, :finished_at, :duration
- expose :git_commit_message, :git_author_name, :git_author_email
- end
-
- class CommitWithBuilds < Commit
- expose :builds
- end
-
- class ArtifactFile < Grape::Entity
- expose :filename, :size
- end
-
- class BuildOptions < Grape::Entity
- expose :image
- expose :services
- expose :artifacts
- expose :cache
- expose :dependencies
- expose :after_script
- end
-
- class Build < Grape::Entity
- expose :id, :ref, :tag, :sha, :status
- expose :name, :token, :stage
- expose :project_id
- expose :project_name
- expose :artifacts_file, using: ArtifactFile, if: ->(build, _) { build.artifacts? }
- end
-
- class BuildCredentials < Grape::Entity
- expose :type, :url, :username, :password
- end
-
- class BuildDetails < Build
- expose :commands
- expose :repo_url
- expose :before_sha
- expose :allow_git_fetch
- expose :token
- expose :artifacts_expire_at, if: ->(build, _) { build.artifacts? }
-
- expose :options do |model|
- # This part ensures that output of old API is still the same after adding support
- # for extended docker configuration options, used by new API
- #
- # I'm leaving this here, not in the model, because it should be removed at the same time
- # when old API will be removed (planned for August 2017).
- model.options.dup.tap do |options|
- options[:image] = options[:image][:name] if options[:image].is_a?(Hash)
- options[:services]&.map! do |service|
- if service.is_a?(Hash)
- service[:name]
- else
- service
- end
- end
- end
- end
-
- expose :timeout do |model|
- model.timeout
- end
-
- expose :variables
- expose :depends_on_builds, using: Build
-
- expose :credentials, using: BuildCredentials
- end
-
- class Runner < Grape::Entity
- expose :id, :token
- end
-
- class RunnerProject < Grape::Entity
- expose :id, :project_id, :runner_id
- end
-
- class WebHook < Grape::Entity
- expose :id, :project_id, :url
- end
-
- class TriggerRequest < Grape::Entity
- expose :id, :variables
- expose :pipeline, using: Commit, as: :commit
- end
- end
- end
-end
diff --git a/lib/ci/api/helpers.rb b/lib/ci/api/helpers.rb
deleted file mode 100644
index a40b6ab6c9f..00000000000
--- a/lib/ci/api/helpers.rb
+++ /dev/null
@@ -1,89 +0,0 @@
-module Ci
- module API
- module Helpers
- BUILD_TOKEN_HEADER = "HTTP_BUILD_TOKEN".freeze
- BUILD_TOKEN_PARAM = :token
- UPDATE_RUNNER_EVERY = 10 * 60
-
- def authenticate_runners!
- forbidden! unless runner_registration_token_valid?
- end
-
- def authenticate_runner!
- forbidden! unless current_runner
- end
-
- def authenticate_build!
- build = Ci::Build.find_by_id(params[:id])
-
- validate_build!(build) do
- forbidden! unless build_token_valid?(build)
- end
-
- build
- end
-
- def validate_build!(build)
- not_found! unless build
-
- yield if block_given?
-
- project = build.project
- forbidden!('Project has been deleted!') if project.nil? || project.pending_delete?
- forbidden!('Build has been erased!') if build.erased?
- end
-
- def runner_registration_token_valid?
- ActiveSupport::SecurityUtils.variable_size_secure_compare(
- params[:token],
- current_application_settings.runners_registration_token)
- end
-
- def build_token_valid?(build)
- token = (params[BUILD_TOKEN_PARAM] || env[BUILD_TOKEN_HEADER]).to_s
-
- # We require to also check `runners_token` to maintain compatibility with old version of runners
- token && (build.valid_token?(token) || build.project.valid_runners_token?(token))
- end
-
- def update_runner_info
- return unless update_runner?
-
- current_runner.contacted_at = Time.now
- current_runner.assign_attributes(get_runner_version_from_params)
- current_runner.save if current_runner.changed?
- end
-
- def update_runner?
- # Use a random threshold to prevent beating DB updates.
- # It generates a distribution between [40m, 80m].
- #
- contacted_at_max_age = UPDATE_RUNNER_EVERY + Random.rand(UPDATE_RUNNER_EVERY)
-
- current_runner.contacted_at.nil? ||
- (Time.now - current_runner.contacted_at) >= contacted_at_max_age
- end
-
- def build_not_found!
- if headers['User-Agent'].to_s =~ /gitlab-ci-multi-runner \d+\.\d+\.\d+(~beta\.\d+\.g[0-9a-f]+)? /
- no_content!
- else
- not_found!
- end
- end
-
- def current_runner
- @runner ||= Runner.find_by_token(params[:token].to_s)
- end
-
- def get_runner_version_from_params
- return unless params["info"].present?
- attributes_for_keys(%w(name version revision platform architecture), params["info"])
- end
-
- def max_artifacts_size
- current_application_settings.max_artifacts_size.megabytes.to_i
- end
- end
- end
-end
diff --git a/lib/ci/api/runners.rb b/lib/ci/api/runners.rb
deleted file mode 100644
index 45aa2adccf5..00000000000
--- a/lib/ci/api/runners.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-module Ci
- module API
- class Runners < Grape::API
- resource :runners do
- desc 'Delete a runner'
- params do
- requires :token, type: String, desc: 'The unique token of the runner'
- end
- delete "delete" do
- authenticate_runner!
-
- status(200)
- Ci::Runner.find_by_token(params[:token]).destroy
- end
-
- desc 'Register a new runner' do
- success Entities::Runner
- end
- params do
- requires :token, type: String, desc: 'The unique token of the runner'
- optional :description, type: String, desc: 'The description of the runner'
- optional :tag_list, type: Array[String], desc: 'A list of tags the runner should run for'
- optional :run_untagged, type: Boolean, desc: 'Flag if the runner should execute untagged jobs'
- optional :locked, type: Boolean, desc: 'Lock this runner for this specific project'
- end
- post "register" do
- runner_params = declared(params, include_missing: false).except(:token)
-
- runner =
- if runner_registration_token_valid?
- # Create shared runner. Requires admin access
- Ci::Runner.create(runner_params.merge(is_shared: true))
- elsif project = Project.find_by(runners_token: params[:token])
- # Create a specific runner for project.
- project.runners.create(runner_params)
- end
-
- return forbidden! unless runner
-
- if runner.id
- runner.update(get_runner_version_from_params)
- present runner, with: Entities::Runner
- else
- not_found!
- end
- end
- end
- end
- end
-end
diff --git a/lib/ci/api/triggers.rb b/lib/ci/api/triggers.rb
deleted file mode 100644
index 6225203f223..00000000000
--- a/lib/ci/api/triggers.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-module Ci
- module API
- class Triggers < Grape::API
- resource :projects do
- desc 'Trigger a GitLab CI project build' do
- success Entities::TriggerRequest
- end
- params do
- requires :id, type: Integer, desc: 'The ID of a CI project'
- requires :ref, type: String, desc: "The name of project's branch or tag"
- requires :token, type: String, desc: 'The unique token of the trigger'
- optional :variables, type: Hash, desc: 'Optional build variables'
- end
- post ":id/refs/:ref/trigger" do
- project = Project.find_by(ci_id: params[:id])
- trigger = Ci::Trigger.find_by_token(params[:token])
- not_found! unless project && trigger
- unauthorized! unless trigger.project == project
-
- # Validate variables
- variables = params[:variables].to_h
- unless variables.all? { |key, value| key.is_a?(String) && value.is_a?(String) }
- render_api_error!('variables needs to be a map of key-valued strings', 400)
- end
-
- # create request and trigger builds
- result = Ci::CreateTriggerRequestService.execute(project, trigger, params[:ref], variables)
- pipeline = result.pipeline
-
- if pipeline.persisted?
- present result.trigger_request, with: Entities::TriggerRequest
- else
- render_validation_error!(pipeline)
- end
- end
- end
- end
- end
-end
diff --git a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
index 310a69a4bd4..3fde1b09efb 100644
--- a/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
+++ b/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits.rb
@@ -81,12 +81,15 @@ module Gitlab
relative_order: index
)
- # Compatibility with old diffs created with Psych.
diff_hash.tap do |hash|
diff_text = hash[:diff]
hash[:too_large] = !!hash[:too_large]
+ hash[:a_mode] ||= guess_mode(hash[:new_file], hash[:diff])
+ hash[:b_mode] ||= guess_mode(hash[:deleted_file], hash[:diff])
+
+ # Compatibility with old diffs created with Psych.
if diff_text.encoding == Encoding::BINARY && !diff_text.ascii_only?
hash[:binary] = true
hash[:diff] = [diff_text].pack('m0')
@@ -97,6 +100,15 @@ module Gitlab
[commit_rows, file_rows]
end
+ # This doesn't have to be 100% accurate, because it's only used for
+ # display - it won't change file modes in the repository. Submodules are
+ # created as 600, regular files as 644.
+ def guess_mode(file_missing, diff)
+ return '0' if file_missing
+
+ diff.include?('Subproject commit') ? '160000' : '100644'
+ end
+
# Unlike MergeRequestDiff#valid_raw_diff?, don't count Rugged objects as
# valid, because we don't render them usefully anyway.
def valid_raw_diffs?(diffs)
diff --git a/lib/gitlab/background_migration/migrate_stage_status.rb b/lib/gitlab/background_migration/migrate_stage_status.rb
new file mode 100644
index 00000000000..b1ff0900709
--- /dev/null
+++ b/lib/gitlab/background_migration/migrate_stage_status.rb
@@ -0,0 +1,77 @@
+module Gitlab
+ module BackgroundMigration
+ class MigrateStageStatus
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ class Build < ActiveRecord::Base
+ self.table_name = 'ci_builds'
+
+ scope :latest, -> { where(retried: [false, nil]) }
+ scope :created, -> { where(status: 'created') }
+ scope :running, -> { where(status: 'running') }
+ scope :pending, -> { where(status: 'pending') }
+ scope :success, -> { where(status: 'success') }
+ scope :failed, -> { where(status: 'failed') }
+ scope :canceled, -> { where(status: 'canceled') }
+ scope :skipped, -> { where(status: 'skipped') }
+ scope :manual, -> { where(status: 'manual') }
+
+ scope :failed_but_allowed, -> do
+ where(allow_failure: true, status: [:failed, :canceled])
+ end
+
+ scope :exclude_ignored, -> do
+ where("allow_failure = ? OR status IN (?)",
+ false, %w[created pending running success skipped])
+ end
+
+ def self.status_sql
+ scope_relevant = latest.exclude_ignored
+ scope_warnings = latest.failed_but_allowed
+
+ builds = scope_relevant.select('count(*)').to_sql
+ created = scope_relevant.created.select('count(*)').to_sql
+ success = scope_relevant.success.select('count(*)').to_sql
+ manual = scope_relevant.manual.select('count(*)').to_sql
+ pending = scope_relevant.pending.select('count(*)').to_sql
+ running = scope_relevant.running.select('count(*)').to_sql
+ skipped = scope_relevant.skipped.select('count(*)').to_sql
+ canceled = scope_relevant.canceled.select('count(*)').to_sql
+ warnings = scope_warnings.select('count(*) > 0').to_sql
+
+ <<-SQL.strip_heredoc
+ (CASE
+ WHEN (#{builds}) = (#{skipped}) AND (#{warnings}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{skipped}) THEN #{STATUSES[:skipped]}
+ WHEN (#{builds}) = (#{success}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{created}) THEN #{STATUSES[:created]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) THEN #{STATUSES[:success]}
+ WHEN (#{builds}) = (#{success}) + (#{skipped}) + (#{canceled}) THEN #{STATUSES[:canceled]}
+ WHEN (#{builds}) = (#{created}) + (#{skipped}) + (#{pending}) THEN #{STATUSES[:pending]}
+ WHEN (#{running}) + (#{pending}) > 0 THEN #{STATUSES[:running]}
+ WHEN (#{manual}) > 0 THEN #{STATUSES[:manual]}
+ WHEN (#{created}) > 0 THEN #{STATUSES[:running]}
+ ELSE #{STATUSES[:failed]}
+ END)
+ SQL
+ end
+ end
+
+ def perform(start_id, stop_id)
+ status_sql = Build
+ .where('ci_builds.commit_id = ci_stages.pipeline_id')
+ .where('ci_builds.stage = ci_stages.name')
+ .status_sql
+
+ sql = <<-SQL
+ UPDATE ci_stages SET status = (#{status_sql})
+ WHERE ci_stages.status IS NULL
+ AND ci_stages.id BETWEEN #{start_id.to_i} AND #{stop_id.to_i}
+ SQL
+
+ ActiveRecord::Base.connection.execute(sql)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb
index 69ca9aa596b..b83e633c7ed 100644
--- a/lib/gitlab/database/migration_helpers.rb
+++ b/lib/gitlab/database/migration_helpers.rb
@@ -606,6 +606,11 @@ module Gitlab
Arel::Nodes::SqlLiteral.new(replace.to_sql)
end
end
+
+ def remove_foreign_key_without_error(*args)
+ remove_foreign_key(*args)
+ rescue ArgumentError
+ end
end
end
end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index 1d5ca68137a..eb3731ba35a 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -64,7 +64,6 @@ module Gitlab
end
delegate :empty?,
- :bare?,
to: :rugged
delegate :exists?, to: :gitaly_repository_client
@@ -126,6 +125,8 @@ module Gitlab
# This is to work around a bug in libgit2 that causes in-memory refs to
# be stale/invalid when packed-refs is changed.
# See https://gitlab.com/gitlab-org/gitlab-ce/issues/15392#note_14538333
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/474
def find_branch(name, force_reload = false)
reload_rugged if force_reload
@@ -204,21 +205,26 @@ module Gitlab
#
# name - The name of the tag as a String.
def tag_exists?(name)
- !!rugged.tags[name]
+ gitaly_migrate(:ref_exists_tags) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/tags/#{name}")
+ else
+ rugged_tag_exists?(name)
+ end
+ end
end
# Returns true if the given branch exists
#
# name - The name of the branch as a String.
def branch_exists?(name)
- rugged.branches.exists?(name)
-
- # If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
- # Whatever code calls this method shouldn't have to deal with that so
- # instead we just return `false` (which is true since a branch doesn't
- # exist when it has an invalid name).
- rescue Rugged::ReferenceError
- false
+ gitaly_migrate(:ref_exists_branches) do |is_enabled|
+ if is_enabled
+ gitaly_ref_exists?("refs/heads/#{name}")
+ else
+ rugged_branch_exists?(name)
+ end
+ end
end
# Returns an Array of branch and tag names
@@ -226,10 +232,6 @@ module Gitlab
branch_names + tag_names
end
- def has_commits?
- !empty?
- end
-
# Discovers the default branch based on the repository's available branches
#
# - If no branches are present, returns nil
@@ -569,6 +571,8 @@ module Gitlab
end
# Delete the specified branch from the repository
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def delete_branch(branch_name)
rugged.branches.delete(branch_name)
end
@@ -578,6 +582,8 @@ module Gitlab
# Examples:
# create_branch("feature")
# create_branch("other-feature", "master")
+ #
+ # Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/476
def create_branch(ref, start_point = "HEAD")
rugged_ref = rugged.branches.create(ref, start_point)
target_commit = Gitlab::Git::Commit.find(self, rugged_ref.target)
@@ -587,38 +593,26 @@ module Gitlab
raise InvalidRef.new("Invalid reference #{start_point}")
end
- # Return an array of this repository's remote names
- def remote_names
- rugged.remotes.each_name.to_a
- end
-
# Delete the specified remote from this repository.
def remote_delete(remote_name)
rugged.remotes.delete(remote_name)
+ nil
end
- # Add a new remote to this repository. Returns a Rugged::Remote object
+ # Add a new remote to this repository.
def remote_add(remote_name, url)
rugged.remotes.create(remote_name, url)
+ nil
end
# Update the specified remote using the values in the +options+ hash
#
# Example
# repo.update_remote("origin", url: "path/to/repo")
- def remote_update(remote_name, options = {})
+ def remote_update(remote_name, url:)
# TODO: Implement other remote options
- rugged.remotes.set_url(remote_name, options[:url]) if options[:url]
- end
-
- # Fetch the specified remote
- def fetch(remote_name)
- rugged.remotes[remote_name].fetch
- end
-
- # Push +*refspecs+ to the remote identified by +remote_name+.
- def push(remote_name, *refspecs)
- rugged.remotes[remote_name].push(refspecs)
+ rugged.remotes.set_url(remote_name, url)
+ nil
end
AUTOCRLF_VALUES = {
@@ -653,33 +647,15 @@ module Gitlab
# Gitaly migration: https://gitlab.com/gitlab-org/gitaly/issues/328
def copy_gitattributes(ref)
- begin
- commit = lookup(ref)
- rescue Rugged::ReferenceError
- raise InvalidRef.new("Ref #{ref} is invalid")
- end
-
- # Create the paths
- info_dir_path = File.join(path, 'info')
- info_attributes_path = File.join(info_dir_path, 'attributes')
-
- begin
- # Retrieve the contents of the blob
- gitattributes_content = blob_content(commit, '.gitattributes')
- rescue InvalidBlobName
- # No .gitattributes found. Should now remove any info/attributes and return
- File.delete(info_attributes_path) if File.exist?(info_attributes_path)
- return
- end
-
- # Create the info directory if needed
- Dir.mkdir(info_dir_path) unless File.directory?(info_dir_path)
-
- # Write the contents of the .gitattributes file to info/attributes
- # Use binary mode to prevent Rails from converting ASCII-8BIT to UTF-8
- File.open(info_attributes_path, "wb") do |file|
- file.write(gitattributes_content)
+ Gitlab::GitalyClient.migrate(:apply_gitattributes) do |is_enabled|
+ if is_enabled
+ gitaly_copy_gitattributes(ref)
+ else
+ rugged_copy_gitattributes(ref)
+ end
end
+ rescue GRPC::InvalidArgument
+ raise InvalidRef
end
# Returns the Git attributes for the given file path.
@@ -1012,6 +988,68 @@ module Gitlab
raw_output.compact
end
+
+ # Returns true if the given ref name exists
+ #
+ # Ref names must start with `refs/`.
+ def gitaly_ref_exists?(ref_name)
+ gitaly_ref_client.ref_exists?(ref_name)
+ end
+
+ # Returns true if the given tag exists
+ #
+ # name - The name of the tag as a String.
+ def rugged_tag_exists?(name)
+ !!rugged.tags[name]
+ end
+
+ # Returns true if the given branch exists
+ #
+ # name - The name of the branch as a String.
+ def rugged_branch_exists?(name)
+ rugged.branches.exists?(name)
+
+ # If the branch name is invalid (e.g. ".foo") Rugged will raise an error.
+ # Whatever code calls this method shouldn't have to deal with that so
+ # instead we just return `false` (which is true since a branch doesn't
+ # exist when it has an invalid name).
+ rescue Rugged::ReferenceError
+ false
+ end
+
+ def gitaly_copy_gitattributes(revision)
+ gitaly_repository_client.apply_gitattributes(revision)
+ end
+
+ def rugged_copy_gitattributes(ref)
+ begin
+ commit = lookup(ref)
+ rescue Rugged::ReferenceError
+ raise InvalidRef.new("Ref #{ref} is invalid")
+ end
+
+ # Create the paths
+ info_dir_path = File.join(path, 'info')
+ info_attributes_path = File.join(info_dir_path, 'attributes')
+
+ begin
+ # Retrieve the contents of the blob
+ gitattributes_content = blob_content(commit, '.gitattributes')
+ rescue InvalidBlobName
+ # No .gitattributes found. Should now remove any info/attributes and return
+ File.delete(info_attributes_path) if File.exist?(info_attributes_path)
+ return
+ end
+
+ # Create the info directory if needed
+ Dir.mkdir(info_dir_path) unless File.directory?(info_dir_path)
+
+ # Write the contents of the .gitattributes file to info/attributes
+ # Use binary mode to prevent Rails from converting ASCII-8BIT to UTF-8
+ File.open(info_attributes_path, "wb") do |file|
+ file.write(gitattributes_content)
+ end
+ end
end
end
end
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index 0b62911958d..3e8b83c0f90 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -4,6 +4,7 @@ module Gitlab
class GitAccess
UnauthorizedError = Class.new(StandardError)
NotFoundError = Class.new(StandardError)
+ ProjectMovedError = Class.new(NotFoundError)
ERROR_MESSAGES = {
upload: 'You are not allowed to upload code for this project.',
@@ -90,18 +91,18 @@ module Gitlab
end
def check_project_moved!
- if redirected_path
- url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
- message = <<-MESSAGE.strip_heredoc
- Project '#{redirected_path}' was moved to '#{project.full_path}'.
+ return unless redirected_path
- Please update your Git remote and try again:
+ url = protocol == 'ssh' ? project.ssh_url_to_repo : project.http_url_to_repo
+ message = <<-MESSAGE.strip_heredoc
+ Project '#{redirected_path}' was moved to '#{project.full_path}'.
- git remote set-url origin #{url}
- MESSAGE
+ Please update your Git remote and try again:
- raise NotFoundError, message
- end
+ git remote set-url origin #{url}
+ MESSAGE
+
+ raise ProjectMovedError, message
end
def check_command_disabled!(cmd)
diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb
index 7ea8e8d0857..a250eb75bd4 100644
--- a/lib/gitlab/gitaly_client/blob_service.rb
+++ b/lib/gitlab/gitaly_client/blob_service.rb
@@ -13,10 +13,17 @@ module Gitlab
)
response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_blob, request)
- blob = response.first
- return unless blob.oid.present?
+ data = ''
+ blob = nil
+ response.each do |msg|
+ if blob.nil?
+ blob = msg
+ end
- data = response.reduce(blob.data.dup) { |memo, msg| memo << msg.data.dup }
+ data << msg.data
+ end
+
+ return nil if blob.oid.blank?
Gitlab::Git::Blob.new(
id: blob.oid,
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index 93268d9f33c..2d58fb0186e 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -60,22 +60,28 @@ module Gitlab
)
response = GitalyClient.call(@repository.storage, :commit_service, :tree_entry, request)
- entry = response.first
- return unless entry.oid.present?
- if entry.type == :BLOB
- rest_of_data = response.reduce("") { |memo, msg| memo << msg.data }
- entry.data += rest_of_data
+ entry = nil
+ data = ''
+ response.each do |msg|
+ if entry.nil?
+ entry = msg
+
+ break unless entry.type == :BLOB
+ end
+
+ data << msg.data
end
+ entry.data = data
- entry
+ entry unless entry.oid.blank?
end
def tree_entries(repository, revision, path)
request = Gitaly::GetTreeEntriesRequest.new(
repository: @gitaly_repo,
- revision: revision,
- path: path.presence || '.'
+ revision: GitalyClient.encode(revision),
+ path: path.present? ? GitalyClient.encode(path) : '.'
)
response = GitalyClient.call(@repository.storage, :commit_service, :get_tree_entries, request)
diff --git a/lib/gitlab/gitaly_client/ref_service.rb b/lib/gitlab/gitaly_client/ref_service.rb
index 919fb68b8c7..cdcfed36740 100644
--- a/lib/gitlab/gitaly_client/ref_service.rb
+++ b/lib/gitlab/gitaly_client/ref_service.rb
@@ -70,6 +70,14 @@ module Gitlab
consume_tags_response(response)
end
+ def ref_exists?(ref_name)
+ request = Gitaly::RefExistsRequest.new(repository: @gitaly_repo, ref: ref_name)
+ response = GitalyClient.call(@storage, :ref_service, :ref_exists, request)
+ response.value
+ rescue GRPC::InvalidArgument => e
+ raise ArgumentError, e.message
+ end
+
private
def consume_refs_response(response)
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 6ad97e62941..a74a6dc6e78 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -32,6 +32,11 @@ module Gitlab
request = Gitaly::RepositorySizeRequest.new(repository: @gitaly_repo)
GitalyClient.call(@storage, :repository_service, :repository_size, request).size
end
+
+ def apply_gitattributes(revision)
+ request = Gitaly::ApplyGitattributesRequest.new(repository: @gitaly_repo, revision: revision)
+ GitalyClient.call(@storage, :repository_service, :apply_gitattributes, request)
+ end
end
end
end
diff --git a/lib/gitlab/import_export/import_export.yml b/lib/gitlab/import_export/import_export.yml
index 9d9ebcb389a..e5d4bb686e7 100644
--- a/lib/gitlab/import_export/import_export.yml
+++ b/lib/gitlab/import_export/import_export.yml
@@ -98,6 +98,7 @@ excluded_attributes:
- :last_activity_at
- :last_repository_updated_at
- :last_repository_check_at
+ - :storage_version
snippets:
- :expired_at
merge_request_diff:
@@ -133,5 +134,7 @@ methods:
- :utf8_diff
merge_requests:
- :diff_head_sha
+ - :source_branch_sha
+ - :target_branch_sha
project:
- :description_html
diff --git a/lib/gitlab/import_export/merge_request_parser.rb b/lib/gitlab/import_export/merge_request_parser.rb
index c20adc20bfd..81a213e8321 100644
--- a/lib/gitlab/import_export/merge_request_parser.rb
+++ b/lib/gitlab/import_export/merge_request_parser.rb
@@ -30,7 +30,7 @@ module Gitlab
end
def branch_exists?(branch_name)
- @project.repository.branch_exists?(branch_name)
+ @project.repository.raw.branch_exists?(branch_name)
end
def fork_merge_request?
diff --git a/lib/gitlab/job_waiter.rb b/lib/gitlab/job_waiter.rb
index 208f0e1bbea..4d6bbda15f3 100644
--- a/lib/gitlab/job_waiter.rb
+++ b/lib/gitlab/job_waiter.rb
@@ -1,12 +1,31 @@
module Gitlab
# JobWaiter can be used to wait for a number of Sidekiq jobs to complete.
+ #
+ # Its use requires the cooperation of the sidekiq jobs themselves. Set up the
+ # waiter, then start the jobs, passing them its `key`. Their `perform` methods
+ # should look like:
+ #
+ # def perform(args, notify_key)
+ # # do work
+ # ensure
+ # ::Gitlab::JobWaiter.notify(notify_key, jid)
+ # end
+ #
+ # The JobWaiter blocks popping items from a Redis array. All the sidekiq jobs
+ # push to that array when done. Once the waiter has popped `count` items, it
+ # knows all the jobs are done.
class JobWaiter
- # The sleep interval between checking keys, in seconds.
- INTERVAL = 0.1
+ def self.notify(key, jid)
+ Gitlab::Redis::SharedState.with { |redis| redis.lpush(key, jid) }
+ end
+
+ attr_reader :key, :jobs_remaining, :finished
- # jobs - The job IDs to wait for.
- def initialize(jobs)
- @jobs = jobs
+ # jobs_remaining - the number of jobs left to wait for
+ def initialize(jobs_remaining)
+ @key = "gitlab:job_waiter:#{SecureRandom.uuid}"
+ @jobs_remaining = jobs_remaining
+ @finished = []
end
# Waits for all the jobs to be completed.
@@ -15,13 +34,33 @@ module Gitlab
# ensures we don't indefinitely block a caller in case a job takes
# long to process, or is never processed.
def wait(timeout = 10)
- start = Time.current
+ deadline = Time.now.utc + timeout
+
+ Gitlab::Redis::SharedState.with do |redis|
+ # Fallback key expiry: allow a long grace period to reduce the chance of
+ # a job pushing to an expired key and recreating it
+ redis.expire(key, [timeout * 2, 10.minutes.to_i].max)
+
+ while jobs_remaining > 0
+ # Redis will not take fractional seconds. Prefer waiting too long over
+ # not waiting long enough
+ seconds_left = (deadline - Time.now.utc).ceil
- while (Time.current - start) <= timeout
- break if SidekiqStatus.all_completed?(@jobs)
+ # Redis interprets 0 as "wait forever", so skip the final `blpop` call
+ break if seconds_left <= 0
- sleep(INTERVAL) # to not overload Redis too much.
+ list, jid = redis.blpop(key, timeout: seconds_left)
+ break unless list && jid # timed out
+
+ @finished << jid
+ @jobs_remaining -= 1
+ end
+
+ # All jobs have finished, so expire the key immediately
+ redis.expire(key, 0) if jobs_remaining == 0
end
+
+ finished
end
end
end
diff --git a/lib/gitlab/logger.rb b/lib/gitlab/logger.rb
index 59b21149a9a..6bffd410ed0 100644
--- a/lib/gitlab/logger.rb
+++ b/lib/gitlab/logger.rb
@@ -14,13 +14,9 @@ module Gitlab
def self.read_latest
path = Rails.root.join("log", file_name)
- self.build unless File.exist?(path)
- tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
- tail_output.split("\n")
- end
- def self.read_latest_for(filename)
- path = Rails.root.join("log", filename)
+ return [] unless File.readable?(path)
+
tail_output, _ = Gitlab::Popen.popen(%W(tail -n 2000 #{path}))
tail_output.split("\n")
end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 1adc5ec952a..58f6245579a 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -53,7 +53,8 @@ module Gitlab
end
def kubernetes_namespace_regex_message
- "can contain only letters, digits or '-', and cannot start or end with '-'"
+ "can contain only lowercase letters, digits, and '-'. " \
+ "Must start with a letter, and cannot end with '-'"
end
def environment_slug_regex
diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb
index ca8d3271541..a0a2769cf9e 100644
--- a/lib/gitlab/sidekiq_status.rb
+++ b/lib/gitlab/sidekiq_status.rb
@@ -90,9 +90,14 @@ module Gitlab
#
# Returns an array of completed JIDs
def self.completed_jids(job_ids)
- Sidekiq.redis do |redis|
- job_ids.reject { |jid| redis.exists(key_for(jid)) }
+ statuses = job_status(job_ids)
+
+ completed = []
+ job_ids.zip(statuses).each do |job_id, status|
+ completed << job_id unless status
end
+
+ completed
end
def self.key_for(jid)
diff --git a/lib/gitlab/sidekiq_throttler.rb b/lib/gitlab/sidekiq_throttler.rb
index d4d39a888e7..5512afa45a8 100644
--- a/lib/gitlab/sidekiq_throttler.rb
+++ b/lib/gitlab/sidekiq_throttler.rb
@@ -3,6 +3,8 @@ module Gitlab
class << self
def execute!
if Gitlab::CurrentSettings.sidekiq_throttling_enabled?
+ require 'sidekiq-limit_fetch'
+
Gitlab::CurrentSettings.current_application_settings.sidekiq_throttling_queues.each do |queue|
Sidekiq::Queue[queue].limit = queue_limit
end
diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb
index 94fba0a221a..11aeec1ebfa 100644
--- a/lib/gitlab/string_range_marker.rb
+++ b/lib/gitlab/string_range_marker.rb
@@ -1,21 +1,31 @@
module Gitlab
class StringRangeMarker
- attr_accessor :raw_line, :rich_line
-
- def initialize(raw_line, rich_line = raw_line)
- @raw_line = raw_line
- @rich_line = ERB::Util.html_escape(rich_line)
+ attr_accessor :raw_line, :rich_line, :html_escaped
+
+ def initialize(raw_line, rich_line = nil)
+ @raw_line = raw_line.dup
+ if rich_line.nil?
+ @rich_line = raw_line.dup
+ @html_escaped = false
+ else
+ @rich_line = ERB::Util.html_escape(rich_line)
+ @html_escaped = true
+ end
end
def mark(marker_ranges)
return rich_line unless marker_ranges
- rich_marker_ranges = []
- marker_ranges.each do |range|
- # Map the inline-diff range based on the raw line to character positions in the rich line
- rich_positions = position_mapping[range].flatten
- # Turn the array of character positions into ranges
- rich_marker_ranges.concat(collapse_ranges(rich_positions))
+ if html_escaped
+ rich_marker_ranges = []
+ marker_ranges.each do |range|
+ # Map the inline-diff range based on the raw line to character positions in the rich line
+ rich_positions = position_mapping[range].flatten
+ # Turn the array of character positions into ranges
+ rich_marker_ranges.concat(collapse_ranges(rich_positions))
+ end
+ else
+ rich_marker_ranges = marker_ranges
end
offset = 0
@@ -31,7 +41,7 @@ module Gitlab
offset += text.length - original_text.length
end
- rich_line.html_safe
+ @html_escaped ? rich_line.html_safe : rich_line
end
private
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 48bd9139ce8..6e10ba374bf 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -11,6 +11,12 @@ namespace :gitlab do
#
desc "GitLab | Import bare repositories from repositories -> storages into GitLab project instance"
task repos: :environment do
+ if Project.current_application_settings.hashed_storage_enabled
+ puts 'Cannot import repositories when Hashed Storage is enabled'.color(:red)
+
+ exit 1
+ end
+
Gitlab.config.repositories.storages.each_value do |repository_storage|
git_base_path = repository_storage['path']
repos_to_import = Dir.glob(git_base_path + '/**/*.git')
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e60504e1395..a4a3ef6c42c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2017-07-13 12:07-0500\n"
-"PO-Revision-Date: 2017-07-13 12:07-0500\n"
+"POT-Creation-Date: 2017-08-18 14:15+0530\n"
+"PO-Revision-Date: 2017-08-18 14:15+0530\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@@ -31,6 +31,23 @@ msgstr[1] ""
msgid "%{commit_author_link} committed %{commit_timeago}"
msgstr ""
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will allow access on the next attempt."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will block access for %{number_of_seconds} seconds."
+msgstr ""
+
+msgid "%{number_of_failures} of %{maximum_failures} failures. GitLab will not retry automatically. Reset storage information when the problem is resolved."
+msgstr ""
+
+msgid "%{storage_name}: failed storage access attempt on host:"
+msgid_plural "%{storage_name}: %{failed_attempts} failed storage access attempts:"
+msgstr[0] ""
+msgstr[1] ""
+
+msgid "(checkout the %{link} for information on how to install it)."
+msgstr ""
+
msgid "1 pipeline"
msgid_plural "%d pipelines"
msgstr[0] ""
@@ -42,6 +59,9 @@ msgstr ""
msgid "About auto deploy"
msgstr ""
+msgid "Access to failing storages has been temporarily disabled to allow the mount to recover. Reset storage information after the issue has been resolved to allow access again."
+msgstr ""
+
msgid "Active"
msgstr ""
@@ -63,12 +83,27 @@ msgstr ""
msgid "Add new directory"
msgstr ""
+msgid "All"
+msgstr ""
+
msgid "Archived project! Repository is read-only"
msgstr ""
msgid "Are you sure you want to delete this pipeline schedule?"
msgstr ""
+msgid "Are you sure you want to discard your changes?"
+msgstr ""
+
+msgid "Are you sure you want to reset registration token?"
+msgstr ""
+
+msgid "Are you sure you want to reset the health check token?"
+msgstr ""
+
+msgid "Are you sure?"
+msgstr ""
+
msgid "Attach a file by drag &amp; drop or %{upload_link}"
msgstr ""
@@ -110,6 +145,9 @@ msgstr ""
msgid "Cancel"
msgstr ""
+msgid "Cancel edit"
+msgstr ""
+
msgid "ChangeTypeActionLabel|Pick into branch"
msgstr ""
@@ -188,6 +226,9 @@ msgstr ""
msgid "CiStatus|running"
msgstr ""
+msgid "Comments"
+msgstr ""
+
msgid "Commit"
msgid_plural "Commits"
msgstr[0] ""
@@ -235,6 +276,9 @@ msgstr ""
msgid "Create New Directory"
msgstr ""
+msgid "Create a new branch"
+msgstr ""
+
msgid "Create a personal access token on your account to pull or push via %{protocol}."
msgstr ""
@@ -312,9 +356,15 @@ msgstr[1] ""
msgid "Description"
msgstr ""
+msgid "Details"
+msgstr ""
+
msgid "Directory name"
msgstr ""
+msgid "Discard changes"
+msgstr ""
+
msgid "Don't show again"
msgstr ""
@@ -351,6 +401,24 @@ msgstr ""
msgid "Edit Pipeline Schedule %{id}"
msgstr ""
+msgid "EventFilterBy|Filter by all"
+msgstr ""
+
+msgid "EventFilterBy|Filter by comments"
+msgstr ""
+
+msgid "EventFilterBy|Filter by issue events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by merge events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by push events"
+msgstr ""
+
+msgid "EventFilterBy|Filter by team"
+msgstr ""
+
msgid "Every day (at 4:00am)"
msgstr ""
@@ -398,12 +466,36 @@ msgstr ""
msgid "From merge request merge until deploy to production"
msgstr ""
+msgid "Git storage health information has been reset"
+msgstr ""
+
+msgid "GitLab Runner section"
+msgstr ""
+
msgid "Go to your fork"
msgstr ""
msgid "GoToYourFork|Fork"
msgstr ""
+msgid "Health Check"
+msgstr ""
+
+msgid "Health information can be retrieved from the following endpoints. More information is available"
+msgstr ""
+
+msgid "HealthCheck|Access token is"
+msgstr ""
+
+msgid "HealthCheck|Healthy"
+msgstr ""
+
+msgid "HealthCheck|No Health Problems Detected"
+msgstr ""
+
+msgid "HealthCheck|Unhealthy"
+msgstr ""
+
msgid "Home"
msgstr ""
@@ -413,12 +505,18 @@ msgstr ""
msgid "Import repository"
msgstr ""
+msgid "Install a Runner compatible with GitLab CI"
+msgstr ""
+
msgid "Interval Pattern"
msgstr ""
msgid "Introducing Cycle Analytics"
msgstr ""
+msgid "Issue events"
+msgstr ""
+
msgid "Jobs for last month"
msgstr ""
@@ -448,6 +546,12 @@ msgstr ""
msgid "Last commit"
msgstr ""
+msgid "LastPushEvent|You pushed to"
+msgstr ""
+
+msgid "LastPushEvent|at"
+msgstr ""
+
msgid "Learn more in the"
msgstr ""
@@ -468,9 +572,15 @@ msgstr[1] ""
msgid "Median"
msgstr ""
+msgid "Merge events"
+msgstr ""
+
msgid "MissingSSHKeyWarningLink|add an SSH key"
msgstr ""
+msgid "More information is available|here"
+msgstr ""
+
msgid "New Issue"
msgid_plural "New Issues"
msgstr[0] ""
@@ -668,6 +778,9 @@ msgstr ""
msgid "Pipeline|with stages"
msgstr ""
+msgid "Project"
+msgstr ""
+
msgid "Project '%{project_name}' queued for deletion."
msgstr ""
@@ -683,6 +796,9 @@ msgstr ""
msgid "Project access must be granted explicitly to each user."
msgstr ""
+msgid "Project details"
+msgstr ""
+
msgid "Project export could not be deleted."
msgstr ""
@@ -698,6 +814,9 @@ msgstr ""
msgid "Project home"
msgstr ""
+msgid "ProjectActivityRSS|Subscribe"
+msgstr ""
+
msgid "ProjectFeature|Disabled"
msgstr ""
@@ -719,6 +838,9 @@ msgstr ""
msgid "ProjectNetworkGraph|Graph"
msgstr ""
+msgid "Push events"
+msgstr ""
+
msgid "Read more"
msgstr ""
@@ -755,9 +877,21 @@ msgstr ""
msgid "Remove project"
msgstr ""
+msgid "Repository"
+msgstr ""
+
msgid "Request Access"
msgstr ""
+msgid "Reset git storage health information"
+msgstr ""
+
+msgid "Reset health check access token"
+msgstr ""
+
+msgid "Reset runners registration token"
+msgstr ""
+
msgid "Revert this commit"
msgstr ""
@@ -782,6 +916,9 @@ msgstr ""
msgid "Select a timezone"
msgstr ""
+msgid "Select existing branch"
+msgstr ""
+
msgid "Select target branch"
msgstr ""
@@ -808,12 +945,18 @@ msgstr[1] ""
msgid "Source code"
msgstr ""
+msgid "Specify the following URL during the Runner setup:"
+msgstr ""
+
msgid "StarProject|Star"
msgstr ""
msgid "Start a %{new_merge_request} with these changes"
msgstr ""
+msgid "Start the Runner!"
+msgstr ""
+
msgid "Switch branch/tag"
msgstr ""
@@ -828,6 +971,9 @@ msgstr ""
msgid "Target Branch"
msgstr ""
+msgid "Team"
+msgstr ""
+
msgid "The coding stage shows the time from the first commit to creating the merge request. The data will automatically be added here once you create your first merge request."
msgstr ""
@@ -876,6 +1022,9 @@ msgstr ""
msgid "The value lying at the midpoint of a series of observed values. E.g., between 3, 5, 9, the median is 5. Between 3, 5, 7, 8, the median is (5+7)/2 = 6."
msgstr ""
+msgid "There are problems accessing Git storage: "
+msgstr ""
+
msgid "This means you can not push code until you create an empty repository or import existing one."
msgstr ""
@@ -1045,6 +1194,9 @@ msgstr ""
msgid "UploadLink|click to upload"
msgstr ""
+msgid "Use the following registration token during setup:"
+msgstr ""
+
msgid "Use your global notification setting"
msgstr ""
diff --git a/package.json b/package.json
index 8f37ac21c2e..43be99f451b 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"babel-preset-latest": "^6.24.0",
"babel-preset-stage-2": "^6.22.0",
"bootstrap-sass": "^3.3.6",
- "compression-webpack-plugin": "^0.3.2",
+ "compression-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.0.1",
"core-js": "^2.4.1",
"cropper": "^2.3.0",
@@ -64,7 +64,7 @@
"vue-resource": "^1.3.4",
"vue-template-compiler": "^2.2.6",
"vuex": "^2.3.1",
- "webpack": "^3.5.4",
+ "webpack": "^3.5.5",
"webpack-bundle-analyzer": "^2.8.2",
"webpack-stats-plugin": "^0.1.5"
},
diff --git a/spec/controllers/projects/services_controller_spec.rb b/spec/controllers/projects/services_controller_spec.rb
index 4e9b0c09ff2..efba9cc7306 100644
--- a/spec/controllers/projects/services_controller_spec.rb
+++ b/spec/controllers/projects/services_controller_spec.rb
@@ -10,9 +10,6 @@ describe Projects::ServicesController do
before do
sign_in(user)
project.team << [user, :master]
-
- controller.instance_variable_set(:@project, project)
- controller.instance_variable_set(:@service, service)
end
describe '#test' do
@@ -20,7 +17,7 @@ describe Projects::ServicesController do
it 'renders 404' do
allow_any_instance_of(Service).to receive(:can_test?).and_return(false)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param
expect(response).to have_http_status(404)
end
@@ -36,7 +33,7 @@ describe Projects::ServicesController do
it 'returns success' do
allow_any_instance_of(MicrosoftTeams::Notifier).to receive(:ping).and_return(true)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param
expect(response.status).to eq(200)
end
@@ -45,7 +42,7 @@ describe Projects::ServicesController do
it 'returns success' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
end
@@ -54,17 +51,42 @@ describe Projects::ServicesController do
it 'returns success' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_return(hipchat_client)
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
end
+
+ context 'when service is configured for the first time' do
+ before do
+ allow_any_instance_of(ServiceHook).to receive(:execute).and_return(true)
+ end
+
+ it 'persist the object' do
+ do_put
+
+ expect(BuildkiteService.first).to be_present
+ end
+
+ it 'creates the ServiceHook object' do
+ do_put
+
+ expect(BuildkiteService.first.service_hook).to be_present
+ end
+
+ def do_put
+ put :test, namespace_id: project.namespace,
+ project_id: project,
+ id: 'buildkite',
+ service: { 'active' => '1', 'push_events' => '1', token: 'token', 'project_url' => 'http://test.com' }
+ end
+ end
end
context 'failure' do
it 'returns success status code and the error message' do
expect(HipChat::Client).to receive(:new).with('hipchat_token_p', anything).and_raise('Bad test')
- put :test, namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: service_params
+ put :test, namespace_id: project.namespace, project_id: project, id: service.to_param, service: service_params
expect(response.status).to eq(200)
expect(JSON.parse(response.body))
@@ -77,7 +99,7 @@ describe Projects::ServicesController do
context 'when param `active` is set to true' do
it 'activates the service and redirects to integrations paths' do
put :update,
- namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: { active: true }
+ namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: true }
expect(response).to redirect_to(project_settings_integrations_path(project))
expect(flash[:notice]).to eq 'HipChat activated.'
@@ -87,7 +109,7 @@ describe Projects::ServicesController do
context 'when param `active` is set to false' do
it 'does not activate the service but saves the settings' do
put :update,
- namespace_id: project.namespace.id, project_id: project.id, id: service.id, service: { active: false }
+ namespace_id: project.namespace, project_id: project, id: service.to_param, service: { active: false }
expect(flash[:notice]).to eq 'HipChat settings saved, but not activated.'
end
diff --git a/spec/factories/ci/stages.rb b/spec/factories/ci/stages.rb
index d3c8bf9d54f..b2ded945738 100644
--- a/spec/factories/ci/stages.rb
+++ b/spec/factories/ci/stages.rb
@@ -15,4 +15,12 @@ FactoryGirl.define do
warnings: warnings)
end
end
+
+ factory :ci_stage_entity, class: Ci::Stage do
+ project factory: :project
+ pipeline factory: :ci_empty_pipeline
+
+ name 'test'
+ status 'pending'
+ end
end
diff --git a/spec/factories/projects.rb b/spec/factories/projects.rb
index 4a2034b31b3..9ebda0ba03b 100644
--- a/spec/factories/projects.rb
+++ b/spec/factories/projects.rb
@@ -81,6 +81,10 @@ FactoryGirl.define do
archived true
end
+ trait :hashed do
+ storage_version Project::LATEST_STORAGE_VERSION
+ end
+
trait :access_requestable do
request_access_enabled true
end
diff --git a/spec/features/atom/users_spec.rb b/spec/features/atom/users_spec.rb
index 79069bbca8e..9ce687afb31 100644
--- a/spec/features/atom/users_spec.rb
+++ b/spec/features/atom/users_spec.rb
@@ -41,6 +41,8 @@ describe "User Feed" do
target_project: project,
description: "Here is the fix: ![an image](image.png)")
end
+ let(:push_event) { create(:push_event, project: project, author: user) }
+ let!(:push_event_payload) { create(:push_event_payload, event: push_event) }
before do
project.team << [user, :master]
@@ -70,6 +72,10 @@ describe "User Feed" do
it 'has XHTML summaries in merge request descriptions' do
expect(body).to match /Here is the fix: <a[^>]*><img[^>]*\/><\/a>/
end
+
+ it 'has push event commit ID' do
+ expect(body).to have_content(Commit.truncate_sha(push_event.commit_id))
+ end
end
end
diff --git a/spec/features/explore/new_menu_spec.rb b/spec/features/explore/new_menu_spec.rb
index 2cd06258e22..e1c74a24890 100644
--- a/spec/features/explore/new_menu_spec.rb
+++ b/spec/features/explore/new_menu_spec.rb
@@ -74,7 +74,7 @@ feature 'Top Plus Menu', :js do
expect(page).to have_content('Title')
end
- scenario 'Click on New subgroup shows new group page' do
+ scenario 'Click on New subgroup shows new group page', :nested_groups do
visit group_path(group)
click_topmenuitem("New subgroup")
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index e59a484d992..20f9818b08b 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -104,18 +104,15 @@ feature 'Group' do
end
context 'as group owner' do
- let(:user) { create(:user) }
+ it 'creates a nested group' do
+ user = create(:user)
- before do
group.add_owner(user)
sign_out(:user)
sign_in(user)
visit subgroups_group_path(group)
click_link 'New Subgroup'
- end
-
- it 'creates a nested group' do
fill_in 'Group path', with: 'bar'
click_button 'Create group'
@@ -123,6 +120,16 @@ feature 'Group' do
expect(page).to have_content("Group 'bar' was successfully created.")
end
end
+
+ context 'when nested group feature is disabled' do
+ it 'renders 404' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+
+ visit subgroups_group_path(group)
+
+ expect(page.status_code).to eq(404)
+ end
+ end
end
it 'checks permissions to avoid exposing groups by parent_id' do
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index 672022304da..f183dd8cb75 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -7,9 +7,8 @@ describe 'Profile account page' do
sign_in(user)
end
- describe 'when signup is enabled' do
+ describe 'when I delete my account' do
before do
- stub_application_setting(signup_enabled: true)
visit profile_account_path
end
@@ -21,18 +20,6 @@ describe 'Profile account page' do
end
end
- describe 'when signup is disabled' do
- before do
- stub_application_setting(signup_enabled: false)
- visit profile_account_path
- end
-
- it 'does not have option to remove account' do
- expect(page).not_to have_content('Remove account')
- expect(current_path).to eq(profile_account_path)
- end
- end
-
describe 'when I reset private token' do
before do
visit profile_account_path
diff --git a/spec/features/projects/import_export/import_file_spec.rb b/spec/features/projects/import_export/import_file_spec.rb
index 6a324d32ca7..9f2c86923b7 100644
--- a/spec/features/projects/import_export/import_file_spec.rb
+++ b/spec/features/projects/import_export/import_file_spec.rb
@@ -3,11 +3,13 @@ require 'spec_helper'
feature 'Import/Export - project import integration test', js: true do
include Select2Helper
+ let(:user) { create(:user) }
let(:file) { File.join(Rails.root, 'spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:export_path) { "#{Dir.tmpdir}/import_file_spec" }
background do
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ gitlab_sign_in(user)
end
after do
@@ -18,57 +20,67 @@ feature 'Import/Export - project import integration test', js: true do
let(:user) { create(:admin) }
let!(:namespace) { create(:namespace, name: "asd", owner: user) }
- before do
- gitlab_sign_in(user)
- end
+ context 'prefilled the path' do
+ scenario 'user imports an exported project successfully' do
+ visit new_project_path
- scenario 'user imports an exported project successfully' do
- visit new_project_path
+ select2(namespace.id, from: '#project_namespace_id')
+ fill_in :project_path, with: 'test-project-path', visible: true
+ click_link 'GitLab export'
- select2(namespace.id, from: '#project_namespace_id')
- fill_in :project_path, with: 'test-project-path', visible: true
- click_link 'GitLab export'
+ expect(page).to have_content('Import an exported GitLab project')
+ expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=test-project-path")
+ expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}_test-project-path\z/).and_call_original
- expect(page).to have_content('Import an exported GitLab project')
- expect(URI.parse(current_url).query).to eq("namespace_id=#{namespace.id}&path=test-project-path")
- expect(Gitlab::ImportExport).to receive(:import_upload_path).with(filename: /\A\h{32}_test-project-path\z/).and_call_original
+ attach_file('file', file)
- attach_file('file', file)
+ expect { click_on 'Import project' }.to change { Project.count }.by(1)
- expect { click_on 'Import project' }.to change { Project.count }.from(0).to(1)
-
- project = Project.last
- expect(project).not_to be_nil
- expect(project.issues).not_to be_empty
- expect(project.merge_requests).not_to be_empty
- expect(project_hook_exists?(project)).to be true
- expect(wiki_exists?(project)).to be true
- expect(project.import_status).to eq('finished')
+ project = Project.last
+ expect(project).not_to be_nil
+ expect(project.issues).not_to be_empty
+ expect(project.merge_requests).not_to be_empty
+ expect(project_hook_exists?(project)).to be true
+ expect(wiki_exists?(project)).to be true
+ expect(project.import_status).to eq('finished')
+ end
end
- scenario 'invalid project' do
- project = create(:project, namespace: namespace)
+ context 'path is not prefilled' do
+ scenario 'user imports an exported project successfully' do
+ visit new_project_path
+ click_link 'GitLab export'
- visit new_project_path
+ fill_in :path, with: 'test-project-path', visible: true
+ attach_file('file', file)
- select2(namespace.id, from: '#project_namespace_id')
- fill_in :project_path, with: project.name, visible: true
- click_link 'GitLab export'
- attach_file('file', file)
- click_on 'Import project'
+ expect { click_on 'Import project' }.to change { Project.count }.by(1)
- page.within('.flash-container') do
- expect(page).to have_content('Project could not be imported')
+ project = Project.last
+ expect(project).not_to be_nil
+ expect(page).to have_content("Project 'test-project-path' is being imported")
end
end
end
- context 'when limited to the default user namespace' do
- let(:user) { create(:user) }
- before do
- gitlab_sign_in(user)
+ scenario 'invalid project' do
+ namespace = create(:namespace, name: "asd", owner: user)
+ project = create(:project, namespace: namespace)
+
+ visit new_project_path
+
+ select2(namespace.id, from: '#project_namespace_id')
+ fill_in :project_path, with: project.name, visible: true
+ click_link 'GitLab export'
+ attach_file('file', file)
+ click_on 'Import project'
+
+ page.within('.flash-container') do
+ expect(page).to have_content('Project could not be imported')
end
+ end
+ context 'when limited to the default user namespace' do
scenario 'passes correct namespace ID in the URL' do
visit new_project_path
diff --git a/spec/helpers/diff_helper_spec.rb b/spec/helpers/diff_helper_spec.rb
index f81a9b6492c..0deea0ff6a3 100644
--- a/spec/helpers/diff_helper_spec.rb
+++ b/spec/helpers/diff_helper_spec.rb
@@ -135,10 +135,10 @@ describe DiffHelper do
it "returns strings with marked inline diffs" do
marked_old_line, marked_new_line = mark_inline_diffs(old_line, new_line)
- expect(marked_old_line).to eq(%q{abc <span class="idiff left right deletion">&#39;def&#39;</span>})
- expect(marked_old_line).to be_html_safe
- expect(marked_new_line).to eq(%q{abc <span class="idiff left right addition">&quot;def&quot;</span>})
- expect(marked_new_line).to be_html_safe
+ expect(marked_old_line).to eq(%q{abc <span class="idiff left right deletion">'def'</span>})
+ expect(marked_old_line).not_to be_html_safe
+ expect(marked_new_line).to eq(%q{abc <span class="idiff left right addition">"def"</span>})
+ expect(marked_new_line).not_to be_html_safe
end
end
diff --git a/spec/helpers/events_helper_spec.rb b/spec/helpers/events_helper_spec.rb
index aa138f25bd3..4b72dbb7964 100644
--- a/spec/helpers/events_helper_spec.rb
+++ b/spec/helpers/events_helper_spec.rb
@@ -62,6 +62,12 @@ describe EventsHelper do
expect(helper.event_note(input)).to eq(expected)
end
+ it 'preserves data-src for lazy images' do
+ input = "![ImageTest](/uploads/test.png)"
+ image_url = "data-src=\"/uploads/test.png\""
+ expect(helper.event_note(input)).to match(image_url)
+ end
+
context 'labels formatting' do
let(:input) { 'this should be ~label_1' }
diff --git a/spec/initializers/settings_spec.rb b/spec/initializers/settings_spec.rb
index e5ec90cb8f9..9a974e70e8c 100644
--- a/spec/initializers/settings_spec.rb
+++ b/spec/initializers/settings_spec.rb
@@ -2,6 +2,22 @@ require 'spec_helper'
require_relative '../../config/initializers/1_settings'
describe Settings do
+ describe '#ldap' do
+ it 'can be accessed with dot syntax all the way down' do
+ expect(Gitlab.config.ldap.servers.main.label).to eq('ldap')
+ end
+
+ # Specifically trying to cause this error discovered in EE when removing the
+ # reassignment of each server element with Settingslogic.
+ #
+ # `undefined method `label' for #<Hash:0x007fbd18b59c08>`
+ #
+ it 'can be accessed in a very specific way that breaks without reassigning each element with Settingslogic' do
+ server_settings = Gitlab.config.ldap.servers['main']
+ expect(server_settings.label).to eq('ldap')
+ end
+ end
+
describe '#repositories' do
it 'assigns the default failure attributes' do
repository_settings = Gitlab.config.repositories.storages['broken']
@@ -11,6 +27,15 @@ describe Settings do
expect(repository_settings['failure_reset_time']).to eq(1800)
expect(repository_settings['storage_timeout']).to eq(5)
end
+
+ it 'can be accessed with dot syntax all the way down' do
+ expect(Gitlab.config.repositories.storages.broken.failure_count_threshold).to eq(10)
+ end
+
+ it 'can be accessed in a very specific way that breaks without reassigning each element with Settingslogic' do
+ storage_settings = Gitlab.config.repositories.storages['broken']
+ expect(storage_settings.failure_count_threshold).to eq(10)
+ end
end
describe '#host_without_www' do
diff --git a/spec/javascripts/boards/board_new_issue_spec.js b/spec/javascripts/boards/board_new_issue_spec.js
index c0a7323a505..eac2eecb6bc 100644
--- a/spec/javascripts/boards/board_new_issue_spec.js
+++ b/spec/javascripts/boards/board_new_issue_spec.js
@@ -30,6 +30,8 @@ describe('Issue boards new issue form', () => {
};
beforeEach((done) => {
+ setFixtures('<div class="test-container"></div>');
+
const BoardNewIssueComp = Vue.extend(boardNewIssue);
Vue.http.interceptors.push(boardsMockInterceptor);
@@ -46,15 +48,17 @@ describe('Issue boards new issue form', () => {
propsData: {
list,
},
- }).$mount();
+ }).$mount(document.querySelector('.test-container'));
Vue.nextTick()
.then(done)
.catch(done.fail);
});
+ afterEach(() => vm.$destroy());
+
it('calls submit if submit button is clicked', (done) => {
- spyOn(vm, 'submit');
+ spyOn(vm, 'submit').and.callFake(e => e.preventDefault());
vm.title = 'Testing Title';
Vue.nextTick()
diff --git a/spec/javascripts/boards/issue_card_spec.js b/spec/javascripts/boards/issue_card_spec.js
index 69cfcbbce5a..47aaa57e6b9 100644
--- a/spec/javascripts/boards/issue_card_spec.js
+++ b/spec/javascripts/boards/issue_card_spec.js
@@ -278,6 +278,25 @@ describe('Issue card component', () => {
nodes.includes(label1.color),
).toBe(true);
});
+
+ it('does not render label if label does not have an ID', (done) => {
+ component.issue.addLabel(new ListLabel({
+ title: 'closed',
+ }));
+
+ Vue.nextTick()
+ .then(() => {
+ expect(
+ component.$el.querySelectorAll('.label').length,
+ ).toBe(2);
+ expect(
+ component.$el.textContent,
+ ).not.toContain('closed');
+
+ done();
+ })
+ .catch(done.fail);
+ });
});
});
});
diff --git a/spec/javascripts/fixtures/project_select_combo_button.html.haml b/spec/javascripts/fixtures/project_select_combo_button.html.haml
index 54bc1a59279..432cd5fcc74 100644
--- a/spec/javascripts/fixtures/project_select_combo_button.html.haml
+++ b/spec/javascripts/fixtures/project_select_combo_button.html.haml
@@ -1,6 +1,6 @@
.project-item-select-holder
%input.project-item-select{ data: { group_id: '12345' , relative_path: 'issues/new' } }
- %a.new-project-item-link{ data: { label: 'New issue' }, href: ''}
+ %a.new-project-item-link{ data: { label: 'New issue', type: 'issues' }, href: ''}
%i.fa.fa-spinner.spin
%a.new-project-item-select-button
%i.fa.fa-caret-down
diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js
index 55037bbbf73..a6ad250bd86 100644
--- a/spec/javascripts/lib/utils/common_utils_spec.js
+++ b/spec/javascripts/lib/utils/common_utils_spec.js
@@ -266,6 +266,12 @@ import '~/lib/utils/common_utils';
});
describe('gl.utils.backOff', () => {
+ beforeEach(() => {
+ // shortcut our timeouts otherwise these tests will take a long time to finish
+ const origSetTimeout = window.setTimeout;
+ spyOn(window, 'setTimeout').and.callFake(cb => origSetTimeout(cb, 0));
+ });
+
it('solves the promise from the callback', (done) => {
const expectedResponseValue = 'Success!';
gl.utils.backOff((next, stop) => (
@@ -299,37 +305,33 @@ import '~/lib/utils/common_utils';
let numberOfCalls = 1;
const expectedResponseValue = 'Success!';
gl.utils.backOff((next, stop) => (
- new Promise((resolve) => {
- resolve(expectedResponseValue);
- }).then((resp) => {
- if (numberOfCalls < 3) {
- numberOfCalls += 1;
- next();
- } else {
- stop(resp);
- }
- })
+ Promise.resolve(expectedResponseValue)
+ .then((resp) => {
+ if (numberOfCalls < 3) {
+ numberOfCalls += 1;
+ next();
+ } else {
+ stop(resp);
+ }
+ })
)).then((respBackoff) => {
+ const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
+ expect(timeouts).toEqual([2000, 4000]);
expect(respBackoff).toBe(expectedResponseValue);
- expect(numberOfCalls).toBe(3);
done();
});
- }, 10000);
+ });
it('rejects the backOff promise after timing out', (done) => {
- const expectedResponseValue = 'Success!';
- gl.utils.backOff(next => (
- new Promise((resolve) => {
- resolve(expectedResponseValue);
- }).then(() => {
- setTimeout(next(), 5000); // it will time out
- })
- ), 3000).catch((errBackoffResp) => {
- expect(errBackoffResp instanceof Error).toBe(true);
- expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
- done();
- });
- }, 10000);
+ gl.utils.backOff(next => next(), 64000)
+ .catch((errBackoffResp) => {
+ const timeouts = window.setTimeout.calls.allArgs().map(([, timeout]) => timeout);
+ expect(timeouts).toEqual([2000, 4000, 8000, 16000, 32000, 32000]);
+ expect(errBackoffResp instanceof Error).toBe(true);
+ expect(errBackoffResp.message).toBe('BACKOFF_TIMEOUT');
+ done();
+ });
+ });
});
describe('gl.utils.setFavicon', () => {
diff --git a/spec/javascripts/lib/utils/text_utility_spec.js b/spec/javascripts/lib/utils/text_utility_spec.js
index ca1b1b7cc3c..f1a975ba962 100644
--- a/spec/javascripts/lib/utils/text_utility_spec.js
+++ b/spec/javascripts/lib/utils/text_utility_spec.js
@@ -52,6 +52,7 @@ describe('text_utility', () => {
beforeAll(() => {
textArea = document.createElement('textarea');
document.querySelector('body').appendChild(textArea);
+ textArea.focus();
});
afterAll(() => {
diff --git a/spec/javascripts/project_select_combo_button_spec.js b/spec/javascripts/project_select_combo_button_spec.js
index e10a5a3bef6..021804e0769 100644
--- a/spec/javascripts/project_select_combo_button_spec.js
+++ b/spec/javascripts/project_select_combo_button_spec.js
@@ -101,5 +101,40 @@ describe('Project Select Combo Button', function () {
window.localStorage.clear();
});
});
+
+ describe('deriveTextVariants', function () {
+ beforeEach(function () {
+ this.mockExecutionContext = {
+ resourceType: '',
+ resourceLabel: '',
+ };
+
+ this.comboButton = new ProjectSelectComboButton(this.projectSelectInput);
+
+ this.method = this.comboButton.deriveTextVariants.bind(this.mockExecutionContext);
+ });
+
+ it('correctly derives test variants for merge requests', function () {
+ this.mockExecutionContext.resourceType = 'merge_requests';
+ this.mockExecutionContext.resourceLabel = 'New merge request';
+
+ const returnedVariants = this.method();
+
+ expect(returnedVariants.localStorageItemType).toBe('new-merge-request');
+ expect(returnedVariants.defaultTextPrefix).toBe('New merge request');
+ expect(returnedVariants.presetTextSuffix).toBe('merge request');
+ });
+
+ it('correctly derives text variants for issues', function () {
+ this.mockExecutionContext.resourceType = 'issues';
+ this.mockExecutionContext.resourceLabel = 'New issue';
+
+ const returnedVariants = this.method();
+
+ expect(returnedVariants.localStorageItemType).toBe('new-issue');
+ expect(returnedVariants.defaultTextPrefix).toBe('New issue');
+ expect(returnedVariants.presetTextSuffix).toBe('issue');
+ });
+ });
});
diff --git a/spec/javascripts/repo/monaco_loader_spec.js b/spec/javascripts/repo/monaco_loader_spec.js
index be6e779c50f..887a80160fc 100644
--- a/spec/javascripts/repo/monaco_loader_spec.js
+++ b/spec/javascripts/repo/monaco_loader_spec.js
@@ -1,17 +1,13 @@
-/* global __webpack_public_path__ */
import monacoContext from 'monaco-editor/dev/vs/loader';
+import monacoLoader from '~/repo/monaco_loader';
describe('MonacoLoader', () => {
it('calls require.config and exports require', () => {
- spyOn(monacoContext.require, 'config');
-
- const monacoLoader = require('~/repo/monaco_loader'); // eslint-disable-line global-require
-
- expect(monacoContext.require.config).toHaveBeenCalledWith({
+ expect(monacoContext.require.getConfig()).toEqual(jasmine.objectContaining({
paths: {
vs: `${__webpack_public_path__}monaco-editor/vs`, // eslint-disable-line camelcase
},
- });
- expect(monacoLoader.default).toBe(monacoContext.require);
+ }));
+ expect(monacoLoader).toBe(monacoContext.require);
});
});
diff --git a/spec/lib/after_commit_queue_spec.rb b/spec/lib/after_commit_queue_spec.rb
new file mode 100644
index 00000000000..6e7c2ec2363
--- /dev/null
+++ b/spec/lib/after_commit_queue_spec.rb
@@ -0,0 +1,15 @@
+require 'spec_helper'
+
+describe AfterCommitQueue do
+ it 'runs after transaction is committed' do
+ called = false
+ test_proc = proc { called = true }
+
+ project = build(:project)
+ project.run_after_commit(&test_proc)
+
+ project.save
+
+ expect(called).to be true
+ end
+end
diff --git a/spec/lib/api/helpers/pagination_spec.rb b/spec/lib/api/helpers/pagination_spec.rb
index fb3ef04b860..59deca7757b 100644
--- a/spec/lib/api/helpers/pagination_spec.rb
+++ b/spec/lib/api/helpers/pagination_spec.rb
@@ -52,7 +52,13 @@ describe API::Helpers::Pagination do
expect_header('X-Page', '1')
expect_header('X-Next-Page', '2')
expect_header('X-Prev-Page', '')
- expect_header('Link', any_args)
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="first"')
+ expect(val).to include('rel="last"')
+ expect(val).to include('rel="next"')
+ expect(val).not_to include('rel="prev"')
+ end
subject.paginate(resource)
end
@@ -75,15 +81,53 @@ describe API::Helpers::Pagination do
expect_header('X-Page', '2')
expect_header('X-Next-Page', '')
expect_header('X-Prev-Page', '1')
- expect_header('Link', any_args)
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="first"')
+ expect(val).to include('rel="last"')
+ expect(val).to include('rel="prev"')
+ expect(val).not_to include('rel="next"')
+ end
+
+ subject.paginate(resource)
+ end
+ end
+ end
+
+ context 'when resource empty' do
+ describe 'first page' do
+ before do
+ allow(subject).to receive(:params)
+ .and_return({ page: 1, per_page: 2 })
+ end
+
+ it 'returns appropriate amount of resources' do
+ expect(subject.paginate(resource).count).to eq 0
+ end
+
+ it 'adds appropriate headers' do
+ expect_header('X-Total', '0')
+ expect_header('X-Total-Pages', '1')
+ expect_header('X-Per-Page', '2')
+ expect_header('X-Page', '1')
+ expect_header('X-Next-Page', '')
+ expect_header('X-Prev-Page', '')
+
+ expect_header('Link', anything) do |_key, val|
+ expect(val).to include('rel="first"')
+ expect(val).to include('rel="last"')
+ expect(val).not_to include('rel="prev"')
+ expect(val).not_to include('rel="next"')
+ expect(val).not_to include('page=0')
+ end
subject.paginate(resource)
end
end
end
- def expect_header(name, value)
- expect(subject).to receive(:header).with(name, value)
+ def expect_header(*args, &block)
+ expect(subject).to receive(:header).with(*args, &block)
end
def expect_message(method)
diff --git a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
index 7cd2ce82eda..c0427639746 100644
--- a/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
+++ b/spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb
@@ -134,6 +134,17 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits do
include_examples 'updated MR diff'
end
+ context 'when the merge request diffs do not have a_mode and b_mode set' do
+ let(:commits) { merge_request_diff.commits.map(&:to_hash) }
+ let(:expected_diffs) { diffs_to_hashes(merge_request_diff.merge_request_diff_files) }
+
+ let(:diffs) do
+ expected_diffs.map { |diff| diff.except(:a_mode, :b_mode) }
+ end
+
+ include_examples 'updated MR diff'
+ end
+
context 'when the merge request diffs have binary content' do
let(:commits) { merge_request_diff.commits.map(&:to_hash) }
let(:expected_diffs) { diffs }
diff --git a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
index 87f45619e7a..0d5fffa38ff 100644
--- a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
+++ b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb
@@ -210,7 +210,11 @@ describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads::Event do
end
end
-describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads do
+##
+# The background migration relies on a temporary table, hence we're migrating
+# to a specific version of the database where said table is still present.
+#
+describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads, :migration, schema: 20170608152748 do
let(:migration) { described_class.new }
let(:project) { create(:project_empty_repo) }
let(:author) { create(:user) }
@@ -229,21 +233,6 @@ describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads do
)
end
- # The background migration relies on a temporary table, hence we're migrating
- # to a specific version of the database where said table is still present.
- before :all do
- ActiveRecord::Migration.verbose = false
-
- ActiveRecord::Migrator
- .migrate(ActiveRecord::Migrator.migrations_paths, 20170608152748)
- end
-
- after :all do
- ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths)
-
- ActiveRecord::Migration.verbose = true
- end
-
describe '#perform' do
it 'returns if data should not be migrated' do
allow(migration).to receive(:migrate?).and_return(false)
diff --git a/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb
new file mode 100644
index 00000000000..878158910be
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/migrate_stage_status_spec.rb
@@ -0,0 +1,80 @@
+require 'spec_helper'
+
+describe Gitlab::BackgroundMigration::MigrateStageStatus, :migration, schema: 20170711145320 do
+ let(:projects) { table(:projects) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:stages) { table(:ci_stages) }
+ let(:jobs) { table(:ci_builds) }
+
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ before do
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
+ pipelines.create!(id: 1, project_id: 1, ref: 'master', sha: 'adf43c3a')
+ stages.create!(id: 1, pipeline_id: 1, project_id: 1, name: 'test', status: nil)
+ stages.create!(id: 2, pipeline_id: 1, project_id: 1, name: 'deploy', status: nil)
+ end
+
+ context 'when stage status is known' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'running')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'failed')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:running]
+ expect(stages.second.status).to eq STATUSES[:failed]
+ end
+ end
+
+ context 'when stage status is not known' do
+ it 'sets a skipped stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:skipped]
+ expect(stages.second.status).to eq STATUSES[:skipped]
+ end
+ end
+
+ context 'when stage status includes status of a retried job' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'canceled')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'failed', retried: true)
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'success')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:canceled]
+ expect(stages.second.status).to eq STATUSES[:success]
+ end
+ end
+
+ context 'when some job in the stage is blocked / manual' do
+ before do
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'failed')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'manual')
+ create_job(project: 1, pipeline: 1, stage: 'deploy', status: 'success', when: 'manual')
+ end
+
+ it 'sets a correct stage status' do
+ described_class.new.perform(1, 2)
+
+ expect(stages.first.status).to eq STATUSES[:manual]
+ expect(stages.second.status).to eq STATUSES[:success]
+ end
+ end
+
+ def create_job(project:, pipeline:, stage:, status:, **opts)
+ stages = { test: 1, build: 2, deploy: 3 }
+
+ jobs.create!(project_id: project, commit_id: pipeline,
+ stage_idx: stages[stage.to_sym], stage: stage,
+ status: status, **opts)
+ end
+end
diff --git a/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb
index 046b096e366..7e17437fa2a 100644
--- a/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb
@@ -6,9 +6,9 @@ describe Gitlab::Diff::InlineDiffMarkdownMarker do
let(:inline_diffs) { [2..5] }
let(:subject) { described_class.new(raw).mark(inline_diffs, mode: :deletion) }
- it 'marks the range' do
- expect(subject).to eq("ab{-c &#39;d-}ef&#39;")
- expect(subject).to be_html_safe
+ it 'does not escape html etities and marks the range' do
+ expect(subject).to eq("ab{-c 'd-}ef'")
+ expect(subject).not_to be_html_safe
end
end
end
diff --git a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
index c3bf34c24ae..7296bbf5df3 100644
--- a/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
+++ b/spec/lib/gitlab/diff/inline_diff_marker_spec.rb
@@ -2,11 +2,13 @@ require 'spec_helper'
describe Gitlab::Diff::InlineDiffMarker do
describe '#mark' do
+ let(:inline_diffs) { [2..5] }
+ let(:raw) { "abc 'def'" }
+
+ subject { described_class.new(raw, rich).mark(inline_diffs) }
+
context "when the rich text is html safe" do
- let(:raw) { "abc 'def'" }
let(:rich) { %{<span class="abc">abc</span><span class="space"> </span><span class="def">&#39;def&#39;</span>}.html_safe }
- let(:inline_diffs) { [2..5] }
- let(:subject) { described_class.new(raw, rich).mark(inline_diffs) }
it 'marks the range' do
expect(subject).to eq(%{<span class="abc">ab<span class="idiff left">c</span></span><span class="space"><span class="idiff"> </span></span><span class="def"><span class="idiff right">&#39;d</span>ef&#39;</span>})
@@ -15,12 +17,10 @@ describe Gitlab::Diff::InlineDiffMarker do
end
context "when the text text is not html safe" do
- let(:raw) { "abc 'def'" }
- let(:inline_diffs) { [2..5] }
- let(:subject) { described_class.new(raw).mark(inline_diffs) }
+ let(:rich) { "abc 'def' differs" }
it 'marks the range' do
- expect(subject).to eq(%{ab<span class="idiff left right">c &#39;d</span>ef&#39;})
+ expect(subject).to eq(%{ab<span class="idiff left right">c &#39;d</span>ef&#39; differs})
expect(subject).to be_html_safe
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 4ef5d9070a2..8ec8dfe6acf 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -235,18 +235,10 @@ describe Gitlab::Git::Repository, seed_helper: true do
it { is_expected.to be < 2 }
end
- describe '#has_commits?' do
- it { expect(repository.has_commits?).to be_truthy }
- end
-
describe '#empty?' do
it { expect(repository.empty?).to be_falsey }
end
- describe '#bare?' do
- it { expect(repository.bare?).to be_truthy }
- end
-
describe '#ref_names' do
let(:ref_names) { repository.ref_names }
subject { ref_names }
@@ -441,15 +433,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe "#remote_names" do
- let(:remotes) { repository.remote_names }
-
- it "should have one entry: 'origin'" do
- expect(remotes.size).to eq(1)
- expect(remotes.first).to eq("origin")
- end
- end
-
describe "#refs_hash" do
let(:refs) { repository.refs_hash }
@@ -1098,28 +1081,48 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
describe '#tag_exists?' do
- it 'returns true for an existing tag' do
- tag = repository.tag_names.first
+ shared_examples 'checks the existence of tags' do
+ it 'returns true for an existing tag' do
+ tag = repository.tag_names.first
+
+ expect(repository.tag_exists?(tag)).to eq(true)
+ end
- expect(repository.tag_exists?(tag)).to eq(true)
+ it 'returns false for a non-existing tag' do
+ expect(repository.tag_exists?('v9000')).to eq(false)
+ end
end
- it 'returns false for a non-existing tag' do
- expect(repository.tag_exists?('v9000')).to eq(false)
+ context 'when Gitaly ref_exists_tags feature is enabled' do
+ it_behaves_like 'checks the existence of tags'
+ end
+
+ context 'when Gitaly ref_exists_tags feature is disabled', skip_gitaly_mock: true do
+ it_behaves_like 'checks the existence of tags'
end
end
describe '#branch_exists?' do
- it 'returns true for an existing branch' do
- expect(repository.branch_exists?('master')).to eq(true)
+ shared_examples 'checks the existence of branches' do
+ it 'returns true for an existing branch' do
+ expect(repository.branch_exists?('master')).to eq(true)
+ end
+
+ it 'returns false for a non-existing branch' do
+ expect(repository.branch_exists?('kittens')).to eq(false)
+ end
+
+ it 'returns false when using an invalid branch name' do
+ expect(repository.branch_exists?('.bla')).to eq(false)
+ end
end
- it 'returns false for a non-existing branch' do
- expect(repository.branch_exists?('kittens')).to eq(false)
+ context 'when Gitaly ref_exists_branches feature is enabled' do
+ it_behaves_like 'checks the existence of branches'
end
- it 'returns false when using an invalid branch name' do
- expect(repository.branch_exists?('.bla')).to eq(false)
+ context 'when Gitaly ref_exists_branches feature is disabled', skip_gitaly_mock: true do
+ it_behaves_like 'checks the existence of branches'
end
end
diff --git a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
index 12366151f44..c708b15853a 100644
--- a/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
+++ b/spec/lib/gitlab/git/storage/forked_storage_check_spec.rb
@@ -1,6 +1,6 @@
require 'spec_helper'
-describe Gitlab::Git::Storage::ForkedStorageCheck, skip_database_cleaner: true do
+describe Gitlab::Git::Storage::ForkedStorageCheck, broken_storage: true, skip_database_cleaner: true do
let(:existing_path) do
existing_path = TestEnv.repos_path
FileUtils.mkdir_p(existing_path)
diff --git a/spec/lib/gitlab/git_access_spec.rb b/spec/lib/gitlab/git_access_spec.rb
index 2d6ea37d0ac..80dc49e99cb 100644
--- a/spec/lib/gitlab/git_access_spec.rb
+++ b/spec/lib/gitlab/git_access_spec.rb
@@ -1,21 +1,17 @@
require 'spec_helper'
describe Gitlab::GitAccess do
- let(:pull_access_check) { access.check('git-upload-pack', '_any') }
- let(:push_access_check) { access.check('git-receive-pack', '_any') }
- let(:access) { described_class.new(actor, project, protocol, authentication_abilities: authentication_abilities, redirected_path: redirected_path) }
- let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
+ set(:user) { create(:user) }
+
let(:actor) { user }
+ let(:project) { create(:project, :repository) }
let(:protocol) { 'ssh' }
+ let(:authentication_abilities) { %i[read_project download_code push_code] }
let(:redirected_path) { nil }
- let(:authentication_abilities) do
- [
- :read_project,
- :download_code,
- :push_code
- ]
- end
+
+ let(:access) { described_class.new(actor, project, protocol, authentication_abilities: authentication_abilities, redirected_path: redirected_path) }
+ let(:push_access_check) { access.check('git-receive-pack', '_any') }
+ let(:pull_access_check) { access.check('git-upload-pack', '_any') }
describe '#check with single protocols allowed' do
def disable_protocol(protocol)
@@ -27,12 +23,11 @@ describe Gitlab::GitAccess do
disable_protocol('ssh')
end
- it 'blocks ssh git push' do
- expect { push_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
- end
-
- it 'blocks ssh git pull' do
- expect { pull_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ it 'blocks ssh git push and pull' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ expect { pull_access_check }.to raise_unauthorized('Git access over SSH is not allowed')
+ end
end
end
@@ -43,12 +38,11 @@ describe Gitlab::GitAccess do
disable_protocol('http')
end
- it 'blocks http push' do
- expect { push_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
- end
-
- it 'blocks http git pull' do
- expect { pull_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ it 'blocks http push and pull' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ expect { pull_access_check }.to raise_unauthorized('Git access over HTTP is not allowed')
+ end
end
end
end
@@ -65,22 +59,20 @@ describe Gitlab::GitAccess do
deploy_key.projects << project
end
- it 'allows pull access' do
- expect { pull_access_check }.not_to raise_error
- end
-
- it 'allows push access' do
- expect { push_access_check }.not_to raise_error
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.not_to raise_error
+ expect { pull_access_check }.not_to raise_error
+ end
end
end
context 'when the Deploykey does not have access to the project' do
- it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- end
-
- it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_not_found
+ expect { pull_access_check }.to raise_not_found
+ end
end
end
end
@@ -88,25 +80,23 @@ describe Gitlab::GitAccess do
context 'when actor is a User' do
context 'when the User can read the project' do
before do
- project.team << [user, :master]
+ project.add_master(user)
end
- it 'allows pull access' do
- expect { pull_access_check }.not_to raise_error
- end
-
- it 'allows push access' do
- expect { push_access_check }.not_to raise_error
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { pull_access_check }.not_to raise_error
+ expect { push_access_check }.not_to raise_error
+ end
end
end
context 'when the User cannot read the project' do
- it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- end
-
- it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_not_found
+ expect { pull_access_check }.to raise_not_found
+ end
end
end
end
@@ -121,7 +111,7 @@ describe Gitlab::GitAccess do
end
it 'does not block pushes with "not found"' do
- expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.')
+ expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload])
end
end
end
@@ -137,17 +127,17 @@ describe Gitlab::GitAccess do
end
it 'does not block pushes with "not found"' do
- expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.')
+ expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload])
end
end
context 'when guests cannot read the project' do
it 'blocks pulls with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ expect { pull_access_check }.to raise_not_found
end
it 'blocks pushes with "not found"' do
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ expect { push_access_check }.to raise_not_found
end
end
end
@@ -156,48 +146,50 @@ describe Gitlab::GitAccess do
context 'when the project is nil' do
let(:project) { nil }
- it 'blocks any command with "not found"' do
- expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.')
- expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.')
+ it 'blocks push and pull with "not found"' do
+ aggregate_failures do
+ expect { pull_access_check }.to raise_not_found
+ expect { push_access_check }.to raise_not_found
+ end
end
end
end
describe '#check_project_moved!' do
before do
- project.team << [user, :master]
+ project.add_master(user)
end
context 'when a redirect was not followed to find the project' do
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
- end
-
- context 'push code' do
- it { expect { push_access_check }.not_to raise_error }
+ it 'allows push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.not_to raise_error
+ expect { pull_access_check }.not_to raise_error
+ end
end
end
context 'when a redirect was followed to find the project' do
let(:redirected_path) { 'some/other-path' }
- context 'pull code' do
- it { expect { pull_access_check }.to raise_not_found(/Project '#{redirected_path}' was moved to '#{project.full_path}'/) }
- it { expect { pull_access_check }.to raise_not_found(/git remote set-url origin #{project.ssh_url_to_repo}/) }
+ it 'blocks push and pull access' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
- context 'http protocol' do
- let(:protocol) { 'http' }
- it { expect { pull_access_check }.to raise_not_found(/git remote set-url origin #{project.http_url_to_repo}/) }
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /Project '#{redirected_path}' was moved to '#{project.full_path}'/)
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.ssh_url_to_repo}/)
end
end
- context 'push code' do
- it { expect { push_access_check }.to raise_not_found(/Project '#{redirected_path}' was moved to '#{project.full_path}'/) }
- it { expect { push_access_check }.to raise_not_found(/git remote set-url origin #{project.ssh_url_to_repo}/) }
+ context 'http protocol' do
+ let(:protocol) { 'http' }
- context 'http protocol' do
- let(:protocol) { 'http' }
- it { expect { push_access_check }.to raise_not_found(/git remote set-url origin #{project.http_url_to_repo}/) }
+ it 'includes the path to the project using HTTP' do
+ aggregate_failures do
+ expect { push_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
+ expect { pull_access_check }.to raise_error(described_class::ProjectMovedError, /git remote set-url origin #{project.http_url_to_repo}/)
+ end
end
end
end
@@ -242,40 +234,28 @@ describe Gitlab::GitAccess do
end
describe '#check_download_access!' do
- describe 'master permissions' do
- before do
- project.team << [user, :master]
- end
+ it 'allows masters to pull' do
+ project.add_master(user)
- context 'pull code' do
- it { expect { pull_access_check }.not_to raise_error }
- end
+ expect { pull_access_check }.not_to raise_error
end
- describe 'guest permissions' do
- before do
- project.team << [user, :guest]
- end
+ it 'disallows guests to pull' do
+ project.add_guest(user)
- context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') }
- end
+ expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download])
end
- describe 'blocked user' do
- before do
- project.team << [user, :master]
- user.block
- end
+ it 'disallows blocked users to pull' do
+ project.add_master(user)
+ user.block
- context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('Your account has been blocked.') }
- end
+ expect { pull_access_check }.to raise_unauthorized('Your account has been blocked.')
end
describe 'without access to project' do
context 'pull code' do
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
context 'when project is public' do
@@ -292,7 +272,7 @@ describe Gitlab::GitAccess do
it 'does not give access to download code' do
public_project.project_feature.update_attribute(:repository_access_level, ProjectFeature::DISABLED)
- expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.')
+ expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download])
end
end
end
@@ -321,13 +301,13 @@ describe Gitlab::GitAccess do
context 'from internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
context 'from private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { pull_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { pull_access_check }.to raise_not_found }
end
end
end
@@ -369,7 +349,7 @@ describe Gitlab::GitAccess do
context 'when is not member of the project' do
context 'pull code' do
- it { expect { pull_access_check }.to raise_unauthorized('You are not allowed to download code from this project.') }
+ it { expect { pull_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:download]) }
end
end
end
@@ -428,28 +408,30 @@ describe Gitlab::GitAccess do
end
end
- # Run permission checks for a user
def self.run_permission_checks(permissions_matrix)
- permissions_matrix.keys.each do |role|
- describe "#{role} access" do
- before do
- if role == :admin
- user.update_attribute(:admin, true)
- else
- project.team << [user, role]
- end
+ permissions_matrix.each_pair do |role, matrix|
+ # Run through the entire matrix for this role in one test to avoid
+ # repeated setup.
+ #
+ # Expectations are given a custom failure message proc so that it's
+ # easier to identify which check(s) failed.
+ it "has the correct permissions for #{role}s" do
+ if role == :admin
+ user.update_attribute(:admin, true)
+ else
+ project.team << [user, role]
end
- permissions_matrix[role].each do |action, allowed|
- context action.to_s do
- subject { access.send(:check_push_access!, changes[action]) }
+ aggregate_failures do
+ matrix.each do |action, allowed|
+ check = -> { access.send(:check_push_access!, changes[action]) }
- it do
- if allowed
- expect { subject }.not_to raise_error
- else
- expect { subject }.to raise_error(Gitlab::GitAccess::UnauthorizedError)
- end
+ if allowed
+ expect(&check).not_to raise_error,
+ -> { "expected #{action} to be allowed" }
+ else
+ expect(&check).to raise_error(Gitlab::GitAccess::UnauthorizedError),
+ -> { "expected #{action} to be disallowed" }
end
end
end
@@ -588,26 +570,26 @@ describe Gitlab::GitAccess do
project.team << [user, :reporter]
end
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'when unauthorized' do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('You are not allowed to upload code for this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:upload]) }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -631,19 +613,19 @@ describe Gitlab::GitAccess do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -656,26 +638,26 @@ describe Gitlab::GitAccess do
key.projects << project
end
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'when unauthorized' do
context 'to public project' do
let(:project) { create(:project, :public, :repository) }
- it { expect { push_access_check }.to raise_unauthorized('This deploy key does not have write access to this project.') }
+ it { expect { push_access_check }.to raise_unauthorized(described_class::ERROR_MESSAGES[:deploy_key_upload]) }
end
context 'to internal project' do
let(:project) { create(:project, :internal, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
context 'to private project' do
let(:project) { create(:project, :private, :repository) }
- it { expect { push_access_check }.to raise_not_found('The project you were looking for could not be found.') }
+ it { expect { push_access_check }.to raise_not_found }
end
end
end
@@ -687,8 +669,9 @@ describe Gitlab::GitAccess do
raise_error(Gitlab::GitAccess::UnauthorizedError, message)
end
- def raise_not_found(message)
- raise_error(Gitlab::GitAccess::NotFoundError, message)
+ def raise_not_found
+ raise_error(Gitlab::GitAccess::NotFoundError,
+ Gitlab::GitAccess::ERROR_MESSAGES[:project_not_found])
end
def build_authentication_abilities
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index 7fe698fcb18..2eaf4222964 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -111,6 +111,20 @@ describe Gitlab::GitalyClient::CommitService do
client.tree_entries(repository, revision, path)
end
+
+ context 'with UTF-8 params strings' do
+ let(:revision) { "branch\u011F" }
+ let(:path) { "foo/\u011F.txt" }
+
+ it 'handles string encodings correctly' do
+ expect_any_instance_of(Gitaly::CommitService::Stub)
+ .to receive(:get_tree_entries)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return([])
+
+ client.tree_entries(repository, revision, path)
+ end
+ end
end
describe '#find_commit' do
diff --git a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
index 46efc1b18f0..6f59750b4da 100644
--- a/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/ref_service_spec.rb
@@ -1,10 +1,11 @@
require 'spec_helper'
describe Gitlab::GitalyClient::RefService do
- let(:project) { create(:project) }
+ let(:project) { create(:project, :repository) }
let(:storage_name) { project.repository_storage }
let(:relative_path) { project.disk_path + '.git' }
- let(:client) { described_class.new(project.repository) }
+ let(:repository) { project.repository }
+ let(:client) { described_class.new(repository) }
describe '#branches' do
it 'sends a find_all_branches message' do
@@ -84,11 +85,23 @@ describe Gitlab::GitalyClient::RefService do
end
describe '#find_ref_name', seed_helper: true do
- let(:repository) { Gitlab::Git::Repository.new('default', TEST_REPO_PATH) }
- let(:client) { described_class.new(repository) }
subject { client.find_ref_name(SeedRepo::Commit::ID, 'refs/heads/master') }
it { is_expected.to be_utf8 }
it { is_expected.to eq('refs/heads/master') }
end
+
+ describe '#ref_exists?', seed_helper: true do
+ it 'finds the master branch ref' do
+ expect(client.ref_exists?('refs/heads/master')).to eq(true)
+ end
+
+ it 'returns false for an illegal tag name ref' do
+ expect(client.ref_exists?('refs/tags/.this-tag-name-is-illegal')).to eq(false)
+ end
+
+ it 'raises an argument error if the ref name parameter does not start with refs/' do
+ expect { client.ref_exists?('reXXXXX') }.to raise_error(ArgumentError)
+ end
+ end
end
diff --git a/spec/lib/gitlab/gitaly_client/repository_service_spec.rb b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
new file mode 100644
index 00000000000..fd5f984601e
--- /dev/null
+++ b/spec/lib/gitlab/gitaly_client/repository_service_spec.rb
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe Gitlab::GitalyClient::RepositoryService do
+ let(:project) { create(:project) }
+ let(:storage_name) { project.repository_storage }
+ let(:relative_path) { project.disk_path + '.git' }
+ let(:client) { described_class.new(project.repository) }
+
+ describe '#exists?' do
+ it 'sends a repository_exists message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:repository_exists)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(exists: true))
+
+ client.exists?
+ end
+ end
+
+ describe '#garbage_collect' do
+ it 'sends a garbage_collect message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:garbage_collect)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(:garbage_collect_response))
+
+ client.garbage_collect(true)
+ end
+ end
+
+ describe '#repack_full' do
+ it 'sends a repack_full message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:repack_full)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(:repack_full_response))
+
+ client.repack_full(true)
+ end
+ end
+
+ describe '#repack_incremental' do
+ it 'sends a repack_incremental message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:repack_incremental)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(:repack_incremental_response))
+
+ client.repack_incremental
+ end
+ end
+
+ describe '#repository_size' do
+ it 'sends a repository_size message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:repository_size)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(size: 0)
+
+ client.repository_size
+ end
+ end
+
+ describe '#apply_gitattributes' do
+ let(:revision) { 'master' }
+
+ it 'sends an apply_gitattributes message' do
+ expect_any_instance_of(Gitaly::RepositoryService::Stub)
+ .to receive(:apply_gitattributes)
+ .with(gitaly_request_with_path(storage_name, relative_path), kind_of(Hash))
+ .and_return(double(:apply_gitattributes_response))
+
+ client.apply_gitattributes(revision)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/project.json b/spec/lib/gitlab/import_export/project.json
index 4e631e13410..331b7cf2fea 100644
--- a/spec/lib/gitlab/import_export/project.json
+++ b/spec/lib/gitlab/import_export/project.json
@@ -2522,7 +2522,7 @@
"id": 27,
"target_branch": "feature",
"source_branch": "feature_conflict",
- "source_project_id": 5,
+ "source_project_id": 999,
"author_id": 1,
"assignee_id": null,
"title": "MR1",
@@ -2536,6 +2536,9 @@
"position": 0,
"updated_by_id": null,
"merge_error": null,
+ "diff_head_sha": "HEAD",
+ "source_branch_sha": "ABCD",
+ "target_branch_sha": "DCBA",
"merge_params": {
"force_remove_source_branch": null
},
diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
index 956f1d56eb4..c10427d798f 100644
--- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb
@@ -10,6 +10,13 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
@shared = Gitlab::ImportExport::Shared.new(relative_path: "", project_path: 'path')
allow(@shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/')
@project = create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project')
+
+ allow(@project.repository).to receive(:fetch_ref).and_return(true)
+ allow(@project.repository.raw).to receive(:rugged_branch_exists?).and_return(false)
+
+ expect_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch).with('feature', 'DCBA')
+ allow_any_instance_of(Gitlab::Git::Repository).to receive(:create_branch)
+
project_tree_restorer = described_class.new(user: @user, shared: @shared, project: @project)
@restored_project_json = project_tree_restorer.restore
end
diff --git a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
index a278f89c1a1..065b0ec6658 100644
--- a/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project_tree_saver_spec.rb
@@ -11,6 +11,8 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
before do
project.team << [user, :master]
allow_any_instance_of(Gitlab::ImportExport).to receive(:storage_path).and_return(export_path)
+ allow_any_instance_of(MergeRequest).to receive(:source_branch_sha).and_return('ABCD')
+ allow_any_instance_of(MergeRequest).to receive(:target_branch_sha).and_return('DCBA')
end
after do
@@ -43,6 +45,14 @@ describe Gitlab::ImportExport::ProjectTreeSaver do
expect(saved_project_json['merge_requests'].first['milestone']).not_to be_empty
end
+ it 'has merge request\'s source branch SHA' do
+ expect(saved_project_json['merge_requests'].first['source_branch_sha']).to eq('ABCD')
+ end
+
+ it 'has merge request\'s target branch SHA' do
+ expect(saved_project_json['merge_requests'].first['target_branch_sha']).to eq('DCBA')
+ end
+
it 'has events' do
expect(saved_project_json['merge_requests'].first['milestone']['events']).not_to be_empty
end
diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml
index ae3b0173160..a5e03e149a7 100644
--- a/spec/lib/gitlab/import_export/safe_model_attributes.yml
+++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml
@@ -227,6 +227,8 @@ Ci::Pipeline:
Ci::Stage:
- id
- name
+- status
+- lock_version
- project_id
- pipeline_id
- created_at
diff --git a/spec/lib/gitlab/job_waiter_spec.rb b/spec/lib/gitlab/job_waiter_spec.rb
index 6186cec2689..b0b4fdc09bc 100644
--- a/spec/lib/gitlab/job_waiter_spec.rb
+++ b/spec/lib/gitlab/job_waiter_spec.rb
@@ -1,30 +1,39 @@
require 'spec_helper'
describe Gitlab::JobWaiter do
- describe '#wait' do
- let(:waiter) { described_class.new(%w(a)) }
- it 'returns when all jobs have been completed' do
- expect(Gitlab::SidekiqStatus).to receive(:all_completed?).with(%w(a))
- .and_return(true)
+ describe '.notify' do
+ it 'pushes the jid to the named queue' do
+ key = 'gitlab:job_waiter:foo'
+ jid = 1
- expect(waiter).not_to receive(:sleep)
+ redis = double('redis')
+ expect(Gitlab::Redis::SharedState).to receive(:with).and_yield(redis)
+ expect(redis).to receive(:lpush).with(key, jid)
- waiter.wait
+ described_class.notify(key, jid)
end
+ end
+
+ describe '#wait' do
+ let(:waiter) { described_class.new(2) }
- it 'sleeps between checking the job statuses' do
- expect(Gitlab::SidekiqStatus).to receive(:all_completed?)
- .with(%w(a))
- .and_return(false, true)
+ it 'returns when all jobs have been completed' do
+ described_class.notify(waiter.key, 'a')
+ described_class.notify(waiter.key, 'b')
- expect(waiter).to receive(:sleep).with(described_class::INTERVAL)
+ result = nil
+ expect { Timeout.timeout(1) { result = waiter.wait(2) } }.not_to raise_error
- waiter.wait
+ expect(result).to contain_exactly('a', 'b')
end
- it 'returns when timing out' do
- expect(waiter).not_to receive(:sleep)
- waiter.wait(0)
+ it 'times out if not all jobs complete' do
+ described_class.notify(waiter.key, 'a')
+
+ result = nil
+ expect { Timeout.timeout(2) { result = waiter.wait(1) } }.not_to raise_error
+
+ expect(result).to contain_exactly('a')
end
end
end
diff --git a/spec/lib/gitlab/sidekiq_throttler_spec.rb b/spec/lib/gitlab/sidekiq_throttler_spec.rb
index 6374ac80207..2dbb7bb7c34 100644
--- a/spec/lib/gitlab/sidekiq_throttler_spec.rb
+++ b/spec/lib/gitlab/sidekiq_throttler_spec.rb
@@ -1,28 +1,44 @@
require 'spec_helper'
describe Gitlab::SidekiqThrottler do
- before do
- Sidekiq.options[:concurrency] = 35
-
- stub_application_setting(
- sidekiq_throttling_enabled: true,
- sidekiq_throttling_factor: 0.1,
- sidekiq_throttling_queues: %w[build project_cache]
- )
- end
-
describe '#execute!' do
- it 'sets limits on the selected queues' do
- described_class.execute!
+ context 'when job throttling is enabled' do
+ before do
+ Sidekiq.options[:concurrency] = 35
+
+ stub_application_setting(
+ sidekiq_throttling_enabled: true,
+ sidekiq_throttling_factor: 0.1,
+ sidekiq_throttling_queues: %w[build project_cache]
+ )
+ end
+
+ it 'requires sidekiq-limit_fetch' do
+ expect(described_class).to receive(:require).with('sidekiq-limit_fetch').and_call_original
+
+ described_class.execute!
+ end
+
+ it 'sets limits on the selected queues' do
+ described_class.execute!
+
+ expect(Sidekiq::Queue['build'].limit).to eq 4
+ expect(Sidekiq::Queue['project_cache'].limit).to eq 4
+ end
+
+ it 'does not set limits on other queues' do
+ described_class.execute!
- expect(Sidekiq::Queue['build'].limit).to eq 4
- expect(Sidekiq::Queue['project_cache'].limit).to eq 4
+ expect(Sidekiq::Queue['merge'].limit).to be_nil
+ end
end
- it 'does not set limits on other queues' do
- described_class.execute!
+ context 'when job throttling is disabled' do
+ it 'does not require sidekiq-limit_fetch' do
+ expect(described_class).not_to receive(:require).with('sidekiq-limit_fetch')
- expect(Sidekiq::Queue['merge'].limit).to be_nil
+ described_class.execute!
+ end
end
end
end
diff --git a/spec/lib/gitlab/string_range_marker_spec.rb b/spec/lib/gitlab/string_range_marker_spec.rb
index abeaa7f0ddb..6bc02459dbd 100644
--- a/spec/lib/gitlab/string_range_marker_spec.rb
+++ b/spec/lib/gitlab/string_range_marker_spec.rb
@@ -2,34 +2,39 @@ require 'spec_helper'
describe Gitlab::StringRangeMarker do
describe '#mark' do
+ def mark_diff(rich = nil)
+ raw = 'abc <def>'
+ inline_diffs = [2..5]
+
+ described_class.new(raw, rich).mark(inline_diffs) do |text, left:, right:|
+ "LEFT#{text}RIGHT"
+ end
+ end
+
context "when the rich text is html safe" do
- let(:raw) { "abc <def>" }
let(:rich) { %{<span class="abc">abc</span><span class="space"> </span><span class="def">&lt;def&gt;</span>}.html_safe }
- let(:inline_diffs) { [2..5] }
- subject do
- described_class.new(raw, rich).mark(inline_diffs) do |text, left:, right:|
- "LEFT#{text}RIGHT"
- end
- end
it 'marks the inline diffs' do
- expect(subject).to eq(%{<span class="abc">abLEFTcRIGHT</span><span class="space">LEFT RIGHT</span><span class="def">LEFT&lt;dRIGHTef&gt;</span>})
- expect(subject).to be_html_safe
+ expect(mark_diff(rich)).to eq(%{<span class="abc">abLEFTcRIGHT</span><span class="space">LEFT RIGHT</span><span class="def">LEFT&lt;dRIGHTef&gt;</span>})
+ expect(mark_diff(rich)).to be_html_safe
end
end
context "when the rich text is not html safe" do
- let(:raw) { "abc <def>" }
- let(:inline_diffs) { [2..5] }
- subject do
- described_class.new(raw).mark(inline_diffs) do |text, left:, right:|
- "LEFT#{text}RIGHT"
+ context 'when rich text equals raw text' do
+ it 'marks the inline diffs' do
+ expect(mark_diff).to eq(%{abLEFTc <dRIGHTef>})
+ expect(mark_diff).not_to be_html_safe
end
end
- it 'marks the inline diffs' do
- expect(subject).to eq(%{abLEFTc &lt;dRIGHTef&gt;})
- expect(subject).to be_html_safe
+ context 'when rich text doeas not equal raw text' do
+ let(:rich) { "abc <def> differs" }
+
+ it 'marks the inline diffs' do
+ expect(mark_diff(rich)).to eq(%{abLEFTc &lt;dRIGHTef&gt; differs})
+ expect(mark_diff(rich)).to be_html_safe
+ end
end
end
end
diff --git a/spec/migrations/README.md b/spec/migrations/README.md
index 05d4f35db72..45cf25b96de 100644
--- a/spec/migrations/README.md
+++ b/spec/migrations/README.md
@@ -28,6 +28,14 @@ The `after` hook will migrate the database **up** and reinstitutes the latest
schema version, so that the process does not affect subsequent specs and
ensures proper isolation.
+## Testing a class that is not an ActiveRecord::Migration
+
+In order to test a class that is not a migration itself, you will need to
+manually provide a required schema version. Please add a `schema` tag to a
+context that you want to switch the database schema within.
+
+Example: `describe SomeClass, :migration, schema: 20170608152748`.
+
## Available helpers
Use `table` helper to create a temporary `ActiveRecord::Base` derived model
@@ -80,8 +88,6 @@ end
## Best practices
-1. Use only one test example per migration unless there is a good reason to
-use more.
1. Note that this type of tests do not run within the transaction, we use
a truncation database cleanup strategy. Do not depend on transaction being
present.
diff --git a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
index 12cac1d033d..b47f3314926 100644
--- a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
+++ b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb
@@ -4,7 +4,7 @@ require Rails.root.join('db', 'post_migrate', '20170502101023_cleanup_namespacel
describe CleanupNamespacelessPendingDeleteProjects do
before do
# Stub after_save callbacks that will fail when Project has no namespace
- allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exists).and_return(nil)
allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
end
diff --git a/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb b/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb
new file mode 100644
index 00000000000..7879105a334
--- /dev/null
+++ b/spec/migrations/cleanup_nonexisting_namespace_pending_delete_projects_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170816102555_cleanup_nonexisting_namespace_pending_delete_projects.rb')
+
+describe CleanupNonexistingNamespacePendingDeleteProjects do
+ before do
+ # Stub after_save callbacks that will fail when Project has invalid namespace
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
+ end
+
+ describe '#up' do
+ set(:some_project) { create(:project) }
+
+ it 'only cleans up when namespace does not exist' do
+ create(:project, pending_delete: true)
+ project = build(:project, pending_delete: true, namespace: nil, namespace_id: Namespace.maximum(:id).to_i.succ)
+ project.save(validate: false)
+
+ expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]])
+
+ described_class.new.up
+ end
+
+ it 'does nothing when no pending delete projects without namespace found' do
+ create(:project, pending_delete: true, namespace: create(:namespace))
+
+ expect(NamespacelessProjectDestroyWorker).not_to receive(:bulk_perform_async)
+
+ described_class.new.up
+ end
+ end
+end
diff --git a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
index 260378adaa7..9b92f4b70b0 100644
--- a/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
+++ b/spec/migrations/migrate_stage_id_reference_in_background_spec.rb
@@ -2,19 +2,6 @@ require 'spec_helper'
require Rails.root.join('db', 'post_migrate', '20170628080858_migrate_stage_id_reference_in_background')
describe MigrateStageIdReferenceInBackground, :migration, :sidekiq do
- matcher :be_scheduled_migration do |delay, *expected|
- match do |migration|
- BackgroundMigrationWorker.jobs.any? do |job|
- job['args'] == [migration, expected] &&
- job['at'].to_i == (delay.to_i + Time.now.to_i)
- end
- end
-
- failure_message do |migration|
- "Migration `#{migration}` with args `#{expected.inspect}` not scheduled!"
- end
- end
-
let(:jobs) { table(:ci_builds) }
let(:stages) { table(:ci_stages) }
let(:pipelines) { table(:ci_pipelines) }
diff --git a/spec/migrations/migrate_stages_statuses_spec.rb b/spec/migrations/migrate_stages_statuses_spec.rb
new file mode 100644
index 00000000000..4102d57e368
--- /dev/null
+++ b/spec/migrations/migrate_stages_statuses_spec.rb
@@ -0,0 +1,67 @@
+require 'spec_helper'
+require Rails.root.join('db', 'post_migrate', '20170711145558_migrate_stages_statuses.rb')
+
+describe MigrateStagesStatuses, :migration do
+ let(:jobs) { table(:ci_builds) }
+ let(:stages) { table(:ci_stages) }
+ let(:pipelines) { table(:ci_pipelines) }
+ let(:projects) { table(:projects) }
+
+ STATUSES = { created: 0, pending: 1, running: 2, success: 3,
+ failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze
+
+ before do
+ stub_const("#{described_class.name}::BATCH_SIZE", 2)
+ stub_const("#{described_class.name}::RANGE_SIZE", 2)
+
+ projects.create!(id: 1, name: 'gitlab1', path: 'gitlab1')
+ projects.create!(id: 2, name: 'gitlab2', path: 'gitlab2')
+
+ pipelines.create!(id: 1, project_id: 1, ref: 'master', sha: 'adf43c3a')
+ pipelines.create!(id: 2, project_id: 2, ref: 'feature', sha: '21a3deb')
+
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'test', status: 'running')
+ create_job(project: 1, pipeline: 1, stage: 'build', status: 'success')
+ create_job(project: 1, pipeline: 1, stage: 'build', status: 'failed')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'success')
+ create_job(project: 2, pipeline: 2, stage: 'test', status: 'failed', retried: true)
+
+ stages.create!(id: 1, pipeline_id: 1, project_id: 1, name: 'test', status: nil)
+ stages.create!(id: 2, pipeline_id: 1, project_id: 1, name: 'build', status: nil)
+ stages.create!(id: 3, pipeline_id: 2, project_id: 2, name: 'test', status: nil)
+ end
+
+ it 'correctly migrates stages statuses' do
+ Sidekiq::Testing.inline! do
+ expect(stages.where(status: nil).count).to eq 3
+
+ migrate!
+
+ expect(stages.where(status: nil)).to be_empty
+ expect(stages.all.order('id ASC').pluck(:status))
+ .to eq [STATUSES[:running], STATUSES[:failed], STATUSES[:success]]
+ end
+ end
+
+ it 'correctly schedules background migrations' do
+ Sidekiq::Testing.fake! do
+ Timecop.freeze do
+ migrate!
+
+ expect(described_class::MIGRATION).to be_scheduled_migration(5.minutes, 1, 2)
+ expect(described_class::MIGRATION).to be_scheduled_migration(10.minutes, 3, 3)
+ expect(BackgroundMigrationWorker.jobs.size).to eq 2
+ end
+ end
+ end
+
+ def create_job(project:, pipeline:, stage:, status:, **opts)
+ stages = { test: 1, build: 2, deploy: 3 }
+
+ jobs.create!(project_id: project, commit_id: pipeline,
+ stage_idx: stages[stage.to_sym], stage: stage,
+ status: status, **opts)
+ end
+end
diff --git a/spec/migrations/remove_dot_git_from_usernames_spec.rb b/spec/migrations/remove_dot_git_from_usernames_spec.rb
index 8737e00eaeb..129374cb38c 100644
--- a/spec/migrations/remove_dot_git_from_usernames_spec.rb
+++ b/spec/migrations/remove_dot_git_from_usernames_spec.rb
@@ -51,7 +51,6 @@ describe RemoveDotGitFromUsernames do
namespace.path = path
namespace.save!(validate: false)
- user.username = path
- user.save!(validate: false)
+ user.update_column(:username, path)
end
end
diff --git a/spec/models/broadcast_message_spec.rb b/spec/models/broadcast_message_spec.rb
index 3369aef1d3e..461e754dc1f 100644
--- a/spec/models/broadcast_message_spec.rb
+++ b/spec/models/broadcast_message_spec.rb
@@ -53,6 +53,29 @@ describe BroadcastMessage do
2.times { described_class.current }
end
+
+ it 'includes messages that need to be displayed in the future' do
+ create(:broadcast_message)
+
+ future = create(
+ :broadcast_message,
+ starts_at: Time.now + 10.minutes,
+ ends_at: Time.now + 20.minutes
+ )
+
+ expect(described_class.current.length).to eq(1)
+
+ Timecop.travel(future.starts_at) do
+ expect(described_class.current.length).to eq(2)
+ end
+ end
+
+ it 'does not clear the cache if only a future message should be displayed' do
+ create(:broadcast_message, :future)
+
+ expect(Rails.cache).not_to receive(:delete)
+ expect(described_class.current.length).to eq(0)
+ end
end
describe '#active?' do
diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb
new file mode 100644
index 00000000000..74c9d6145e2
--- /dev/null
+++ b/spec/models/ci/stage_spec.rb
@@ -0,0 +1,79 @@
+require 'spec_helper'
+
+describe Ci::Stage, :models do
+ let(:stage) { create(:ci_stage_entity) }
+
+ describe 'associations' do
+ before do
+ create(:ci_build, stage_id: stage.id)
+ create(:commit_status, stage_id: stage.id)
+ end
+
+ describe '#statuses' do
+ it 'returns all commit statuses' do
+ expect(stage.statuses.count).to be 2
+ end
+ end
+
+ describe '#builds' do
+ it 'returns only builds' do
+ expect(stage.builds).to be_one
+ end
+ end
+ end
+
+ describe '#status' do
+ context 'when stage is pending' do
+ let(:stage) { create(:ci_stage_entity, status: 'pending') }
+
+ it 'has a correct status value' do
+ expect(stage.status).to eq 'pending'
+ end
+ end
+
+ context 'when stage is success' do
+ let(:stage) { create(:ci_stage_entity, status: 'success') }
+
+ it 'has a correct status value' do
+ expect(stage.status).to eq 'success'
+ end
+ end
+ end
+
+ describe 'update_status' do
+ context 'when stage objects needs to be updated' do
+ before do
+ create(:ci_build, :success, stage_id: stage.id)
+ create(:ci_build, :running, stage_id: stage.id)
+ end
+
+ it 'updates stage status correctly' do
+ expect { stage.update_status }
+ .to change { stage.reload.status }
+ .to 'running'
+ end
+ end
+
+ context 'when stage is skipped' do
+ it 'updates status to skipped' do
+ expect { stage.update_status }
+ .to change { stage.reload.status }
+ .to 'skipped'
+ end
+ end
+
+ context 'when stage object is locked' do
+ before do
+ create(:ci_build, :failed, stage_id: stage.id)
+ end
+
+ it 'retries a lock to update a stage status' do
+ stage.lock_version = 100
+
+ stage.update_status
+
+ expect(stage.reload).to be_failed
+ end
+ end
+ end
+end
diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb
index 8c4a366ef8f..f7583645e69 100644
--- a/spec/models/commit_status_spec.rb
+++ b/spec/models/commit_status_spec.rb
@@ -7,10 +7,10 @@ describe CommitStatus do
create(:ci_pipeline, project: project, sha: project.commit.id)
end
- let(:commit_status) { create_status }
+ let(:commit_status) { create_status(stage: 'test') }
- def create_status(args = {})
- create(:commit_status, args.merge(pipeline: pipeline))
+ def create_status(**opts)
+ create(:commit_status, pipeline: pipeline, **opts)
end
it { is_expected.to belong_to(:pipeline) }
diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb
index 55b96a0c12e..b1743cd608e 100644
--- a/spec/models/project_services/kubernetes_service_spec.rb
+++ b/spec/models/project_services/kubernetes_service_spec.rb
@@ -38,7 +38,8 @@ describe KubernetesService, :use_clean_rails_memory_store_caching do
'a' * 63 => true,
'a' * 64 => false,
'a.b' => false,
- 'a*b' => false
+ 'a*b' => false,
+ 'FOO' => true
}.each do |namespace, validity|
it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do
subject.namespace = namespace
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e1d64986a76..2e613c44357 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -1251,60 +1251,6 @@ describe Project do
end
end
- describe '#rename_repo' do
- let(:project) { create(:project, :repository) }
- let(:gitlab_shell) { Gitlab::Shell.new }
-
- before do
- # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
- # call. This makes testing a bit easier.
- allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
- allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
- end
-
- it 'renames a repository' do
- stub_container_registry_config(enabled: false)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}")
- .and_return(true)
-
- expect(gitlab_shell).to receive(:mv_repository)
- .ordered
- .with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
- .and_return(true)
-
- expect_any_instance_of(SystemHooksService)
- .to receive(:execute_hooks_for)
- .with(project, :rename)
-
- expect_any_instance_of(Gitlab::UploadsTransfer)
- .to receive(:rename_project)
- .with('foo', project.path, project.namespace.full_path)
-
- expect(project).to receive(:expire_caches_before_rename)
-
- expect(project).to receive(:expires_full_path_cache)
-
- project.rename_repo
- end
-
- context 'container registry with images' do
- let(:container_repository) { create(:container_repository) }
-
- before do
- stub_container_registry_config(enabled: true)
- stub_container_registry_tags(repository: :any, tags: ['tag'])
- project.container_repositories << container_repository
- end
-
- subject { project.rename_repo }
-
- it { expect {subject}.to raise_error(StandardError) }
- end
- end
-
describe '#expire_caches_before_rename' do
let(:project) { create(:project, :repository) }
let(:repo) { double(:repo, exists?: true) }
@@ -1610,8 +1556,7 @@ describe Project do
it 'imports a project' do
expect_any_instance_of(RepositoryImportWorker).to receive(:perform).and_call_original
- project.import_schedule
-
+ expect { project.import_schedule }.to change { project.import_jid }
expect(project.reload.import_status).to eq('finished')
end
end
@@ -1624,6 +1569,13 @@ describe Project do
allow(Projects::HousekeepingService).to receive(:new) { housekeeping_service }
end
+ it 'resets project import_error' do
+ error_message = 'Some error'
+ mirror = create(:project_empty_repo, :import_started, import_error: error_message)
+
+ expect { mirror.import_finish }.to change { mirror.import_error }.from(error_message).to(nil)
+ end
+
it 'performs housekeeping when an import of a fresh project is completed' do
project = create(:project_empty_repo, :import_started, import_type: :github)
@@ -1730,17 +1682,21 @@ describe Project do
end
describe '#add_import_job' do
+ let(:import_jid) { '123' }
+
context 'forked' do
let(:forked_project_link) { create(:forked_project_link, :forked_to_empty_project) }
let(:forked_from_project) { forked_project_link.forked_from_project }
let(:project) { forked_project_link.forked_to_project }
it 'schedules a RepositoryForkWorker job' do
- expect(RepositoryForkWorker).to receive(:perform_async)
- .with(project.id, forked_from_project.repository_storage_path,
- forked_from_project.disk_path, project.namespace.full_path)
+ expect(RepositoryForkWorker).to receive(:perform_async).with(
+ project.id,
+ forked_from_project.repository_storage_path,
+ forked_from_project.disk_path,
+ project.namespace.full_path).and_return(import_jid)
- project.add_import_job
+ expect(project.add_import_job).to eq(import_jid)
end
end
@@ -1748,9 +1704,8 @@ describe Project do
it 'schedules a RepositoryImportWorker job' do
project = create(:project, import_url: generate(:url))
- expect(RepositoryImportWorker).to receive(:perform_async).with(project.id)
-
- project.add_import_job
+ expect(RepositoryImportWorker).to receive(:perform_async).with(project.id).and_return(import_jid)
+ expect(project.add_import_job).to eq(import_jid)
end
end
end
@@ -2358,4 +2313,181 @@ describe Project do
expect(project.forks_count).to eq(1)
end
end
+
+ context 'legacy storage' do
+ let(:project) { create(:project, :repository) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+
+ before do
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ end
+
+ describe '#base_dir' do
+ it 'returns base_dir based on namespace only' do
+ expect(project.base_dir).to eq(project.namespace.full_path)
+ end
+ end
+
+ describe '#disk_path' do
+ it 'returns disk_path based on namespace and project path' do
+ expect(project.disk_path).to eq("#{project.namespace.full_path}/#{project.path}")
+ end
+ end
+
+ describe '#ensure_storage_path_exists' do
+ it 'delegates to gitlab_shell to ensure namespace is created' do
+ expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage_path, project.base_dir)
+
+ project.ensure_storage_path_exists
+ end
+ end
+
+ describe '#legacy_storage?' do
+ it 'returns true when storage_version is nil' do
+ project = build(:project)
+
+ expect(project.legacy_storage?).to be_truthy
+ end
+ end
+
+ describe '#rename_repo' do
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage_path, "#{project.namespace.full_path}/foo", "#{project.full_path}")
+ .and_return(true)
+
+ expect(gitlab_shell).to receive(:mv_repository)
+ .ordered
+ .with(project.repository_storage_path, "#{project.namespace.full_path}/foo.wiki", "#{project.full_path}.wiki")
+ .and_return(true)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect_any_instance_of(Gitlab::UploadsTransfer)
+ .to receive(:rename_project)
+ .with('foo', project.path, project.namespace.full_path)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ expect(project).to receive(:expires_full_path_cache)
+
+ project.rename_repo
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ subject { project.rename_repo }
+
+ it { expect { subject }.to raise_error(StandardError) }
+ end
+ end
+
+ describe '#pages_path' do
+ it 'returns a path where pages are stored' do
+ expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
+ end
+ end
+ end
+
+ context 'hashed storage' do
+ let(:project) { create(:project, :repository) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:hash) { '6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b' }
+
+ before do
+ stub_application_setting(hashed_storage_enabled: true)
+ allow(Digest::SHA2).to receive(:hexdigest) { hash }
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ end
+
+ describe '#base_dir' do
+ it 'returns base_dir based on hash of project id' do
+ expect(project.base_dir).to eq('@hashed/6b/86')
+ end
+ end
+
+ describe '#disk_path' do
+ it 'returns disk_path based on hash of project id' do
+ hashed_path = '@hashed/6b/86/6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b'
+
+ expect(project.disk_path).to eq(hashed_path)
+ end
+ end
+
+ describe '#ensure_storage_path_exists' do
+ it 'delegates to gitlab_shell to ensure namespace is created' do
+ expect(gitlab_shell).to receive(:add_namespace).with(project.repository_storage_path, '@hashed/6b/86')
+
+ project.ensure_storage_path_exists
+ end
+ end
+
+ describe '#rename_repo' do
+ before do
+ # Project#gitlab_shell returns a new instance of Gitlab::Shell on every
+ # call. This makes testing a bit easier.
+ allow(project).to receive(:gitlab_shell).and_return(gitlab_shell)
+ allow(project).to receive(:previous_changes).and_return('path' => ['foo'])
+ end
+
+ it 'renames a repository' do
+ stub_container_registry_config(enabled: false)
+
+ expect(gitlab_shell).not_to receive(:mv_repository)
+
+ expect_any_instance_of(SystemHooksService)
+ .to receive(:execute_hooks_for)
+ .with(project, :rename)
+
+ expect_any_instance_of(Gitlab::UploadsTransfer)
+ .to receive(:rename_project)
+ .with('foo', project.path, project.namespace.full_path)
+
+ expect(project).to receive(:expire_caches_before_rename)
+
+ expect(project).to receive(:expires_full_path_cache)
+
+ project.rename_repo
+ end
+
+ context 'container registry with images' do
+ let(:container_repository) { create(:container_repository) }
+
+ before do
+ stub_container_registry_config(enabled: true)
+ stub_container_registry_tags(repository: :any, tags: ['tag'])
+ project.container_repositories << container_repository
+ end
+
+ subject { project.rename_repo }
+
+ it { expect { subject }.to raise_error(StandardError) }
+ end
+ end
+
+ describe '#pages_path' do
+ it 'returns a path where pages are stored' do
+ expect(project.pages_path).to eq(File.join(Settings.pages.path, project.namespace.full_path, project.path))
+ end
+ end
+ end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 97bb91a6ac8..9a9e255f874 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -2024,4 +2024,65 @@ describe User do
expect(user.projects_limit_left).to eq(5)
end
end
+
+ describe '#ensure_namespace_correct' do
+ context 'for a new user' do
+ let(:user) { build(:user) }
+
+ it 'creates the namespace' do
+ expect(user.namespace).to be_nil
+ user.save!
+ expect(user.namespace).not_to be_nil
+ end
+ end
+
+ context 'for an existing user' do
+ let(:username) { 'foo' }
+ let(:user) { create(:user, username: username) }
+
+ context 'when the user is updated' do
+ context 'when the username is changed' do
+ let(:new_username) { 'bar' }
+
+ it 'changes the namespace (just to compare to when username is not changed)' do
+ expect do
+ user.update_attributes!(username: new_username)
+ end.to change { user.namespace.updated_at }
+ end
+
+ it 'updates the namespace name' do
+ user.update_attributes!(username: new_username)
+ expect(user.namespace.name).to eq(new_username)
+ end
+
+ it 'updates the namespace path' do
+ user.update_attributes!(username: new_username)
+ expect(user.namespace.path).to eq(new_username)
+ end
+
+ context 'when there is a validation error (namespace name taken) while updating namespace' do
+ let!(:conflicting_namespace) { create(:group, name: new_username, path: 'quz') }
+
+ it 'causes the user save to fail' do
+ expect(user.update_attributes(username: new_username)).to be_falsey
+ expect(user.namespace.errors.messages[:name].first).to eq('has already been taken')
+ end
+
+ it 'adds the namespace errors to the user' do
+ user.update_attributes(username: new_username)
+ expect(user.errors.full_messages.first).to eq('Namespace name has already been taken')
+ end
+ end
+ end
+
+ context 'when the username is not changed' do
+ it 'does not change the namespace' do
+ expect do
+ user.update_attributes!(email: 'asdf@asdf.com')
+ end.not_to change { user.namespace.updated_at }
+ end
+ end
+ end
+ end
+ end
end
diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb
index b17a93e3fbe..7f832bfa563 100644
--- a/spec/policies/group_policy_spec.rb
+++ b/spec/policies/group_policy_spec.rb
@@ -105,6 +105,8 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
@@ -116,6 +118,8 @@ describe GroupPolicy do
let(:current_user) { admin }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
@@ -123,6 +127,36 @@ describe GroupPolicy do
end
end
+ describe 'when nested group support feature is disabled' do
+ before do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+ end
+
+ context 'admin' do
+ let(:current_user) { admin }
+
+ it 'allows every owner permission except creating subgroups' do
+ create_subgroup_permission = [:create_subgroup]
+ updated_owner_permissions = owner_permissions - create_subgroup_permission
+
+ expect_disallowed(*create_subgroup_permission)
+ expect_allowed(*updated_owner_permissions)
+ end
+ end
+
+ context 'owner' do
+ let(:current_user) { owner }
+
+ it 'allows every owner permission except creating subgroups' do
+ create_subgroup_permission = [:create_subgroup]
+ updated_owner_permissions = owner_permissions - create_subgroup_permission
+
+ expect_disallowed(*create_subgroup_permission)
+ expect_allowed(*updated_owner_permissions)
+ end
+ end
+ end
+
describe 'private nested group use the highest access level from the group and inherited permissions', :nested_groups do
let(:nested_group) { create(:group, :private, parent: group) }
@@ -199,6 +233,8 @@ describe GroupPolicy do
let(:current_user) { owner }
it do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
expect_allowed(:read_group)
expect_allowed(*reporter_permissions)
expect_allowed(*master_permissions)
diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb
deleted file mode 100644
index 7ccba4ba3ec..00000000000
--- a/spec/requests/ci/api/builds_spec.rb
+++ /dev/null
@@ -1,912 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Builds do
- let(:runner) { FactoryGirl.create(:ci_runner, tag_list: %w(mysql ruby)) }
- let(:project) { FactoryGirl.create(:project, shared_runners_enabled: false) }
- let(:last_update) { nil }
-
- describe "Builds API for runners" do
- let(:pipeline) { create(:ci_pipeline_without_jobs, project: project, ref: 'master') }
-
- before do
- project.runners << runner
- end
-
- describe "POST /builds/register" do
- let!(:build) { create(:ci_build, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
- let(:user_agent) { 'gitlab-ci-multi-runner 1.5.2 (1-5-stable; go1.6.3; linux/amd64)' }
- let!(:last_update) { }
- let!(:new_update) { }
-
- before do
- stub_container_registry_config(enabled: false)
- end
-
- shared_examples 'no builds available' do
- context 'when runner sends version in User-Agent' do
- context 'for stable version' do
- it 'gives 204 and set X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header).to have_key('X-GitLab-Last-Update')
- end
- end
-
- context 'when last_update is up-to-date' do
- let(:last_update) { runner.ensure_runner_queue_value }
-
- it 'gives 204 and set the same X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header['X-GitLab-Last-Update'])
- .to eq(last_update)
- end
- end
-
- context 'when last_update is outdated' do
- let(:last_update) { runner.ensure_runner_queue_value }
- let(:new_update) { runner.tick_runner_queue }
-
- it 'gives 204 and set a new X-GitLab-Last-Update' do
- expect(response).to have_http_status(204)
- expect(response.header['X-GitLab-Last-Update'])
- .to eq(new_update)
- end
- end
-
- context 'for beta version' do
- let(:user_agent) { 'gitlab-ci-multi-runner 1.6.0~beta.167.g2b2bacc (1-5-stable; go1.6.3; linux/amd64)' }
- it { expect(response).to have_http_status(204) }
- end
- end
-
- context "when runner doesn't send version in User-Agent" do
- let(:user_agent) { 'Go-http-client/1.1' }
- it { expect(response).to have_http_status(404) }
- end
-
- context "when runner doesn't have a User-Agent" do
- let(:user_agent) { nil }
- it { expect(response).to have_http_status(404) }
- end
- end
-
- context 'when an old image syntax is used' do
- before do
- build.update!(options: { image: 'codeclimate' })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "image" => "codeclimate" })
- end
- end
-
- context 'when a new image syntax is used' do
- before do
- build.update!(options: { image: { name: 'codeclimate' } })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "image" => "codeclimate" })
- end
- end
-
- context 'when an old service syntax is used' do
- before do
- build.update!(options: { services: ['mysql'] })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "services" => ["mysql"] })
- end
- end
-
- context 'when a new service syntax is used' do
- before do
- build.update!(options: { services: [name: 'mysql'] })
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["options"]).to eq({ "services" => ["mysql"] })
- end
- end
-
- context 'when no image or service is defined' do
- before do
- build.update!(options: {})
- end
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
-
- expect(json_response["options"]).to be_empty
- end
- end
-
- context 'when there is a pending build' do
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(response.headers).not_to have_key('X-GitLab-Last-Update')
- expect(json_response['sha']).to eq(build.sha)
- expect(runner.reload.platform).to eq("darwin")
- expect(json_response["options"]).to eq({ "image" => "ruby:2.1", "services" => ["postgres"] })
- expect(json_response["variables"]).to include(
- { "key" => "CI_JOB_NAME", "value" => "spinach", "public" => true },
- { "key" => "CI_JOB_STAGE", "value" => "test", "public" => true },
- { "key" => "DB_NAME", "value" => "postgres", "public" => true }
- )
- end
-
- it 'updates runner info' do
- expect { register_builds }.to change { runner.reload.contacted_at }
- end
-
- context 'when concurrently updating build' do
- before do
- expect_any_instance_of(Ci::Build).to receive(:run!)
- .and_raise(ActiveRecord::StaleObjectError.new(nil, nil))
- end
-
- it 'returns a conflict' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(409)
- expect(response.headers).not_to have_key('X-GitLab-Last-Update')
- end
- end
-
- context 'registry credentials' do
- let(:registry_credentials) do
- { 'type' => 'registry',
- 'url' => 'registry.example.com:5005',
- 'username' => 'gitlab-ci-token',
- 'password' => build.token }
- end
-
- context 'when registry is enabled' do
- before do
- stub_container_registry_config(enabled: true, host_port: 'registry.example.com:5005')
- end
-
- it 'sends registry credentials key' do
- register_builds info: { platform: :darwin }
-
- expect(json_response).to have_key('credentials')
- expect(json_response['credentials']).to include(registry_credentials)
- end
- end
-
- context 'when registry is disabled' do
- before do
- stub_container_registry_config(enabled: false, host_port: 'registry.example.com:5005')
- end
-
- it 'does not send registry credentials' do
- register_builds info: { platform: :darwin }
-
- expect(json_response).to have_key('credentials')
- expect(json_response['credentials']).not_to include(registry_credentials)
- end
- end
- end
-
- context 'when docker configuration options are used' do
- let!(:build) { create(:ci_build, :extended_options, pipeline: pipeline, name: 'spinach', stage: 'test', stage_idx: 0) }
-
- it 'starts a build' do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response['options']['image']).to eq('ruby:2.1')
- expect(json_response['options']['services']).to eq(['postgres', 'docker:dind'])
- end
- end
- end
-
- context 'when builds are finished' do
- before do
- build.success
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for other project with builds' do
- before do
- build.success
- create(:ci_build, :pending)
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for shared runner' do
- let!(:runner) { create(:ci_runner, :shared, token: "SharedRunner") }
-
- before do
- register_builds(runner.token)
- end
-
- it_behaves_like 'no builds available'
- end
-
- context 'for triggered build' do
- before do
- trigger = create(:ci_trigger, project: project)
- create(:ci_trigger_request_with_variables, pipeline: pipeline, builds: [build], trigger: trigger)
- project.variables << Ci::Variable.new(key: "SECRET_KEY", value: "secret_value")
- end
-
- it "returns variables for triggers" do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["variables"]).to include(
- { "key" => "CI_JOB_NAME", "value" => "spinach", "public" => true },
- { "key" => "CI_JOB_STAGE", "value" => "test", "public" => true },
- { "key" => "CI_PIPELINE_TRIGGERED", "value" => "true", "public" => true },
- { "key" => "DB_NAME", "value" => "postgres", "public" => true },
- { "key" => "SECRET_KEY", "value" => "secret_value", "public" => false },
- { "key" => "TRIGGER_KEY_1", "value" => "TRIGGER_VALUE_1", "public" => false }
- )
- end
- end
-
- context 'with multiple builds' do
- before do
- build.success
- end
-
- let!(:test_build) { create(:ci_build, pipeline: pipeline, name: 'deploy', stage: 'deploy', stage_idx: 1) }
-
- it "returns dependent builds" do
- register_builds info: { platform: :darwin }
-
- expect(response).to have_http_status(201)
- expect(json_response["id"]).to eq(test_build.id)
- expect(json_response["depends_on_builds"].count).to eq(1)
- expect(json_response["depends_on_builds"][0]).to include('id' => build.id, 'name' => 'spinach')
- end
- end
-
- %w(name version revision platform architecture).each do |param|
- context "updates runner #{param}" do
- let(:value) { "#{param}_value" }
-
- subject { runner.read_attribute(param.to_sym) }
-
- it do
- register_builds info: { param => value }
-
- expect(response).to have_http_status(201)
- runner.reload
- is_expected.to eq(value)
- end
- end
- end
-
- context 'when build has no tags' do
- before do
- build.update(tags: [])
- end
-
- context 'when runner is allowed to pick untagged builds' do
- before do
- runner.update_column(:run_untagged, true)
- end
-
- it 'picks build' do
- register_builds
-
- expect(response).to have_http_status 201
- end
- end
-
- context 'when runner is not allowed to pick untagged builds' do
- before do
- runner.update_column(:run_untagged, false)
- register_builds
- end
-
- it_behaves_like 'no builds available'
- end
- end
-
- context 'when runner is paused' do
- let(:runner) { create(:ci_runner, :inactive, token: 'InactiveRunner') }
-
- it 'responds with 404' do
- register_builds
-
- expect(response).to have_http_status 404
- end
-
- it 'does not update runner info' do
- expect { register_builds }
- .not_to change { runner.reload.contacted_at }
- end
- end
-
- def register_builds(token = runner.token, **params)
- new_params = params.merge(token: token, last_update: last_update)
-
- post ci_api("/builds/register"), new_params, { 'User-Agent' => user_agent }
- end
- end
-
- describe "PUT /builds/:id" do
- let(:build) { create(:ci_build, :pending, :trace, pipeline: pipeline, runner_id: runner.id) }
-
- before do
- build.run!
- put ci_api("/builds/#{build.id}"), token: runner.token
- end
-
- it "updates a running build" do
- expect(response).to have_http_status(200)
- end
-
- it 'does not override trace information when no trace is given' do
- expect(build.reload.trace.raw).to eq 'BUILD TRACE'
- end
-
- context 'job has been erased' do
- let(:build) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) }
-
- it 'responds with forbidden' do
- expect(response.status).to eq 403
- end
- end
- end
-
- describe 'PATCH /builds/:id/trace.txt' do
- let(:build) do
- attributes = { runner_id: runner.id, pipeline: pipeline }
- create(:ci_build, :running, :trace, attributes)
- end
-
- let(:headers) { { Ci::API::Helpers::BUILD_TOKEN_HEADER => build.token, 'Content-Type' => 'text/plain' } }
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '11-20' }) }
- let(:update_interval) { 10.seconds.to_i }
-
- def patch_the_trace(content = ' appended', request_headers = nil)
- unless request_headers
- build.trace.read do |stream|
- offset = stream.size
- limit = offset + content.length - 1
- request_headers = headers.merge({ 'Content-Range' => "#{offset}-#{limit}" })
- end
- end
-
- Timecop.travel(build.updated_at + update_interval) do
- patch ci_api("/builds/#{build.id}/trace.txt"), content, request_headers
- build.reload
- end
- end
-
- def initial_patch_the_trace
- patch_the_trace(' appended', headers_with_range)
- end
-
- def force_patch_the_trace
- 2.times { patch_the_trace('') }
- end
-
- before do
- initial_patch_the_trace
- end
-
- context 'when request is valid' do
- it 'gets correct response' do
- expect(response.status).to eq 202
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- expect(response.header).to have_key 'Range'
- expect(response.header).to have_key 'Build-Status'
- end
-
- context 'when build has been updated recently' do
- it { expect { patch_the_trace }.not_to change { build.updated_at }}
-
- it 'changes the build trace' do
- patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended appended'
- end
-
- context 'when Runner makes a force-patch' do
- it { expect { force_patch_the_trace }.not_to change { build.updated_at }}
-
- it "doesn't change the build.trace" do
- force_patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- end
- end
- end
-
- context 'when build was not updated recently' do
- let(:update_interval) { 15.minutes.to_i }
-
- it { expect { patch_the_trace }.to change { build.updated_at } }
-
- it 'changes the build.trace' do
- patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended appended'
- end
-
- context 'when Runner makes a force-patch' do
- it { expect { force_patch_the_trace }.to change { build.updated_at } }
-
- it "doesn't change the build.trace" do
- force_patch_the_trace
-
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- end
- end
- end
-
- context 'when project for the build has been deleted' do
- let(:build) do
- attributes = { runner_id: runner.id, pipeline: pipeline }
- create(:ci_build, :running, :trace, attributes) do |build|
- build.project.update(pending_delete: true)
- end
- end
-
- it 'responds with forbidden' do
- expect(response.status).to eq(403)
- end
- end
- end
-
- context 'when Runner makes a force-patch' do
- before do
- force_patch_the_trace
- end
-
- it 'gets correct response' do
- expect(response.status).to eq 202
- expect(build.reload.trace.raw).to eq 'BUILD TRACE appended'
- expect(response.header).to have_key 'Range'
- expect(response.header).to have_key 'Build-Status'
- end
- end
-
- context 'when content-range start is too big' do
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '15-20' }) }
-
- it 'gets 416 error response with range headers' do
- expect(response.status).to eq 416
- expect(response.header).to have_key 'Range'
- expect(response.header['Range']).to eq '0-11'
- end
- end
-
- context 'when content-range start is too small' do
- let(:headers_with_range) { headers.merge({ 'Content-Range' => '8-20' }) }
-
- it 'gets 416 error response with range headers' do
- expect(response.status).to eq 416
- expect(response.header).to have_key 'Range'
- expect(response.header['Range']).to eq '0-11'
- end
- end
-
- context 'when Content-Range header is missing' do
- let(:headers_with_range) { headers }
-
- it { expect(response.status).to eq 400 }
- end
-
- context 'when build has been errased' do
- let(:build) { create(:ci_build, runner_id: runner.id, erased_at: Time.now) }
-
- it { expect(response.status).to eq 403 }
- end
- end
-
- context "Artifacts" do
- let(:file_upload) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }
- let(:file_upload2) { fixture_file_upload(Rails.root + 'spec/fixtures/dk.png', 'image/gif') }
- let(:build) { create(:ci_build, :pending, pipeline: pipeline, runner_id: runner.id) }
- let(:authorize_url) { ci_api("/builds/#{build.id}/artifacts/authorize") }
- let(:post_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:delete_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:get_url) { ci_api("/builds/#{build.id}/artifacts") }
- let(:jwt_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:headers) { { "GitLab-Workhorse" => "1.0", Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => jwt_token } }
- let(:token) { build.token }
- let(:headers_with_token) { headers.merge(Ci::API::Helpers::BUILD_TOKEN_HEADER => token) }
-
- before do
- build.run!
- end
-
- describe "POST /builds/:id/artifacts/authorize" do
- context "authorizes posting artifact to running build" do
- it "using token as parameter" do
- post authorize_url, { token: build.token }, headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "using token as header" do
- post authorize_url, {}, headers_with_token
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "using runners token" do
- post authorize_url, { token: build.project.runners_token }, headers
-
- expect(response).to have_http_status(200)
- expect(response.content_type.to_s).to eq(Gitlab::Workhorse::INTERNAL_API_CONTENT_TYPE)
- expect(json_response["TempPath"]).not_to be_nil
- end
-
- it "reject requests that did not go through gitlab-workhorse" do
- headers.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER)
-
- post authorize_url, { token: build.token }, headers
-
- expect(response).to have_http_status(500)
- end
- end
-
- context "fails to post too large artifact" do
- it "using token as parameter" do
- stub_application_setting(max_artifacts_size: 0)
-
- post authorize_url, { token: build.token, filesize: 100 }, headers
-
- expect(response).to have_http_status(413)
- end
-
- it "using token as header" do
- stub_application_setting(max_artifacts_size: 0)
-
- post authorize_url, { filesize: 100 }, headers_with_token
-
- expect(response).to have_http_status(413)
- end
- end
-
- context 'authorization token is invalid' do
- before do
- post authorize_url, { token: 'invalid', filesize: 100 }
- end
-
- it 'responds with forbidden' do
- expect(response).to have_http_status(403)
- end
- end
- end
-
- describe "POST /builds/:id/artifacts" do
- context "disable sanitizer" do
- before do
- # by configuring this path we allow to pass temp file from any path
- allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return('/')
- end
-
- describe 'build has been erased' do
- let(:build) { create(:ci_build, erased_at: Time.now) }
-
- before do
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it 'responds with forbidden' do
- expect(response.status).to eq 403
- end
- end
-
- describe 'uploading artifacts for a running build' do
- shared_examples 'successful artifacts upload' do
- it 'updates successfully' do
- response_filename =
- json_response['artifacts_file']['filename']
-
- expect(response).to have_http_status(201)
- expect(response_filename).to eq(file_upload.original_filename)
- end
- end
-
- context 'uses regular file post' do
- before do
- upload_artifacts(file_upload, headers_with_token, false)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'uses accelerated file post' do
- before do
- upload_artifacts(file_upload, headers_with_token, true)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'updates artifact' do
- before do
- upload_artifacts(file_upload2, headers_with_token)
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
-
- context 'when using runners token' do
- let(:token) { build.project.runners_token }
-
- before do
- upload_artifacts(file_upload, headers_with_token)
- end
-
- it_behaves_like 'successful artifacts upload'
- end
- end
-
- context 'posts artifacts file and metadata file' do
- let!(:artifacts) { file_upload }
- let!(:metadata) { file_upload2 }
-
- let(:stored_artifacts_file) { build.reload.artifacts_file.file }
- let(:stored_metadata_file) { build.reload.artifacts_metadata.file }
- let(:stored_artifacts_size) { build.reload.artifacts_size }
-
- before do
- post(post_url, post_data, headers_with_token)
- end
-
- context 'posts data accelerated by workhorse is correct' do
- let(:post_data) do
- { 'file.path' => artifacts.path,
- 'file.name' => artifacts.original_filename,
- 'metadata.path' => metadata.path,
- 'metadata.name' => metadata.original_filename }
- end
-
- it 'stores artifacts and artifacts metadata' do
- expect(response).to have_http_status(201)
- expect(stored_artifacts_file.original_filename).to eq(artifacts.original_filename)
- expect(stored_metadata_file.original_filename).to eq(metadata.original_filename)
- expect(stored_artifacts_size).to eq(71759)
- end
- end
-
- context 'no artifacts file in post data' do
- let(:post_data) do
- { 'metadata' => metadata }
- end
-
- it 'is expected to respond with bad request' do
- expect(response).to have_http_status(400)
- end
-
- it 'does not store metadata' do
- expect(stored_metadata_file).to be_nil
- end
- end
- end
-
- context 'with an expire date' do
- let!(:artifacts) { file_upload }
- let(:default_artifacts_expire_in) {}
-
- let(:post_data) do
- { 'file.path' => artifacts.path,
- 'file.name' => artifacts.original_filename,
- 'expire_in' => expire_in }
- end
-
- before do
- stub_application_setting(
- default_artifacts_expire_in: default_artifacts_expire_in)
-
- post(post_url, post_data, headers_with_token)
- end
-
- context 'with an expire_in given' do
- let(:expire_in) { '7 days' }
-
- it 'updates when specified' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).not_to be_empty
- expect(build.artifacts_expire_at)
- .to be_within(5.minutes).of(7.days.from_now)
- end
- end
-
- context 'with no expire_in given' do
- let(:expire_in) { nil }
-
- it 'ignores if not specified' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).to be_nil
- expect(build.artifacts_expire_at).to be_nil
- end
-
- context 'with application default' do
- context 'default to 5 days' do
- let(:default_artifacts_expire_in) { '5 days' }
-
- it 'sets to application default' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at'])
- .not_to be_empty
- expect(build.artifacts_expire_at)
- .to be_within(5.minutes).of(5.days.from_now)
- end
- end
-
- context 'default to 0' do
- let(:default_artifacts_expire_in) { '0' }
-
- it 'does not set expire_in' do
- build.reload
- expect(response).to have_http_status(201)
- expect(json_response['artifacts_expire_at']).to be_nil
- expect(build.artifacts_expire_at).to be_nil
- end
- end
- end
- end
- end
-
- context "artifacts file is too large" do
- it "fails to post too large artifact" do
- stub_application_setting(max_artifacts_size: 0)
- upload_artifacts(file_upload, headers_with_token)
- expect(response).to have_http_status(413)
- end
- end
-
- context "artifacts post request does not contain file" do
- it "fails to post artifacts without file" do
- post post_url, {}, headers_with_token
- expect(response).to have_http_status(400)
- end
- end
-
- context 'GitLab Workhorse is not configured' do
- it "fails to post artifacts without GitLab-Workhorse" do
- post post_url, { token: build.token }, {}
- expect(response).to have_http_status(403)
- end
- end
- end
-
- context "artifacts are being stored outside of tmp path" do
- before do
- # by configuring this path we allow to pass file from @tmpdir only
- # but all temporary files are stored in system tmp directory
- @tmpdir = Dir.mktmpdir
- allow(ArtifactUploader).to receive(:artifacts_upload_path).and_return(@tmpdir)
- end
-
- after do
- FileUtils.remove_entry @tmpdir
- end
-
- it "fails to post artifacts for outside of tmp path" do
- upload_artifacts(file_upload, headers_with_token)
- expect(response).to have_http_status(400)
- end
- end
-
- def upload_artifacts(file, headers = {}, accelerated = true)
- if accelerated
- post post_url, {
- 'file.path' => file.path,
- 'file.name' => file.original_filename
- }, headers
- else
- post post_url, { file: file }, headers
- end
- end
- end
-
- describe 'DELETE /builds/:id/artifacts' do
- let(:build) { create(:ci_build, :artifacts) }
-
- before do
- delete delete_url, token: build.token
- end
-
- shared_examples 'having removable artifacts' do
- it 'removes build artifacts' do
- build.reload
-
- expect(response).to have_http_status(200)
- expect(build.artifacts_file.exists?).to be_falsy
- expect(build.artifacts_metadata.exists?).to be_falsy
- expect(build.artifacts_size).to be_nil
- end
- end
-
- context 'when using build token' do
- before do
- delete delete_url, token: build.token
- end
-
- it_behaves_like 'having removable artifacts'
- end
-
- context 'when using runnners token' do
- before do
- delete delete_url, token: build.project.runners_token
- end
-
- it_behaves_like 'having removable artifacts'
- end
- end
-
- describe 'GET /builds/:id/artifacts' do
- before do
- get get_url, token: token
- end
-
- context 'build has artifacts' do
- let(:build) { create(:ci_build, :artifacts) }
- let(:download_headers) do
- { 'Content-Transfer-Encoding' => 'binary',
- 'Content-Disposition' => 'attachment; filename=ci_build_artifacts.zip' }
- end
-
- shared_examples 'having downloadable artifacts' do
- it 'download artifacts' do
- expect(response).to have_http_status(200)
- expect(response.headers).to include download_headers
- end
- end
-
- context 'when using build token' do
- let(:token) { build.token }
-
- it_behaves_like 'having downloadable artifacts'
- end
-
- context 'when using runnners token' do
- let(:token) { build.project.runners_token }
-
- it_behaves_like 'having downloadable artifacts'
- end
- end
-
- context 'build does not has artifacts' do
- let(:token) { build.token }
-
- it 'responds with not found' do
- expect(response).to have_http_status(404)
- end
- end
- end
- end
- end
-end
diff --git a/spec/requests/ci/api/runners_spec.rb b/spec/requests/ci/api/runners_spec.rb
deleted file mode 100644
index 75059dd20a0..00000000000
--- a/spec/requests/ci/api/runners_spec.rb
+++ /dev/null
@@ -1,127 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Runners do
- include StubGitlabCalls
-
- let(:registration_token) { 'abcdefg123456' }
-
- before do
- stub_gitlab_calls
- stub_application_setting(runners_registration_token: registration_token)
- end
-
- describe "POST /runners/register" do
- context 'when runner token is provided' do
- before do
- post ci_api("/runners/register"), token: registration_token
- end
-
- it 'creates runner with default values' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.run_untagged).to be true
- expect(Ci::Runner.first.token).not_to eq(registration_token)
- end
- end
-
- context 'when runner description is provided' do
- before do
- post ci_api("/runners/register"), token: registration_token,
- description: "server.hostname"
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.description).to eq("server.hostname")
- end
- end
-
- context 'when runner tags are provided' do
- before do
- post ci_api("/runners/register"), token: registration_token,
- tag_list: "tag1, tag2"
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.tag_list.sort).to eq(%w(tag1 tag2))
- end
- end
-
- context 'when option for running untagged jobs is provided' do
- context 'when tags are provided' do
- it 'creates runner' do
- post ci_api("/runners/register"), token: registration_token,
- run_untagged: false,
- tag_list: ['tag']
-
- expect(response).to have_http_status 201
- expect(Ci::Runner.first.run_untagged).to be false
- end
- end
-
- context 'when tags are not provided' do
- it 'does not create runner' do
- post ci_api("/runners/register"), token: registration_token,
- run_untagged: false
-
- expect(response).to have_http_status 404
- end
- end
- end
-
- context 'when project token is provided' do
- let(:project) { FactoryGirl.create(:project) }
-
- before do
- post ci_api("/runners/register"), token: project.runners_token
- end
-
- it 'creates runner' do
- expect(response).to have_http_status 201
- expect(project.runners.size).to eq(1)
- expect(Ci::Runner.first.token).not_to eq(registration_token)
- expect(Ci::Runner.first.token).not_to eq(project.runners_token)
- end
- end
-
- context 'when token is invalid' do
- it 'returns 403 error' do
- post ci_api("/runners/register"), token: 'invalid'
-
- expect(response).to have_http_status 403
- end
- end
-
- context 'when no token provided' do
- it 'returns 400 error' do
- post ci_api("/runners/register")
-
- expect(response).to have_http_status 400
- end
- end
-
- %w(name version revision platform architecture).each do |param|
- context "creates runner with #{param} saved" do
- let(:value) { "#{param}_value" }
-
- subject { Ci::Runner.first.read_attribute(param.to_sym) }
-
- it do
- post ci_api("/runners/register"), token: registration_token, info: { param => value }
- expect(response).to have_http_status 201
- is_expected.to eq(value)
- end
- end
- end
- end
-
- describe "DELETE /runners/delete" do
- it 'returns 200' do
- runner = FactoryGirl.create(:ci_runner)
- delete ci_api("/runners/delete"), token: runner.token
-
- expect(response).to have_http_status 200
- expect(Ci::Runner.count).to eq(0)
- end
- end
-end
diff --git a/spec/requests/ci/api/triggers_spec.rb b/spec/requests/ci/api/triggers_spec.rb
deleted file mode 100644
index 7c77ebb69a2..00000000000
--- a/spec/requests/ci/api/triggers_spec.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-require 'spec_helper'
-
-describe Ci::API::Triggers do
- describe 'POST /projects/:project_id/refs/:ref/trigger' do
- let!(:trigger_token) { 'secure token' }
- let!(:project) { create(:project, :repository, ci_id: 10) }
- let!(:project2) { create(:project, ci_id: 11) }
-
- let!(:trigger) do
- create(:ci_trigger,
- project: project,
- token: trigger_token,
- owner: create(:user))
- end
-
- let(:options) do
- {
- token: trigger_token
- }
- end
-
- before do
- stub_ci_pipeline_to_return_yaml_file
-
- project.add_developer(trigger.owner)
- end
-
- context 'Handles errors' do
- it 'returns bad request if token is missing' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger")
- expect(response).to have_http_status(400)
- end
-
- it 'returns not found if project is not found' do
- post ci_api('/projects/0/refs/master/trigger'), options
- expect(response).to have_http_status(404)
- end
-
- it 'returns unauthorized if token is for different project' do
- post ci_api("/projects/#{project2.ci_id}/refs/master/trigger"), options
- expect(response).to have_http_status(401)
- end
- end
-
- context 'Have a commit' do
- let(:pipeline) { project.pipelines.last }
-
- it 'creates builds' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options
- expect(response).to have_http_status(201)
- pipeline.builds.reload
- expect(pipeline.builds.pending.size).to eq(2)
- expect(pipeline.builds.size).to eq(5)
- end
-
- it 'returns bad request with no builds created if there\'s no commit for that ref' do
- post ci_api("/projects/#{project.ci_id}/refs/other-branch/trigger"), options
- expect(response).to have_http_status(400)
- expect(json_response['message']['base'])
- .to contain_exactly('Reference not found')
- end
-
- context 'Validates variables' do
- let(:variables) do
- { 'TRIGGER_KEY' => 'TRIGGER_VALUE' }
- end
-
- it 'validates variables to be a hash' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: 'value')
- expect(response).to have_http_status(400)
-
- expect(json_response['error']).to eq('variables is invalid')
- end
-
- it 'validates variables needs to be a map of key-valued strings' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: { key: %w(1 2) })
- expect(response).to have_http_status(400)
- expect(json_response['message']).to eq('variables needs to be a map of key-valued strings')
- end
-
- it 'creates trigger request with variables' do
- post ci_api("/projects/#{project.ci_id}/refs/master/trigger"), options.merge(variables: variables)
- expect(response).to have_http_status(201)
- pipeline.builds.reload
- expect(pipeline.builds.first.trigger_request.variables).to eq(variables)
- end
- end
- end
- end
-end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index 53d4fcfed18..8465a6f99bd 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -55,10 +55,15 @@ describe Ci::CreatePipelineService do
context 'when merge requests already exist for this source branch' do
it 'updates head pipeline of each merge request' do
- merge_request_1 = create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project)
- merge_request_2 = create(:merge_request, source_branch: 'master', target_branch: "branch_2", source_project: project)
+ merge_request_1 = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project)
- head_pipeline = pipeline
+ merge_request_2 = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_2",
+ source_project: project)
+
+ head_pipeline = execute_service
expect(merge_request_1.reload.head_pipeline).to eq(head_pipeline)
expect(merge_request_2.reload.head_pipeline).to eq(head_pipeline)
@@ -66,9 +71,11 @@ describe Ci::CreatePipelineService do
context 'when there is no pipeline for source branch' do
it "does not update merge request head pipeline" do
- merge_request = create(:merge_request, source_branch: 'feature', target_branch: "branch_1", source_project: project)
+ merge_request = create(:merge_request, source_branch: 'feature',
+ target_branch: "branch_1",
+ source_project: project)
- head_pipeline = pipeline
+ head_pipeline = execute_service
expect(merge_request.reload.head_pipeline).not_to eq(head_pipeline)
end
@@ -76,13 +83,19 @@ describe Ci::CreatePipelineService do
context 'when merge request target project is different from source project' do
let!(:target_project) { create(:project, :repository) }
- let!(:forked_project_link) { create(:forked_project_link, forked_to_project: project, forked_from_project: target_project) }
+
+ let!(:forked_project_link) do
+ create(:forked_project_link, forked_to_project: project,
+ forked_from_project: target_project)
+ end
it 'updates head pipeline for merge request' do
- merge_request =
- create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project, target_project: target_project)
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project,
+ target_project: target_project)
- head_pipeline = pipeline
+ head_pipeline = execute_service
expect(merge_request.reload.head_pipeline).to eq(head_pipeline)
end
@@ -90,15 +103,36 @@ describe Ci::CreatePipelineService do
context 'when the pipeline is not the latest for the branch' do
it 'does not update merge request head pipeline' do
- merge_request = create(:merge_request, source_branch: 'master', target_branch: "branch_1", source_project: project)
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: "branch_1",
+ source_project: project)
- allow_any_instance_of(Ci::Pipeline).to receive(:latest?).and_return(false)
+ allow_any_instance_of(Ci::Pipeline)
+ .to receive(:latest?).and_return(false)
- pipeline
+ execute_service
expect(merge_request.reload.head_pipeline).to be_nil
end
end
+
+ context 'when pipeline has errors' do
+ before do
+ stub_ci_pipeline_yaml_file('some invalid syntax')
+ end
+
+ it 'updates merge request head pipeline reference' do
+ merge_request = create(:merge_request, source_branch: 'master',
+ target_branch: 'feature',
+ source_project: project)
+
+ head_pipeline = execute_service
+
+ expect(head_pipeline).to be_persisted
+ expect(head_pipeline.yaml_errors).to be_present
+ expect(merge_request.reload.head_pipeline).to eq head_pipeline
+ end
+ end
end
context 'auto-cancel enabled' do
diff --git a/spec/services/groups/create_service_spec.rb b/spec/services/groups/create_service_spec.rb
index b2175717a70..10dda45d2a1 100644
--- a/spec/services/groups/create_service_spec.rb
+++ b/spec/services/groups/create_service_spec.rb
@@ -22,7 +22,7 @@ describe Groups::CreateService, '#execute' do
end
end
- describe 'creating subgroup' do
+ describe 'creating subgroup', :nested_groups do
let!(:group) { create(:group) }
let!(:service) { described_class.new(user, group_params.merge(parent_id: group.id)) }
@@ -32,12 +32,24 @@ describe Groups::CreateService, '#execute' do
end
it { is_expected.to be_persisted }
+
+ context 'when nested groups feature is disabled' do
+ it 'does not save group and returns an error' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(false)
+
+ is_expected.not_to be_persisted
+ expect(subject.errors[:parent_id]).to include('You don’t have permission to create a subgroup in this group.')
+ expect(subject.parent_id).to be_nil
+ end
+ end
end
context 'as guest' do
it 'does not save group and returns an error' do
+ allow(Group).to receive(:supports_nested_groups?).and_return(true)
+
is_expected.not_to be_persisted
- expect(subject.errors[:parent_id].first).to eq('manage access required to create subgroup')
+ expect(subject.errors[:parent_id].first).to eq('You don’t have permission to create a subgroup in this group.')
expect(subject.parent_id).to be_nil
end
end
diff --git a/spec/services/groups/destroy_service_spec.rb b/spec/services/groups/destroy_service_spec.rb
index 1b2ce3cd03e..ac4b9c02ba7 100644
--- a/spec/services/groups/destroy_service_spec.rb
+++ b/spec/services/groups/destroy_service_spec.rb
@@ -8,8 +8,8 @@ describe Groups::DestroyService do
let!(:nested_group) { create(:group, parent: group) }
let!(:project) { create(:project, namespace: group) }
let!(:notification_setting) { create(:notification_setting, source: group)}
- let!(:gitlab_shell) { Gitlab::Shell.new }
- let!(:remove_path) { group.path + "+#{group.id}+deleted" }
+ let(:gitlab_shell) { Gitlab::Shell.new }
+ let(:remove_path) { group.path + "+#{group.id}+deleted" }
before do
group.add_user(user, Gitlab::Access::OWNER)
@@ -134,4 +134,26 @@ describe Groups::DestroyService do
it_behaves_like 'group destruction', false
end
+
+ describe 'repository removal' do
+ before do
+ destroy_group(group, user, false)
+ end
+
+ context 'legacy storage' do
+ let!(:project) { create(:project, :empty_repo, namespace: group) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+
+ context 'hashed storage' do
+ let!(:project) { create(:project, :hashed, :empty_repo, namespace: group) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+ end
end
diff --git a/spec/services/merge_requests/create_from_issue_service_spec.rb b/spec/services/merge_requests/create_from_issue_service_spec.rb
index 492b55cdece..313f87ae1f6 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -2,8 +2,10 @@ require 'spec_helper'
describe MergeRequests::CreateFromIssueService do
let(:project) { create(:project, :repository) }
- let(:user) { create(:user) }
- let(:issue) { create(:issue, project: project) }
+ let(:user) { create(:user) }
+ let(:label_ids) { create_pair(:label, project: project).map(&:id) }
+ let(:milestone_id) { create(:milestone, project: project).id }
+ let(:issue) { create(:issue, project: project, milestone_id: milestone_id) }
subject(:service) { described_class.new(project, user, issue_iid: issue.iid) }
@@ -25,6 +27,20 @@ describe MergeRequests::CreateFromIssueService do
described_class.new(project, user, issue_iid: -1).execute
end
+ it "inherits labels" do
+ issue.assign_attributes(label_ids: label_ids)
+
+ result = service.execute
+
+ expect(result[:merge_request].label_ids).to eq(label_ids)
+ end
+
+ it "inherits milestones" do
+ result = service.execute
+
+ expect(result[:merge_request].milestone_id).to eq(milestone_id)
+ end
+
it 'delegates the branch creation to CreateBranchService' do
expect_any_instance_of(CreateBranchService).to receive(:execute).once.and_call_original
diff --git a/spec/services/users/destroy_service_spec.rb b/spec/services/users/destroy_service_spec.rb
index a82567f6f43..58a5bede3de 100644
--- a/spec/services/users/destroy_service_spec.rb
+++ b/spec/services/users/destroy_service_spec.rb
@@ -4,9 +4,10 @@ describe Users::DestroyService do
describe "Deletes a user and all their personal projects" do
let!(:user) { create(:user) }
let!(:admin) { create(:admin) }
- let!(:namespace) { create(:namespace, owner: user) }
+ let!(:namespace) { user.namespace }
let!(:project) { create(:project, namespace: namespace) }
let(:service) { described_class.new(admin) }
+ let(:gitlab_shell) { Gitlab::Shell.new }
context 'no options are given' do
it 'deletes the user' do
@@ -14,7 +15,7 @@ describe Users::DestroyService do
expect { user_data['email'].to eq(user.email) }
expect { User.find(user.id) }.to raise_error(ActiveRecord::RecordNotFound)
- expect { Namespace.with_deleted.find(user.namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ expect { Namespace.with_deleted.find(namespace.id) }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'will delete the project' do
@@ -165,5 +166,27 @@ describe Users::DestroyService do
expect(Issue.exists?(issue.id)).to be_falsy
end
end
+
+ describe "user personal's repository removal" do
+ before do
+ Sidekiq::Testing.inline! { service.execute(user) }
+ end
+
+ context 'legacy storage' do
+ let!(:project) { create(:project, :empty_repo, namespace: user.namespace) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+
+ context 'hashed storage' do
+ let!(:project) { create(:project, :empty_repo, :hashed, namespace: user.namespace) }
+
+ it 'removes repository' do
+ expect(gitlab_shell.exists?(project.repository_storage_path, "#{project.disk_path}.git")).to be_falsey
+ end
+ end
+ end
end
end
diff --git a/spec/services/users/update_service_spec.rb b/spec/services/users/update_service_spec.rb
index 343804e3de0..985f6d94876 100644
--- a/spec/services/users/update_service_spec.rb
+++ b/spec/services/users/update_service_spec.rb
@@ -12,9 +12,22 @@ describe Users::UpdateService do
end
it 'returns an error result when record cannot be updated' do
+ result = {}
expect do
- update_user(user, { email: 'invalid' })
+ result = update_user(user, { email: 'invalid' })
end.not_to change { user.reload.email }
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Email is invalid')
+ end
+
+ it 'includes namespace error messages' do
+ create(:group, name: 'taken', path: 'something_else')
+ result = {}
+ expect do
+ result = update_user(user, { username: 'taken' })
+ end.not_to change { user.reload.username }
+ expect(result[:status]).to eq(:error)
+ expect(result[:message]).to eq('Namespace name has already been taken')
end
def update_user(user, opts)
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 3eea39d4bf4..ff1754fbe7e 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -105,6 +105,18 @@ RSpec.configure do |config|
reset_delivered_emails!
end
+ # Stub the `ForkedStorageCheck.storage_available?` method unless
+ # `:broken_storage` metadata is defined
+ #
+ # This check can be slow and is unnecessary in a test environment where we
+ # know the storage is available, because we create it at runtime
+ config.before(:example) do |example|
+ unless example.metadata[:broken_storage]
+ allow(Gitlab::Git::Storage::ForkedStorageCheck)
+ .to receive(:storage_available?).and_return(true)
+ end
+ end
+
config.around(:each, :use_clean_rails_memory_store_caching) do |example|
caching_store = Rails.cache
Rails.cache = ActiveSupport::Cache::MemoryStore.new
@@ -132,17 +144,12 @@ RSpec.configure do |config|
Sidekiq.redis(&:flushall)
end
- config.before(:example, :migration) do
- ActiveRecord::Migrator
- .migrate(migrations_paths, previous_migration.version)
-
- reset_column_in_migration_models
+ config.before(:each, :migration) do
+ schema_migrate_down!
end
- config.after(:example, :migration) do
- ActiveRecord::Migrator.migrate(migrations_paths)
-
- reset_column_in_migration_models
+ config.after(:context, :migration) do
+ schema_migrate_up!
end
config.around(:each, :nested_groups) do |example|
diff --git a/spec/support/background_migrations_matchers.rb b/spec/support/background_migrations_matchers.rb
new file mode 100644
index 00000000000..423c0e4cefc
--- /dev/null
+++ b/spec/support/background_migrations_matchers.rb
@@ -0,0 +1,13 @@
+RSpec::Matchers.define :be_scheduled_migration do |delay, *expected|
+ match do |migration|
+ BackgroundMigrationWorker.jobs.any? do |job|
+ job['args'] == [migration, expected] &&
+ job['at'].to_i == (delay.to_i + Time.now.to_i)
+ end
+ end
+
+ failure_message do |migration|
+ "Migration `#{migration}` with args `#{expected.inspect}` " \
+ 'not scheduled in expected time!'
+ end
+end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index 7f5769209bb..b0f520d08e8 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -20,7 +20,7 @@ RSpec.configure do |config|
end
config.before(:each, :migration) do
- DatabaseCleaner.strategy = :truncation
+ DatabaseCleaner.strategy = :truncation, { cache_tables: false }
end
config.before(:each) do
diff --git a/spec/support/migrations_helpers.rb b/spec/support/migrations_helpers.rb
index aabdad13047..255b3d96a62 100644
--- a/spec/support/migrations_helpers.rb
+++ b/spec/support/migrations_helpers.rb
@@ -31,6 +31,35 @@ module MigrationsHelpers
end
end
+ def migration_schema_version
+ self.class.metadata[:schema] || previous_migration.version
+ end
+
+ def schema_migrate_down!
+ disable_migrations_output do
+ ActiveRecord::Migrator.migrate(migrations_paths,
+ migration_schema_version)
+ end
+
+ reset_column_in_migration_models
+ end
+
+ def schema_migrate_up!
+ disable_migrations_output do
+ ActiveRecord::Migrator.migrate(migrations_paths)
+ end
+
+ reset_column_in_migration_models
+ end
+
+ def disable_migrations_output
+ ActiveRecord::Migration.verbose = false
+
+ yield
+ ensure
+ ActiveRecord::Migration.verbose = true
+ end
+
def migrate!
ActiveRecord::Migrator.up(migrations_paths) do |migration|
migration.name == described_class.name
diff --git a/spec/workers/authorized_projects_worker_spec.rb b/spec/workers/authorized_projects_worker_spec.rb
index 03b9b99e263..f8385ae7c72 100644
--- a/spec/workers/authorized_projects_worker_spec.rb
+++ b/spec/workers/authorized_projects_worker_spec.rb
@@ -29,21 +29,27 @@ describe AuthorizedProjectsWorker do
end
describe '#perform' do
- subject { described_class.new }
+ let(:user) { create(:user) }
- it "refreshes user's authorized projects" do
- user = create(:user)
+ subject(:job) { described_class.new }
+ it "refreshes user's authorized projects" do
expect_any_instance_of(User).to receive(:refresh_authorized_projects)
- subject.perform(user.id)
+ job.perform(user.id)
+ end
+
+ it 'notifies the JobWaiter when done if the key is provided' do
+ expect(Gitlab::JobWaiter).to receive(:notify).with('notify-key', job.jid)
+
+ job.perform(user.id, 'notify-key')
end
context "when the user is not found" do
it "does nothing" do
expect_any_instance_of(User).not_to receive(:refresh_authorized_projects)
- subject.perform(-1)
+ job.perform(-1)
end
end
end
diff --git a/spec/workers/namespaceless_project_destroy_worker_spec.rb b/spec/workers/namespaceless_project_destroy_worker_spec.rb
index f2706254284..20cf580af8a 100644
--- a/spec/workers/namespaceless_project_destroy_worker_spec.rb
+++ b/spec/workers/namespaceless_project_destroy_worker_spec.rb
@@ -5,7 +5,7 @@ describe NamespacelessProjectDestroyWorker do
before do
# Stub after_save callbacks that will fail when Project has no namespace
- allow_any_instance_of(Project).to receive(:ensure_storage_path_exist).and_return(nil)
+ allow_any_instance_of(Project).to receive(:ensure_storage_path_exists).and_return(nil)
allow_any_instance_of(Project).to receive(:update_project_statistics).and_return(nil)
end
@@ -75,5 +75,19 @@ describe NamespacelessProjectDestroyWorker do
end
end
end
+
+ context 'project has non-existing namespace' do
+ let!(:project) do
+ project = build(:project, namespace_id: Namespace.maximum(:id).to_i.succ)
+ project.save(validate: false)
+ project
+ end
+
+ it 'deletes the project' do
+ subject.perform(project.id)
+
+ expect(Project.unscoped.all).not_to include(project)
+ end
+ end
end
end
diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb
index ca904e512ac..100dfc32bbe 100644
--- a/spec/workers/repository_import_worker_spec.rb
+++ b/spec/workers/repository_import_worker_spec.rb
@@ -22,8 +22,8 @@ describe RepositoryImportWorker do
it 'hide the credentials that were used in the import URL' do
error = %q{remote: Not Found fatal: repository 'https://user:pass@test.com/root/repoC.git/' not found }
+ project.update_attributes(import_jid: '123')
expect_any_instance_of(Projects::ImportService).to receive(:execute).and_return({ status: :error, message: error })
- allow(subject).to receive(:jid).and_return('123')
expect do
subject.perform(project.id)
diff --git a/spec/workers/stage_update_worker_spec.rb b/spec/workers/stage_update_worker_spec.rb
new file mode 100644
index 00000000000..7bc76c79464
--- /dev/null
+++ b/spec/workers/stage_update_worker_spec.rb
@@ -0,0 +1,22 @@
+require 'spec_helper'
+
+describe StageUpdateWorker do
+ describe '#perform' do
+ context 'when stage exists' do
+ let(:stage) { create(:ci_stage_entity) }
+
+ it 'updates stage status' do
+ expect_any_instance_of(Ci::Stage).to receive(:update_status)
+
+ described_class.new.perform(stage.id)
+ end
+ end
+
+ context 'when stage does not exist' do
+ it 'does not raise exception' do
+ expect { described_class.new.perform(123) }
+ .not_to raise_error
+ end
+ end
+ end
+end
diff --git a/spec/workers/stuck_import_jobs_worker_spec.rb b/spec/workers/stuck_import_jobs_worker_spec.rb
index 2f5b685a332..a82eb54ffe4 100644
--- a/spec/workers/stuck_import_jobs_worker_spec.rb
+++ b/spec/workers/stuck_import_jobs_worker_spec.rb
@@ -8,29 +8,29 @@ describe StuckImportJobsWorker do
allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).and_return(exclusive_lease_uuid)
end
- describe 'long running import' do
- let(:project) { create(:project, import_jid: '123', import_status: 'started') }
+ describe 'with started import_status' do
+ let(:project) { create(:project, :import_started, import_jid: '123') }
- before do
- allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return(['123'])
- end
+ describe 'long running import' do
+ it 'marks the project as failed' do
+ allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return(['123'])
- it 'marks the project as failed' do
- expect { worker.perform }.to change { project.reload.import_status }.to('failed')
+ expect { worker.perform }.to change { project.reload.import_status }.to('failed')
+ end
end
- end
- describe 'running import' do
- let(:project) { create(:project, import_jid: '123', import_status: 'started') }
-
- before do
- allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([])
- end
+ describe 'running import' do
+ it 'does not mark the project as failed' do
+ allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([])
- it 'does not mark the project as failed' do
- worker.perform
+ expect { worker.perform }.not_to change { project.reload.import_status }
+ end
- expect(project.reload.import_status).to eq('started')
+ describe 'import without import_jid' do
+ it 'marks the project as failed' do
+ expect { worker.perform }.to change { project.reload.import_status }.to('failed')
+ end
+ end
end
end
end
diff --git a/yarn.lock b/yarn.lock
index ca6066dc14d..8ec3cffe831 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -14,8 +14,8 @@ accepts@1.3.3, accepts@~1.3.3:
negotiator "0.6.1"
acorn-dynamic-import@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.1.tgz#23f671eb6e650dab277fef477c321b1178a8cca2"
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz#c752bd210bef679501b6c6cb7fc84f8f47158cc4"
dependencies:
acorn "^4.0.3"
@@ -25,17 +25,17 @@ acorn-jsx@^3.0.0:
dependencies:
acorn "^3.0.4"
-acorn@4.0.4, acorn@^4.0.3:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.4.tgz#17a8d6a7a6c4ef538b814ec9abac2779293bf30a"
-
acorn@^3.0.4:
version "3.3.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a"
-acorn@^5.0.0, acorn@^5.0.3:
- version "5.0.3"
- resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d"
+acorn@^4.0.3:
+ version "4.0.13"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787"
+
+acorn@^5.0.0, acorn@^5.0.3, acorn@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75"
after@0.8.2:
version "0.8.2"
@@ -56,6 +56,13 @@ ajv@^4.7.0:
co "^4.6.0"
json-stable-stringify "^1.0.1"
+ajv@^4.9.1:
+ version "4.11.8"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
+ dependencies:
+ co "^4.6.0"
+ json-stable-stringify "^1.0.1"
+
ajv@^5.1.5:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.0.tgz#c1735024c5da2ef75cc190713073d44f098bf486"
@@ -102,11 +109,11 @@ ansi-styles@^2.2.1:
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
anymatch@^1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.0.tgz#a3e52fa39168c825ff57b0248126ce5a8ff95507"
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
dependencies:
- arrify "^1.0.0"
micromatch "^2.1.5"
+ normalize-path "^2.0.0"
append-transform@^0.4.0:
version "0.4.0"
@@ -115,15 +122,15 @@ append-transform@^0.4.0:
default-require-extensions "^1.0.0"
aproba@^1.0.3:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.0.tgz#4d8f047a318604e18e3c06a0e52230d3d19f147b"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1"
are-we-there-yet@~1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz#80e470e95a084794fe1899262c5667c6e88de1b3"
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.4.tgz#bb5dca382bb94f05e15194373d16fd3ba1ca110d"
dependencies:
delegates "^1.0.0"
- readable-stream "^2.0.0 || ^1.1.13"
+ readable-stream "^2.0.6"
argparse@^1.0.7:
version "1.0.9"
@@ -195,14 +202,14 @@ asn1@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
+assert-plus@1.0.0, assert-plus@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
+
assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
-assert-plus@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
-
assert@^1.1.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/assert/-/assert-1.4.1.tgz#99912d591836b5a6f5b345c0f07eefc08fc65d91"
@@ -213,17 +220,19 @@ async-each@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d"
-async@0.2.x:
- version "0.2.10"
- resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1"
-
async@1.x, async@^1.4.0, async@^1.4.2, async@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a"
+async@2.4.1:
+ version "2.4.1"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7"
+ dependencies:
+ lodash "^4.14.0"
+
async@^2.1.2, async@^2.1.4:
- version "2.1.4"
- resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4"
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/async/-/async-2.5.0.tgz#843190fd6b7357a0b9e1c956edddd5ec8462b54d"
dependencies:
lodash "^4.14.0"
@@ -261,7 +270,7 @@ axios@^0.16.2:
follow-redirects "^1.2.3"
is-buffer "^1.1.5"
-babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
+babel-code-frame@^6.11.0, babel-code-frame@^6.22.0:
version "6.22.0"
resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4"
dependencies:
@@ -269,6 +278,14 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.16.0, babel-code-frame@^6.22.0:
esutils "^2.0.2"
js-tokens "^3.0.0"
+babel-code-frame@^6.16.0:
+ version "6.26.0"
+ resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b"
+ dependencies:
+ chalk "^1.1.3"
+ esutils "^2.0.2"
+ js-tokens "^3.0.2"
+
babel-core@^6.22.1, babel-core@^6.23.0:
version "6.23.1"
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.23.1.tgz#c143cb621bb2f621710c220c5d579d15b8a442df"
@@ -864,6 +881,10 @@ balanced-match@^0.4.1, balanced-match@^0.4.2:
version "0.4.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-0.4.2.tgz#cb3f3e3c732dc0f01ee70b403f302e61d7709838"
+balanced-match@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
+
base64-arraybuffer@0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8"
@@ -876,9 +897,9 @@ base64id@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6"
-batch@0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464"
+batch@0.6.1:
+ version "0.6.1"
+ resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16"
bcrypt-pbkdf@^1.0.0:
version "1.0.1"
@@ -897,8 +918,8 @@ big.js@^3.1.3:
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.1.3.tgz#4cada2193652eb3ca9ec8e55c9015669c9806978"
binary-extensions@^1.0.0:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.8.0.tgz#48ec8d16df4377eae5fa5884682480af4d95c774"
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.10.0.tgz#9aeb9a6c5e88638aad171e167f5900abe24835d0"
blob@0.0.4:
version "0.0.4"
@@ -914,10 +935,14 @@ bluebird@^2.10.2:
version "2.11.0"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1"
-bluebird@^3.0.5, bluebird@^3.1.1, bluebird@^3.3.0:
+bluebird@^3.0.5, bluebird@^3.1.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
+bluebird@^3.3.0:
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c"
+
bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0:
version "4.11.6"
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215"
@@ -965,6 +990,13 @@ brace-expansion@^1.0.0:
balanced-match "^0.4.1"
concat-map "0.0.1"
+brace-expansion@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292"
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
braces@^0.1.2:
version "0.1.5"
resolved "https://registry.yarnpkg.com/braces/-/braces-0.1.5.tgz#c085711085291d8b75fdd74eab0f8597280711e6"
@@ -1069,14 +1101,14 @@ builtin-status-codes@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8"
-bytes@2.3.0:
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.3.0.tgz#d5b680a165b6201739acb611542aabc2d8ceb070"
-
bytes@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.4.0.tgz#7d97196f9d5baf7f6935e25985549edd2a6c2339"
+bytes@2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/bytes/-/bytes-2.5.0.tgz#4c9423ea2d252c270c41b2bdefeff9bb6b62c06a"
+
caller-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f"
@@ -1127,9 +1159,9 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639:
version "1.0.30000649"
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000649.tgz#1ee1754a6df235450c8b7cd15e0ebf507221a86a"
-caseless@~0.11.0:
- version "0.11.0"
- resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
+caseless@~0.12.0:
+ version "0.12.0"
+ resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
center-align@^0.1.1:
version "0.1.3"
@@ -1148,22 +1180,7 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
-chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0:
- version "1.6.1"
- resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.6.1.tgz#2f4447ab5e96e50fb3d789fd90d4c72e0e4c70c2"
- dependencies:
- anymatch "^1.3.0"
- async-each "^1.0.0"
- glob-parent "^2.0.0"
- inherits "^2.0.1"
- is-binary-path "^1.0.0"
- is-glob "^2.0.0"
- path-is-absolute "^1.0.0"
- readdirp "^2.0.0"
- optionalDependencies:
- fsevents "^1.0.0"
-
-chokidar@^1.7.0:
+chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
dependencies:
@@ -1185,8 +1202,8 @@ cipher-base@^1.0.0, cipher-base@^1.0.1:
inherits "^2.0.1"
circular-json@^0.3.1:
- version "0.3.1"
- resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.1.tgz#be8b36aefccde8b3ca7aa2d6afc07a37242c0d2d"
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66"
clap@^1.0.9:
version "1.1.3"
@@ -1294,7 +1311,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
-commander@^2.8.1, commander@^2.9.0:
+commander@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
@@ -1320,37 +1337,36 @@ component-inherit@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143"
-compressible@~2.0.8:
- version "2.0.9"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.9.tgz#6daab4e2b599c2770dd9e21e7a891b1c5a755425"
+compressible@~2.0.10:
+ version "2.0.11"
+ resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.11.tgz#16718a75de283ed8e604041625a2064586797d8a"
dependencies:
- mime-db ">= 1.24.0 < 2"
+ mime-db ">= 1.29.0 < 2"
-compression-webpack-plugin@^0.3.2:
- version "0.3.2"
- resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-0.3.2.tgz#1edfb0e749d7366d3e701670c463359b2c0cf704"
+compression-webpack-plugin@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/compression-webpack-plugin/-/compression-webpack-plugin-1.0.0.tgz#5c5eb6afd08ca6a5d66006eeef71da17b01bd676"
dependencies:
- async "0.2.x"
- webpack-sources "^0.1.0"
- optionalDependencies:
- node-zopfli "^2.0.0"
+ async "2.4.1"
+ webpack-sources "^1.0.1"
compression@^1.5.2:
- version "1.6.2"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.6.2.tgz#cceb121ecc9d09c52d7ad0c3350ea93ddd402bc3"
+ version "1.7.0"
+ resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.0.tgz#030c9f198f1643a057d776a738e922da4373012d"
dependencies:
accepts "~1.3.3"
- bytes "2.3.0"
- compressible "~2.0.8"
- debug "~2.2.0"
+ bytes "2.5.0"
+ compressible "~2.0.10"
+ debug "2.6.8"
on-headers "~1.0.1"
- vary "~1.1.0"
+ safe-buffer "5.1.1"
+ vary "~1.1.1"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
-concat-stream@^1.4.6:
+concat-stream@^1.5.2:
version "1.6.0"
resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7"
dependencies:
@@ -1383,11 +1399,11 @@ connect-history-api-fallback@^1.3.0:
resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169"
connect@^3.6.0:
- version "3.6.2"
- resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.2.tgz#694e8d20681bfe490282c8ab886be98f09f42fe7"
+ version "3.6.3"
+ resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.3.tgz#f7320d46a25b4be7b483a2236517f24b1e27e301"
dependencies:
- debug "2.6.7"
- finalhandler "1.0.3"
+ debug "2.6.8"
+ finalhandler "1.0.4"
parseurl "~1.3.1"
utils-merge "1.0.0"
@@ -1448,7 +1464,11 @@ copy-webpack-plugin@^4.0.1:
minimatch "^3.0.0"
node-dir "^0.1.10"
-core-js@^2.2.0, core-js@^2.4.0, core-js@^2.4.1:
+core-js@^2.2.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.0.tgz#569c050918be6486b3837552028ae0466b717086"
+
+core-js@^2.4.0, core-js@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.4.1.tgz#4de911e667b0eae9124e34254b53aea6fc618d3e"
@@ -1456,7 +1476,7 @@ core-js@~2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.3.0.tgz#fab83fbb0b2d8dc85fa636c4b9d34c75420c6d65"
-core-util-is@~1.0.0:
+core-util-is@1.0.2, core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@@ -1654,7 +1674,7 @@ de-indent@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d"
-debug@2.2.0, debug@~2.2.0:
+debug@2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.2.0.tgz#f87057e995b1a1f6ae6a4960664137bc56f039da"
dependencies:
@@ -1672,7 +1692,7 @@ debug@2.6.7:
dependencies:
ms "2.0.0"
-debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.6, debug@^2.6.8:
+debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.2.0, debug@^2.4.5, debug@^2.6.6, debug@^2.6.8:
version "2.6.8"
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
dependencies:
@@ -1697,8 +1717,8 @@ deep-equal@^1.0.1:
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
deep-extend@~0.4.0:
- version "0.4.1"
- resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.1.tgz#efe4113d08085f4e6f9687759810f807469e2253"
+ version "0.4.2"
+ resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.4.2.tgz#48b699c27e334bf89f10892be432f6e4c7d34a7f"
deep-is@~0.1.3:
version "0.1.3"
@@ -1710,12 +1730,6 @@ default-require-extensions@^1.0.0:
dependencies:
strip-bom "^2.0.0"
-defaults@^1.0.2:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
- dependencies:
- clone "^1.0.2"
-
defined@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693"
@@ -1755,10 +1769,14 @@ delegates@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
-depd@1.1.0, depd@~1.1.0:
+depd@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
+depd@1.1.1, depd@~1.1.0, depd@~1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
+
des.js@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
@@ -1776,6 +1794,10 @@ detect-indent@^4.0.0:
dependencies:
repeating "^2.0.0"
+detect-node@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
+
di@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
@@ -1793,8 +1815,8 @@ dns-equal@^1.0.0:
resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d"
dns-packet@^1.0.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.1.1.tgz#2369d45038af045f3898e6fa56862aed3f40296c"
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.2.2.tgz#a8a26bec7646438963fc86e06f8f8b16d6c8bf7a"
dependencies:
ip "^1.1.0"
safe-buffer "^5.0.1"
@@ -1805,13 +1827,20 @@ dns-txt@^2.0.2:
dependencies:
buffer-indexof "^1.0.0"
-doctrine@1.5.0, doctrine@^1.2.2:
+doctrine@1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa"
dependencies:
esutils "^2.0.2"
isarray "^1.0.0"
+doctrine@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63"
+ dependencies:
+ esutils "^2.0.2"
+ isarray "^1.0.0"
+
document-register-element@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/document-register-element/-/document-register-element-1.3.0.tgz#fb3babb523c74662be47be19c6bc33e71990d940"
@@ -1870,10 +1899,10 @@ duplexer@^0.1.1, duplexer@~0.1.1:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1"
duplexify@^3.2.0:
- version "3.5.0"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.0.tgz#1aa773002e1578457e9d9d4a50b0ccaaebcbd604"
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.5.1.tgz#4e1516be68838bc90a49994f0b39a6e5960befcd"
dependencies:
- end-of-stream "1.0.0"
+ end-of-stream "^1.0.0"
inherits "^2.0.1"
readable-stream "^2.0.0"
stream-shift "^1.0.0"
@@ -1926,11 +1955,11 @@ encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
-end-of-stream@1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e"
+end-of-stream@^1.0.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.0.tgz#7a90d833efda6cfa6eac0f4949dbb0fad3a63206"
dependencies:
- once "~1.3.0"
+ once "^1.4.0"
engine.io-client@1.8.3:
version "1.8.3"
@@ -2034,7 +2063,11 @@ es6-map@^0.1.3:
es6-symbol "~3.1.1"
event-emitter "~0.3.5"
-es6-promise@^3.0.2, es6-promise@~3.0.2:
+es6-promise@^3.0.2:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
+
+es6-promise@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.0.2.tgz#010d5858423a5f118979665f46486a95c6ee2bb6"
@@ -2165,16 +2198,17 @@ eslint-plugin-promise@^3.5.0:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca"
eslint@^3.10.1:
- version "3.15.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.15.0.tgz#bdcc6a6c5ffe08160e7b93c066695362a91e30f2"
+ version "3.19.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-3.19.0.tgz#c8fc6201c7f40dd08941b87c085767386a679acc"
dependencies:
babel-code-frame "^6.16.0"
chalk "^1.1.3"
- concat-stream "^1.4.6"
+ concat-stream "^1.5.2"
debug "^2.1.1"
- doctrine "^1.2.2"
+ doctrine "^2.0.0"
escope "^3.6.0"
espree "^3.4.0"
+ esquery "^1.0.0"
estraverse "^4.2.0"
esutils "^2.0.2"
file-entry-cache "^2.0.0"
@@ -2204,10 +2238,10 @@ eslint@^3.10.1:
user-home "^2.0.0"
espree@^3.4.0:
- version "3.4.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-3.4.0.tgz#41656fa5628e042878025ef467e78f125cb86e1d"
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d"
dependencies:
- acorn "4.0.4"
+ acorn "^5.1.1"
acorn-jsx "^3.0.0"
esprima@2.7.x, esprima@^2.6.0, esprima@^2.7.1:
@@ -2218,6 +2252,16 @@ esprima@^3.1.1:
version "3.1.3"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633"
+esprima@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804"
+
+esquery@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa"
+ dependencies:
+ estraverse "^4.0.0"
+
esrecurse@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.1.0.tgz#4713b6536adf7f2ac4f327d559e7756bff648220"
@@ -2229,7 +2273,7 @@ estraverse@^1.9.1:
version "1.9.3"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
-estraverse@^4.1.1, estraverse@^4.2.0:
+estraverse@^4.0.0, estraverse@^4.1.1, estraverse@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13"
@@ -2339,8 +2383,8 @@ exports-loader@^0.6.4:
source-map "0.5.x"
express@^4.13.3, express@^4.15.2:
- version "4.15.3"
- resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662"
+ version "4.15.4"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
dependencies:
accepts "~1.3.3"
array-flatten "1.1.1"
@@ -2348,23 +2392,23 @@ express@^4.13.3, express@^4.15.2:
content-type "~1.0.2"
cookie "0.3.1"
cookie-signature "1.0.6"
- debug "2.6.7"
- depd "~1.1.0"
+ debug "2.6.8"
+ depd "~1.1.1"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
- finalhandler "~1.0.3"
+ finalhandler "~1.0.4"
fresh "0.5.0"
merge-descriptors "1.0.1"
methods "~1.1.2"
on-finished "~2.3.0"
parseurl "~1.3.1"
path-to-regexp "0.1.7"
- proxy-addr "~1.1.4"
- qs "6.4.0"
+ proxy-addr "~1.1.5"
+ qs "6.5.0"
range-parser "~1.2.0"
- send "0.15.3"
- serve-static "1.12.3"
+ send "0.15.4"
+ serve-static "1.12.4"
setprototypeof "1.0.3"
statuses "~1.3.1"
type-is "~1.6.15"
@@ -2372,8 +2416,8 @@ express@^4.13.3, express@^4.15.2:
vary "~1.1.1"
extend@^3.0.0, extend@~3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4"
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
extglob@^0.3.1:
version "0.3.2"
@@ -2381,9 +2425,9 @@ extglob@^0.3.1:
dependencies:
is-extglob "^1.0.0"
-extsprintf@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.0.2.tgz#e1080e0658e300b06294990cc70e1502235fd550"
+extsprintf@1.3.0, extsprintf@^1.2.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
fast-deep-equal@^0.1.0:
version "0.1.0"
@@ -2464,11 +2508,11 @@ fill-range@^2.1.0:
repeat-element "^1.1.2"
repeat-string "^1.5.2"
-finalhandler@1.0.3, finalhandler@~1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89"
+finalhandler@1.0.4, finalhandler@~1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
dependencies:
- debug "2.6.7"
+ debug "2.6.8"
encodeurl "~1.0.1"
escape-html "~1.0.3"
on-finished "~2.3.0"
@@ -2535,8 +2579,8 @@ forever-agent@~0.6.1:
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
form-data@~2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.2.tgz#89c3534008b97eada4cbb157d58f6f5df025eae4"
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1"
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.5"
@@ -2575,13 +2619,13 @@ fs.realpath@^1.0.0:
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
fsevents@^1.0.0:
- version "1.0.17"
- resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.0.17.tgz#8537f3f12272678765b4fd6528c0f1f66f8f4558"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.1.2.tgz#3282b713fb3ad80ede0e9fcf4611b5aa6fc033f4"
dependencies:
nan "^2.3.0"
- node-pre-gyp "^0.6.29"
+ node-pre-gyp "^0.6.36"
-fstream-ignore@~1.0.5:
+fstream-ignore@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/fstream-ignore/-/fstream-ignore-1.0.5.tgz#9c31dae34767018fe1d249b24dada67d092da105"
dependencies:
@@ -2589,9 +2633,9 @@ fstream-ignore@~1.0.5:
inherits "2"
minimatch "^3.0.0"
-fstream@^1.0.0, fstream@^1.0.2, fstream@~1.0.10:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.10.tgz#604e8a92fe26ffd9f6fae30399d4984e1ab22822"
+fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2:
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
@@ -2602,9 +2646,9 @@ function-bind@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
-gauge@~2.7.1:
- version "2.7.2"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.2.tgz#15cecc31b02d05345a5d6b0e171cdb3ad2307774"
+gauge@~2.7.3:
+ version "2.7.4"
+ resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
dependencies:
aproba "^1.0.3"
console-control-strings "^1.0.0"
@@ -2613,7 +2657,6 @@ gauge@~2.7.1:
signal-exit "^3.0.0"
string-width "^1.0.1"
strip-ansi "^3.0.1"
- supports-color "^0.2.0"
wide-align "^1.1.0"
generate-function@^2.0.0:
@@ -2639,8 +2682,8 @@ get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
getpass@^0.1.1:
- version "0.1.6"
- resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.6.tgz#283ffd9fc1256840875311c1b60e8c40187110e6"
+ version "0.1.7"
+ resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
dependencies:
assert-plus "^1.0.0"
@@ -2677,7 +2720,18 @@ glob@^6.0.4:
once "^1.3.0"
path-is-absolute "^1.0.0"
-glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
+glob@^7.0.0, glob@^7.1.1:
+ version "7.1.2"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15"
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+glob@^7.0.3, glob@^7.0.5:
version "7.1.1"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8"
dependencies:
@@ -2688,10 +2742,14 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.1.1:
once "^1.3.0"
path-is-absolute "^1.0.0"
-globals@^9.0.0, globals@^9.14.0:
+globals@^9.0.0:
version "9.14.0"
resolved "https://registry.yarnpkg.com/globals/-/globals-9.14.0.tgz#8859936af0038741263053b39d0e76ca241e4034"
+globals@^9.14.0:
+ version "9.18.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a"
+
globby@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d"
@@ -2767,7 +2825,7 @@ gzip-size@3.0.0, gzip-size@^3.0.0:
dependencies:
duplexer "^0.1.1"
-handle-thing@^1.2.4:
+handle-thing@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4"
@@ -2781,14 +2839,16 @@ handlebars@^4.0.1, handlebars@^4.0.3:
optionalDependencies:
uglify-js "^2.6"
-har-validator@~2.0.6:
- version "2.0.6"
- resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-2.0.6.tgz#cdcbc08188265ad119b6a5a7c8ab70eecfb5d27d"
+har-schema@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e"
+
+har-validator@~4.2.1:
+ version "4.2.1"
+ resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a"
dependencies:
- chalk "^1.1.1"
- commander "^2.9.0"
- is-my-json-valid "^2.12.4"
- pinkie-promise "^2.0.0"
+ ajv "^4.9.1"
+ har-schema "^1.0.5"
has-ansi@^2.0.0:
version "2.0.0"
@@ -2885,10 +2945,14 @@ html-comment-regex@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.1.tgz#668b93776eaae55ebde8f3ad464b307a4963625e"
-html-entities@1.2.0, html-entities@^1.2.0:
+html-entities@1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.0.tgz#41948caf85ce82fed36e4e6a0ed371a6664379e2"
+html-entities@^1.2.0:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f"
+
htmlparser2@^3.8.2:
version "3.9.2"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.9.2.tgz#1bdf87acca0f3f9e53fa4fcceb0f4b4cbb00b338"
@@ -2900,18 +2964,10 @@ htmlparser2@^3.8.2:
inherits "^2.0.1"
readable-stream "^2.0.2"
-http-deceiver@^1.2.4:
+http-deceiver@^1.2.7:
version "1.2.7"
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
-http-errors@~1.5.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750"
- dependencies:
- inherits "2.0.3"
- setprototypeof "1.0.2"
- statuses ">= 1.3.1 < 2"
-
http-errors@~1.6.1:
version "1.6.1"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257"
@@ -2921,6 +2977,15 @@ http-errors@~1.6.1:
setprototypeof "1.0.3"
statuses ">= 1.3.1 < 2"
+http-errors@~1.6.2:
+ version "1.6.2"
+ resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
+ dependencies:
+ depd "1.1.1"
+ inherits "2.0.3"
+ setprototypeof "1.0.3"
+ statuses ">= 1.3.1 < 2"
+
http-proxy-middleware@~0.17.4:
version "0.17.4"
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
@@ -2966,8 +3031,8 @@ ignore-by-default@^1.0.0:
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
ignore@^3.2.0:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.2.2.tgz#1c51e1ef53bab6ddc15db4d9ac4ec139eceb3410"
+ version "3.3.3"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d"
immediate@~3.0.5:
version "3.0.6"
@@ -3009,7 +3074,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
-inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1:
+inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
@@ -3059,13 +3124,13 @@ invert-kv@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6"
-ip@^1.1.0:
+ip@^1.1.0, ip@^1.1.5:
version "1.1.5"
resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a"
-ipaddr.js@1.3.0:
- version "1.3.0"
- resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
+ipaddr.js@1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
is-absolute-url@^2.0.0:
version "2.1.0"
@@ -3148,9 +3213,9 @@ is-glob@^3.1.0:
dependencies:
is-extglob "^2.1.0"
-is-my-json-valid@^2.10.0, is-my-json-valid@^2.12.4:
- version "2.15.0"
- resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.15.0.tgz#936edda3ca3c211fd98f3b2d3e08da43f7b2915b"
+is-my-json-valid@^2.10.0:
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz#f079dd9bfdae65ee2038aae8acbc86ab109e3693"
dependencies:
generate-function "^2.0.0"
generate-object-property "^1.1.0"
@@ -3271,6 +3336,10 @@ isexe@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/isexe/-/isexe-1.1.2.tgz#36f3e22e60750920f5e7241a476a8c6a42275ad0"
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+
isobject@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
@@ -3383,12 +3452,6 @@ jed@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/jed/-/jed-1.1.1.tgz#7a549bbd9ffe1585b0cd0a191e203055bee574b4"
-jodid25519@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967"
- dependencies:
- jsbn "~0.1.0"
-
jquery-ujs@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.1.tgz#6ee75b1ef4e9ac95e7124f8d71f7d351f5548e92"
@@ -3420,13 +3483,24 @@ js-tokens@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
-js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.5.1, js-yaml@^3.7.0:
+js-tokens@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
+js-yaml@3.x, js-yaml@^3.4.3, js-yaml@^3.7.0:
version "3.8.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.8.1.tgz#782ba50200be7b9e5a8537001b7804db3ad02628"
dependencies:
argparse "^1.0.7"
esprima "^3.1.1"
+js-yaml@^3.5.1:
+ version "3.9.1"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0"
+ dependencies:
+ argparse "^1.0.7"
+ esprima "^4.0.0"
+
js-yaml@~3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
@@ -3435,8 +3509,8 @@ js-yaml@~3.7.0:
esprima "^2.6.0"
jsbn@~0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.0.tgz#650987da0dd74f4ebf5a11377a2aa2d273e97dfd"
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
jsesc@^1.3.0:
version "1.3.0"
@@ -3447,12 +3521,12 @@ jsesc@~0.5.0:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
json-loader@^0.5.4:
- version "0.5.4"
- resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.4.tgz#8baa1365a632f58a3c46d20175fc6002c96e37de"
+ version "0.5.7"
+ resolved "https://registry.yarnpkg.com/json-loader/-/json-loader-0.5.7.tgz#dca14a70235ff82f0ac9a3abeb60d337a365185d"
json-schema-traverse@^0.3.0:
- version "0.3.0"
- resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.0.tgz#0016c0b1ca1efe46d44d37541bcdfc19dcfae0db"
+ version "0.3.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"
json-schema@0.2.3:
version "0.2.3"
@@ -3491,12 +3565,13 @@ jsonpointer@^4.0.0:
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
jsprim@^1.2.2:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.3.1.tgz#2a7256f70412a29ee3670aaca625994c4dcff252"
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
dependencies:
- extsprintf "1.0.2"
+ assert-plus "1.0.0"
+ extsprintf "1.3.0"
json-schema "0.2.3"
- verror "1.3.6"
+ verror "1.10.0"
jszip-utils@^0.0.2:
version "0.0.2"
@@ -3960,11 +4035,21 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-"mime-db@>= 1.24.0 < 2", mime-db@~1.27.0:
+"mime-db@>= 1.29.0 < 2", mime-db@~1.29.0:
+ version "1.29.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.29.0.tgz#48d26d235589651704ac5916ca06001914266878"
+
+mime-db@~1.27.0:
version "1.27.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.27.0.tgz#820f572296bbd20ec25ed55e5b5de869e5436eb1"
-mime-types@^2.1.12, mime-types@~2.1.11, mime-types@~2.1.15, mime-types@~2.1.7:
+mime-types@^2.1.12, mime-types@~2.1.7:
+ version "2.1.16"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.16.tgz#2b858a52e5ecd516db897ac2be87487830698e23"
+ dependencies:
+ mime-db "~1.29.0"
+
+mime-types@~2.1.11, mime-types@~2.1.15:
version "2.1.15"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.15.tgz#a4ebf5064094569237b8cf70046776d09fc92aed"
dependencies:
@@ -3992,6 +4077,12 @@ minimalistic-assert@^1.0.0:
dependencies:
brace-expansion "^1.0.0"
+minimatch@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
+ dependencies:
+ brace-expansion "^1.1.7"
+
minimist@0.0.8, minimist@~0.0.1:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
@@ -4049,9 +4140,9 @@ name-all-modules-plugin@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/name-all-modules-plugin/-/name-all-modules-plugin-1.0.1.tgz#0abfb6ad835718b9fb4def0674e06657a954375c"
-nan@^2.0.0, nan@^2.3.0:
- version "2.5.1"
- resolved "https://registry.yarnpkg.com/nan/-/nan-2.5.1.tgz#d5b01691253326a97a2bbee9e61c55d8d60351e2"
+nan@^2.3.0:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
natural-compare@^1.4.0:
version "1.4.0"
@@ -4133,28 +4224,19 @@ node-libs-browser@^2.0.0:
util "^0.10.3"
vm-browserify "0.0.4"
-node-pre-gyp@^0.6.29, node-pre-gyp@^0.6.4:
- version "0.6.33"
- resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.33.tgz#640ac55198f6a925972e0c16c4ac26a034d5ecc9"
- dependencies:
- mkdirp "~0.5.1"
- nopt "~3.0.6"
- npmlog "^4.0.1"
- rc "~1.1.6"
- request "^2.79.0"
- rimraf "~2.5.4"
- semver "~5.3.0"
- tar "~2.2.1"
- tar-pack "~3.3.0"
-
-node-zopfli@^2.0.0:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/node-zopfli/-/node-zopfli-2.0.2.tgz#a7a473ae92aaea85d4c68d45bbf2c944c46116b8"
+node-pre-gyp@^0.6.36:
+ version "0.6.36"
+ resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786"
dependencies:
- commander "^2.8.1"
- defaults "^1.0.2"
- nan "^2.0.0"
- node-pre-gyp "^0.6.4"
+ mkdirp "^0.5.1"
+ nopt "^4.0.1"
+ npmlog "^4.0.2"
+ rc "^1.1.7"
+ request "^2.81.0"
+ rimraf "^2.6.1"
+ semver "^5.3.0"
+ tar "^2.2.1"
+ tar-pack "^3.4.0"
nodemon@^1.11.0:
version "1.11.0"
@@ -4171,19 +4253,26 @@ nodemon@^1.11.0:
undefsafe "0.0.3"
update-notifier "0.5.0"
-nopt@3.x, nopt@~3.0.1, nopt@~3.0.6:
+nopt@3.x, nopt@~3.0.1:
version "3.0.6"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9"
dependencies:
abbrev "1"
+nopt@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d"
+ dependencies:
+ abbrev "1"
+ osenv "^0.1.4"
+
nopt@~1.0.10:
version "1.0.10"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
dependencies:
abbrev "1"
-normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
+normalize-package-data@^2.3.2:
version "2.3.5"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.3.5.tgz#8d924f142960e1777e7ffe170543631cc7cb02df"
dependencies:
@@ -4192,9 +4281,20 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
semver "2 || 3 || 4 || 5"
validate-npm-package-license "^3.0.1"
-normalize-path@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.0.1.tgz#47886ac1662760d4261b7d979d241709d3ce3f7a"
+normalize-package-data@^2.3.4:
+ version "2.4.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f"
+ dependencies:
+ hosted-git-info "^2.1.4"
+ is-builtin-module "^1.0.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^2.0.0, normalize-path@^2.0.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9"
+ dependencies:
+ remove-trailing-separator "^1.0.1"
normalize-range@^0.1.2:
version "0.1.2"
@@ -4215,13 +4315,13 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
-npmlog@^4.0.1:
- version "4.0.2"
- resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.0.2.tgz#d03950e0e78ce1527ba26d2a7592e9348ac3e75f"
+npmlog@^4.0.2:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
dependencies:
are-we-there-yet "~1.1.2"
console-control-strings "~1.1.0"
- gauge "~2.7.1"
+ gauge "~2.7.3"
set-blocking "~2.0.0"
null-check@^1.0.0:
@@ -4263,7 +4363,7 @@ object.omit@^2.0.0:
for-own "^0.1.4"
is-extendable "^0.1.1"
-obuf@^1.0.0, obuf@^1.1.0:
+obuf@^1.0.0, obuf@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e"
@@ -4277,18 +4377,12 @@ on-headers@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.1.tgz#928f5d0f470d49342651ea6794b0857c100693f7"
-once@1.x, once@^1.3.0, once@^1.4.0:
+once@1.x, once@^1.3.0, once@^1.3.3, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
dependencies:
wrappy "1"
-once@~1.3.0, once@~1.3.3:
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/once/-/once-1.3.3.tgz#b2e261557ce4c314ec8304f3fa82663e4297ca20"
- dependencies:
- wrappy "1"
-
onetime@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789"
@@ -4354,11 +4448,11 @@ os-locale@^2.0.0:
lcid "^1.0.0"
mem "^1.1.0"
-os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1:
+os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.1, os-tmpdir@~1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
-osenv@^0.1.0:
+osenv@^0.1.0, osenv@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.4.tgz#42fe6d5953df06c8064be6f176c3d05aaaa34644"
dependencies:
@@ -4515,6 +4609,10 @@ pbkdf2@^3.0.3:
dependencies:
create-hmac "^1.1.2"
+performance-now@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5"
+
pify@^2.0.0, pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -4868,12 +4966,12 @@ proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
-proxy-addr@~1.1.4:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3"
+proxy-addr@~1.1.5:
+ version "1.1.5"
+ resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
dependencies:
forwarded "~0.1.0"
- ipaddr.js "1.3.0"
+ ipaddr.js "1.4.0"
prr@~0.0.0:
version "0.0.0"
@@ -4915,13 +5013,13 @@ qjobs@^1.1.4:
version "1.1.5"
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
-qs@6.4.0:
+qs@6.4.0, qs@~6.4.0:
version "6.4.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
-qs@~6.3.0:
- version "6.3.0"
- resolved "https://registry.yarnpkg.com/qs/-/qs-6.3.0.tgz#f403b264f23bc01228c74131b407f18d5ea5d442"
+qs@6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
query-string@^4.1.0:
version "4.3.2"
@@ -4985,14 +5083,14 @@ raw-loader@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-0.5.1.tgz#0c3d0beaed8a01c966d9787bf778281252a979aa"
-rc@^1.0.1, rc@~1.1.6:
- version "1.1.6"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.1.6.tgz#43651b76b6ae53b5c802f1151fa3fc3b059969c9"
+rc@^1.0.1, rc@^1.1.7:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.1.tgz#2e03e8e42ee450b8cb3dce65be1bf8974e1dfd95"
dependencies:
deep-extend "~0.4.0"
ini "~1.3.0"
minimist "^1.2.0"
- strip-json-comments "~1.0.4"
+ strip-json-comments "~2.0.1"
react-dev-utils@^0.5.2:
version "0.5.2"
@@ -5046,16 +5144,16 @@ read-pkg@^2.0.0:
normalize-package-data "^2.3.2"
path-type "^2.0.0"
-readable-stream@^2.0.0, "readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.1.0, readable-stream@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
+readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.2.2, readable-stream@^2.2.9:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c"
dependencies:
- buffer-shims "^1.0.0"
core-util-is "~1.0.0"
- inherits "~2.0.1"
+ inherits "~2.0.3"
isarray "~1.0.0"
process-nextick-args "~1.0.6"
- string_decoder "~0.10.x"
+ safe-buffer "~5.1.1"
+ string_decoder "~1.0.3"
util-deprecate "~1.0.1"
readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@~2.0.6:
@@ -5069,26 +5167,26 @@ readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable
string_decoder "~0.10.x"
util-deprecate "~1.0.1"
-readable-stream@~1.0.2:
- version "1.0.34"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
+readable-stream@^2.1.0:
+ version "2.2.2"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.2.tgz#a9e6fec3c7dda85f8bb1b3ba7028604556fc825e"
dependencies:
+ buffer-shims "^1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
- isarray "0.0.1"
+ isarray "~1.0.0"
+ process-nextick-args "~1.0.6"
string_decoder "~0.10.x"
+ util-deprecate "~1.0.1"
-readable-stream@~2.1.4:
- version "2.1.5"
- resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.1.5.tgz#66fa8b720e1438b364681f2ad1a63c618448c9d0"
+readable-stream@~1.0.2:
+ version "1.0.34"
+ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c"
dependencies:
- buffer-shims "^1.0.0"
core-util-is "~1.0.0"
inherits "~2.0.1"
- isarray "~1.0.0"
- process-nextick-args "~1.0.6"
+ isarray "0.0.1"
string_decoder "~0.10.x"
- util-deprecate "~1.0.1"
readdirp@^2.0.0:
version "2.1.0"
@@ -5195,6 +5293,10 @@ regjsparser@^0.1.4:
dependencies:
jsesc "~0.5.0"
+remove-trailing-separator@^1.0.1:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
+
repeat-element@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.2.tgz#ef089a178d1483baae4d93eb98b4f9e4e11d990a"
@@ -5219,18 +5321,18 @@ repeating@^2.0.0:
dependencies:
is-finite "^1.0.0"
-request@^2.79.0:
- version "2.79.0"
- resolved "https://registry.yarnpkg.com/request/-/request-2.79.0.tgz#4dfe5bf6be8b8cdc37fcf93e04b65577722710de"
+request@^2.81.0:
+ version "2.81.0"
+ resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0"
dependencies:
aws-sign2 "~0.6.0"
aws4 "^1.2.1"
- caseless "~0.11.0"
+ caseless "~0.12.0"
combined-stream "~1.0.5"
extend "~3.0.0"
forever-agent "~0.6.1"
form-data "~2.1.1"
- har-validator "~2.0.6"
+ har-validator "~4.2.1"
hawk "~3.1.3"
http-signature "~1.1.0"
is-typedarray "~1.0.0"
@@ -5238,10 +5340,12 @@ request@^2.79.0:
json-stringify-safe "~5.0.1"
mime-types "~2.1.7"
oauth-sign "~0.8.1"
- qs "~6.3.0"
+ performance-now "^0.2.0"
+ qs "~6.4.0"
+ safe-buffer "^5.0.1"
stringstream "~0.0.4"
tough-cookie "~2.3.0"
- tunnel-agent "~0.4.1"
+ tunnel-agent "^0.6.0"
uuid "^3.0.0"
require-directory@^2.1.1:
@@ -5292,18 +5396,12 @@ right-align@^0.1.1:
dependencies:
align-text "^0.1.1"
-rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.6.0:
+rimraf@2, rimraf@^2.2.8, rimraf@^2.4.3, rimraf@^2.4.4, rimraf@^2.5.1, rimraf@^2.6.0, rimraf@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d"
dependencies:
glob "^7.0.5"
-rimraf@~2.5.1, rimraf@~2.5.4:
- version "2.5.4"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.5.4.tgz#96800093cbf1a0c86bd95b4625467535c29dfa04"
- dependencies:
- glob "^7.0.5"
-
ripemd160@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-1.0.1.tgz#93a4bbd4942bc574b69a8fa57c71de10ecca7d6e"
@@ -5318,6 +5416,10 @@ rx-lite@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102"
+safe-buffer@5.1.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853"
+
safe-buffer@^5.0.1, safe-buffer@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7"
@@ -5339,8 +5441,8 @@ select@^1.1.2:
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
selfsigned@^1.9.1:
- version "1.9.1"
- resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.9.1.tgz#cdda4492d70d486570f87c65546023558e1dfa5a"
+ version "1.10.1"
+ resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.1.tgz#bf8cb7b83256c4551e31347c6311778db99eec52"
dependencies:
node-forge "0.6.33"
@@ -5350,26 +5452,30 @@ semver-diff@^2.0.0:
dependencies:
semver "^5.0.3"
-"semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.3.0, semver@~5.3.0:
+"semver@2 || 3 || 4 || 5", semver@^5.3.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
+semver@^5.0.3:
+ version "5.4.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
+
semver@~4.3.3:
version "4.3.6"
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
-send@0.15.3:
- version "0.15.3"
- resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309"
+send@0.15.4:
+ version "0.15.4"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
dependencies:
- debug "2.6.7"
- depd "~1.1.0"
+ debug "2.6.8"
+ depd "~1.1.1"
destroy "~1.0.4"
encodeurl "~1.0.1"
escape-html "~1.0.3"
etag "~1.8.0"
fresh "0.5.0"
- http-errors "~1.6.1"
+ http-errors "~1.6.2"
mime "1.3.4"
ms "2.0.0"
on-finished "~2.3.0"
@@ -5377,25 +5483,25 @@ send@0.15.3:
statuses "~1.3.1"
serve-index@^1.7.2:
- version "1.8.0"
- resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.8.0.tgz#7c5d96c13fb131101f93c1c5774f8516a1e78d3b"
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7"
dependencies:
accepts "~1.3.3"
- batch "0.5.3"
- debug "~2.2.0"
+ batch "0.6.1"
+ debug "2.6.8"
escape-html "~1.0.3"
- http-errors "~1.5.0"
- mime-types "~2.1.11"
+ http-errors "~1.6.1"
+ mime-types "~2.1.15"
parseurl "~1.3.1"
-serve-static@1.12.3:
- version "1.12.3"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2"
+serve-static@1.12.4:
+ version "1.12.4"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
dependencies:
encodeurl "~1.0.1"
escape-html "~1.0.3"
parseurl "~1.3.1"
- send "0.15.3"
+ send "0.15.4"
set-blocking@^2.0.0, set-blocking@~2.0.0:
version "2.0.0"
@@ -5409,10 +5515,6 @@ setimmediate@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
-setprototypeof@1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08"
-
setprototypeof@1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04"
@@ -5434,8 +5536,8 @@ shebang-regex@^1.0.0:
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3"
shelljs@^0.7.5:
- version "0.7.6"
- resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.6.tgz#379cccfb56b91c8601e4793356eb5382924de9ad"
+ version "0.7.8"
+ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3"
dependencies:
glob "^7.0.0"
interpret "^1.0.0"
@@ -5546,7 +5648,7 @@ sort-keys@^1.0.0:
dependencies:
is-plain-obj "^1.0.0"
-source-list-map@^0.1.7, source-list-map@~0.1.7:
+source-list-map@^0.1.7:
version "0.1.8"
resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106"
@@ -5596,25 +5698,28 @@ spdx-license-ids@^1.0.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57"
-spdy-transport@^2.0.15:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.18.tgz#43fc9c56be2cccc12bb3e2754aa971154e836ea6"
+spdy-transport@^2.0.18:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d"
dependencies:
- debug "^2.2.0"
+ debug "^2.6.8"
+ detect-node "^2.0.3"
hpack.js "^2.1.6"
- obuf "^1.1.0"
- readable-stream "^2.0.1"
- wbuf "^1.4.0"
+ obuf "^1.1.1"
+ readable-stream "^2.2.9"
+ safe-buffer "^5.0.1"
+ wbuf "^1.7.2"
spdy@^3.4.1:
- version "3.4.4"
- resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.4.tgz#e0406407ca90ff01b553eb013505442649f5a819"
+ version "3.4.7"
+ resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc"
dependencies:
- debug "^2.2.0"
- handle-thing "^1.2.4"
- http-deceiver "^1.2.4"
+ debug "^2.6.8"
+ handle-thing "^1.2.5"
+ http-deceiver "^1.2.7"
+ safe-buffer "^5.0.1"
select-hose "^2.0.0"
- spdy-transport "^2.0.15"
+ spdy-transport "^2.0.18"
split@0.3:
version "0.3.3"
@@ -5631,8 +5736,8 @@ sql.js@^0.4.0:
resolved "https://registry.yarnpkg.com/sql.js/-/sql.js-0.4.0.tgz#23be9635520eb0ff43a741e7e830397266e88445"
sshpk@^1.7.0:
- version "1.10.2"
- resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.10.2.tgz#d5a804ce22695515638e798dbe23273de070a5fa"
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
@@ -5641,7 +5746,6 @@ sshpk@^1.7.0:
optionalDependencies:
bcrypt-pbkdf "^1.0.0"
ecc-jsbn "~0.1.1"
- jodid25519 "^1.0.0"
jsbn "~0.1.0"
tweetnacl "~0.14.0"
@@ -5705,6 +5809,12 @@ string_decoder@^0.10.25, string_decoder@~0.10.x:
version "0.10.31"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
+string_decoder@~1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab"
+ dependencies:
+ safe-buffer "~5.1.0"
+
stringstream@~0.0.4:
version "0.0.5"
resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878"
@@ -5735,18 +5845,10 @@ strip-indent@^1.0.1:
dependencies:
get-stdin "^4.0.1"
-strip-json-comments@~1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91"
-
strip-json-comments@~2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
-supports-color@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
-
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -5791,23 +5893,23 @@ tapable@^0.1.8:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.1.10.tgz#29c35707c2b70e50d07482b5d202e8ed446dafd4"
tapable@^0.2.7:
- version "0.2.7"
- resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.7.tgz#e46c0daacbb2b8a98b9b0cea0f4052105817ed5c"
+ version "0.2.8"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-0.2.8.tgz#99372a5c999bf2df160afc0d74bed4f47948cd22"
-tar-pack@~3.3.0:
- version "3.3.0"
- resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.3.0.tgz#30931816418f55afc4d21775afdd6720cee45dae"
- dependencies:
- debug "~2.2.0"
- fstream "~1.0.10"
- fstream-ignore "~1.0.5"
- once "~1.3.3"
- readable-stream "~2.1.4"
- rimraf "~2.5.1"
- tar "~2.2.1"
- uid-number "~0.0.6"
-
-tar@~2.2.1:
+tar-pack@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/tar-pack/-/tar-pack-3.4.0.tgz#23be2d7f671a8339376cbdb0b8fe3fdebf317984"
+ dependencies:
+ debug "^2.2.0"
+ fstream "^1.0.10"
+ fstream-ignore "^1.0.5"
+ once "^1.3.3"
+ readable-stream "^2.1.4"
+ rimraf "^2.5.1"
+ tar "^2.2.1"
+ uid-number "^0.0.6"
+
+tar@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1"
dependencies:
@@ -5849,6 +5951,10 @@ thunky@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/thunky/-/thunky-0.1.0.tgz#bf30146824e2b6e67b0f2d7a4ac8beb26908684e"
+time-stamp@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-2.0.0.tgz#95c6a44530e15ba8d6f4a3ecb8c3a3fac46da357"
+
timeago.js@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/timeago.js/-/timeago.js-2.0.5.tgz#730c74fbdb0b0917a553675a4460e3a7f80db86c"
@@ -5868,8 +5974,8 @@ timers-browserify@^1.4.2:
process "~0.11.0"
timers-browserify@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.2.tgz#ab4883cf597dcd50af211349a00fbca56ac86b86"
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.4.tgz#96ca53f4b794a5e7c0e1bd7cc88a372298fa01e6"
dependencies:
setimmediate "^1.0.4"
@@ -5877,12 +5983,18 @@ tiny-emitter@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-1.1.0.tgz#ab405a21ffed814a76c19739648093d70654fecb"
-tmp@0.0.31, tmp@0.0.x:
+tmp@0.0.31:
version "0.0.31"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7"
dependencies:
os-tmpdir "~1.0.1"
+tmp@0.0.x:
+ version "0.0.33"
+ resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
+ dependencies:
+ os-tmpdir "~1.0.2"
+
to-array@0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890"
@@ -5927,9 +6039,11 @@ tty-browserify@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6"
-tunnel-agent@~0.4.1:
- version "0.4.3"
- resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.4.3.tgz#6373db76909fe570e08d73583365ed828a74eeeb"
+tunnel-agent@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
+ dependencies:
+ safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
@@ -5973,7 +6087,7 @@ uglifyjs-webpack-plugin@^0.4.6:
uglify-js "^2.8.29"
webpack-sources "^1.0.1"
-uid-number@~0.0.6:
+uid-number@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81"
@@ -6079,8 +6193,8 @@ user-home@^2.0.0:
os-homedir "^1.0.0"
useragent@^2.1.12:
- version "2.1.13"
- resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.1.13.tgz#bba43e8aa24d5ceb83c2937473e102e21df74c10"
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/useragent/-/useragent-2.2.1.tgz#cf593ef4f2d175875e8bb658ea92e18a4fd06d8e"
dependencies:
lru-cache "2.2.x"
tmp "0.0.x"
@@ -6104,8 +6218,8 @@ uuid@^2.0.1, uuid@^2.0.2:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a"
uuid@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1"
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"
validate-npm-package-license@^3.0.1:
version "3.0.1"
@@ -6114,7 +6228,7 @@ validate-npm-package-license@^3.0.1:
spdx-correct "~1.0.0"
spdx-expression-parse "~1.0.0"
-vary@~1.1.0, vary@~1.1.1:
+vary@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37"
@@ -6122,11 +6236,13 @@ vendors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.1.tgz#37ad73c8ee417fb3d580e785312307d274847f22"
-verror@1.3.6:
- version "1.3.6"
- resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
+verror@1.10.0:
+ version "1.10.0"
+ resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
dependencies:
- extsprintf "1.0.2"
+ assert-plus "^1.0.0"
+ core-util-is "1.0.2"
+ extsprintf "^1.2.0"
visibilityjs@^1.2.4:
version "1.2.4"
@@ -6203,7 +6319,7 @@ watchpack@^1.4.0:
chokidar "^1.7.0"
graceful-fs "^4.1.2"
-wbuf@^1.1.0, wbuf@^1.4.0:
+wbuf@^1.1.0, wbuf@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe"
dependencies:
@@ -6225,7 +6341,7 @@ webpack-bundle-analyzer@^2.8.2:
opener "^1.4.3"
ws "^2.3.1"
-webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.11.0:
+webpack-dev-middleware@^1.0.11:
version "1.11.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.11.0.tgz#09691d0973a30ad1f82ac73a12e2087f0a4754f9"
dependencies:
@@ -6234,9 +6350,19 @@ webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.11.0:
path-is-absolute "^1.0.0"
range-parser "^1.0.3"
+webpack-dev-middleware@^1.11.0:
+ version "1.12.0"
+ resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.12.0.tgz#d34efefb2edda7e1d3b5dbe07289513219651709"
+ dependencies:
+ memory-fs "~0.4.1"
+ mime "^1.3.4"
+ path-is-absolute "^1.0.0"
+ range-parser "^1.0.3"
+ time-stamp "^2.0.0"
+
webpack-dev-server@^2.6.1:
- version "2.6.1"
- resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.6.1.tgz#0b292a9da96daf80a65988f69f87b4166e5defe7"
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.7.1.tgz#21580f5a08cd065c71144cf6f61c345bca59a8b8"
dependencies:
ansi-html "0.0.7"
bonjour "^3.5.0"
@@ -6248,6 +6374,7 @@ webpack-dev-server@^2.6.1:
html-entities "^1.2.0"
http-proxy-middleware "~0.17.4"
internal-ip "^1.2.0"
+ ip "^1.1.5"
loglevel "^1.4.1"
opn "4.0.2"
portfinder "^1.0.9"
@@ -6261,13 +6388,6 @@ webpack-dev-server@^2.6.1:
webpack-dev-middleware "^1.11.0"
yargs "^6.0.0"
-webpack-sources@^0.1.0:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.4.tgz#ccc2c817e08e5fa393239412690bb481821393cd"
- dependencies:
- source-list-map "~0.1.7"
- source-map "~0.5.3"
-
webpack-sources@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf"
@@ -6279,9 +6399,9 @@ webpack-stats-plugin@^0.1.5:
version "0.1.5"
resolved "https://registry.yarnpkg.com/webpack-stats-plugin/-/webpack-stats-plugin-0.1.5.tgz#29e5f12ebfd53158d31d656a113ac1f7b86179d9"
-webpack@^3.5.4:
- version "3.5.4"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.5.4.tgz#5583eb263ed27b78b5bd17bfdfb0eb1b1cd1bf81"
+webpack@^3.5.5:
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-3.5.5.tgz#3226f09fc8b3e435ff781e7af34f82b68b26996c"
dependencies:
acorn "^5.0.0"
acorn-dynamic-import "^2.0.0"
@@ -6328,17 +6448,23 @@ which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
-which@^1.1.1, which@^1.2.1, which@^1.2.9:
+which@^1.1.1, which@^1.2.1:
version "1.2.12"
resolved "https://registry.yarnpkg.com/which/-/which-1.2.12.tgz#de67b5e450269f194909ef23ece4ebe416fa1192"
dependencies:
isexe "^1.1.1"
+which@^1.2.9:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a"
+ dependencies:
+ isexe "^2.0.0"
+
wide-align@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.0.tgz#40edde802a71fea1f070da3e62dcda2e7add96ad"
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.2.tgz#571e0f1b0604636ebc0dfc21b0339bbe31341710"
dependencies:
- string-width "^1.0.1"
+ string-width "^1.0.2"
window-size@0.1.0:
version "0.1.0"
@@ -6368,8 +6494,8 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
write-file-atomic@^1.1.2:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.1.tgz#7d45ba32316328dd1ec7d90f60ebc0d845bb759a"
+ version "1.3.4"
+ resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f"
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"