summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/merge_request_templates/Documentation.md2
-rw-r--r--CHANGELOG.md5
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--Gemfile4
-rw-r--r--Gemfile.lock8
-rw-r--r--app/assets/javascripts/dispatcher.js110
-rw-r--r--app/assets/javascripts/issuable/auto_width_dropdown_select.js12
-rw-r--r--app/assets/javascripts/issuable_form.js40
-rw-r--r--app/assets/javascripts/job.js13
-rw-r--r--app/assets/javascripts/jobs/components/header.vue1
-rw-r--r--app/assets/javascripts/merge_request.js8
-rw-r--r--app/assets/javascripts/pages/groups/milestones/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/groups/milestones/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/clusters/index/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/clusters/show/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/commit/pipelines/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js22
-rw-r--r--app/assets/javascripts/pages/projects/commits/show/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/compare/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/compare/show/index.js8
-rw-r--r--app/assets/javascripts/pages/projects/milestones/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/milestones/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/tags/new/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js15
-rw-r--r--app/assets/javascripts/pipelines/components/async_button.vue12
-rw-r--r--app/assets/javascripts/pipelines/components/header_component.vue1
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_actions.vue9
-rw-r--r--app/assets/javascripts/pipelines/components/pipelines_table_row.vue2
-rw-r--r--app/assets/javascripts/shared/milestones/form.js9
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js9
-rw-r--r--app/assets/javascripts/vue_shared/components/modal.vue4
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss2
-rw-r--r--app/assets/stylesheets/framework/header.scss2
-rw-r--r--app/assets/stylesheets/framework/modal.scss32
-rw-r--r--app/assets/stylesheets/framework/tw_bootstrap_variables.scss4
-rw-r--r--app/assets/stylesheets/framework/variables.scss5
-rw-r--r--app/assets/stylesheets/pages/pipelines.scss7
-rw-r--r--app/assets/stylesheets/pages/xterm.scss29
-rw-r--r--app/controllers/projects/merge_requests/creations_controller.rb6
-rw-r--r--app/helpers/blob_helper.rb2
-rw-r--r--app/models/ci/build.rb1
-rw-r--r--app/models/ci/pipeline.rb2
-rw-r--r--app/models/commit.rb8
-rw-r--r--app/models/concerns/sha_attribute.rb1
-rw-r--r--app/models/project.rb4
-rw-r--r--app/models/push_event.rb3
-rw-r--r--app/models/repository.rb8
-rw-r--r--app/services/labels/promote_service.rb12
-rw-r--r--app/services/merge_requests/create_from_issue_service.rb1
-rw-r--r--app/services/system_note_service.rb23
-rw-r--r--app/views/dashboard/_activity_head.html.haml4
-rw-r--r--app/views/dashboard/_snippets_head.html.haml4
-rw-r--r--app/views/profiles/gpg_keys/index.html.haml4
-rw-r--r--app/views/projects/blob/_new_dir.html.haml2
-rw-r--r--app/views/projects/blob/_upload.html.haml2
-rw-r--r--app/views/projects/buttons/_dropdown.html.haml26
-rw-r--r--app/views/projects/forks/index.html.haml4
-rw-r--r--app/views/projects/jobs/_sidebar.html.haml2
-rw-r--r--app/views/projects/merge_requests/creations/_diffs.html.haml6
-rw-r--r--app/views/projects/merge_requests/creations/_new_submit.html.haml2
-rw-r--r--app/views/projects/runners/_shared_runners.html.haml3
-rw-r--r--app/views/shared/issuable/form/_branch_chooser.html.haml5
-rw-r--r--app/views/shared/projects/_project.html.haml2
-rw-r--r--app/workers/repository_fork_worker.rb5
-rw-r--r--changelogs/unreleased-ee/4378-fix-cluster-js-not-running-on-update-page.yml5
-rw-r--r--changelogs/unreleased/16301-update-removed-assignee-note-to-include-old-assignee-reference.yml5
-rw-r--r--changelogs/unreleased/19493-fork-does-not-protect-default-branch.yml5
-rw-r--r--changelogs/unreleased/36571-ignore-root-in-repo.yml5
-rw-r--r--changelogs/unreleased/37199-labels-fix.yml5
-rw-r--r--changelogs/unreleased/37898-increase-readability-of-colored-text-in-job-output-log.yml5
-rw-r--r--changelogs/unreleased/38540-ssh-env-file.yml6
-rw-r--r--changelogs/unreleased/40818-last-push-widget-does-not-appear-after-pushing-new-commit.yml5
-rw-r--r--changelogs/unreleased/41118-add-sorting-to-deployments-api.yml5
-rw-r--r--changelogs/unreleased/41476-enable-project-milestons-deletion-via-api.yml5
-rw-r--r--changelogs/unreleased/41666-cannot-search-with-keyword-merge-2.yml5
-rw-r--r--changelogs/unreleased/41666-cannot-search-with-keyword-merge.yml6
-rw-r--r--changelogs/unreleased/41727-target-branch-name.yml5
-rw-r--r--changelogs/unreleased/42031-fix-links-to-uploads-in-wikis.yml5
-rw-r--r--changelogs/unreleased/42046-fork-icon.yml5
-rw-r--r--changelogs/unreleased/42047-pg-10-support.yml5
-rw-r--r--changelogs/unreleased/42055-update-marked-from-0-3-6-to-0-3-12.yml5
-rw-r--r--changelogs/unreleased/fix-gb-improve-manual-action-tooltips.yml5
-rw-r--r--changelogs/unreleased/issue_41460.yml5
-rw-r--r--changelogs/unreleased/jej-lfs-rev-list-handles-non-utf-paths-41627.yml5
-rw-r--r--changelogs/unreleased/merge-request-target-branch-perf.yml5
-rw-r--r--changelogs/unreleased/mr-status-box-update.yml5
-rw-r--r--changelogs/unreleased/sh-remove-shared-runners-and-more.yml5
-rw-r--r--changelogs/unreleased/winh-style-modals.yml5
-rw-r--r--config/initializers/ar5_pg_10_support.rb57
-rw-r--r--db/migrate/20171207185153_add_merge_request_state_index.rb18
-rw-r--r--db/schema.rb1
-rw-r--r--doc/api/deployments.md2
-rw-r--r--doc/api/milestones.md13
-rw-r--r--doc/articles/index.md77
-rw-r--r--doc/ci/README.md24
-rw-r--r--doc/ci/autodeploy/index.md2
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md5
-rw-r--r--doc/development/doc_styleguide.md40
-rw-r--r--doc/development/ee_features.md20
-rw-r--r--doc/development/utilities.md45
-rw-r--r--doc/development/writing_documentation.md20
-rw-r--r--doc/install/README.md6
-rw-r--r--doc/install/openshift_and_gitlab/index.md2
-rw-r--r--doc/install/requirements.md2
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/user/index.md19
-rw-r--r--lib/api/deployments.rb4
-rw-r--r--lib/api/jobs.rb1
-rw-r--r--lib/api/project_milestones.rb9
-rw-r--r--lib/api/v3/builds.rb1
-rw-r--r--lib/backup/manager.rb9
-rw-r--r--lib/banzai/filter/wiki_link_filter/rewriter.rb4
-rw-r--r--lib/gitlab/ci/status/build/action.rb5
-rw-r--r--lib/gitlab/git/commit.rb37
-rw-r--r--lib/gitlab/git/gitlab_projects.rb64
-rw-r--r--lib/gitlab/git/repository.rb31
-rw-r--r--lib/gitlab/git/rev_list.rb2
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb2
-rw-r--r--lib/gitlab/gitaly_client/repository_service.rb15
-rw-r--r--lib/gitlab/kubernetes/helm/install_command.rb6
-rw-r--r--lib/gitlab/kubernetes/helm/pod.rb39
-rw-r--r--lib/gitlab/project_search_results.rb13
-rw-r--r--lib/gitlab/utils/override.rb111
-rw-r--r--lib/tasks/dev.rake5
-rw-r--r--lib/tasks/gitlab/shell.rake10
-rw-r--r--lib/tasks/lint.rake12
-rw-r--r--package.json2
-rwxr-xr-xscripts/static-analysis5
-rw-r--r--spec/controllers/projects/merge_requests/creations_controller_spec.rb42
-rw-r--r--spec/helpers/blob_helper_spec.rb7
-rw-r--r--spec/javascripts/job_spec.js5
-rw-r--r--spec/javascripts/merge_request_spec.js7
-rw-r--r--spec/javascripts/pipelines/async_button_spec.js6
-rw-r--r--spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js45
-rw-r--r--spec/lib/backup/manager_spec.rb6
-rw-r--r--spec/lib/banzai/filter/wiki_link_filter_spec.rb8
-rw-r--r--spec/lib/gitlab/background_migration/deserialize_merge_request_diffs_and_commits_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/status/build/action_spec.rb8
-rw-r--r--spec/lib/gitlab/git/gitlab_projects_spec.rb56
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb8
-rw-r--r--spec/lib/gitlab/git/rev_list_spec.rb11
-rw-r--r--spec/lib/gitlab/kubernetes/helm/install_command_spec.rb19
-rw-r--r--spec/lib/gitlab/kubernetes/helm/pod_spec.rb10
-rw-r--r--spec/lib/gitlab/project_search_results_spec.rb39
-rw-r--r--spec/lib/gitlab/utils/override_spec.rb158
-rw-r--r--spec/models/ci/build_spec.rb7
-rw-r--r--spec/models/ci/pipeline_spec.rb7
-rw-r--r--spec/models/commit_spec.rb24
-rw-r--r--spec/models/push_event_spec.rb26
-rw-r--r--spec/models/repository_spec.rb14
-rw-r--r--spec/requests/api/deployments_spec.rb54
-rw-r--r--spec/requests/api/jobs_spec.rb27
-rw-r--r--spec/requests/api/project_milestones_spec.rb40
-rw-r--r--spec/requests/api/v3/builds_spec.rb27
-rw-r--r--spec/services/labels/promote_service_spec.rb13
-rw-r--r--spec/services/merge_requests/create_from_issue_service_spec.rb19
-rw-r--r--spec/services/system_note_service_spec.rb2
-rw-r--r--spec/spec_helper.rb4
-rw-r--r--spec/support/test_env.rb8
-rw-r--r--spec/workers/repository_fork_worker_spec.rb8
-rw-r--r--vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml30
-rw-r--r--vendor/prometheus/values.yaml205
-rw-r--r--yarn.lock6
163 files changed, 1749 insertions, 647 deletions
diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md
index 9b541aadad1..102eb7e7953 100644
--- a/.gitlab/merge_request_templates/Documentation.md
+++ b/.gitlab/merge_request_templates/Documentation.md
@@ -11,4 +11,6 @@ See the guidelines: http://docs.gitlab.com/ce/development/doc_styleguide.html#ch
- [ ] Make sure the old link is not removed and has its contents replaced with a link to the new location.
- [ ] Make sure internal links pointing to the document in question are not broken.
- [ ] Search and replace any links referring to old docs in GitLab Rails app, specifically under the `app/views/` directory.
+- [ ] Make sure to add [`redirect_from`](https://docs.gitlab.com/ee/development/doc_styleguide.html#redirections-for-pages-with-disqus-comments) to the new document if there are any Disqus comments on the old document thread.
- [ ] If working on CE, submit an MR to EE with the changes as well.
+- [ ] Ping one of the technical writers for review.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c29c289310d..87260744190 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -992,6 +992,11 @@ entry.
- Added type to CHANGELOG entries. (Jacopo Beschi @jacopo-beschi)
- [BUGIFX] Improves subgroup creation permissions. !13418
+## 9.5.10 (2017-11-08)
+
+- [SECURITY] Add SSRF protections for hostnames that will never resolve but will still connect to localhost
+- [SECURITY] Include X-Content-Type-Options (XCTO) header into API responses
+
## 9.5.9 (2017-10-16)
- [SECURITY] Move project repositories between namespaces when renaming users.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 328185caaeb..106d4ac0005 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.67.0
+0.69.0
diff --git a/Gemfile b/Gemfile
index 5c455ab15e3..9e1e0b3c0c6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -115,7 +115,7 @@ gem 'google-api-client', '~> 0.13.6'
gem 'unf', '~> 0.1.4'
# Seed data
-gem 'seed-fu', '2.3.6' # Upgrade to > 2.3.7 once https://github.com/mbleigh/seed-fu/issues/123 is solved
+gem 'seed-fu', '~> 2.3.7'
# Markdown and HTML processing
gem 'html-pipeline', '~> 1.11.0'
@@ -403,7 +403,7 @@ group :ed25519 do
end
# Gitaly GRPC client
-gem 'gitaly-proto', '~> 0.69.0', require: 'gitaly'
+gem 'gitaly-proto', '~> 0.73.0', require: 'gitaly'
gem 'toml-rb', '~> 0.3.15', require: false
diff --git a/Gemfile.lock b/Gemfile.lock
index 8e31ac1f993..10e2585a0e8 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -284,7 +284,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
- gitaly-proto (0.69.0)
+ gitaly-proto (0.73.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (4.7.6)
@@ -831,7 +831,7 @@ GEM
rake (>= 0.9, < 13)
sass (~> 3.5.3)
securecompare (1.0.0)
- seed-fu (2.3.6)
+ seed-fu (2.3.7)
activerecord (>= 3.1)
activesupport (>= 3.1)
select2-rails (3.5.9.3)
@@ -1054,7 +1054,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
- gitaly-proto (~> 0.69.0)
+ gitaly-proto (~> 0.73.0)
github-linguist (~> 4.7.0)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-markup (~> 1.6.2)
@@ -1170,7 +1170,7 @@ DEPENDENCIES
sanitize (~> 2.0)
sass-rails (~> 5.0.6)
scss_lint (~> 0.56.0)
- seed-fu (= 2.3.6)
+ seed-fu (~> 2.3.7)
select2-rails (~> 3.5.9)
selenium-webdriver (~> 3.5)
sentry-raven (~> 2.5.3)
diff --git a/app/assets/javascripts/dispatcher.js b/app/assets/javascripts/dispatcher.js
index 1b03741882e..0c784084b0d 100644
--- a/app/assets/javascripts/dispatcher.js
+++ b/app/assets/javascripts/dispatcher.js
@@ -1,5 +1,4 @@
/* eslint-disable func-names, space-before-function-paren, no-var, prefer-arrow-callback, wrap-iife, no-shadow, consistent-return, one-var, one-var-declaration-per-line, camelcase, default-case, no-new, quotes, no-duplicate-case, no-case-declarations, no-fallthrough, max-len */
-import { s__ } from './locale';
import projectSelect from './project_select';
import Milestone from './milestone';
import IssuableForm from './issuable_form';
@@ -10,30 +9,24 @@ import notificationsDropdown from './notifications_dropdown';
import groupAvatar from './group_avatar';
import GroupLabelSubscription from './group_label_subscription';
import LineHighlighter from './line_highlighter';
-import NewCommitForm from './new_commit_form';
import Project from './project';
import projectAvatar from './project_avatar';
import MergeRequest from './merge_request';
import Compare from './compare';
-import initCompareAutocomplete from './compare_autocomplete';
import ProjectNew from './project_new';
import Labels from './labels';
import LabelManager from './label_manager';
import Sidebar from './right_sidebar';
import IssuableTemplateSelectors from './templates/issuable_template_selectors';
import Flash from './flash';
-import CommitsList from './commits';
import BindInOut from './behaviors/bind_in_out';
import SecretValues from './behaviors/secret_values';
import Group from './group';
import ProjectsList from './projects_list';
-import MiniPipelineGraph from './mini_pipeline_graph_dropdown';
import UserCallout from './user_callout';
import ShortcutsWiki from './shortcuts_wiki';
import BlobViewer from './blob/viewer/index';
-import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import UsersSelect from './users_select';
-import RefSelectDropdown from './ref_select_dropdown';
import GfmAutoComplete from './gfm_auto_complete';
import Star from './star';
import TreeView from './tree';
@@ -44,8 +37,6 @@ import PerformanceBar from './performance_bar';
import initNotes from './init_notes';
import initIssuableSidebar from './init_issuable_sidebar';
import initProjectVisibilitySelector from './project_visibility';
-import GpgBadges from './gpg_badges';
-import initChangesDropdown from './init_changes_dropdown';
import NewGroupChild from './groups/new_group_child';
import { ajaxGet, convertPermissionToBoolean } from './lib/utils/common_utils';
import GlFieldErrors from './gl_field_errors';
@@ -56,12 +47,10 @@ import ShortcutsIssuable from './shortcuts_issuable';
import U2FAuthenticate from './u2f/authenticate';
import Members from './members';
import memberExpirationDate from './member_expiration_date';
-import DueDateSelectors from './due_date_select';
import Diff from './diff';
import ProjectLabelSubscription from './project_label_subscription';
import SearchAutocomplete from './search_autocomplete';
import Activities from './activities';
-import { fetchCommitMergeRequests } from './commit_merge_requests';
(function() {
var Dispatcher;
@@ -187,23 +176,33 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
.catch(fail);
break;
case 'projects:milestones:new':
+ case 'projects:milestones:create':
+ import('./pages/projects/milestones/new')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'projects:milestones:edit':
case 'projects:milestones:update':
- new ZenMode();
- new DueDateSelectors();
- new GLForm($('.milestone-form'), true);
+ import('./pages/projects/milestones/edit')
+ .then(callDefault)
+ .catch(fail);
break;
case 'groups:milestones:new':
+ case 'groups:milestones:create':
+ import('./pages/groups/milestones/new')
+ .then(callDefault)
+ .catch(fail);
+ break;
case 'groups:milestones:edit':
case 'groups:milestones:update':
- new ZenMode();
- new DueDateSelectors();
- new GLForm($('.milestone-form'), false);
+ import('./pages/groups/milestones/edit')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:compare:show':
- new Diff();
- const paddingTop = 16;
- initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop);
+ import('./pages/projects/compare/show')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:branches:new':
import('./pages/projects/branches/new')
@@ -255,12 +254,11 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
new LabelsSelect();
new MilestoneSelect();
new IssuableTemplateSelectors();
- new AutoWidthDropdownSelect($('.js-target-branch-select')).init();
break;
case 'projects:tags:new':
- new ZenMode();
- new GLForm($('.tag-form'), true);
- new RefSelectDropdown($('.js-branch-select'));
+ import('./pages/projects/tags/new')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:snippets:show':
initNotes();
@@ -317,23 +315,15 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
.catch(fail);
break;
case 'projects:commit:show':
- new Diff();
- new ZenMode();
- shortcut_handler = new ShortcutsNavigation();
- new MiniPipelineGraph({
- container: '.js-commit-pipeline-graph',
- }).bindEvents();
- initNotes();
- const stickyBarPaddingTop = 16;
- initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop);
- $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
- fetchCommitMergeRequests();
+ import('./pages/projects/commit/show')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:commit:pipelines':
- new MiniPipelineGraph({
- container: '.js-commit-pipeline-graph',
- }).bindEvents();
- $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
+ import('./pages/projects/commit/pipelines')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:activity':
import('./pages/projects/activity')
@@ -342,9 +332,10 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
shortcut_handler = true;
break;
case 'projects:commits:show':
- CommitsList.init(document.querySelector('.js-project-commits-show').dataset.commitsLimit);
- shortcut_handler = new ShortcutsNavigation();
- GpgBadges.fetch();
+ import('./pages/projects/commits/show')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:show':
shortcut_handler = new ShortcutsNavigation();
@@ -429,13 +420,10 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
groupAvatar();
break;
case 'projects:tree:show':
- shortcut_handler = new ShortcutsNavigation();
- new TreeView();
- new BlobViewer();
- new NewCommitForm($('.js-create-dir-form'));
- $('#tree-slider').waitForImages(function() {
- ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath);
- });
+ import('./pages/projects/tree/show')
+ .then(callDefault)
+ .catch(fail);
+ shortcut_handler = true;
break;
case 'projects:find_file:show':
import('./pages/projects/find_file/show')
@@ -569,20 +557,16 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
.catch(fail);
break;
case 'projects:clusters:show':
- import(/* webpackChunkName: "clusters" */ './clusters/clusters_bundle')
- .then(cluster => new cluster.default()) // eslint-disable-line new-cap
- .catch((err) => {
- Flash(s__('ClusterIntegration|Problem setting up the cluster'));
- throw err;
- });
+ case 'projects:clusters:update':
+ case 'projects:clusters:destroy':
+ import('./pages/projects/clusters/show')
+ .then(callDefault)
+ .catch(fail);
break;
case 'projects:clusters:index':
- import(/* webpackChunkName: "clusters_index" */ './clusters/clusters_index')
- .then(clusterIndex => clusterIndex.default())
- .catch((err) => {
- Flash(s__('ClusterIntegration|Problem setting up the clusters list'));
- throw err;
- });
+ import('./pages/projects/clusters/index')
+ .then(callDefault)
+ .catch(fail);
break;
}
switch (path[0]) {
@@ -662,7 +646,9 @@ import { fetchCommitMergeRequests } from './commit_merge_requests';
projectAvatar();
switch (path[1]) {
case 'compare':
- initCompareAutocomplete();
+ import('./pages/projects/compare')
+ .then(callDefault)
+ .catch(fail);
break;
case 'edit':
shortcut_handler = new ShortcutsNavigation();
diff --git a/app/assets/javascripts/issuable/auto_width_dropdown_select.js b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
index 2203a56315e..14a2bfbe4e0 100644
--- a/app/assets/javascripts/issuable/auto_width_dropdown_select.js
+++ b/app/assets/javascripts/issuable/auto_width_dropdown_select.js
@@ -11,6 +11,14 @@ class AutoWidthDropdownSelect {
const dropdownClass = this.dropdownClass;
this.$selectElement.select2({
dropdownCssClass: dropdownClass,
+ ...AutoWidthDropdownSelect.selectOptions(this.dropdownClass),
+ });
+
+ return this;
+ }
+
+ static selectOptions(dropdownClass) {
+ return {
dropdownCss() {
let resultantWidth = 'auto';
const $dropdown = $(`.${dropdownClass}`);
@@ -29,9 +37,7 @@ class AutoWidthDropdownSelect {
maxWidth: offsetParentWidth,
};
},
- });
-
- return this;
+ };
}
}
diff --git a/app/assets/javascripts/issuable_form.js b/app/assets/javascripts/issuable_form.js
index 57dcaa0e1ac..fdfad0b6a4f 100644
--- a/app/assets/javascripts/issuable_form.js
+++ b/app/assets/javascripts/issuable_form.js
@@ -6,6 +6,7 @@ import Autosave from './autosave';
import UsersSelect from './users_select';
import GfmAutoComplete from './gfm_auto_complete';
import ZenMode from './zen_mode';
+import AutoWidthDropdownSelect from './issuable/auto_width_dropdown_select';
import { parsePikadayDate, pikadayToString } from './lib/utils/datefix';
export default class IssuableForm {
@@ -46,6 +47,12 @@ export default class IssuableForm {
});
calendar.setDate(parsePikadayDate($issuableDueDate.val()));
}
+
+ this.$targetBranchSelect = $('.js-target-branch-select', this.form);
+
+ if (this.$targetBranchSelect.length) {
+ this.initTargetBranchDropdown();
+ }
}
initAutosave() {
@@ -104,4 +111,37 @@ export default class IssuableForm {
addWip() {
this.titleField.val(`WIP: ${(this.titleField.val())}`);
}
+
+ initTargetBranchDropdown() {
+ this.$targetBranchSelect.select2({
+ ...AutoWidthDropdownSelect.selectOptions('js-target-branch-select'),
+ ajax: {
+ url: this.$targetBranchSelect.data('endpoint'),
+ dataType: 'JSON',
+ quietMillis: 250,
+ data(search) {
+ return {
+ search,
+ };
+ },
+ results(data) {
+ return {
+ // `data` keys are translated so we can't just access them with a string based key
+ results: data[Object.keys(data)[0]].map(name => ({
+ id: name,
+ text: name,
+ })),
+ };
+ },
+ },
+ initSelection(el, callback) {
+ const val = el.val();
+
+ callback({
+ id: val,
+ text: val,
+ });
+ },
+ });
+ }
}
diff --git a/app/assets/javascripts/job.js b/app/assets/javascripts/job.js
index 8f32dcc94e2..9b5092c5e3f 100644
--- a/app/assets/javascripts/job.js
+++ b/app/assets/javascripts/job.js
@@ -3,7 +3,6 @@ import { visitUrl } from './lib/utils/url_utility';
import bp from './breakpoints';
import { numberToHumanSize } from './lib/utils/number_utils';
import { setCiStatusFavicon } from './lib/utils/common_utils';
-import { timeFor } from './lib/utils/datetime_utility';
export default class Job {
constructor(options) {
@@ -71,7 +70,6 @@ export default class Job {
.off('resize.build')
.on('resize.build', _.throttle(this.sidebarOnResize.bind(this), 100));
- this.updateArtifactRemoveDate();
this.initAffixTopArea();
this.getBuildTrace();
@@ -261,16 +259,7 @@ export default class Job {
sidebarOnClick() {
if (this.shouldHideSidebarForViewport()) this.toggleSidebar();
}
- // eslint-disable-next-line class-methods-use-this, consistent-return
- updateArtifactRemoveDate() {
- const $date = $('.js-artifacts-remove');
- if ($date.length) {
- const date = $date.text();
- return $date.text(
- timeFor(new Date(date.replace(/([0-9]+)-([0-9]+)-([0-9]+)/g, '$1/$2/$3'))),
- );
- }
- }
+
// eslint-disable-next-line class-methods-use-this
populateJobs(stage) {
$('.build-job').hide();
diff --git a/app/assets/javascripts/jobs/components/header.vue b/app/assets/javascripts/jobs/components/header.vue
index 321a4872ccc..357bc9aab17 100644
--- a/app/assets/javascripts/jobs/components/header.vue
+++ b/app/assets/javascripts/jobs/components/header.vue
@@ -76,6 +76,7 @@
<loading-icon
v-if="isLoading"
size="2"
+ class="prepend-top-default append-bottom-default"
/>
</div>
</template>
diff --git a/app/assets/javascripts/merge_request.js b/app/assets/javascripts/merge_request.js
index cb3cdea8111..e26bf437efc 100644
--- a/app/assets/javascripts/merge_request.js
+++ b/app/assets/javascripts/merge_request.js
@@ -110,7 +110,7 @@ MergeRequest.prototype.initCommitMessageListeners = function() {
});
};
-MergeRequest.prototype.updateStatusText = function(classToRemove, classToAdd, newStatusText) {
+MergeRequest.updateStatusText = function(classToRemove, classToAdd, newStatusText) {
$('.detail-page-header .status-box')
.removeClass(classToRemove)
.addClass(classToAdd)
@@ -118,14 +118,14 @@ MergeRequest.prototype.updateStatusText = function(classToRemove, classToAdd, ne
.text(newStatusText);
};
-MergeRequest.prototype.decreaseCounter = function(by = 1) {
- const $el = $('.nav-links .js-merge-counter');
+MergeRequest.decreaseCounter = function(by = 1) {
+ const $el = $('.js-merge-counter');
const count = Math.max((parseInt($el.text().replace(/[^\d]/, ''), 10) - by), 0);
$el.text(addDelimiter(count));
};
-MergeRequest.prototype.hideCloseButton = function() {
+MergeRequest.hideCloseButton = function() {
const el = document.querySelector('.merge-request .js-issuable-actions');
const closeDropdownItem = el.querySelector('li.close-item');
if (closeDropdownItem) {
diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js
new file mode 100644
index 00000000000..5c99c90e24d
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/milestones/edit/index.js
@@ -0,0 +1,3 @@
+import initForm from '../../../../shared/milestones/form';
+
+export default () => initForm(false);
diff --git a/app/assets/javascripts/pages/groups/milestones/new/index.js b/app/assets/javascripts/pages/groups/milestones/new/index.js
new file mode 100644
index 00000000000..5c99c90e24d
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/milestones/new/index.js
@@ -0,0 +1,3 @@
+import initForm from '../../../../shared/milestones/form';
+
+export default () => initForm(false);
diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js
new file mode 100644
index 00000000000..d531ab81dc7
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/clusters/index/index.js
@@ -0,0 +1,5 @@
+import ClustersIndex from '~/clusters/clusters_index';
+
+export default () => {
+ new ClustersIndex(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/clusters/show/index.js b/app/assets/javascripts/pages/projects/clusters/show/index.js
new file mode 100644
index 00000000000..0458c02a66f
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/clusters/show/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+export default () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/commit/pipelines/index.js b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
new file mode 100644
index 00000000000..523ad567021
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
@@ -0,0 +1,8 @@
+import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
+
+export default () => {
+ new MiniPipelineGraph({
+ container: '.js-commit-pipeline-graph',
+ }).bindEvents();
+ $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
+};
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
new file mode 100644
index 00000000000..5ac38e6f278
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -0,0 +1,22 @@
+/* eslint-disable no-new */
+import Diff from '~/diff';
+import ZenMode from '~/zen_mode';
+import ShortcutsNavigation from '~/shortcuts_navigation';
+import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
+import initNotes from '~/init_notes';
+import initChangesDropdown from '~/init_changes_dropdown';
+import { fetchCommitMergeRequests } from '~/commit_merge_requests';
+
+export default () => {
+ new Diff();
+ new ZenMode();
+ new ShortcutsNavigation();
+ new MiniPipelineGraph({
+ container: '.js-commit-pipeline-graph',
+ }).bindEvents();
+ initNotes();
+ const stickyBarPaddingTop = 16;
+ initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop);
+ $('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
+ fetchCommitMergeRequests();
+};
diff --git a/app/assets/javascripts/pages/projects/commits/show/index.js b/app/assets/javascripts/pages/projects/commits/show/index.js
new file mode 100644
index 00000000000..90b5882a24f
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/commits/show/index.js
@@ -0,0 +1,9 @@
+import CommitsList from '~/commits';
+import GpgBadges from '~/gpg_badges';
+import ShortcutsNavigation from '~/shortcuts_navigation';
+
+export default () => {
+ CommitsList.init(document.querySelector('.js-project-commits-show').dataset.commitsLimit);
+ new ShortcutsNavigation(); // eslint-disable-line no-new
+ GpgBadges.fetch();
+};
diff --git a/app/assets/javascripts/pages/projects/compare/index.js b/app/assets/javascripts/pages/projects/compare/index.js
new file mode 100644
index 00000000000..890062eeee6
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/compare/index.js
@@ -0,0 +1,5 @@
+import initCompareAutocomplete from '~/compare_autocomplete';
+
+export default () => {
+ initCompareAutocomplete();
+};
diff --git a/app/assets/javascripts/pages/projects/compare/show/index.js b/app/assets/javascripts/pages/projects/compare/show/index.js
new file mode 100644
index 00000000000..6b8d4503568
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/compare/show/index.js
@@ -0,0 +1,8 @@
+import Diff from '~/diff';
+import initChangesDropdown from '~/init_changes_dropdown';
+
+export default () => {
+ new Diff(); // eslint-disable-line no-new
+ const paddingTop = 16;
+ initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop);
+};
diff --git a/app/assets/javascripts/pages/projects/milestones/edit/index.js b/app/assets/javascripts/pages/projects/milestones/edit/index.js
new file mode 100644
index 00000000000..10e3979a36e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/milestones/edit/index.js
@@ -0,0 +1,3 @@
+import initForm from '../../../../shared/milestones/form';
+
+export default () => initForm();
diff --git a/app/assets/javascripts/pages/projects/milestones/new/index.js b/app/assets/javascripts/pages/projects/milestones/new/index.js
new file mode 100644
index 00000000000..10e3979a36e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/milestones/new/index.js
@@ -0,0 +1,3 @@
+import initForm from '../../../../shared/milestones/form';
+
+export default () => initForm();
diff --git a/app/assets/javascripts/pages/projects/tags/new/index.js b/app/assets/javascripts/pages/projects/tags/new/index.js
new file mode 100644
index 00000000000..dacc2875c8c
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tags/new/index.js
@@ -0,0 +1,9 @@
+import RefSelectDropdown from '../../../../ref_select_dropdown';
+import ZenMode from '../../../../zen_mode';
+import GLForm from '../../../../gl_form';
+
+export default () => {
+ new ZenMode(); // eslint-disable-line no-new
+ new GLForm($('.tag-form'), true); // eslint-disable-line no-new
+ new RefSelectDropdown($('.js-branch-select')); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
new file mode 100644
index 00000000000..28a0160f47d
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -0,0 +1,15 @@
+import TreeView from '../../../../tree';
+import ShortcutsNavigation from '../../../../shortcuts_navigation';
+import BlobViewer from '../../../../blob/viewer';
+import NewCommitForm from '../../../../new_commit_form';
+import { ajaxGet } from '../../../../lib/utils/common_utils';
+
+export default () => {
+ new ShortcutsNavigation(); // eslint-disable-line no-new
+ new TreeView(); // eslint-disable-line no-new
+ new BlobViewer(); // eslint-disable-line no-new
+ new NewCommitForm($('.js-create-dir-form')); // eslint-disable-line no-new
+ $('#tree-slider').waitForImages(() =>
+ ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath));
+};
+
diff --git a/app/assets/javascripts/pipelines/components/async_button.vue b/app/assets/javascripts/pipelines/components/async_button.vue
index 4ad3f66ee8c..77553ca67cc 100644
--- a/app/assets/javascripts/pipelines/components/async_button.vue
+++ b/app/assets/javascripts/pipelines/components/async_button.vue
@@ -3,6 +3,7 @@
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+ import icon from '../../vue_shared/components/icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
export default {
@@ -11,6 +12,7 @@
},
components: {
loadingIcon,
+ icon,
},
props: {
endpoint: {
@@ -41,9 +43,6 @@
};
},
computed: {
- iconClass() {
- return `fa fa-${this.icon}`;
- },
buttonClass() {
return `btn ${this.cssClass}`;
},
@@ -76,10 +75,9 @@
data-container="body"
data-placement="top"
:disabled="isLoading">
- <i
- :class="iconClass"
- aria-hidden="true">
- </i>
+ <icon
+ :name="icon"
+ />
<loading-icon v-if="isLoading" />
</button>
</template>
diff --git a/app/assets/javascripts/pipelines/components/header_component.vue b/app/assets/javascripts/pipelines/components/header_component.vue
index 942acc8c412..e08c2092680 100644
--- a/app/assets/javascripts/pipelines/components/header_component.vue
+++ b/app/assets/javascripts/pipelines/components/header_component.vue
@@ -92,6 +92,7 @@
<loading-icon
v-if="isLoading"
size="2"
+ class="prepend-top-default append-bottom-default"
/>
</div>
</template>
diff --git a/app/assets/javascripts/pipelines/components/pipelines_actions.vue b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
index efda36c12d6..3297af7bde4 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_actions.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_actions.vue
@@ -1,7 +1,7 @@
<script>
- import playIconSvg from 'icons/_icon_play.svg';
import eventHub from '../event_hub';
import loadingIcon from '../../vue_shared/components/loading_icon.vue';
+ import icon from '../../vue_shared/components/icon.vue';
import tooltip from '../../vue_shared/directives/tooltip';
export default {
@@ -10,6 +10,7 @@
},
components: {
loadingIcon,
+ icon,
},
props: {
actions: {
@@ -19,7 +20,6 @@
},
data() {
return {
- playIconSvg,
isLoading: false,
};
},
@@ -52,7 +52,10 @@
aria-label="Manual job"
:disabled="isLoading"
>
- <span v-html="playIconSvg"></span>
+ <icon
+ name="play"
+ class="icon-play"
+ />
<i
class="fa fa-caret-down"
aria-hidden="true">
diff --git a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
index 670b777199c..d87e24cc8a7 100644
--- a/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
+++ b/app/assets/javascripts/pipelines/components/pipelines_table_row.vue
@@ -312,7 +312,7 @@
:endpoint="pipeline.cancel_path"
css-class="js-pipelines-cancel-button btn-remove"
title="Cancel"
- icon="remove"
+ icon="close"
confirm-action-message="Are you sure you want to cancel this pipeline?"
/>
</div>
diff --git a/app/assets/javascripts/shared/milestones/form.js b/app/assets/javascripts/shared/milestones/form.js
new file mode 100644
index 00000000000..db466f722c4
--- /dev/null
+++ b/app/assets/javascripts/shared/milestones/form.js
@@ -0,0 +1,9 @@
+import ZenMode from '../../zen_mode';
+import DueDateSelectors from '../../due_date_select';
+import GLForm from '../../gl_form';
+
+export default (initGFM = true) => {
+ new ZenMode(); // eslint-disable-line no-new
+ new DueDateSelectors(); // eslint-disable-line no-new
+ new GLForm($('.milestone-form'), initGFM); // eslint-disable-line no-new
+};
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
index e82fb979162..60f42c46ffe 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
+++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js
@@ -1,6 +1,7 @@
import successSvg from 'icons/_icon_status_success.svg';
import warningSvg from 'icons/_icon_status_warning.svg';
import simplePoll from '~/lib/utils/simple_poll';
+import MergeRequest from '../../../merge_request';
import Flash from '../../../flash';
import statusIcon from '../mr_widget_status_icon';
import eventHub from '../../event_hub';
@@ -165,11 +166,9 @@ export default {
// If state is merged we should update the widget and stop the polling
eventHub.$emit('MRWidgetUpdateRequested');
eventHub.$emit('FetchActionsContent');
- if (window.mergeRequest) {
- window.mergeRequest.updateStatusText('status-box-open', 'status-box-merged', 'Merged');
- window.mergeRequest.hideCloseButton();
- window.mergeRequest.decreaseCounter();
- }
+ MergeRequest.updateStatusText('status-box-open', 'status-box-merged', 'Merged');
+ MergeRequest.hideCloseButton();
+ MergeRequest.decreaseCounter();
stopPolling();
// If user checked remove source branch and we didn't remove the branch yet
diff --git a/app/assets/javascripts/vue_shared/components/modal.vue b/app/assets/javascripts/vue_shared/components/modal.vue
index c103c45c7dd..8227428d8ba 100644
--- a/app/assets/javascripts/vue_shared/components/modal.vue
+++ b/app/assets/javascripts/vue_shared/components/modal.vue
@@ -122,7 +122,7 @@
>
<button
type="button"
- class="btn pull-left"
+ class="btn"
:class="btnCancelKindClass"
@click="emitCancel($event)"
data-dismiss="modal"
@@ -132,7 +132,7 @@
<button
v-if="primaryButtonLabel"
type="button"
- class="btn pull-right js-primary-button"
+ class="btn js-primary-button"
:disabled="submitDisabled"
:class="btnKindClass"
@click="emitSubmit($event)"
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 1d2303a3a2b..4c6b32630e1 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -30,7 +30,7 @@
@include set-visible;
min-height: $dropdown-min-height;
max-height: $dropdown-max-height;
- overflow: auto;
+ overflow-y: auto;
@media (max-width: $screen-xs-max) {
width: 100%;
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 3b7256f3000..634593aefd0 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -303,6 +303,8 @@
.projects-dropdown-menu {
padding: 0;
+ overflow-y: initial;
+ max-height: initial;
}
.dropdown-chevron {
diff --git a/app/assets/stylesheets/framework/modal.scss b/app/assets/stylesheets/framework/modal.scss
index 1be66d0ab21..924472f2d7e 100644
--- a/app/assets/stylesheets/framework/modal.scss
+++ b/app/assets/stylesheets/framework/modal.scss
@@ -1,4 +1,5 @@
.modal-header {
+ background-color: $modal-body-bg;
padding: #{3 * $grid-size} #{2 * $grid-size};
.page-title {
@@ -8,6 +9,7 @@
.modal-body {
background-color: $modal-body-bg;
+ min-height: $modal-body-height;
position: relative;
padding: #{3 * $grid-size} #{2 * $grid-size};
@@ -20,6 +22,30 @@
}
}
+.modal-footer {
+ display: flex;
+ flex-direction: row;
+
+ .btn + .btn {
+ margin-left: $grid-size;
+ }
+
+ @media (max-width: $screen-xs-max) {
+ flex-direction: column;
+
+ .btn + .btn {
+ margin-left: 0;
+ margin-top: $grid-size;
+ }
+ }
+
+ @media (min-width: $screen-sm-min) {
+ .btn:first-of-type {
+ margin-left: auto;
+ }
+ }
+}
+
body.modal-open {
overflow: hidden;
}
@@ -32,12 +58,6 @@ body.modal-open {
}
}
-@media (min-width: $screen-md-min) {
- .modal-dialog {
- width: 860px;
- }
-}
-
@media (min-width: $screen-lg-min) {
.modal-full {
width: 98%;
diff --git a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
index a23131e0818..d04e555769b 100644
--- a/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
+++ b/app/assets/stylesheets/framework/tw_bootstrap_variables.scss
@@ -194,6 +194,6 @@ $modal-body-bg: $white-light;
//** Modal footer border color
// $modal-footer-border-color: $modal-header-border-color
-// $modal-lg: 900px
-// $modal-md: 600px
+$modal-lg: 860px;
+$modal-md: 540px;
// $modal-sm: 300px
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index ef1520f1f63..da18ddf78d3 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -733,3 +733,8 @@ $popup-box-shadow-color: rgba(90, 90, 90, 0.05);
Multi file editor
*/
$border-color-settings: #e1e1e1;
+
+/*
+Modals
+*/
+$modal-body-height: 134px;
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index 370b07663fd..766e02b12ea 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -69,13 +69,6 @@
border-color: $border-white-normal;
}
}
-
- .btn {
- .icon-play {
- height: 13px;
- width: 12px;
- }
- }
}
.btn .text-center {
diff --git a/app/assets/stylesheets/pages/xterm.scss b/app/assets/stylesheets/pages/xterm.scss
index c7297a34ad8..7d40c61da26 100644
--- a/app/assets/stylesheets/pages/xterm.scss
+++ b/app/assets/stylesheets/pages/xterm.scss
@@ -3,22 +3,21 @@
// see also: https://gist.github.com/jasonm23/2868981
$black: #000;
- $red: #cd0000;
- $green: #00cd00;
- $yellow: #cdcd00;
- $blue: #00e; // according to wikipedia, this is the xterm standard
- //$blue: #1e90ff; // this is used by all the terminals I tried (when configured with the xterm color profile)
- $magenta: #cd00cd;
- $cyan: #00cdcd;
- $white: #e5e5e5;
+ $red: #ea1010;
+ $green: #009900;
+ $yellow: #999900;
+ $blue: #0073e6;
+ $magenta: #d411d4;
+ $cyan: #009999;
+ $white: #ccc;
$l-black: #373b41;
- $l-red: #c66;
- $l-green: #b5bd68;
- $l-yellow: #f0c674;
- $l-blue: #81a2be;
- $l-magenta: #b294bb;
- $l-cyan: #8abeb7;
- $l-white: $gray-darkest;
+ $l-red: #ff6161;
+ $l-green: #00d600;
+ $l-yellow: #bdbd00;
+ $l-blue: #5797ff;
+ $l-magenta: #d96dd9;
+ $l-cyan: #00bdbd;
+ $l-white: #fff;
/*
* xterm colors
diff --git a/app/controllers/projects/merge_requests/creations_controller.rb b/app/controllers/projects/merge_requests/creations_controller.rb
index 3d2926d5d75..0df80fa700f 100644
--- a/app/controllers/projects/merge_requests/creations_controller.rb
+++ b/app/controllers/projects/merge_requests/creations_controller.rb
@@ -43,11 +43,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
end
def diffs
- @diffs = if @merge_request.can_be_created
- @merge_request.diffs(diff_options)
- else
- []
- end
+ @diffs = @merge_request.diffs(diff_options) if @merge_request.can_be_created
@diff_notes_disabled = true
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 5e3b2e5581c..a6e1de6ffdc 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -1,6 +1,8 @@
module BlobHelper
def highlight(blob_name, blob_content, repository: nil, plain: false)
+ plain ||= blob_content.length > Blob::MAXIMUM_TEXT_HIGHLIGHT_SIZE
highlighted = Gitlab::Highlight.highlight(blob_name, blob_content, plain: plain, repository: repository)
+
raw %(<pre class="code highlight"><code>#{highlighted}</code></pre>)
end
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 6012dbba1b9..df67fb243ad 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -8,6 +8,7 @@ module Ci
MissingDependenciesError = Class.new(StandardError)
+ belongs_to :project, inverse_of: :builds
belongs_to :runner
belongs_to :trigger_request
belongs_to :erased_by, class_name: 'User'
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index d4690da3be6..d7153d7b816 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -7,7 +7,7 @@ module Ci
include Presentable
include Gitlab::OptimisticLocking
- belongs_to :project
+ belongs_to :project, inverse_of: :pipelines
belongs_to :user
belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
belongs_to :pipeline_schedule, class_name: 'Ci::PipelineSchedule'
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 21904c87f01..2d2d89af030 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -372,19 +372,19 @@ class Commit
# uri_type('doc/README.md') # => :blob
# uri_type('doc/logo.png') # => :raw
# uri_type('doc/api') # => :tree
- # uri_type('not/found') # => :nil
+ # uri_type('not/found') # => nil
#
# Returns a symbol
def uri_type(path)
- entry = @raw.rugged_tree_entry(path)
+ entry = @raw.tree_entry(path)
+ return unless entry
+
if entry[:type] == :blob
blob = ::Blob.decorate(Gitlab::Git::Blob.new(name: entry[:name]), @project)
blob.image? || blob.video? ? :raw : :blob
else
entry[:type]
end
- rescue Rugged::TreeError
- nil
end
def raw_diffs(*args)
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index 67ecf470f7e..703a72c355c 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -3,6 +3,7 @@ module ShaAttribute
module ClassMethods
def sha_attribute(name)
+ return if ENV['STATIC_VERIFICATION']
return unless table_exists?
column = columns.find { |c| c.name == name.to_s }
diff --git a/app/models/project.rb b/app/models/project.rb
index 7ab7df4fdcd..d011b614c69 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -199,13 +199,13 @@ class Project < ActiveRecord::Base
has_many :container_repositories, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :commit_statuses
- has_many :pipelines, class_name: 'Ci::Pipeline'
+ has_many :pipelines, class_name: 'Ci::Pipeline', inverse_of: :project
# Ci::Build objects store data on the file system such as artifact files and
# build traces. Currently there's no efficient way of removing this data in
# bulk that doesn't involve loading the rows into memory. As a result we're
# still using `dependent: :destroy` here.
- has_many :builds, class_name: 'Ci::Build', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
+ has_many :builds, class_name: 'Ci::Build', inverse_of: :project, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :build_trace_section_names, class_name: 'Ci::BuildTraceSectionName'
has_many :runner_projects, class_name: 'Ci::RunnerProject'
has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
diff --git a/app/models/push_event.rb b/app/models/push_event.rb
index 83ce9014094..90c085c888e 100644
--- a/app/models/push_event.rb
+++ b/app/models/push_event.rb
@@ -46,10 +46,11 @@ class PushEvent < Event
# Returns PushEvent instances for which no merge requests have been created.
def self.without_existing_merge_requests
- existing_mrs = MergeRequest.except(:order)
+ existing_mrs = MergeRequest.except(:order, :where)
.select(1)
.where('merge_requests.source_project_id = events.project_id')
.where('merge_requests.source_branch = push_event_payloads.ref')
+ .where(state: :opened)
# For reasons unknown the use of #eager_load will result in the
# "push_event_payload" association not being set. Because of this we're
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 2ffd9558ebc..b4bc0f87458 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -932,15 +932,17 @@ class Repository
return [] if empty? || query.blank?
offset = 2
- args = %W(grep -i -I -n --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
+ args = %W(grep -i -I -n -z --before-context #{offset} --after-context #{offset} -E -e #{Regexp.escape(query)} #{ref || root_ref})
run_git(args).first.scrub.split(/^--$/)
end
def search_files_by_name(query, ref)
- return [] if empty? || query.blank?
+ safe_query = Regexp.escape(query.sub(/^\/*/, ""))
+
+ return [] if empty? || safe_query.blank?
- args = %W(ls-tree --full-tree -r #{ref || root_ref} --name-status | #{Regexp.escape(query)})
+ args = %W(ls-tree --full-tree -r #{ref || root_ref} --name-status | #{safe_query})
run_git(args).first.lines.map(&:strip)
end
diff --git a/app/services/labels/promote_service.rb b/app/services/labels/promote_service.rb
index 997d247be46..74a85e5c9f0 100644
--- a/app/services/labels/promote_service.rb
+++ b/app/services/labels/promote_service.rb
@@ -13,6 +13,7 @@ module Labels
update_issuables(new_label, batched_ids)
update_issue_board_lists(new_label, batched_ids)
update_priorities(new_label, batched_ids)
+ subscribe_users(new_label, batched_ids)
# Order is important, project labels need to be last
update_project_labels(batched_ids)
end
@@ -26,6 +27,15 @@ module Labels
private
+ def subscribe_users(new_label, label_ids)
+ # users can be subscribed to multiple labels that will be merged into the group one
+ # we want to keep only one subscription / user
+ ids_to_update = Subscription.where(subscribable_id: label_ids, subscribable_type: 'Label')
+ .group(:user_id)
+ .pluck('MAX(id)')
+ Subscription.where(id: ids_to_update).update_all(subscribable_id: new_label.id)
+ end
+
def label_ids_for_merge(new_label)
LabelsFinder
.new(current_user, title: new_label.title, group_id: project.group.id)
@@ -53,7 +63,7 @@ module Labels
end
def update_project_labels(label_ids)
- Label.where(id: label_ids).delete_all
+ Label.where(id: label_ids).destroy_all
end
def clone_label_to_group_label(label)
diff --git a/app/services/merge_requests/create_from_issue_service.rb b/app/services/merge_requests/create_from_issue_service.rb
index 89dab1dd028..cf687b71d16 100644
--- a/app/services/merge_requests/create_from_issue_service.rb
+++ b/app/services/merge_requests/create_from_issue_service.rb
@@ -54,6 +54,7 @@ module MergeRequests
source_project_id: project.id,
source_branch: branch_name,
target_project_id: project.id,
+ target_branch: ref,
milestone_id: issue.milestone_id
}
end
diff --git a/app/services/system_note_service.rb b/app/services/system_note_service.rb
index 30a5aab13bf..06b23cd7076 100644
--- a/app/services/system_note_service.rb
+++ b/app/services/system_note_service.rb
@@ -68,21 +68,14 @@ module SystemNoteService
#
# Returns the created Note object
def change_issue_assignees(issue, project, author, old_assignees)
- body =
- if issue.assignees.any? && old_assignees.any?
- unassigned_users = old_assignees - issue.assignees
- added_users = issue.assignees.to_a - old_assignees
-
- text_parts = []
- text_parts << "assigned to #{added_users.map(&:to_reference).to_sentence}" if added_users.any?
- text_parts << "unassigned #{unassigned_users.map(&:to_reference).to_sentence}" if unassigned_users.any?
-
- text_parts.join(' and ')
- elsif old_assignees.any?
- "removed assignee"
- elsif issue.assignees.any?
- "assigned to #{issue.assignees.map(&:to_reference).to_sentence}"
- end
+ unassigned_users = old_assignees - issue.assignees
+ added_users = issue.assignees.to_a - old_assignees
+
+ text_parts = []
+ text_parts << "assigned to #{added_users.map(&:to_reference).to_sentence}" if added_users.any?
+ text_parts << "unassigned #{unassigned_users.map(&:to_reference).to_sentence}" if unassigned_users.any?
+
+ body = text_parts.join(' and ')
create_note(NoteSummary.new(issue, project, author, body, action: 'assignee'))
end
diff --git a/app/views/dashboard/_activity_head.html.haml b/app/views/dashboard/_activity_head.html.haml
index ecdf76ef5c5..7a3f3667ac1 100644
--- a/app/views/dashboard/_activity_head.html.haml
+++ b/app/views/dashboard/_activity_head.html.haml
@@ -2,7 +2,7 @@
%ul.nav-links
%li{ class: active_when(params[:filter].nil?) }>
= link_to activity_dashboard_path, class: 'shortcuts-activity', data: {placement: 'right'} do
- Your Projects
+ Your projects
%li{ class: active_when(params[:filter] == 'starred') }>
= link_to activity_dashboard_path(filter: 'starred'), data: {placement: 'right'} do
- Starred Projects
+ Starred projects
diff --git a/app/views/dashboard/_snippets_head.html.haml b/app/views/dashboard/_snippets_head.html.haml
index 7330f4cb523..a9488df07bd 100644
--- a/app/views/dashboard/_snippets_head.html.haml
+++ b/app/views/dashboard/_snippets_head.html.haml
@@ -2,10 +2,10 @@
%ul.nav-links
= nav_link(page: dashboard_snippets_path, html_options: {class: 'home'}) do
= link_to dashboard_snippets_path, title: 'Your snippets', data: {placement: 'right'} do
- Your Snippets
+ Your snippets
= nav_link(page: explore_snippets_path) do
= link_to explore_snippets_path, title: 'Explore snippets', data: {placement: 'right'} do
- Explore Snippets
+ Explore snippets
- if current_user
.nav-controls.hidden-xs
diff --git a/app/views/profiles/gpg_keys/index.html.haml b/app/views/profiles/gpg_keys/index.html.haml
index 86ebec0179c..e44506ec9c9 100644
--- a/app/views/profiles/gpg_keys/index.html.haml
+++ b/app/views/profiles/gpg_keys/index.html.haml
@@ -3,12 +3,12 @@
= render 'profiles/head'
.row.prepend-top-default
- .col-lg-3.profile-settings-sidebar
+ .col-lg-4.profile-settings-sidebar
%h4.prepend-top-0
= page_title
%p
GPG keys allow you to verify signed commits.
- .col-lg-9
+ .col-lg-8
%h5.prepend-top-0
Add a GPG key
%p.profile-settings-content
diff --git a/app/views/projects/blob/_new_dir.html.haml b/app/views/projects/blob/_new_dir.html.haml
index 03ab1bb59e4..5d48a35dc4c 100644
--- a/app/views/projects/blob/_new_dir.html.haml
+++ b/app/views/projects/blob/_new_dir.html.haml
@@ -1,5 +1,5 @@
#modal-create-new-dir.modal
- .modal-dialog
+ .modal-dialog.modal-lg
.modal-content
.modal-header
%a.close{ href: "#", "data-dismiss" => "modal" } ×
diff --git a/app/views/projects/blob/_upload.html.haml b/app/views/projects/blob/_upload.html.haml
index 05b7dfe2872..21b6aa4bad9 100644
--- a/app/views/projects/blob/_upload.html.haml
+++ b/app/views/projects/blob/_upload.html.haml
@@ -1,5 +1,5 @@
#modal-upload-blob.modal
- .modal-dialog
+ .modal-dialog.modal-lg
.modal-content
.modal-header
%a.close{ href: "#", "data-dismiss" => "modal" } ×
diff --git a/app/views/projects/buttons/_dropdown.html.haml b/app/views/projects/buttons/_dropdown.html.haml
index 8e8c911185a..a94d9c14722 100644
--- a/app/views/projects/buttons/_dropdown.html.haml
+++ b/app/views/projects/buttons/_dropdown.html.haml
@@ -10,37 +10,28 @@
- if can_create_issue
%li
- = link_to new_project_issue_path(@project) do
- #{ _('New issue') }
-
+ = link_to _('New issue'), new_project_issue_path(@project)
- if merge_project
%li
- = link_to project_new_merge_request_path(merge_project) do
- #{ _('New merge request') }
-
+ = link_to _('New merge request'), project_new_merge_request_path(merge_project)
- if can_create_snippet
%li
- = link_to new_project_snippet_path(@project) do
- #{ _('New snippet') }
+ = link_to _('New snippet'), new_project_snippet_path(@project)
- if can_create_issue || merge_project || can_create_snippet
%li.divider
- if can?(current_user, :push_code, @project)
%li
- = link_to project_new_blob_path(@project, @project.default_branch || 'master') do
- #{ _('New file') }
+ = link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
- unless @project.empty_repo?
%li
- = link_to new_project_branch_path(@project) do
- #{ _('New branch') }
+ = link_to _('New branch'), new_project_branch_path(@project)
%li
- = link_to new_project_tag_path(@project) do
- #{ _('New tag') }
+ = link_to _('New tag'), new_project_tag_path(@project)
- elsif current_user && current_user.already_forked?(@project)
%li
- = link_to project_new_blob_path(@project, @project.default_branch || 'master') do
- #{ _('New file') }
+ = link_to _('New file'), project_new_blob_path(@project, @project.default_branch || 'master')
- elsif can?(current_user, :fork_project, @project)
%li
- continue_params = { to: project_new_blob_path(@project, @project.default_branch || 'master'),
@@ -48,5 +39,4 @@
notice_now: edit_in_new_fork_notice_now }
- fork_path = project_forks_path(@project, namespace_key: current_user.namespace.id,
continue: continue_params)
- = link_to fork_path, method: :post do
- #{ _('New file') }
+ = link_to _('New file'), fork_path, method: :post
diff --git a/app/views/projects/forks/index.html.haml b/app/views/projects/forks/index.html.haml
index 111cbcda266..21a4702a2a9 100644
--- a/app/views/projects/forks/index.html.haml
+++ b/app/views/projects/forks/index.html.haml
@@ -31,11 +31,11 @@
- if current_user && can?(current_user, :fork_project, @project)
- if current_user.already_forked?(@project) && current_user.manageable_namespaces.size < 2
= link_to namespace_project_path(current_user, current_user.fork_of(@project)), title: 'Go to your fork', class: 'btn btn-new' do
- = custom_icon('icon_fork')
+ = sprite_icon('fork', size: 12)
%span Fork
- else
= link_to new_project_fork_path(@project), title: "Fork project", class: 'btn btn-new' do
- = custom_icon('icon_fork')
+ = sprite_icon('fork', size: 12)
%span Fork
diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml
index a71333497e6..e779473c239 100644
--- a/app/views/projects/jobs/_sidebar.html.haml
+++ b/app/views/projects/jobs/_sidebar.html.haml
@@ -24,7 +24,7 @@
- elsif @build.has_expiring_artifacts?
%p.build-detail-row
The artifacts will be removed in
- %span.js-artifacts-remove= @build.artifacts_expire_at
+ %span= time_ago_in_words @build.artifacts_expire_at
- if @build.artifacts?
.btn-group.btn-group-justified{ role: :group }
diff --git a/app/views/projects/merge_requests/creations/_diffs.html.haml b/app/views/projects/merge_requests/creations/_diffs.html.haml
index 627fc4e9671..5b70e894b39 100644
--- a/app/views/projects/merge_requests/creations/_diffs.html.haml
+++ b/app/views/projects/merge_requests/creations/_diffs.html.haml
@@ -1 +1,5 @@
-= render "projects/diffs/diffs", diffs: @diffs, environment: @environment, show_whitespace_toggle: false
+- if @merge_request.can_be_created
+ = render "projects/diffs/diffs", diffs: @diffs, environment: @environment, show_whitespace_toggle: false
+- else
+ .nothing-here-block
+ This merge request cannot be created.
diff --git a/app/views/projects/merge_requests/creations/_new_submit.html.haml b/app/views/projects/merge_requests/creations/_new_submit.html.haml
index 4b5fa28078a..376ac377562 100644
--- a/app/views/projects/merge_requests/creations/_new_submit.html.haml
+++ b/app/views/projects/merge_requests/creations/_new_submit.html.haml
@@ -15,7 +15,7 @@
= f.hidden_field :source_project_id
= f.hidden_field :source_branch
= f.hidden_field :target_project_id
- = f.hidden_field :target_branch
+ = f.hidden_field :target_branch, id: ''
.mr-compare.merge-request.js-merge-request-new-submit{ 'data-mr-submit-action': "#{j params[:tab].presence || 'new'}" }
- if @commits.empty?
diff --git a/app/views/projects/runners/_shared_runners.html.haml b/app/views/projects/runners/_shared_runners.html.haml
index a4e820628f3..67607e4e9c6 100644
--- a/app/views/projects/runners/_shared_runners.html.haml
+++ b/app/views/projects/runners/_shared_runners.html.haml
@@ -23,6 +23,3 @@
%h4.underlined-title Available shared Runners : #{@shared_runners_count}
%ul.bordered-list.available-shared-runners
= render partial: 'projects/runners/runner', collection: @shared_runners, as: :runner
- - if @shared_runners_count > 10
- .light
- and #{@shared_runners_count - 10} more...
diff --git a/app/views/shared/issuable/form/_branch_chooser.html.haml b/app/views/shared/issuable/form/_branch_chooser.html.haml
index 203d2adc8db..9a589387255 100644
--- a/app/views/shared/issuable/form/_branch_chooser.html.haml
+++ b/app/views/shared/issuable/form/_branch_chooser.html.haml
@@ -15,11 +15,10 @@
= form.label :target_branch, class: 'control-label'
.col-sm-10.target-branch-select-dropdown-container
.issuable-form-select-holder
- = form.select(:target_branch, issuable.target_branches,
- { include_blank: true },
+ = form.hidden_field(:target_branch,
{ class: 'target_branch js-target-branch-select ref-name',
disabled: issuable.new_record?,
- data: { placeholder: "Select branch" }})
+ data: { placeholder: "Select branch", endpoint: refs_project_path(@project, sort: 'updated_desc', find: 'branches') }})
- if issuable.new_record?
&nbsp;
= link_to 'Change branches', mr_change_branches_path(issuable)
diff --git a/app/views/shared/projects/_project.html.haml b/app/views/shared/projects/_project.html.haml
index 63aa4e29ec9..2a75b46d376 100644
--- a/app/views/shared/projects/_project.html.haml
+++ b/app/views/shared/projects/_project.html.haml
@@ -52,7 +52,7 @@
= render_project_pipeline_status(project.pipeline_status)
- if forks
%span.prepend-left-10
- = sprite_icon('fork')
+ = sprite_icon('fork', size: 12)
= number_with_delimiter(project.forks_count)
- if stars
%span.prepend-left-10
diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb
index d1c57b82681..07584fab7c8 100644
--- a/app/workers/repository_fork_worker.rb
+++ b/app/workers/repository_fork_worker.rb
@@ -17,10 +17,7 @@ class RepositoryForkWorker
project.repository_storage_path, project.disk_path)
raise "Unable to fork project #{project_id} for repository #{source_disk_path} -> #{project.disk_path}" unless result
- project.repository.after_import
- raise "Project #{project_id} had an invalid repository after fork" unless project.valid_repo?
-
- project.import_finish
+ project.after_import
end
private
diff --git a/changelogs/unreleased-ee/4378-fix-cluster-js-not-running-on-update-page.yml b/changelogs/unreleased-ee/4378-fix-cluster-js-not-running-on-update-page.yml
new file mode 100644
index 00000000000..bbb6cbd05be
--- /dev/null
+++ b/changelogs/unreleased-ee/4378-fix-cluster-js-not-running-on-update-page.yml
@@ -0,0 +1,5 @@
+---
+title: Fix JavaScript bundle running on Cluster update/destroy pages
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/16301-update-removed-assignee-note-to-include-old-assignee-reference.yml b/changelogs/unreleased/16301-update-removed-assignee-note-to-include-old-assignee-reference.yml
new file mode 100644
index 00000000000..e94b4f8bb26
--- /dev/null
+++ b/changelogs/unreleased/16301-update-removed-assignee-note-to-include-old-assignee-reference.yml
@@ -0,0 +1,5 @@
+---
+title: "Update 'removed assignee' note to include old assignee reference"
+merge_request: 16301
+author: Maurizio De Santis
+type: changed
diff --git a/changelogs/unreleased/19493-fork-does-not-protect-default-branch.yml b/changelogs/unreleased/19493-fork-does-not-protect-default-branch.yml
new file mode 100644
index 00000000000..962f918e9db
--- /dev/null
+++ b/changelogs/unreleased/19493-fork-does-not-protect-default-branch.yml
@@ -0,0 +1,5 @@
+---
+title: Makes forking protect default branch on completion
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/36571-ignore-root-in-repo.yml b/changelogs/unreleased/36571-ignore-root-in-repo.yml
new file mode 100644
index 00000000000..396e82be51b
--- /dev/null
+++ b/changelogs/unreleased/36571-ignore-root-in-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Ignore leading slashes when searching for files within context of repository.
+merge_request:
+author: Andrew McCallum
+type: fixed
diff --git a/changelogs/unreleased/37199-labels-fix.yml b/changelogs/unreleased/37199-labels-fix.yml
new file mode 100644
index 00000000000..bd70babb73d
--- /dev/null
+++ b/changelogs/unreleased/37199-labels-fix.yml
@@ -0,0 +1,5 @@
+---
+title: Keep subscribers when promoting labels to group labels
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/37898-increase-readability-of-colored-text-in-job-output-log.yml b/changelogs/unreleased/37898-increase-readability-of-colored-text-in-job-output-log.yml
new file mode 100644
index 00000000000..813b9ab81fa
--- /dev/null
+++ b/changelogs/unreleased/37898-increase-readability-of-colored-text-in-job-output-log.yml
@@ -0,0 +1,5 @@
+---
+title: increase-readability-of-colored-text-in-job-output-log
+merge_request:
+author:
+type: other
diff --git a/changelogs/unreleased/38540-ssh-env-file.yml b/changelogs/unreleased/38540-ssh-env-file.yml
new file mode 100644
index 00000000000..5ada0ede76d
--- /dev/null
+++ b/changelogs/unreleased/38540-ssh-env-file.yml
@@ -0,0 +1,6 @@
+---
+title: 'Closes #38540 - Remove .ssh/environment file that now breaks the gitlab:check
+ rake task'
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/40818-last-push-widget-does-not-appear-after-pushing-new-commit.yml b/changelogs/unreleased/40818-last-push-widget-does-not-appear-after-pushing-new-commit.yml
new file mode 100644
index 00000000000..c57caf31d10
--- /dev/null
+++ b/changelogs/unreleased/40818-last-push-widget-does-not-appear-after-pushing-new-commit.yml
@@ -0,0 +1,5 @@
+---
+title: Last push widget will show banner for new pushes to previously merged branch
+merge_request:
+author:
+type: changed
diff --git a/changelogs/unreleased/41118-add-sorting-to-deployments-api.yml b/changelogs/unreleased/41118-add-sorting-to-deployments-api.yml
new file mode 100644
index 00000000000..a08f75f9fb9
--- /dev/null
+++ b/changelogs/unreleased/41118-add-sorting-to-deployments-api.yml
@@ -0,0 +1,5 @@
+---
+title: Adds sorting to deployments API
+merge_request: !16396
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/41476-enable-project-milestons-deletion-via-api.yml b/changelogs/unreleased/41476-enable-project-milestons-deletion-via-api.yml
new file mode 100644
index 00000000000..bb5c1fdf082
--- /dev/null
+++ b/changelogs/unreleased/41476-enable-project-milestons-deletion-via-api.yml
@@ -0,0 +1,5 @@
+---
+title: Enables Project Milestone Deletion via the API
+merge_request: 16478
+author: Jacopo Beschi @jacopo-beschi
+type: added
diff --git a/changelogs/unreleased/41666-cannot-search-with-keyword-merge-2.yml b/changelogs/unreleased/41666-cannot-search-with-keyword-merge-2.yml
new file mode 100644
index 00000000000..48893862071
--- /dev/null
+++ b/changelogs/unreleased/41666-cannot-search-with-keyword-merge-2.yml
@@ -0,0 +1,5 @@
+---
+title: Only highlight search results under the highlighting size limit
+merge_request: 16462
+author:
+type: performance
diff --git a/changelogs/unreleased/41666-cannot-search-with-keyword-merge.yml b/changelogs/unreleased/41666-cannot-search-with-keyword-merge.yml
new file mode 100644
index 00000000000..3a6fa425c9c
--- /dev/null
+++ b/changelogs/unreleased/41666-cannot-search-with-keyword-merge.yml
@@ -0,0 +1,6 @@
+---
+title: Fix file search results when they match file contents with a number between
+ two colons
+merge_request: 16462
+author:
+type: fixed
diff --git a/changelogs/unreleased/41727-target-branch-name.yml b/changelogs/unreleased/41727-target-branch-name.yml
new file mode 100644
index 00000000000..aaedf6f1d12
--- /dev/null
+++ b/changelogs/unreleased/41727-target-branch-name.yml
@@ -0,0 +1,5 @@
+---
+title: Set target_branch to the ref branch when creating MR from issue
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/42031-fix-links-to-uploads-in-wikis.yml b/changelogs/unreleased/42031-fix-links-to-uploads-in-wikis.yml
new file mode 100644
index 00000000000..027cb414f23
--- /dev/null
+++ b/changelogs/unreleased/42031-fix-links-to-uploads-in-wikis.yml
@@ -0,0 +1,5 @@
+---
+title: Fix links to uploaded files on wiki pages
+merge_request: 16499
+author:
+type: fixed
diff --git a/changelogs/unreleased/42046-fork-icon.yml b/changelogs/unreleased/42046-fork-icon.yml
new file mode 100644
index 00000000000..def89ff7b08
--- /dev/null
+++ b/changelogs/unreleased/42046-fork-icon.yml
@@ -0,0 +1,5 @@
+---
+title: Fix giant fork icons on forks page
+merge_request: 16474
+author:
+type: fixed
diff --git a/changelogs/unreleased/42047-pg-10-support.yml b/changelogs/unreleased/42047-pg-10-support.yml
new file mode 100644
index 00000000000..f98e59329c3
--- /dev/null
+++ b/changelogs/unreleased/42047-pg-10-support.yml
@@ -0,0 +1,5 @@
+---
+title: Support PostgreSQL 10
+merge_request: 16471
+author:
+type: added
diff --git a/changelogs/unreleased/42055-update-marked-from-0-3-6-to-0-3-12.yml b/changelogs/unreleased/42055-update-marked-from-0-3-6-to-0-3-12.yml
new file mode 100644
index 00000000000..2b043761856
--- /dev/null
+++ b/changelogs/unreleased/42055-update-marked-from-0-3-6-to-0-3-12.yml
@@ -0,0 +1,5 @@
+---
+title: Update marked from 0.3.6 to 0.3.12
+merge_request: 16480
+author: Takuya Noguchi
+type: security
diff --git a/changelogs/unreleased/fix-gb-improve-manual-action-tooltips.yml b/changelogs/unreleased/fix-gb-improve-manual-action-tooltips.yml
new file mode 100644
index 00000000000..31b4734bc79
--- /dev/null
+++ b/changelogs/unreleased/fix-gb-improve-manual-action-tooltips.yml
@@ -0,0 +1,5 @@
+---
+title: Fix tooltip displayed for running manual actions
+merge_request: 16489
+author:
+type: fixed
diff --git a/changelogs/unreleased/issue_41460.yml b/changelogs/unreleased/issue_41460.yml
new file mode 100644
index 00000000000..24d3eae6bf8
--- /dev/null
+++ b/changelogs/unreleased/issue_41460.yml
@@ -0,0 +1,5 @@
+---
+title: Fix error on changes tab when merge request cannot be created
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/jej-lfs-rev-list-handles-non-utf-paths-41627.yml b/changelogs/unreleased/jej-lfs-rev-list-handles-non-utf-paths-41627.yml
new file mode 100644
index 00000000000..24f18c07ac5
--- /dev/null
+++ b/changelogs/unreleased/jej-lfs-rev-list-handles-non-utf-paths-41627.yml
@@ -0,0 +1,5 @@
+---
+title: Prevent RevList failing on non utf8 paths
+merge_request: 16440
+author:
+type: fixed
diff --git a/changelogs/unreleased/merge-request-target-branch-perf.yml b/changelogs/unreleased/merge-request-target-branch-perf.yml
new file mode 100644
index 00000000000..37e326bfde3
--- /dev/null
+++ b/changelogs/unreleased/merge-request-target-branch-perf.yml
@@ -0,0 +1,5 @@
+---
+title: Improve performance of target branch dropdown
+merge_request:
+author:
+type: performance
diff --git a/changelogs/unreleased/mr-status-box-update.yml b/changelogs/unreleased/mr-status-box-update.yml
new file mode 100644
index 00000000000..68265be16a1
--- /dev/null
+++ b/changelogs/unreleased/mr-status-box-update.yml
@@ -0,0 +1,5 @@
+---
+title: Fixed merge request status badge not updating after merging
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/sh-remove-shared-runners-and-more.yml b/changelogs/unreleased/sh-remove-shared-runners-and-more.yml
new file mode 100644
index 00000000000..cc079617883
--- /dev/null
+++ b/changelogs/unreleased/sh-remove-shared-runners-and-more.yml
@@ -0,0 +1,5 @@
+---
+title: Remove erroneous text in shared runners page that suggested more runners available
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/winh-style-modals.yml b/changelogs/unreleased/winh-style-modals.yml
new file mode 100644
index 00000000000..b7d0293960d
--- /dev/null
+++ b/changelogs/unreleased/winh-style-modals.yml
@@ -0,0 +1,5 @@
+---
+title: Adjust modal style to new design
+merge_request: 16310
+author:
+type: other
diff --git a/config/initializers/ar5_pg_10_support.rb b/config/initializers/ar5_pg_10_support.rb
new file mode 100644
index 00000000000..6fae770015c
--- /dev/null
+++ b/config/initializers/ar5_pg_10_support.rb
@@ -0,0 +1,57 @@
+raise "Vendored ActiveRecord 5 code! Delete #{__FILE__}!" if ActiveRecord::VERSION::MAJOR >= 5
+
+require 'active_record/connection_adapters/postgresql_adapter'
+require 'active_record/connection_adapters/postgresql/schema_statements'
+
+#
+# Monkey-patch the refused Rails 4.2 patch at https://github.com/rails/rails/pull/31330
+#
+# Updates sequence logic to support PostgreSQL 10.
+#
+# rubocop:disable all
+module ActiveRecord
+ module ConnectionAdapters
+
+ # We need #postgresql_version to be public as in ActiveRecord 5 for seed_fu
+ # to work. In ActiveRecord 4, it is protected.
+ # https://github.com/mbleigh/seed-fu/issues/123
+ class PostgreSQLAdapter
+ public :postgresql_version
+ end
+
+ module PostgreSQL
+ module SchemaStatements
+ # Resets the sequence of a table's primary key to the maximum value.
+ def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:
+ unless pk and sequence
+ default_pk, default_sequence = pk_and_sequence_for(table)
+
+ pk ||= default_pk
+ sequence ||= default_sequence
+ end
+
+ if @logger && pk && !sequence
+ @logger.warn "#{table} has primary key #{pk} with no default sequence"
+ end
+
+ if pk && sequence
+ quoted_sequence = quote_table_name(sequence)
+ max_pk = select_value("SELECT MAX(#{quote_column_name pk}) FROM #{quote_table_name(table)}")
+ if max_pk.nil?
+ if postgresql_version >= 100000
+ minvalue = select_value("SELECT seqmin FROM pg_sequence WHERE seqrelid = #{quote(quoted_sequence)}::regclass")
+ else
+ minvalue = select_value("SELECT min_value FROM #{quoted_sequence}")
+ end
+ end
+
+ select_value <<-end_sql, 'SCHEMA'
+ SELECT setval(#{quote(quoted_sequence)}, #{max_pk ? max_pk : minvalue}, #{max_pk ? true : false})
+ end_sql
+ end
+ end
+ end
+ end
+ end
+end
+# rubocop:enable all
diff --git a/db/migrate/20171207185153_add_merge_request_state_index.rb b/db/migrate/20171207185153_add_merge_request_state_index.rb
new file mode 100644
index 00000000000..72f846c5c38
--- /dev/null
+++ b/db/migrate/20171207185153_add_merge_request_state_index.rb
@@ -0,0 +1,18 @@
+class AddMergeRequestStateIndex < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index :merge_requests, [:source_project_id, :source_branch],
+ where: "state = 'opened'",
+ name: 'index_merge_requests_on_source_project_and_branch_state_opened'
+ end
+
+ def down
+ remove_concurrent_index_by_name :merge_requests,
+ 'index_merge_requests_on_source_project_and_branch_state_opened'
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index f47accca21a..a32d20b8f28 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -1109,6 +1109,7 @@ ActiveRecord::Schema.define(version: 20180105212544) do
add_index "merge_requests", ["merge_user_id"], name: "index_merge_requests_on_merge_user_id", where: "(merge_user_id IS NOT NULL)", using: :btree
add_index "merge_requests", ["milestone_id"], name: "index_merge_requests_on_milestone_id", using: :btree
add_index "merge_requests", ["source_branch"], name: "index_merge_requests_on_source_branch", using: :btree
+ add_index "merge_requests", ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_and_branch_state_opened", where: "((state)::text = 'opened'::text)", using: :btree
add_index "merge_requests", ["source_project_id", "source_branch"], name: "index_merge_requests_on_source_project_id_and_source_branch", using: :btree
add_index "merge_requests", ["target_branch"], name: "index_merge_requests_on_target_branch", using: :btree
add_index "merge_requests", ["target_project_id", "iid"], name: "index_merge_requests_on_target_project_id_and_iid", unique: true, using: :btree
diff --git a/doc/api/deployments.md b/doc/api/deployments.md
index ab9e63e01d3..fd11894ea8f 100644
--- a/doc/api/deployments.md
+++ b/doc/api/deployments.md
@@ -11,6 +11,8 @@ GET /projects/:id/deployments
| Attribute | Type | Required | Description |
|-----------|---------|----------|---------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
+| `order_by`| string | no | Return deployments ordered by `id` or `iid` or `created_at` or `ref` fields. Default is `id` |
+| `sort` | string | no | Return deployments sorted in `asc` or `desc` order. Default is `asc` |
```bash
curl --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/projects/1/deployments"
diff --git a/doc/api/milestones.md b/doc/api/milestones.md
index 84930f0bdc9..d35e940d7b1 100644
--- a/doc/api/milestones.md
+++ b/doc/api/milestones.md
@@ -93,6 +93,19 @@ Parameters:
- `start_date` (optional) - The start date of the milestone
- `state_event` (optional) - The state event of the milestone (close|activate)
+## Delete project milestone
+
+Only for user with developer access to the project.
+
+```
+DELETE /projects/:id/milestones/:milestone_id
+```
+
+Parameters:
+
+- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
+- `milestone_id` (required) - The ID of the project's milestone
+
## Get all issues assigned to a single milestone
Gets all issues assigned to a single project milestone.
diff --git a/doc/articles/index.md b/doc/articles/index.md
index 01fb6cdf374..c1c3ff67328 100644
--- a/doc/articles/index.md
+++ b/doc/articles/index.md
@@ -1,74 +1,13 @@
-# Technical Articles
+# Technical articles list (deprecated)
-[Technical Articles](../development/writing_documentation.md#technical-articles) are
+[Technical articles](../development/writing_documentation.md#technical-articles) are
topic-related documentation, written with an user-friendly approach and language, aiming
to provide the community with guidance on specific processes to achieve certain objectives.
-They are written by members of the GitLab Team and by
-[Community Writers](https://about.gitlab.com/handbook/product/technical-writing/community-writers/).
+The list of technical articles was [deprecated](https://gitlab.com/gitlab-org/gitlab-ce/issues/41138) in favor of having them linked from their topic-related documentation:
-Part of the articles listed below link to the [GitLab Blog](https://about.gitlab.com/blog/),
-where they were originally published.
-
-## GitLab Pages
-
-Learn how to deploy a static website with [GitLab Pages](../user/project/pages/index.md#getting-started):
-
-| 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 |
-| **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 |
-
-## Install and maintain GitLab
-
-[Admin](../README.md#administrator-documentation), [install](../install/README.md),
-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 |
-| [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
-
-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 |
-
-## 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 |
+- [Git](../topics/git/index.md)
+- [GitLab administrator](../administration/index.md)
+- [GitLab CI/CD](../ci/README.md)
+- [GitLab Pages](../user/project/pages/index.md)
+- [Install GitLab](../install/README.md)
diff --git a/doc/ci/README.md b/doc/ci/README.md
index 3a10365af77..eabeb4510db 100644
--- a/doc/ci/README.md
+++ b/doc/ci/README.md
@@ -28,6 +28,7 @@ you don't need to set up anything to start to use them with GitLab CI/CD.
- Article (2016-08-05): [Continuous Integration, Delivery, and Deployment with GitLab - Intro to CI/CD](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/)
- Article (2015-12-14): [Getting started with GitLab and GitLab CI - Intro to CI](https://about.gitlab.com/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/)
- Article (2017-07-13): [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/)
+- Article (2017-05-22): [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/)
- **Videos:**
- Demo (Streamed live on Jul 17, 2017): [GitLab CI/CD Deep Dive](https://youtu.be/pBe4t1CD8Fc?t=195)
- Demo (March, 2017): [How to get started using CI/CD with GitLab](https://about.gitlab.com/2017/03/13/ci-cd-demo/)
@@ -93,17 +94,6 @@ Leverage the power of Docker to run your CI pipelines.
See the documentation on [GitLab Pages](../user/project/pages/index.md).
-## Special configuration (GitLab admin)
-
-As a GitLab administrator, you can change the default behavior of GitLab CI/CD in
-your whole GitLab instance as well as in each project.
-
-- **Project specific:**
- - [Pipelines settings](../user/project/pipelines/settings.md)
- - [Learn how to enable or disable GitLab CI](enable_or_disable_ci.md)
-- **Affecting the whole GitLab instance:**
- - [Continuous Integration admin settings](../user/admin_area/settings/continuous_integration.md)
-
## Examples
Check the [GitLab CI/CD examples](examples/README.md) for a collection of tutorials and guides on setting up your CI/CD pipeline for various programming languages, frameworks,
@@ -115,6 +105,18 @@ and operating systems.
- Article (2016-05-05): [Getting Started with GitLab and Shippable Continuous Integration](https://about.gitlab.com/2016/05/05/getting-started-gitlab-and-shippable/)
- Article (2016-04-19): [GitLab Partners with DigitalOcean to make Continuous Integration faster, safer, and more affordable](https://about.gitlab.com/2016/04/19/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/)
+## Special configuration (GitLab admin)
+
+As a GitLab administrator, you can change the default behavior of GitLab CI/CD in
+your whole GitLab instance as well as in each project.
+
+- [Continuous Integration admin settings](../administration/index.md#continuous-integration-settings)
+- **Project specific:**
+ - [Pipelines settings](../user/project/pipelines/settings.md)
+ - [Learn how to enable or disable GitLab CI](enable_or_disable_ci.md)
+- **Affecting the whole GitLab instance:**
+ - [Continuous Integration admin settings](../user/admin_area/settings/continuous_integration.md)
+
## Breaking changes
- [CI variables renaming for GitLab 9.0](variables/README.md#9-0-renaming) Read about the
diff --git a/doc/ci/autodeploy/index.md b/doc/ci/autodeploy/index.md
index 474cb28b9e4..7102af5c529 100644
--- a/doc/ci/autodeploy/index.md
+++ b/doc/ci/autodeploy/index.md
@@ -37,6 +37,8 @@ during the deployment.
We made a [simple guide](quick_start_guide.md) to using Auto Deploy with GitLab.com.
+For a demonstration of GitLab Auto Deploy, read the blog post [Auto Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/)
+
## Supported templates
The list of supported auto deploy templates is available in the
diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
index 10fd2616fab..7f9ab1f3a5e 100644
--- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md
@@ -10,6 +10,7 @@ This is what the `.gitlab-ci.yml` file looks like for this project:
```yaml
test:
+ stage: test
script:
- apt-get update -qy
- apt-get install -y nodejs
@@ -18,7 +19,7 @@ test:
- bundle exec rake test
staging:
- type: deploy
+ stage: deploy
script:
- gem install dpl
- dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY
@@ -26,7 +27,7 @@ staging:
- master
production:
- type: deploy
+ stage: deploy
script:
- gem install dpl
- dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
index 9cb1f708a6a..f41d31797af 100644
--- a/doc/development/doc_styleguide.md
+++ b/doc/development/doc_styleguide.md
@@ -34,7 +34,6 @@ The table below shows what kind of documentation goes where.
| `doc/install/`| Probably the most visited directory, since `installation.md` is there. Ideally this should go under `doc/administration/`, but it's best to leave it as-is in order to avoid confusion (still debated though). |
| `doc/update/` | Same with `doc/install/`. Should be under `administration/`, but this is a well known location, better leave as-is, at least for now. |
| `doc/topics/` | Indexes per Topic (`doc/topics/topic-name/index.md`): all resources for that topic (user and admin documentation, articles, and third-party docs) |
-| `doc/articles/` | [Technical Articles](writing_documentation.md#technical-articles): user guides, admin guides, technical overviews, tutorials (`doc/articles/article-title/index.md`). |
---
@@ -67,11 +66,10 @@ The table below shows what kind of documentation goes where.
1. The `doc/topics/` directory holds topic-related technical content. Create
`doc/topics/topic-name/subtopic-name/index.md` when subtopics become necessary.
General user- and admin- related documentation, should be placed accordingly.
-1. For technical articles, place their images under `doc/articles/article-title/img/`.
---
-If you are unsure where a document should live, you can ping `@axil` in your
+If you are unsure where a document should live, you can ping `@axil` or `@marcia` in your
merge request.
## Text
@@ -108,8 +106,8 @@ merge request.
- Avoid adding things that show ephemeral statuses. For example, if a feature is
considered beta or experimental, put this info in a note, not in the heading.
- When introducing a new document, be careful for the headings to be
- grammatically and syntactically correct. It is advised to mention one or all
- of the following GitLab members for a review: `@axil`, `@rspeicher`, `@marcia`.
+ grammatically and syntactically correct. Mention one or all
+ of the following GitLab members for a review: `@axil` or `@marcia`.
This is to ensure that no document with wrong heading is going
live without an audit, thus preventing dead links and redirection issues when
corrected
@@ -203,7 +201,7 @@ You can combine one or more of the following:
- Keep all file names in lower case.
- Consider using PNG images instead of JPEG.
- Compress all images with <https://tinypng.com/> or similar tool.
-- Compress gifs with <https://ezgif.com/optimize> or similar toll.
+- Compress gifs with <https://ezgif.com/optimize> or similar tool.
- Images should be used (only when necessary) to _illustrate_ the description
of a process, not to _replace_ it.
@@ -330,6 +328,10 @@ For example, if you were to move `doc/workflow/lfs/lfs_administration.md` to
git grep -n "lfs/lfs_administration"
```
+NOTE: **Note:**
+If the document being moved has any Disqus comments on it, there are extra steps
+to follow documented just [below](#redirections-for-pages-with-disqus-comments).
+
Things to note:
- Since we also use inline documentation, except for the documentation itself,
@@ -342,6 +344,32 @@ Things to note:
documentation, sometimes it might be useful to search a path deeper.
- The `*.md` extension is not used when a document is linked to GitLab's
built-in help page, that's why we omit it in `git grep`.
+- Use the checklist on the documentation MR description template.
+
+### Redirections for pages with Disqus comments
+
+If the documentation page being relocated already has any Disqus comments,
+we need to preserve the Disqus thread.
+
+Disqus uses an identifier per page, and for docs.gitlab.com, the page identifier
+is configured to be the page URL. Therefore, when we change the document location,
+we need to preserve the old URL as the same Disqus identifier.
+
+To do that, add to the frontmatter the variable `redirect_from`,
+using the old URL as value. For example, let's say I moved the document
+available under `https://docs.gitlab.com/my-old-location/README.html` to a new location,
+`https://docs.gitlab.com/my-new-location/index.html`.
+
+Into the **new document** frontmatter add the following:
+
+```yaml
+---
+redirect_from: 'https://docs.gitlab.com/my-old-location/README.html'
+---
+```
+
+Note: it is necessary to include the file name in the `redirect_from` URL,
+even if it's `index.html` or `README.html`.
## Configuration documentation for source and Omnibus installations
diff --git a/doc/development/ee_features.md b/doc/development/ee_features.md
index 1af839a27e1..f8cee89e650 100644
--- a/doc/development/ee_features.md
+++ b/doc/development/ee_features.md
@@ -87,9 +87,9 @@ still having access the class's implementation with `super`.
There are a few gotchas with it:
-- you should always add a `raise NotImplementedError unless defined?(super)`
- guard clause in the "overrider" method to ensure that if the method gets
- renamed in CE, the EE override won't be silently forgotten.
+- you should always [`extend ::Gitlab::Utils::Override`] and use `override` to
+ guard the "overrider" method to ensure that if the method gets renamed in
+ CE, the EE override won't be silently forgotten.
- when the "overrider" would add a line in the middle of the CE
implementation, you should refactor the CE method and split it in
smaller methods. Or create a "hook" method that is empty in CE,
@@ -134,6 +134,9 @@ There are a few gotchas with it:
guards:
``` ruby
module EE::Base
+ extend ::Gitlab::Utils::Override
+
+ override :do_something
def do_something
# Follow the above pattern to call super and extend it
end
@@ -174,10 +177,11 @@ implementation:
```ruby
module EE
- class ApplicationController
- def after_sign_out_path_for(resource)
- raise NotImplementedError unless defined?(super)
+ module ApplicationController
+ extend ::Gitlab::Utils::Override
+ override :after_sign_out_path_for
+ def after_sign_out_path_for(resource)
if Gitlab::Geo.secondary?
Gitlab::Geo.primary_node.oauth_logout_url(@geo_logout_state)
else
@@ -188,6 +192,8 @@ module EE
end
```
+[`extend ::Gitlab::Utils::Override`]: utilities.md#override
+
#### Use self-descriptive wrapper methods
When it's not possible/logical to modify the implementation of a
@@ -208,8 +214,8 @@ end
In EE, the implementation `ee/app/models/ee/users.rb` would be:
```ruby
+override :full_private_access?
def full_private_access?
- raise NotImplementedError unless defined?(super)
super || auditor?
end
```
diff --git a/doc/development/utilities.md b/doc/development/utilities.md
index 951c3ef85ce..8f9aff1a35f 100644
--- a/doc/development/utilities.md
+++ b/doc/development/utilities.md
@@ -45,6 +45,51 @@ We developed a number of utilities to ease development.
[:hello, "world", :this, :crushes, "an entire", "hash"]
```
+## [`Override`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/override.rb)
+
+* This utility could help us check if a particular method would override
+ another method or not. It has the same idea of Java's `@Override` annotation
+ or Scala's `override` keyword. However we only do this check when
+ `ENV['STATIC_VERIFICATION']` is set to avoid production runtime overhead.
+ This is useful to check:
+
+ * If we have typos in overriding methods.
+ * If we renamed the overridden methods, making original overriding methods
+ overrides nothing.
+
+ Here's a simple example:
+
+ ``` ruby
+ class Base
+ def execute
+ end
+ end
+
+ class Derived < Base
+ extend ::Gitlab::Utils::Override
+
+ override :execute # Override check happens here
+ def execute
+ end
+ end
+ ```
+
+ This also works on modules:
+
+ ``` ruby
+ module Extension
+ extend ::Gitlab::Utils::Override
+
+ override :execute # Modules do not check this immediately
+ def execute
+ end
+ end
+
+ class Derived < Base
+ prepend Extension # Override check happens here, not in the module
+ end
+ ```
+
## [`StrongMemoize`](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/utils/strong_memoize.rb)
* Memoize the value even if it is `nil` or `false`.
diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md
index 133ac0234cf..2a1d744668b 100644
--- a/doc/development/writing_documentation.md
+++ b/doc/development/writing_documentation.md
@@ -25,6 +25,26 @@ them to review it for you.
We use the [monthly release blog post](https://about.gitlab.com/handbook/marketing/blog/release-posts/#monthly-releases) as a changelog checklist to ensure everything
is documented.
+Whenever you submit a merge request for the documentation, use the documentation MR description template.
+
+### Documentation directory structure
+
+The documentation is structured based on the GitLab UI structure itself,
+separated by [`user`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/user),
+[`administrator`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/administration), and [`contributor`](https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/development).
+
+To learn where to place a new document, check the [documentation style guide](doc_styleguide.md#location-and-naming-of-documents).
+
+In order to have a [solid site structure](https://searchengineland.com/seo-benefits-developing-solid-site-structure-277456) for our documentation,
+all docs should be linked. Every new document should be cross-linked to its related documentation, and linked from its topic-related index, when existent.
+
+The directories `/workflow/`, `/gitlab-basics/`, `/university/`, and `/articles/` have
+been deprecated and the majority their docs have been moved to their correct location
+in small iterations. Please don't create new docs in these folders.
+
+To move a document from its location to another directory, read the section
+[changing document location](doc_styleguide.md#changing-document-location) of the doc style guide.
+
### Feature overview and use cases
Every major feature (regardless if present in GitLab Community or Enterprise editions)
diff --git a/doc/install/README.md b/doc/install/README.md
index 43197351db3..87f6969b415 100644
--- a/doc/install/README.md
+++ b/doc/install/README.md
@@ -25,15 +25,19 @@ the hardware requirements.
## Install GitLab on cloud providers
-- [Installing in Kubernetes](kubernetes/index.md) - Install GitLab into a Kubernetes
+- [Installing in Kubernetes](kubernetes/index.md): Install GitLab into a Kubernetes
Cluster using our official Helm Chart Repository.
- [Install GitLab on OpenShift](openshift_and_gitlab/index.md)
- [Install GitLab on DC/OS](https://mesosphere.com/blog/gitlab-dcos/) via [GitLab-Mesosphere integration](https://about.gitlab.com/2016/09/16/announcing-gitlab-and-mesosphere/)
- [Install GitLab on Azure](azure/index.md)
- [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md)
+- [Install GitLab on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/): video tutorial on
+the full process of installing GitLab on Google Container Engine (GKE), pushing an application to GitLab, building the app with GitLab CI/CD, and deploying to production.
- [Install on AWS](https://about.gitlab.com/aws/)
- _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md) -
Quickly test any version of GitLab on DigitalOcean using Docker Machine.
+- [Getting started with GitLab and DigitalOcean](ttps://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/): requirements, installation process, updates.
+- [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/): video demonstration on how to install GitLab on Kubernetes, build a project, create Review Apps, store Docker images in Container Registry, deploy to production on Kubernetes, and monitor with Prometheus.
## Database
diff --git a/doc/install/openshift_and_gitlab/index.md b/doc/install/openshift_and_gitlab/index.md
index 8fba44aea02..448cbe1077d 100644
--- a/doc/install/openshift_and_gitlab/index.md
+++ b/doc/install/openshift_and_gitlab/index.md
@@ -15,6 +15,8 @@ In this tutorial, we will see how to deploy GitLab in OpenShift using GitLab's
official Docker image while getting familiar with the web interface and CLI
tools that will help us achieve our goal.
+For a video demonstration on installing GitLab on Openshift, check the article [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/).
+
---
## Prerequisites
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index baecf9455b0..272148033b5 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -121,7 +121,7 @@ Existing users using GitLab with MySQL/MariaDB are advised to
### PostgreSQL Requirements
-As of GitLab 10.0, PostgreSQL 9.6 or newer (but less than 10) is required, and earlier versions are
+As of GitLab 10.0, PostgreSQL 9.6 or newer is required, and earlier versions are
not supported. We highly recommend users to use PostgreSQL 9.6 as this
is the PostgreSQL version used for development and testing.
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 7e3d418ca6c..6ad314647ee 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -39,6 +39,8 @@ knowledge of the following:
Auto DevOps provides great defaults for all the stages; you can, however,
[customize](#customizing) almost everything to your needs.
+For an overview on the creation of Auto DevOps, read the blog post [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/).
+
## Prerequisites
TIP: **Tip:**
diff --git a/doc/user/index.md b/doc/user/index.md
index f239a15d441..01db8becc43 100644
--- a/doc/user/index.md
+++ b/doc/user/index.md
@@ -23,9 +23,20 @@ all the way through, from within the same platform.
Please check this page for an overview on [GitLab's features](https://about.gitlab.com/features/).
+### Concepts
+
+For an overview on concepts involved when developing code on GitLab,
+read the articles on:
+
+- [Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/).
+- [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario).
+- [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/): an overview on code collaboration with GitLab.
+- [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/).
+- [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/).
+
## Use cases
-GitLab is a git-based platforms that integrates a great number of essential tools for software development and deployment, and project management:
+GitLab is a Git-based platform that integrates a great number of essential tools for software development and deployment, and project management:
- Code hosting in repositories with version control
- Track proposals for new implementations, bug reports, and feedback with a
@@ -58,12 +69,6 @@ and [Multiple Issue Boards](https://docs.gitlab.com/ee/user/project/issue_board.
You can also [integrate](project/integrations/project_services.md) GitLab with numerous third-party applications, such as Mattermost, Microsoft Teams, HipChat, Trello, Slack, Bamboo CI, JIRA, and a lot more.
-### Articles
-
-For a complete workflow use case please check [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/#gitlab-workflow-use-case-scenario).
-
-For more use cases please check our [Technical Articles](../articles/index.md).
-
## Projects
In GitLab, you can create [projects](project/index.md) for numerous reasons, such as, host
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index 1efee9a1324..184fae0eb76 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -15,11 +15,13 @@ module API
end
params do
use :pagination
+ optional :order_by, type: String, values: %w[id iid created_at ref], default: 'id', desc: 'Return deployments ordered by `id` or `iid` or `created_at` or `ref`'
+ optional :sort, type: String, values: %w[asc desc], default: 'asc', desc: 'Sort by asc (ascending) or desc (descending)'
end
get ':id/deployments' do
authorize! :read_deployment, user_project
- present paginate(user_project.deployments), with: Entities::Deployment
+ present paginate(user_project.deployments.order(params[:order_by] => params[:sort])), with: Entities::Deployment
end
desc 'Gets a specific deployment' do
diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb
index a116ab3c9bd..9c205514b3a 100644
--- a/lib/api/jobs.rb
+++ b/lib/api/jobs.rb
@@ -38,6 +38,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
+ builds = builds.preload(:user, :job_artifacts_archive, :runner, pipeline: :project)
present paginate(builds), with: Entities::Job
end
diff --git a/lib/api/project_milestones.rb b/lib/api/project_milestones.rb
index 0cb209a02d0..306dc0e63d7 100644
--- a/lib/api/project_milestones.rb
+++ b/lib/api/project_milestones.rb
@@ -60,6 +60,15 @@ module API
update_milestone_for(user_project)
end
+ desc 'Remove a project milestone'
+ delete ":id/milestones/:milestone_id" do
+ authorize! :admin_milestone, user_project
+
+ user_project.milestones.find(params[:milestone_id]).destroy
+
+ status(204)
+ end
+
desc 'Get all issues for a single project milestone' do
success Entities::IssueBasic
end
diff --git a/lib/api/v3/builds.rb b/lib/api/v3/builds.rb
index fa0bef39602..ac76fece931 100644
--- a/lib/api/v3/builds.rb
+++ b/lib/api/v3/builds.rb
@@ -36,6 +36,7 @@ module API
builds = user_project.builds.order('id DESC')
builds = filter_builds(builds, params[:scope])
+ builds = builds.preload(:user, :job_artifacts_archive, :runner, pipeline: :project)
present paginate(builds), with: ::API::V3::Entities::Build
end
diff --git a/lib/backup/manager.rb b/lib/backup/manager.rb
index 05aa79dc160..f27ce4d2b2b 100644
--- a/lib/backup/manager.rb
+++ b/lib/backup/manager.rb
@@ -108,7 +108,10 @@ module Backup
$progress.puts "Please make sure that file name ends with #{FILE_NAME_SUFFIX}"
exit 1
elsif backup_file_list.many? && ENV["BACKUP"].nil?
- $progress.puts 'Found more than one backup, please specify which one you want to restore:'
+ $progress.puts 'Found more than one backup:'
+ # print list of available backups
+ $progress.puts " " + available_timestamps.join("\n ")
+ $progress.puts 'Please specify which one you want to restore:'
$progress.puts 'rake gitlab:backup:restore BACKUP=timestamp_of_backup'
exit 1
end
@@ -169,6 +172,10 @@ module Backup
@backup_file_list ||= Dir.glob("*#{FILE_NAME_SUFFIX}")
end
+ def available_timestamps
+ @backup_file_list.map {|item| item.gsub("#{FILE_NAME_SUFFIX}", "")}
+ end
+
def connect_to_remote_directory(connection_settings)
# our settings use string keys, but Fog expects symbols
connection = ::Fog::Storage.new(connection_settings.symbolize_keys)
diff --git a/lib/banzai/filter/wiki_link_filter/rewriter.rb b/lib/banzai/filter/wiki_link_filter/rewriter.rb
index e7a1ec8457d..072d24e5a11 100644
--- a/lib/banzai/filter/wiki_link_filter/rewriter.rb
+++ b/lib/banzai/filter/wiki_link_filter/rewriter.rb
@@ -9,6 +9,10 @@ module Banzai
end
def apply_rules
+ # Special case: relative URLs beginning with `/uploads/` refer to
+ # user-uploaded files and will be handled elsewhere.
+ return @uri.to_s if @uri.relative? && @uri.path.starts_with?('/uploads/')
+
apply_file_link_rules!
apply_hierarchical_link_rules!
apply_relative_link_rules!
diff --git a/lib/gitlab/ci/status/build/action.rb b/lib/gitlab/ci/status/build/action.rb
index 45fd0d4aa07..6c9125647ad 100644
--- a/lib/gitlab/ci/status/build/action.rb
+++ b/lib/gitlab/ci/status/build/action.rb
@@ -2,6 +2,9 @@ module Gitlab
module Ci
module Status
module Build
+ ##
+ # Extended status for playable manual actions.
+ #
class Action < Status::Extended
def label
if has_action?
@@ -12,7 +15,7 @@ module Gitlab
end
def self.matches?(build, user)
- build.action?
+ build.playable?
end
end
end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index 016437b2419..46e0c0e82a2 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -436,6 +436,16 @@ module Gitlab
parent_ids.size > 1
end
+ def tree_entry(path)
+ @repository.gitaly_migrate(:commit_tree_entry) do |is_migrated|
+ if is_migrated
+ gitaly_tree_entry(path)
+ else
+ rugged_tree_entry(path)
+ end
+ end
+ end
+
def to_gitaly_commit
return raw_commit if raw_commit.is_a?(Gitaly::GitCommit)
@@ -450,11 +460,6 @@ module Gitlab
)
end
- # Is this the same as Blob.find_entry_by_path ?
- def rugged_tree_entry(path)
- rugged_commit.tree.path(path)
- end
-
private
def init_from_hash(hash)
@@ -501,6 +506,28 @@ module Gitlab
SERIALIZE_KEYS
end
+ def gitaly_tree_entry(path)
+ # We're only interested in metadata, so limit actual data to 1 byte
+ # since Gitaly doesn't support "send no data" option.
+ entry = @repository.gitaly_commit_client.tree_entry(id, path, 1)
+ return unless entry
+
+ # To be compatible with the rugged format
+ entry = entry.to_h
+ entry.delete(:data)
+ entry[:name] = File.basename(path)
+ entry[:type] = entry[:type].downcase
+
+ entry
+ end
+
+ # Is this the same as Blob.find_entry_by_path ?
+ def rugged_tree_entry(path)
+ rugged_commit.tree.path(path)
+ rescue Rugged::TreeError
+ nil
+ end
+
def gitaly_commit_author_from_rugged(author_or_committer)
Gitaly::CommitAuthor.new(
name: author_or_committer[:name].b,
diff --git a/lib/gitlab/git/gitlab_projects.rb b/lib/gitlab/git/gitlab_projects.rb
index 976fa1ddfe6..e5a747cb987 100644
--- a/lib/gitlab/git/gitlab_projects.rb
+++ b/lib/gitlab/git/gitlab_projects.rb
@@ -44,29 +44,13 @@ module Gitlab
# Import project via git clone --bare
# URL must be publicly cloneable
def import_project(source, timeout)
- # Skip import if repo already exists
- return false if File.exist?(repository_absolute_path)
-
- masked_source = mask_password_in_url(source)
-
- logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
- cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
-
- success = run_with_timeout(cmd, timeout, nil)
-
- unless success
- logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
- FileUtils.rm_rf(repository_absolute_path)
- return false
+ Gitlab::GitalyClient.migrate(:import_repository) do |is_enabled|
+ if is_enabled
+ gitaly_import_repository(source)
+ else
+ git_import_repository(source, timeout)
+ end
end
-
- Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
-
- # The project was imported successfully.
- # Remove the origin URL since it may contain password.
- remove_origin_in_repo
-
- true
end
def fork_repository(new_shard_path, new_repository_relative_path)
@@ -231,6 +215,42 @@ module Gitlab
raise(ShardNameNotFoundError, "no shard found for path '#{shard_path}'")
end
+ def git_import_repository(source, timeout)
+ # Skip import if repo already exists
+ return false if File.exist?(repository_absolute_path)
+
+ masked_source = mask_password_in_url(source)
+
+ logger.info "Importing project from <#{masked_source}> to <#{repository_absolute_path}>."
+ cmd = %W(git clone --bare -- #{source} #{repository_absolute_path})
+
+ success = run_with_timeout(cmd, timeout, nil)
+
+ unless success
+ logger.error("Importing project from <#{masked_source}> to <#{repository_absolute_path}> failed.")
+ FileUtils.rm_rf(repository_absolute_path)
+ return false
+ end
+
+ Gitlab::Git::Repository.create_hooks(repository_absolute_path, global_hooks_path)
+
+ # The project was imported successfully.
+ # Remove the origin URL since it may contain password.
+ remove_origin_in_repo
+
+ true
+ end
+
+ def gitaly_import_repository(source)
+ raw_repository = Gitlab::Git::Repository.new(shard_name, repository_relative_path, nil)
+
+ Gitlab::GitalyClient::RepositoryService.new(raw_repository).import_repository(source)
+ true
+ rescue GRPC::BadStatus => e
+ @output << e.message
+ false
+ end
+
def git_fork_repository(new_shard_path, new_repository_relative_path)
from_path = repository_absolute_path
to_path = File.join(new_shard_path, new_repository_relative_path)
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index d0467bca992..c5d5c3a72c0 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -621,37 +621,6 @@ module Gitlab
end
end
- # Returns branch names collection that contains the special commit(SHA1
- # or name)
- #
- # Ex.
- # repo.branch_names_contains('master')
- #
- def branch_names_contains(commit)
- branches_contains(commit).map { |c| c.name }
- end
-
- # Returns branch collection that contains the special commit(SHA1 or name)
- #
- # Ex.
- # repo.branch_names_contains('master')
- #
- def branches_contains(commit)
- commit_obj = rugged.rev_parse(commit)
- parent = commit_obj.parents.first unless commit_obj.parents.empty?
-
- walker = Rugged::Walker.new(rugged)
-
- rugged.branches.select do |branch|
- walker.push(branch.target_id)
- walker.hide(parent) if parent
- result = walker.any? { |c| c.oid == commit_obj.oid }
- walker.reset
-
- result
- end
- end
-
# Get refs hash which key is SHA1
# and value is a Rugged::Reference
def refs_hash
diff --git a/lib/gitlab/git/rev_list.rb b/lib/gitlab/git/rev_list.rb
index 4974205b8fd..f8b2e7e0e21 100644
--- a/lib/gitlab/git/rev_list.rb
+++ b/lib/gitlab/git/rev_list.rb
@@ -95,7 +95,7 @@ module Gitlab
object_output.map do |output_line|
sha, path = output_line.split(' ', 2)
- next if require_path && path.blank?
+ next if require_path && path.to_s.empty?
sha
end.reject(&:nil?)
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index fed05bb6c64..71b212023d6 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -177,7 +177,7 @@ module Gitlab
response = GitalyClient.call(@repository.storage, :commit_service, :list_commits_by_oid, request, timeout: GitalyClient.medium_timeout)
consume_commits_response(response)
- rescue GRPC::Unknown # If no repository is found, happens mainly during testing
+ rescue GRPC::NotFound # If no repository is found, happens mainly during testing
[]
end
diff --git a/lib/gitlab/gitaly_client/repository_service.rb b/lib/gitlab/gitaly_client/repository_service.rb
index 72ee92e78dc..12016aee2a6 100644
--- a/lib/gitlab/gitaly_client/repository_service.rb
+++ b/lib/gitlab/gitaly_client/repository_service.rb
@@ -100,6 +100,21 @@ module Gitlab
)
end
+ def import_repository(source)
+ request = Gitaly::CreateRepositoryFromURLRequest.new(
+ repository: @gitaly_repo,
+ url: source
+ )
+
+ GitalyClient.call(
+ @storage,
+ :repository_service,
+ :create_repository_from_url,
+ request,
+ timeout: GitalyClient.default_timeout
+ )
+ end
+
def rebase_in_progress?(rebase_id)
request = Gitaly::IsRebaseInProgressRequest.new(
repository: @gitaly_repo,
diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb
index 8d8c441a4b1..bf6981035f4 100644
--- a/lib/gitlab/kubernetes/helm/install_command.rb
+++ b/lib/gitlab/kubernetes/helm/install_command.rb
@@ -36,7 +36,11 @@ module Gitlab
def complete_command(namespace_name)
return unless chart
- "helm install #{chart} --name #{name} --namespace #{namespace_name} >/dev/null"
+ if chart_values_file
+ "helm install #{chart} --name #{name} --namespace #{namespace_name} -f /data/helm/#{name}/config/values.yaml >/dev/null"
+ else
+ "helm install #{chart} --name #{name} --namespace #{namespace_name} >/dev/null"
+ end
end
def install_dps_command
diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb
index 97ad3c97e95..a3216759cae 100644
--- a/lib/gitlab/kubernetes/helm/pod.rb
+++ b/lib/gitlab/kubernetes/helm/pod.rb
@@ -10,9 +10,10 @@ module Gitlab
def generate
spec = { containers: [container_specification], restartPolicy: 'Never' }
+
if command.chart_values_file
- generate_config_map
- spec['volumes'] = volumes_specification
+ create_config_map
+ spec[:volumes] = volumes_specification
end
::Kubeclient::Resource.new(metadata: metadata, spec: spec)
@@ -35,19 +36,39 @@ module Gitlab
end
def labels
- { 'gitlab.org/action': 'install', 'gitlab.org/application': command.name }
+ {
+ 'gitlab.org/action': 'install',
+ 'gitlab.org/application': command.name
+ }
end
def metadata
- { name: command.pod_name, namespace: namespace_name, labels: labels }
+ {
+ name: command.pod_name,
+ namespace: namespace_name,
+ labels: labels
+ }
end
def volume_mounts_specification
- [{ name: 'config-volume', mountPath: '/etc/config' }]
+ [
+ {
+ name: 'configuration-volume',
+ mountPath: "/data/helm/#{command.name}/config"
+ }
+ ]
end
def volumes_specification
- [{ name: 'config-volume', configMap: { name: 'values-config' } }]
+ [
+ {
+ name: 'configuration-volume',
+ configMap: {
+ name: 'values-content-configuration',
+ items: [{ key: 'values', path: 'values.yaml' }]
+ }
+ }
+ ]
end
def generate_pod_env(command)
@@ -58,10 +79,10 @@ module Gitlab
}.map { |key, value| { name: key, value: value } }
end
- def generate_config_map
+ def create_config_map
resource = ::Kubeclient::Resource.new
- resource.metadata = { name: 'values-config', namespace: namespace_name }
- resource.data = YAML.load_file(command.chart_values_file)
+ resource.metadata = { name: 'values-content-configuration', namespace: namespace_name, labels: { name: 'values-content-configuration' } }
+ resource.data = { values: File.read(command.chart_values_file) }
kubeclient.create_config_map(resource)
end
end
diff --git a/lib/gitlab/project_search_results.rb b/lib/gitlab/project_search_results.rb
index e2662fc362b..7771b15069b 100644
--- a/lib/gitlab/project_search_results.rb
+++ b/lib/gitlab/project_search_results.rb
@@ -44,25 +44,20 @@ module Gitlab
ref = nil
filename = nil
basename = nil
+ data = ""
startline = 0
- result.each_line.each_with_index do |line, index|
- matches = line.match(/^(?<ref>[^:]*):(?<filename>.*):(?<startline>\d+):/)
- if matches
+ result.strip.each_line.each_with_index do |line, index|
+ prefix ||= line.match(/^(?<ref>[^:]*):(?<filename>.*)\x00(?<startline>\d+)\x00/)&.tap do |matches|
ref = matches[:ref]
filename = matches[:filename]
startline = matches[:startline]
startline = startline.to_i - index
extname = Regexp.escape(File.extname(filename))
basename = filename.sub(/#{extname}$/, '')
- break
end
- end
-
- data = ""
- result.each_line do |line|
- data << line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
+ data << line.sub(prefix.to_s, '')
end
FoundBlob.new(
diff --git a/lib/gitlab/utils/override.rb b/lib/gitlab/utils/override.rb
new file mode 100644
index 00000000000..8bf6bcb1fe2
--- /dev/null
+++ b/lib/gitlab/utils/override.rb
@@ -0,0 +1,111 @@
+module Gitlab
+ module Utils
+ module Override
+ class Extension
+ def self.verify_class!(klass, method_name)
+ instance_method_defined?(klass, method_name) ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+
+ def self.instance_method_defined?(klass, name, include_super: true)
+ klass.instance_methods(include_super).include?(name) ||
+ klass.private_instance_methods(include_super).include?(name)
+ end
+
+ attr_reader :subject
+
+ def initialize(subject)
+ @subject = subject
+ end
+
+ def add_method_name(method_name)
+ method_names << method_name
+ end
+
+ def add_class(klass)
+ classes << klass
+ end
+
+ def verify!
+ classes.each do |klass|
+ index = klass.ancestors.index(subject)
+ parents = klass.ancestors.drop(index + 1)
+
+ method_names.each do |method_name|
+ parents.any? do |parent|
+ self.class.instance_method_defined?(
+ parent, method_name, include_super: false)
+ end ||
+ raise(
+ NotImplementedError.new(
+ "#{klass}\##{method_name} doesn't exist!"))
+ end
+ end
+ end
+
+ private
+
+ def method_names
+ @method_names ||= []
+ end
+
+ def classes
+ @classes ||= []
+ end
+ end
+
+ # Instead of writing patterns like this:
+ #
+ # def f
+ # raise NotImplementedError unless defined?(super)
+ #
+ # true
+ # end
+ #
+ # We could write it like:
+ #
+ # extend ::Gitlab::Utils::Override
+ #
+ # override :f
+ # def f
+ # true
+ # end
+ #
+ # This would make sure we're overriding something. See:
+ # https://gitlab.com/gitlab-org/gitlab-ee/issues/1819
+ def override(method_name)
+ return unless ENV['STATIC_VERIFICATION']
+
+ if is_a?(Class)
+ Extension.verify_class!(self, method_name)
+ else # We delay the check for modules
+ Override.extensions[self] ||= Extension.new(self)
+ Override.extensions[self].add_method_name(method_name)
+ end
+ end
+
+ def included(base = nil)
+ return super if base.nil? # Rails concern, ignoring it
+
+ super
+
+ if base.is_a?(Class) # We could check for Class in `override`
+ # This could be `nil` if `override` was never called
+ Override.extensions[self]&.add_class(base)
+ end
+ end
+
+ alias_method :prepended, :included
+
+ def self.extensions
+ @extensions ||= {}
+ end
+
+ def self.verify!
+ extensions.values.each(&:verify!)
+ end
+ end
+ end
+end
diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake
index e65609d7001..4beb94eeb8e 100644
--- a/lib/tasks/dev.rake
+++ b/lib/tasks/dev.rake
@@ -7,4 +7,9 @@ namespace :dev do
Rake::Task["gitlab:setup"].invoke
Rake::Task["gitlab:shell:setup"].invoke
end
+
+ desc "GitLab | Eager load application"
+ task load: :environment do
+ Rails.application.eager_load!
+ end
end
diff --git a/lib/tasks/gitlab/shell.rake b/lib/tasks/gitlab/shell.rake
index 0e6aed32c52..12ae4199b69 100644
--- a/lib/tasks/gitlab/shell.rake
+++ b/lib/tasks/gitlab/shell.rake
@@ -54,16 +54,6 @@ namespace :gitlab do
# (Re)create hooks
Rake::Task['gitlab:shell:create_hooks'].invoke
- # Required for debian packaging with PKGR: Setup .ssh/environment with
- # the current PATH, so that the correct ruby version gets loaded
- # Requires to set "PermitUserEnvironment yes" in sshd config (should not
- # be an issue since it is more than likely that there are no "normal"
- # user accounts on a gitlab server). The alternative is for the admin to
- # install a ruby (1.9.3+) in the global path.
- File.open(File.join(user_home, ".ssh", "environment"), "w+") do |f|
- f.puts "PATH=#{ENV['PATH']}"
- end
-
Gitlab::Shell.ensure_secret_token!
end
diff --git a/lib/tasks/lint.rake b/lib/tasks/lint.rake
index 7b63e93db0e..3ab406eff2c 100644
--- a/lib/tasks/lint.rake
+++ b/lib/tasks/lint.rake
@@ -1,5 +1,17 @@
unless Rails.env.production?
namespace :lint do
+ task :static_verification_env do
+ ENV['STATIC_VERIFICATION'] = 'true'
+ end
+
+ desc "GitLab | lint | Static verification"
+ task static_verification: %w[
+ lint:static_verification_env
+ dev:load
+ ] do
+ Gitlab::Utils::Override.verify!
+ end
+
desc "GitLab | lint | Lint JavaScript files using ESLint"
task :javascript do
Rake::Task['eslint'].invoke
diff --git a/package.json b/package.json
index 4759ae76817..35c145aaebe 100644
--- a/package.json
+++ b/package.json
@@ -54,7 +54,7 @@
"js-cookie": "^2.1.3",
"jszip": "^3.1.3",
"jszip-utils": "^0.0.2",
- "marked": "^0.3.6",
+ "marked": "^0.3.12",
"monaco-editor": "0.10.0",
"mousetrap": "^1.4.6",
"name-all-modules-plugin": "^1.0.1",
diff --git a/scripts/static-analysis b/scripts/static-analysis
index 2a2bc67800d..9690b42c788 100755
--- a/scripts/static-analysis
+++ b/scripts/static-analysis
@@ -10,9 +10,10 @@ tasks = [
%w[bundle exec license_finder],
%w[yarn run eslint],
%w[bundle exec rubocop --parallel],
- %w[scripts/lint-conflicts.sh],
%w[bundle exec rake gettext:lint],
- %w[scripts/lint-changelog-yaml]
+ %w[bundle exec rake lint:static_verification],
+ %w[scripts/lint-changelog-yaml],
+ %w[scripts/lint-conflicts.sh]
]
failed_tasks = tasks.reduce({}) do |failures, task|
diff --git a/spec/controllers/projects/merge_requests/creations_controller_spec.rb b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
index 7e2366847f4..92db7284e0e 100644
--- a/spec/controllers/projects/merge_requests/creations_controller_spec.rb
+++ b/spec/controllers/projects/merge_requests/creations_controller_spec.rb
@@ -4,6 +4,16 @@ describe Projects::MergeRequests::CreationsController do
let(:project) { create(:project, :repository) }
let(:user) { project.owner }
let(:fork_project) { create(:forked_project_with_submodules) }
+ let(:get_diff_params) do
+ {
+ namespace_id: fork_project.namespace.to_param,
+ project_id: fork_project,
+ merge_request: {
+ source_branch: 'remove-submodule',
+ target_branch: 'master'
+ }
+ }
+ end
before do
fork_project.add_master(user)
@@ -13,18 +23,23 @@ describe Projects::MergeRequests::CreationsController do
describe 'GET new' do
context 'merge request that removes a submodule' do
- render_views
-
it 'renders new merge request widget template' do
- get :new,
- namespace_id: fork_project.namespace.to_param,
- project_id: fork_project,
- merge_request: {
- source_branch: 'remove-submodule',
- target_branch: 'master'
- }
+ get :new, get_diff_params
+
+ expect(response).to be_success
+ end
+ end
+ end
+
+ describe 'GET diffs' do
+ context 'when merge request cannot be created' do
+ it 'does not assign diffs var' do
+ allow_any_instance_of(MergeRequest).to receive(:can_be_created).and_return(false)
+
+ get :diffs, get_diff_params.merge(format: 'json')
expect(response).to be_success
+ expect(assigns[:diffs]).to be_nil
end
end
end
@@ -37,14 +52,7 @@ describe Projects::MergeRequests::CreationsController do
end
it 'renders JSON including serialized pipelines' do
- get :pipelines,
- namespace_id: fork_project.namespace.to_param,
- project_id: fork_project,
- merge_request: {
- source_branch: 'remove-submodule',
- target_branch: 'master'
- },
- format: :json
+ get :pipelines, get_diff_params.merge(format: 'json')
expect(response).to be_ok
expect(json_response).to have_key 'pipelines'
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 04620f6d88c..a030796c54e 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -22,6 +22,13 @@ describe BlobHelper do
expect(result).to eq(%[<pre class="code highlight"><code><span id="LC1" class="line" lang="">:type "assem"))</span></code></pre>])
end
+ it 'returns plaintext for long blobs' do
+ stub_const('Blob::MAXIMUM_TEXT_HIGHLIGHT_SIZE', 1)
+ result = helper.highlight(blob_name, blob_content)
+
+ expect(result).to eq(%[<pre class="code highlight"><code><span id="LC1" class="line" lang="">(make-pathname :defaults name</span>\n<span id="LC2" class="line" lang="">:type "assem"))</span></code></pre>])
+ end
+
it 'highlights single block' do
expected = %Q[<pre class="code highlight"><code><span id="LC1" class="line" lang="common_lisp"><span class="p">(</span><span class="nb">make-pathname</span> <span class="ss">:defaults</span> <span class="nv">name</span></span>
<span id="LC2" class="line" lang="common_lisp"><span class="ss">:type</span> <span class="s">"assem"</span><span class="p">))</span></span></code></pre>]
diff --git a/spec/javascripts/job_spec.js b/spec/javascripts/job_spec.js
index b740c9ed893..feb341d22e6 100644
--- a/spec/javascripts/job_spec.js
+++ b/spec/javascripts/job_spec.js
@@ -52,11 +52,6 @@ describe('Job', () => {
expect($('.build-job[data-stage="test"]').is(':visible')).toBe(false);
expect($('.build-job[data-stage="deploy"]').is(':visible')).toBe(false);
});
-
- it('displays the remove date correctly', () => {
- const removeDateElement = document.querySelector('.js-artifacts-remove');
- expect(removeDateElement.innerText.trim()).toBe('1 year remaining');
- });
});
describe('running build', () => {
diff --git a/spec/javascripts/merge_request_spec.js b/spec/javascripts/merge_request_spec.js
index 9d6ea3781bc..bae3219b043 100644
--- a/spec/javascripts/merge_request_spec.js
+++ b/spec/javascripts/merge_request_spec.js
@@ -70,8 +70,8 @@ import IssuablesHelper from '~/helpers/issuables_helper';
beforeEach(() => {
loadFixtures('merge_requests/merge_request_with_task_list.html.raw');
this.el = document.querySelector('.js-issuable-actions');
- const merge = new MergeRequest();
- merge.hideCloseButton();
+ new MergeRequest(); // eslint-disable-line no-new
+ MergeRequest.hideCloseButton();
});
it('hides the dropdown close item and selects the next item', () => {
@@ -90,8 +90,7 @@ import IssuablesHelper from '~/helpers/issuables_helper';
beforeEach(() => {
loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
this.el = document.querySelector('.js-issuable-actions');
- const merge = new MergeRequest();
- merge.hideCloseButton();
+ MergeRequest.hideCloseButton();
});
it('hides the close button', () => {
diff --git a/spec/javascripts/pipelines/async_button_spec.js b/spec/javascripts/pipelines/async_button_spec.js
index 48620898357..d010d897642 100644
--- a/spec/javascripts/pipelines/async_button_spec.js
+++ b/spec/javascripts/pipelines/async_button_spec.js
@@ -13,7 +13,7 @@ describe('Pipelines Async Button', () => {
propsData: {
endpoint: '/foo',
title: 'Foo',
- icon: 'fa fa-foo',
+ icon: 'repeat',
cssClass: 'bar',
},
}).$mount();
@@ -23,8 +23,8 @@ describe('Pipelines Async Button', () => {
expect(component.$el.tagName).toEqual('BUTTON');
});
- it('should render the provided icon', () => {
- expect(component.$el.querySelector('i').getAttribute('class')).toContain('fa fa-foo');
+ it('should render svg icon', () => {
+ expect(component.$el.querySelector('svg')).not.toBeNull();
});
it('should render the provided title', () => {
diff --git a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
index 1127576617b..11858e45386 100644
--- a/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
+++ b/spec/javascripts/vue_mr_widget/components/states/mr_widget_ready_to_merge_spec.js
@@ -371,6 +371,10 @@ describe('MRWidgetReadyToMerge', () => {
});
});
+ beforeEach(() => {
+ loadFixtures('merge_requests/merge_request_of_current_user.html.raw');
+ });
+
it('should call start and stop polling when MR merged', (done) => {
spyOn(eventHub, '$emit');
spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
@@ -392,6 +396,47 @@ describe('MRWidgetReadyToMerge', () => {
}, 333);
});
+ it('updates status box', (done) => {
+ spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
+ spyOn(vm, 'initiateRemoveSourceBranchPolling');
+
+ vm.handleMergePolling(() => {}, () => {});
+
+ setTimeout(() => {
+ const statusBox = document.querySelector('.status-box');
+ expect(statusBox.classList.contains('status-box-merged')).toBeTruthy();
+ expect(statusBox.textContent).toContain('Merged');
+
+ done();
+ });
+ });
+
+ it('hides close button', (done) => {
+ spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
+ spyOn(vm, 'initiateRemoveSourceBranchPolling');
+
+ vm.handleMergePolling(() => {}, () => {});
+
+ setTimeout(() => {
+ expect(document.querySelector('.btn-close').classList.contains('hidden')).toBeTruthy();
+
+ done();
+ });
+ });
+
+ it('updates merge request count badge', (done) => {
+ spyOn(vm.service, 'poll').and.returnValue(returnPromise('merged'));
+ spyOn(vm, 'initiateRemoveSourceBranchPolling');
+
+ vm.handleMergePolling(() => {}, () => {});
+
+ setTimeout(() => {
+ expect(document.querySelector('.js-merge-counter').textContent).toBe('0');
+
+ done();
+ });
+ });
+
it('should continue polling until MR is merged', (done) => {
spyOn(vm.service, 'poll').and.returnValue(returnPromise('some_other_state'));
spyOn(vm, 'initiateRemoveSourceBranchPolling');
diff --git a/spec/lib/backup/manager_spec.rb b/spec/lib/backup/manager_spec.rb
index b68301a066a..5100f5737c2 100644
--- a/spec/lib/backup/manager_spec.rb
+++ b/spec/lib/backup/manager_spec.rb
@@ -194,6 +194,12 @@ describe Backup::Manager do
)
end
+ it 'prints the list of available backups' do
+ expect { subject.unpack }.to raise_error SystemExit
+ expect(progress).to have_received(:puts)
+ .with(a_string_matching('1451606400_2016_01_01_1.2.3\n 1451520000_2015_12_31'))
+ end
+
it 'fails the operation and prints an error' do
expect { subject.unpack }.to raise_error SystemExit
expect(progress).to have_received(:puts)
diff --git a/spec/lib/banzai/filter/wiki_link_filter_spec.rb b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
index 9596f004052..50d053011b3 100644
--- a/spec/lib/banzai/filter/wiki_link_filter_spec.rb
+++ b/spec/lib/banzai/filter/wiki_link_filter_spec.rb
@@ -10,15 +10,23 @@ describe Banzai::Filter::WikiLinkFilter do
it "doesn't rewrite absolute links" do
filtered_link = filter("<a href='http://example.com:8000/'>Link</a>", project_wiki: wiki).children[0]
+
expect(filtered_link.attribute('href').value).to eq('http://example.com:8000/')
end
+ it "doesn't rewrite links to project uploads" do
+ filtered_link = filter("<a href='/uploads/a.test'>Link</a>", project_wiki: wiki).children[0]
+
+ expect(filtered_link.attribute('href').value).to eq('/uploads/a.test')
+ end
+
describe "invalid links" do
invalid_links = ["http://:8080", "http://", "http://:8080/path"]
invalid_links.each do |invalid_link|
it "doesn't rewrite invalid invalid_links like #{invalid_link}" do
filtered_link = filter("<a href='#{invalid_link}'>Link</a>", project_wiki: wiki).children[0]
+
expect(filtered_link.attribute('href').value).to eq(invalid_link)
end
end
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 98730602863..d21183b668b 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
@@ -15,6 +15,10 @@ describe Gitlab::BackgroundMigration::DeserializeMergeRequestDiffsAndCommits, :t
.to receive(:commits_count=).and_return(nil)
end
+ after do
+ [Project, MergeRequest, MergeRequestDiff].each(&:reset_column_information)
+ end
+
def diffs_to_hashes(diffs)
diffs.as_json(only: Gitlab::Git::Diff::SERIALIZE_KEYS).map(&:with_indifferent_access)
end
diff --git a/spec/lib/gitlab/ci/status/build/action_spec.rb b/spec/lib/gitlab/ci/status/build/action_spec.rb
index 8c25f72804b..d612d29e3e0 100644
--- a/spec/lib/gitlab/ci/status/build/action_spec.rb
+++ b/spec/lib/gitlab/ci/status/build/action_spec.rb
@@ -37,16 +37,16 @@ describe Gitlab::Ci::Status::Build::Action do
describe '.matches?' do
subject { described_class.matches?(build, user) }
- context 'when build is an action' do
- let(:build) { create(:ci_build, :manual) }
+ context 'when build is playable action' do
+ let(:build) { create(:ci_build, :playable) }
it 'is a correct match' do
expect(subject).to be true
end
end
- context 'when build is not manual' do
- let(:build) { create(:ci_build) }
+ context 'when build is not playable action' do
+ let(:build) { create(:ci_build, :non_playable) }
it 'does not match' do
expect(subject).to be false
diff --git a/spec/lib/gitlab/git/gitlab_projects_spec.rb b/spec/lib/gitlab/git/gitlab_projects_spec.rb
index beef843537d..78e4fbca28e 100644
--- a/spec/lib/gitlab/git/gitlab_projects_spec.rb
+++ b/spec/lib/gitlab/git/gitlab_projects_spec.rb
@@ -158,39 +158,55 @@ describe Gitlab::Git::GitlabProjects do
subject { gl_projects.import_project(import_url, timeout) }
- context 'success import' do
- it 'imports a repo' do
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
+ shared_examples 'importing repository' do
+ context 'success import' do
+ it 'imports a repo' do
+ expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
- message = "Importing project from <#{import_url}> to <#{tmp_repo_path}>."
- expect(logger).to receive(:info).with(message)
+ is_expected.to be_truthy
- is_expected.to be_truthy
+ expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_truthy
+ end
+ end
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_truthy
+ context 'already exists' do
+ it "doesn't import" do
+ FileUtils.mkdir_p(tmp_repo_path)
+
+ is_expected.to be_falsy
+ end
end
end
- context 'already exists' do
- it "doesn't import" do
- FileUtils.mkdir_p(tmp_repo_path)
+ context 'when Gitaly import_repository feature is enabled' do
+ it_behaves_like 'importing repository'
+ end
+
+ context 'when Gitaly import_repository feature is disabled', :disable_gitaly do
+ describe 'logging' do
+ it 'imports a repo' do
+ message = "Importing project from <#{import_url}> to <#{tmp_repo_path}>."
+ expect(logger).to receive(:info).with(message)
- is_expected.to be_falsy
+ subject
+ end
end
- end
- context 'timeout' do
- it 'does not import a repo' do
- stub_spawn_timeout(cmd, timeout, nil)
+ context 'timeout' do
+ it 'does not import a repo' do
+ stub_spawn_timeout(cmd, timeout, nil)
- message = "Importing project from <#{import_url}> to <#{tmp_repo_path}> failed."
- expect(logger).to receive(:error).with(message)
+ message = "Importing project from <#{import_url}> to <#{tmp_repo_path}> failed."
+ expect(logger).to receive(:error).with(message)
- is_expected.to be_falsy
+ is_expected.to be_falsy
- expect(gl_projects.output).to eq("Timed out\n")
- expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
+ expect(gl_projects.output).to eq("Timed out\n")
+ expect(File.exist?(File.join(tmp_repo_path, 'HEAD'))).to be_falsy
+ end
end
+
+ it_behaves_like 'importing repository'
end
end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index f4e781c599e..3cf165716bd 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1104,14 +1104,6 @@ describe Gitlab::Git::Repository, seed_helper: true do
end
end
- describe "branch_names_contains" do
- subject { repository.branch_names_contains(SeedRepo::LastCommit::ID) }
-
- it { is_expected.to include('master') }
- it { is_expected.not_to include('feature') }
- it { is_expected.not_to include('fix') }
- end
-
describe '#autocrlf' do
before(:all) do
@repo = Gitlab::Git::Repository.new('default', TEST_MUTABLE_REPO_PATH, '')
diff --git a/spec/lib/gitlab/git/rev_list_spec.rb b/spec/lib/gitlab/git/rev_list_spec.rb
index eaf74951b0e..90fbef9d248 100644
--- a/spec/lib/gitlab/git/rev_list_spec.rb
+++ b/spec/lib/gitlab/git/rev_list_spec.rb
@@ -39,7 +39,7 @@ describe Gitlab::Git::RevList do
]
expect(rev_list).to receive(:popen).with(*params) do |*_, lazy_block:|
- lazy_block.call(output.split("\n").lazy)
+ lazy_block.call(output.lines.lazy.map(&:chomp))
end
end
@@ -64,6 +64,15 @@ describe Gitlab::Git::RevList do
expect(rev_list.new_objects(require_path: true)).to eq(%w[sha2])
end
+ it 'can handle non utf-8 paths' do
+ non_utf_char = [0x89].pack("c*").force_encoding("UTF-8")
+ stub_lazy_popen_rev_list('newrev', '--not', '--all', '--objects', output: "sha2 πå†h/†ø/ƒîlé#{non_utf_char}\nsha1")
+
+ rev_list.new_objects(require_path: true) do |object_ids|
+ expect(object_ids.force).to eq(%w[sha2])
+ end
+ end
+
it 'can yield a lazy enumerator' do
stub_lazy_popen_rev_list('newrev', '--not', '--all', '--objects', output: "sha1\nsha2")
diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
index 4afe48e72ad..63997a40d52 100644
--- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb
@@ -100,6 +100,25 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
is_expected.to eq(command)
end
end
+
+ context 'when chart values file is present' do
+ let(:install_command) { described_class.new(prometheus.name, chart: prometheus.chart, chart_values_file: prometheus.chart_values_file) }
+ let(:command) do
+ <<~MSG.chomp
+ set -eo pipefail
+ apk add -U ca-certificates openssl >/dev/null
+ wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null
+ mv /tmp/linux-amd64/helm /usr/bin/
+
+ helm init --client-only >/dev/null
+ helm install #{prometheus.chart} --name #{prometheus.name} --namespace #{namespace.name} -f /data/helm/#{prometheus.name}/config/values.yaml >/dev/null
+ MSG
+ end
+
+ it 'should return appropriate command' do
+ is_expected.to eq(command)
+ end
+ end
end
describe "#pod_name" do
diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
index 906b10b96d4..0b8e97b8948 100644
--- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
+++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb
@@ -52,18 +52,20 @@ describe Gitlab::Kubernetes::Helm::Pod do
it 'should include volumes for the container' do
container = subject.generate.spec.containers.first
- expect(container.volumeMounts.first['name']).to eq('config-volume')
- expect(container.volumeMounts.first['mountPath']).to eq('/etc/config')
+ expect(container.volumeMounts.first['name']).to eq('configuration-volume')
+ expect(container.volumeMounts.first['mountPath']).to eq("/data/helm/#{app.name}/config")
end
it 'should include a volume inside the specification' do
spec = subject.generate.spec
- expect(spec.volumes.first['name']).to eq('config-volume')
+ expect(spec.volumes.first['name']).to eq('configuration-volume')
end
it 'should mount configMap specification in the volume' do
spec = subject.generate.spec
- expect(spec.volumes.first.configMap['name']).to eq('values-config')
+ expect(spec.volumes.first.configMap['name']).to eq('values-content-configuration')
+ expect(spec.volumes.first.configMap['items'].first['key']).to eq('values')
+ expect(spec.volumes.first.configMap['items'].first['path']).to eq('values.yaml')
end
end
diff --git a/spec/lib/gitlab/project_search_results_spec.rb b/spec/lib/gitlab/project_search_results_spec.rb
index 17937726f2c..1ebb0105cf5 100644
--- a/spec/lib/gitlab/project_search_results_spec.rb
+++ b/spec/lib/gitlab/project_search_results_spec.rb
@@ -70,15 +70,6 @@ describe Gitlab::ProjectSearchResults do
subject { described_class.parse_search_result(search_result) }
- it 'can correctly parse filenames including ":"' do
- special_char_result = "\nmaster:testdata/project::function1.yaml-1----\nmaster:testdata/project::function1.yaml:2:test: data1\n"
-
- blob = described_class.parse_search_result(special_char_result)
-
- expect(blob.ref).to eq('master')
- expect(blob.filename).to eq('testdata/project::function1.yaml')
- end
-
it "returns a valid FoundBlob" do
is_expected.to be_an Gitlab::SearchResults::FoundBlob
expect(subject.id).to be_nil
@@ -90,8 +81,32 @@ describe Gitlab::ProjectSearchResults do
expect(subject.data.lines[2]).to eq(" - Feature: Replace teams with group membership\n")
end
+ context 'when the matching filename contains a colon' do
+ let(:search_result) { "\nmaster:testdata/project::function1.yaml\x001\x00---\n" }
+
+ it 'returns a valid FoundBlob' do
+ expect(subject.filename).to eq('testdata/project::function1.yaml')
+ expect(subject.basename).to eq('testdata/project::function1')
+ expect(subject.ref).to eq('master')
+ expect(subject.startline).to eq(1)
+ expect(subject.data).to eq('---')
+ end
+ end
+
+ context 'when the matching content contains a number surrounded by colons' do
+ let(:search_result) { "\nmaster:testdata/foo.txt\x001\x00blah:9:blah" }
+
+ it 'returns a valid FoundBlob' do
+ expect(subject.filename).to eq('testdata/foo.txt')
+ expect(subject.basename).to eq('testdata/foo')
+ expect(subject.ref).to eq('master')
+ expect(subject.startline).to eq(1)
+ expect(subject.data).to eq('blah:9:blah')
+ end
+ end
+
context "when filename has extension" do
- let(:search_result) { "master:CONTRIBUTE.md:5:- [Contribute to GitLab](#contribute-to-gitlab)\n" }
+ let(:search_result) { "master:CONTRIBUTE.md\x005\x00- [Contribute to GitLab](#contribute-to-gitlab)\n" }
it { expect(subject.path).to eq('CONTRIBUTE.md') }
it { expect(subject.filename).to eq('CONTRIBUTE.md') }
@@ -99,7 +114,7 @@ describe Gitlab::ProjectSearchResults do
end
context "when file under directory" do
- let(:search_result) { "master:a/b/c.md:5:a b c\n" }
+ let(:search_result) { "master:a/b/c.md\x005\x00a b c\n" }
it { expect(subject.path).to eq('a/b/c.md') }
it { expect(subject.filename).to eq('a/b/c.md') }
@@ -144,7 +159,7 @@ describe Gitlab::ProjectSearchResults do
end
it 'finds by content' do
- expect(results).to include("master:Title.md:1:Content\n")
+ expect(results).to include("master:Title.md\x001\x00Content\n")
end
end
diff --git a/spec/lib/gitlab/utils/override_spec.rb b/spec/lib/gitlab/utils/override_spec.rb
new file mode 100644
index 00000000000..7c97cee982a
--- /dev/null
+++ b/spec/lib/gitlab/utils/override_spec.rb
@@ -0,0 +1,158 @@
+require 'spec_helper'
+
+describe Gitlab::Utils::Override do
+ let(:base) { Struct.new(:good) }
+
+ let(:derived) { Class.new(base).tap { |m| m.extend described_class } }
+ let(:extension) { Module.new.tap { |m| m.extend described_class } }
+
+ let(:prepending_class) { base.tap { |m| m.prepend extension } }
+ let(:including_class) { base.tap { |m| m.include extension } }
+
+ let(:klass) { subject }
+
+ def good(mod)
+ mod.module_eval do
+ override :good
+ def good
+ super.succ
+ end
+ end
+
+ mod
+ end
+
+ def bad(mod)
+ mod.module_eval do
+ override :bad
+ def bad
+ true
+ end
+ end
+
+ mod
+ end
+
+ shared_examples 'checking as intended' do
+ it 'checks ok for overriding method' do
+ good(subject)
+ result = klass.new(0).good
+
+ expect(result).to eq(1)
+ described_class.verify!
+ end
+
+ it 'raises NotImplementedError when it is not overriding anything' do
+ expect do
+ bad(subject)
+ klass.new(0).bad
+ described_class.verify!
+ end.to raise_error(NotImplementedError)
+ end
+ end
+
+ shared_examples 'nothing happened' do
+ it 'does not complain when it is overriding something' do
+ good(subject)
+ result = klass.new(0).good
+
+ expect(result).to eq(1)
+ described_class.verify!
+ end
+
+ it 'does not complain when it is not overriding anything' do
+ bad(subject)
+ result = klass.new(0).bad
+
+ expect(result).to eq(true)
+ described_class.verify!
+ end
+ end
+
+ before do
+ # Make sure we're not touching the internal cache
+ allow(described_class).to receive(:extensions).and_return({})
+ end
+
+ describe '#override' do
+ context 'when STATIC_VERIFICATION is set' do
+ before do
+ stub_env('STATIC_VERIFICATION', 'true')
+ end
+
+ context 'when subject is a class' do
+ subject { derived }
+
+ it_behaves_like 'checking as intended'
+ end
+
+ context 'when subject is a module, and class is prepending it' do
+ subject { extension }
+ let(:klass) { prepending_class }
+
+ it_behaves_like 'checking as intended'
+ end
+
+ context 'when subject is a module, and class is including it' do
+ subject { extension }
+ let(:klass) { including_class }
+
+ it 'raises NotImplementedError because it is not overriding it' do
+ expect do
+ good(subject)
+ klass.new(0).good
+ described_class.verify!
+ end.to raise_error(NotImplementedError)
+ end
+
+ it 'raises NotImplementedError when it is not overriding anything' do
+ expect do
+ bad(subject)
+ klass.new(0).bad
+ described_class.verify!
+ end.to raise_error(NotImplementedError)
+ end
+ end
+ end
+ end
+
+ context 'when STATIC_VERIFICATION is not set' do
+ before do
+ stub_env('STATIC_VERIFICATION', nil)
+ end
+
+ context 'when subject is a class' do
+ subject { derived }
+
+ it_behaves_like 'nothing happened'
+ end
+
+ context 'when subject is a module, and class is prepending it' do
+ subject { extension }
+ let(:klass) { prepending_class }
+
+ it_behaves_like 'nothing happened'
+ end
+
+ context 'when subject is a module, and class is including it' do
+ subject { extension }
+ let(:klass) { including_class }
+
+ it 'does not complain when it is overriding something' do
+ good(subject)
+ result = klass.new(0).good
+
+ expect(result).to eq(0)
+ described_class.verify!
+ end
+
+ it 'does not complain when it is not overriding anything' do
+ bad(subject)
+ result = klass.new(0).bad
+
+ expect(result).to eq(true)
+ described_class.verify!
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 3eaeeebf97d..45a606c1ea8 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -25,6 +25,13 @@ describe Ci::Build do
it { is_expected.to be_a(ArtifactMigratable) }
+ describe 'associations' do
+ it 'has a bidirectional relationship with projects' do
+ expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:builds)
+ expect(Project.reflect_on_association(:builds).has_inverse?).to eq(:project)
+ end
+ end
+
describe 'callbacks' do
context 'when running after_create callback' do
it 'triggers asynchronous build hooks worker' do
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 7bef798a782..14d234f6aab 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -28,6 +28,13 @@ describe Ci::Pipeline, :mailer do
it { is_expected.to respond_to :short_sha }
it { is_expected.to delegate_method(:full_path).to(:project).with_prefix }
+ describe 'associations' do
+ it 'has a bidirectional relationship with projects' do
+ expect(described_class.reflect_on_association(:project).has_inverse?).to eq(:pipelines)
+ expect(Project.reflect_on_association(:pipelines).has_inverse?).to eq(:project)
+ end
+ end
+
describe '#source' do
context 'when creating new pipeline' do
let(:pipeline) do
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index d3826417762..f8a98b43e46 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -439,15 +439,25 @@ eos
end
describe '#uri_type' do
- it 'returns the URI type at the given path' do
- expect(commit.uri_type('files/html')).to be(:tree)
- expect(commit.uri_type('files/images/logo-black.png')).to be(:raw)
- expect(project.commit('video').uri_type('files/videos/intro.mp4')).to be(:raw)
- expect(commit.uri_type('files/js/application.js')).to be(:blob)
+ shared_examples 'URI type' do
+ it 'returns the URI type at the given path' do
+ expect(commit.uri_type('files/html')).to be(:tree)
+ expect(commit.uri_type('files/images/logo-black.png')).to be(:raw)
+ expect(project.commit('video').uri_type('files/videos/intro.mp4')).to be(:raw)
+ expect(commit.uri_type('files/js/application.js')).to be(:blob)
+ end
+
+ it "returns nil if the path doesn't exists" do
+ expect(commit.uri_type('this/path/doesnt/exist')).to be_nil
+ end
+ end
+
+ context 'when Gitaly commit_tree_entry feature is enabled' do
+ it_behaves_like 'URI type'
end
- it "returns nil if the path doesn't exists" do
- expect(commit.uri_type('this/path/doesnt/exist')).to be_nil
+ context 'when Gitaly commit_tree_entry feature is disabled', :disable_gitaly do
+ it_behaves_like 'URI type'
end
end
diff --git a/spec/models/push_event_spec.rb b/spec/models/push_event_spec.rb
index ad3c3a406d9..bfe7a30b96a 100644
--- a/spec/models/push_event_spec.rb
+++ b/spec/models/push_event_spec.rb
@@ -63,12 +63,14 @@ describe PushEvent do
let(:event2) { create(:push_event, project: project) }
let(:event3) { create(:push_event, project: project) }
let(:event4) { create(:push_event, project: project) }
+ let(:event5) { create(:push_event, project: project) }
before do
create(:push_event_payload, event: event1, ref: 'foo', action: :created)
create(:push_event_payload, event: event2, ref: 'bar', action: :created)
- create(:push_event_payload, event: event3, ref: 'baz', action: :removed)
- create(:push_event_payload, event: event4, ref: 'baz', ref_type: :tag)
+ create(:push_event_payload, event: event3, ref: 'qux', action: :created)
+ create(:push_event_payload, event: event4, ref: 'baz', action: :removed)
+ create(:push_event_payload, event: event5, ref: 'baz', ref_type: :tag)
project.repository.create_branch('bar', 'master')
@@ -78,6 +80,16 @@ describe PushEvent do
target_project: project,
source_branch: 'bar'
)
+
+ project.repository.create_branch('qux', 'master')
+
+ create(
+ :merge_request,
+ :closed,
+ source_project: project,
+ target_project: project,
+ source_branch: 'qux'
+ )
end
let(:relation) { described_class.without_existing_merge_requests }
@@ -86,16 +98,20 @@ describe PushEvent do
expect(relation).to include(event1)
end
- it 'does not include events that have a corresponding merge request' do
+ it 'does not include events that have a corresponding open merge request' do
expect(relation).not_to include(event2)
end
+ it 'includes events that has corresponding closed/merged merge requests' do
+ expect(relation).to include(event3)
+ end
+
it 'does not include events for removed refs' do
- expect(relation).not_to include(event3)
+ expect(relation).not_to include(event4)
end
it 'does not include events for pushing to tags' do
- expect(relation).not_to include(event4)
+ expect(relation).not_to include(event5)
end
end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index f3456e5b354..baaa9e3ef44 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -657,7 +657,7 @@ describe Repository do
subject { results.first }
it { is_expected.to be_an String }
- it { expect(subject.lines[2]).to eq("master:CHANGELOG:190: - Feature: Replace teams with group membership\n") }
+ it { expect(subject.lines[2]).to eq("master:CHANGELOG\x00190\x00 - Feature: Replace teams with group membership\n") }
end
end
@@ -668,6 +668,18 @@ describe Repository do
expect(results.first).to eq('files/html/500.html')
end
+ it 'ignores leading slashes' do
+ results = repository.search_files_by_name('/files', 'master')
+
+ expect(results.first).to eq('files/html/500.html')
+ end
+
+ it 'properly handles when query is only slashes' do
+ results = repository.search_files_by_name('//', 'master')
+
+ expect(results).to match_array([])
+ end
+
it 'properly handles when query is not present' do
results = repository.search_files_by_name('', 'master')
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index 6732c99e329..51b70fda148 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -3,24 +3,65 @@ require 'spec_helper'
describe API::Deployments do
let(:user) { create(:user) }
let(:non_member) { create(:user) }
- let(:project) { deployment.environment.project }
- let!(:deployment) { create(:deployment) }
before do
project.add_master(user)
end
describe 'GET /projects/:id/deployments' do
+ let(:project) { create(:project) }
+ let!(:deployment_1) { create(:deployment, project: project, iid: 11, ref: 'master', created_at: Time.now) }
+ let!(:deployment_2) { create(:deployment, project: project, iid: 12, ref: 'feature', created_at: 1.day.ago) }
+ let!(:deployment_3) { create(:deployment, project: project, iid: 8, ref: 'feature', created_at: 2.days.ago) }
+
context 'as member of the project' do
- it 'returns projects deployments' do
+ it 'returns projects deployments sorted by id asc' do
get api("/projects/#{project.id}/deployments", user)
expect(response).to have_gitlab_http_status(200)
expect(response).to include_pagination_headers
expect(json_response).to be_an Array
- expect(json_response.size).to eq(1)
- expect(json_response.first['iid']).to eq(deployment.iid)
+ expect(json_response.size).to eq(3)
+ expect(json_response.first['iid']).to eq(deployment_1.iid)
expect(json_response.first['sha']).to match /\A\h{40}\z/
+ expect(json_response.second['iid']).to eq(deployment_2.iid)
+ expect(json_response.last['iid']).to eq(deployment_3.iid)
+ end
+
+ describe 'ordering' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:order_by) { nil }
+ let(:sort) { nil }
+
+ subject { get api("/projects/#{project.id}/deployments?order_by=#{order_by}&sort=#{sort}", user) }
+
+ def expect_deployments(ordered_deployments)
+ json_response.each_with_index do |deployment_json, index|
+ expect(deployment_json['id']).to eq(public_send(ordered_deployments[index]).id)
+ end
+ end
+
+ before do
+ subject
+ end
+
+ where(:order_by, :sort, :ordered_deployments) do
+ 'created_at' | 'asc' | [:deployment_3, :deployment_2, :deployment_1]
+ 'created_at' | 'desc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'id' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
+ 'id' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
+ 'iid' | 'asc' | [:deployment_3, :deployment_1, :deployment_2]
+ 'iid' | 'desc' | [:deployment_2, :deployment_1, :deployment_3]
+ 'ref' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
+ 'ref' | 'desc' | [:deployment_1, :deployment_2, :deployment_3]
+ end
+
+ with_them do
+ it 'returns the deployments ordered' do
+ expect_deployments(ordered_deployments)
+ end
+ end
end
end
@@ -34,6 +75,9 @@ describe API::Deployments do
end
describe 'GET /projects/:id/deployments/:deployment_id' do
+ let(:project) { deployment.environment.project }
+ let!(:deployment) { create(:deployment) }
+
context 'as a member of the project' do
it 'returns the projects deployment' do
get api("/projects/#{project.id}/deployments/#{deployment.id}", user)
diff --git a/spec/requests/api/jobs_spec.rb b/spec/requests/api/jobs_spec.rb
index 805496e4a54..e211c347266 100644
--- a/spec/requests/api/jobs_spec.rb
+++ b/spec/requests/api/jobs_spec.rb
@@ -25,8 +25,10 @@ describe API::Jobs do
describe 'GET /projects/:id/jobs' do
let(:query) { Hash.new }
- before do
- get api("/projects/#{project.id}/jobs", api_user), query
+ before do |example|
+ unless example.metadata[:skip_before_request]
+ get api("/projects/#{project.id}/jobs", api_user), query
+ end
end
context 'authorized user' do
@@ -51,6 +53,23 @@ describe API::Jobs do
expect(json_job['pipeline']['status']).to eq job.pipeline.status
end
+ it 'avoids N+1 queries', skip_before_request: true do
+ first_build = create(:ci_build, :artifacts, pipeline: pipeline)
+ first_build.runner = create(:ci_runner)
+ first_build.user = create(:user)
+ first_build.save
+
+ control_count = ActiveRecord::QueryRecorder.new { go }.count
+
+ second_pipeline = create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch)
+ second_build = create(:ci_build, :artifacts, pipeline: second_pipeline)
+ second_build.runner = create(:ci_runner)
+ second_build.user = create(:user)
+ second_build.save
+
+ expect { go }.not_to exceed_query_limit(control_count)
+ end
+
context 'filter project with one scope element' do
let(:query) { { 'scope' => 'pending' } }
@@ -83,6 +102,10 @@ describe API::Jobs do
expect(response).to have_gitlab_http_status(401)
end
end
+
+ def go
+ get api("/projects/#{project.id}/jobs", api_user), query
+ end
end
describe 'GET /projects/:id/pipelines/:pipeline_id/jobs' do
diff --git a/spec/requests/api/project_milestones_spec.rb b/spec/requests/api/project_milestones_spec.rb
index 08ea7314bb3..6c05c166bd6 100644
--- a/spec/requests/api/project_milestones_spec.rb
+++ b/spec/requests/api/project_milestones_spec.rb
@@ -14,6 +14,46 @@ describe API::ProjectMilestones do
let(:route) { "/projects/#{project.id}/milestones" }
end
+ describe 'DELETE /projects/:id/milestones/:milestone_id' do
+ let(:guest) { create(:user) }
+ let(:reporter) { create(:user) }
+
+ before do
+ project.add_reporter(reporter)
+ end
+
+ it 'returns 404 response when the project does not exists' do
+ delete api("/projects/999/milestones/#{milestone.id}", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it 'returns 404 response when the milestone does not exists' do
+ delete api("/projects/#{project.id}/milestones/999", user)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it "returns 404 from guest user deleting a milestone" do
+ delete api("/projects/#{project.id}/milestones/#{milestone.id}", guest)
+
+ expect(response).to have_gitlab_http_status(404)
+ end
+
+ it "rejects a member with reporter access from deleting a milestone" do
+ delete api("/projects/#{project.id}/milestones/#{milestone.id}", reporter)
+
+ expect(response).to have_gitlab_http_status(403)
+ end
+
+ it 'deletes the milestone when the user has developer access to the project' do
+ delete api("/projects/#{project.id}/milestones/#{milestone.id}", user)
+
+ expect(project.milestones.find_by_id(milestone.id)).to be_nil
+ expect(response).to have_gitlab_http_status(204)
+ end
+ end
+
describe 'PUT /projects/:id/milestones/:milestone_id to test observer on close' do
it 'creates an activity event when an milestone is closed' do
expect(Event).to receive(:create!)
diff --git a/spec/requests/api/v3/builds_spec.rb b/spec/requests/api/v3/builds_spec.rb
index a73bb456b52..cdbc5692e19 100644
--- a/spec/requests/api/v3/builds_spec.rb
+++ b/spec/requests/api/v3/builds_spec.rb
@@ -13,10 +13,12 @@ describe API::V3::Builds do
describe 'GET /projects/:id/builds ' do
let(:query) { '' }
- before do
+ before do |example|
create(:ci_build, :skipped, pipeline: pipeline)
- get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
+ unless example.metadata[:skip_before_request]
+ get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
+ end
end
context 'authorized user' do
@@ -40,6 +42,23 @@ describe API::V3::Builds do
expect(json_build['pipeline']['status']).to eq build.pipeline.status
end
+ it 'avoids N+1 queries', skip_before_request: true do
+ first_build = create(:ci_build, :artifacts, pipeline: pipeline)
+ first_build.runner = create(:ci_runner)
+ first_build.user = create(:user)
+ first_build.save
+
+ control_count = ActiveRecord::QueryRecorder.new { go }.count
+
+ second_pipeline = create(:ci_empty_pipeline, project: project, sha: project.commit.id, ref: project.default_branch)
+ second_build = create(:ci_build, :artifacts, pipeline: second_pipeline)
+ second_build.runner = create(:ci_runner)
+ second_build.user = create(:user)
+ second_build.save
+
+ expect { go }.not_to exceed_query_limit(control_count)
+ end
+
context 'filter project with one scope element' do
let(:query) { 'scope=pending' }
@@ -84,6 +103,10 @@ describe API::V3::Builds do
expect(response).to have_gitlab_http_status(401)
end
end
+
+ def go
+ get v3_api("/projects/#{project.id}/builds?#{query}", api_user)
+ end
end
describe 'GET /projects/:id/repository/commits/:sha/builds' do
diff --git a/spec/services/labels/promote_service_spec.rb b/spec/services/labels/promote_service_spec.rb
index 8809b282127..aa9aba6bdff 100644
--- a/spec/services/labels/promote_service_spec.rb
+++ b/spec/services/labels/promote_service_spec.rb
@@ -85,6 +85,19 @@ describe Labels::PromoteService do
change(project_3.labels, :count).by(-1)
end
+ it 'keeps users\' subscriptions' do
+ user2 = create(:user)
+ project_label_1_1.subscriptions.create(user: user, subscribed: true)
+ project_label_2_1.subscriptions.create(user: user, subscribed: true)
+ project_label_3_2.subscriptions.create(user: user, subscribed: true)
+ project_label_2_1.subscriptions.create(user: user2, subscribed: true)
+
+ expect { service.execute(project_label_1_1) }.to change { Subscription.count }.from(4).to(3)
+
+ expect(new_label.subscribed?(user)).to be_truthy
+ expect(new_label.subscribed?(user2)).to be_truthy
+ end
+
it 'recreates priorities' do
service.execute(project_label_1_1)
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 623b182b205..75553afc033 100644
--- a/spec/services/merge_requests/create_from_issue_service_spec.rb
+++ b/spec/services/merge_requests/create_from_issue_service_spec.rb
@@ -112,5 +112,24 @@ describe MergeRequests::CreateFromIssueService do
expect(result[:merge_request].assignee).to eq(user)
end
+
+ context 'when ref branch is set' do
+ subject { described_class.new(project, user, issue_iid: issue.iid, ref: 'feature').execute }
+
+ it 'sets the merge request source branch to the new issue branch' do
+ expect(subject[:merge_request].source_branch).to eq(issue.to_branch_name)
+ end
+
+ it 'sets the merge request target branch to the ref branch' do
+ expect(subject[:merge_request].target_branch).to eq('feature')
+ end
+
+ context 'when ref branch does not exist' do
+ it 'does not create a merge request' do
+ expect { described_class.new(project, user, issue_iid: issue.iid, ref: 'nobr').execute }
+ .not_to change { project.merge_requests.count }
+ end
+ end
+ end
end
end
diff --git a/spec/services/system_note_service_spec.rb b/spec/services/system_note_service_spec.rb
index 965fd39c967..ab3a257f36f 100644
--- a/spec/services/system_note_service_spec.rb
+++ b/spec/services/system_note_service_spec.rb
@@ -158,7 +158,7 @@ describe SystemNoteService do
end
it 'builds a correct phrase when assignee removed' do
- expect(build_note([assignee1], [])).to eq 'removed assignee'
+ expect(build_note([assignee1], [])).to eq "unassigned @#{assignee1.username}"
end
it 'builds a correct phrase when assignees changed' do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index f51bb44086b..6186fb92bad 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -97,10 +97,6 @@ RSpec.configure do |config|
TestEnv.init
end
- config.after(:suite) do
- TestEnv.cleanup
- end
-
config.before(:example) do
# Skip pre-receive hook check so we can use the web editor and merge.
allow_any_instance_of(Gitlab::Git::Hook).to receive(:trigger).and_return([true, nil])
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
index 25ff6094408..fd6368e7b40 100644
--- a/spec/support/test_env.rb
+++ b/spec/support/test_env.rb
@@ -90,10 +90,6 @@ module TestEnv
setup_forked_repo
end
- def cleanup
- stop_gitaly
- end
-
def disable_mailer
allow_any_instance_of(NotificationService).to receive(:mailer)
.and_return(double.as_null_object)
@@ -163,6 +159,8 @@ module TestEnv
spawn_script = Rails.root.join('scripts/gitaly-test-spawn').to_s
@gitaly_pid = Bundler.with_original_env { IO.popen([spawn_script], &:read).to_i }
+ Kernel.at_exit { stop_gitaly }
+
wait_gitaly
end
@@ -309,7 +307,7 @@ module TestEnv
# Before we used Git clone's --mirror option, bare repos could end up
# with missing refs, clearing them and retrying should fix the issue.
- cleanup && clean_gitlab_test_path && init unless reset.call
+ clean_gitlab_test_path && init unless reset.call
end
end
diff --git a/spec/workers/repository_fork_worker_spec.rb b/spec/workers/repository_fork_worker_spec.rb
index 31598586f59..4912baa348c 100644
--- a/spec/workers/repository_fork_worker_spec.rb
+++ b/spec/workers/repository_fork_worker_spec.rb
@@ -47,6 +47,14 @@ describe RepositoryForkWorker do
perform!
end
+ it 'protects the default branch' do
+ expect_fork_repository.and_return(true)
+
+ perform!
+
+ expect(fork_project.protected_branches.first.name).to eq(fork_project.default_branch)
+ end
+
it 'flushes various caches' do
expect_fork_repository.and_return(true)
diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
index 75de266369d..eec356b9f47 100644
--- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
@@ -90,10 +90,14 @@ codequality:
performance:
stage: performance
- image:
- name: sitespeedio/sitespeed.io:6.0.3
- entrypoint: [""]
+ image: docker:latest
+ variables:
+ DOCKER_DRIVER: overlay2
+ allow_failure: true
+ services:
+ - docker:dind
script:
+ - setup_docker
- performance
artifacts:
paths:
@@ -112,7 +116,7 @@ sast:
- sast .
artifacts:
paths: [gl-sast-report.json]
-
+
sast:container:
image: docker:latest
variables:
@@ -260,7 +264,7 @@ production:
export CI_APPLICATION_TAG=$CI_COMMIT_SHA
export CI_CONTAINER_NAME=ci_job_build_${CI_JOB_ID}
export TILLER_NAMESPACE=$KUBE_NAMESPACE
-
+
function sast_container() {
docker run -d --name db arminc/clair-db:latest
docker run -p 6060:6060 --link db:postgres -d --name clair arminc/clair-local-scan:v2.0.1
@@ -466,26 +470,26 @@ production:
--docker-email="$GITLAB_USER_EMAIL" \
-o yaml --dry-run | kubectl replace -n "$KUBE_NAMESPACE" --force -f -
}
-
+
function performance() {
export CI_ENVIRONMENT_URL=$(cat environment_url.txt)
-
+
mkdir gitlab-exporter
wget -O gitlab-exporter/index.js https://gitlab.com/gitlab-org/gl-performance/raw/10-3/index.js
-
+
mkdir sitespeed-results
-
+
if [ -f .gitlab-urls.txt ]
then
sed -i -e 's@^@'"$CI_ENVIRONMENT_URL"'@' .gitlab-urls.txt
- /start.sh --plugins.add gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.0.3 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results .gitlab-urls.txt
else
- /start.sh --plugins.add gitlab-exporter --outputFolder sitespeed-results $CI_ENVIRONMENT_URL
+ docker run --shm-size=1g --rm -v "$(pwd)":/sitespeed.io sitespeedio/sitespeed.io:6.0.3 --plugins.add ./gitlab-exporter --outputFolder sitespeed-results "$CI_ENVIRONMENT_URL"
fi
-
+
mv sitespeed-results/data/performance.json performance.json
}
-
+
function persist_environment_url() {
echo $CI_ENVIRONMENT_URL > environment_url.txt
}
diff --git a/vendor/prometheus/values.yaml b/vendor/prometheus/values.yaml
index dd9496deb4d..5249449c7f8 100644
--- a/vendor/prometheus/values.yaml
+++ b/vendor/prometheus/values.yaml
@@ -1,134 +1,117 @@
-alertmanager: |
+alertmanager:
enabled: false
-kubeStateMetrics: |
- enabled: 'false'
+kubeStateMetrics:
+ enabled: false
-nodeExporter: |
- enabled: 'false'
+nodeExporter:
+ enabled: false
-pushgateway: |
- enabled: 'false'
+pushgateway:
+ enabled: false
-serverFiles: |
- alerts: ''
- rules: ''
+serverFiles:
+ alerts: ""
+ rules: ""
prometheus.yml: |-
- rule_files: |
+ rule_files:
- /etc/config/rules
- /etc/config/alerts
- scrape_configs: |
+ scrape_configs:
- job_name: prometheus
- static_configs: |
+ static_configs:
- targets:
- localhost:9090
-
- - job_name: 'kubernetes-apiservers'
- kubernetes_sd_configs: |
- - role: endpoints
+ - job_name: kubernetes-cadvisor
scheme: https
-
tls_config:
- ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
insecure_skip_verify: true
- bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
+ kubernetes_sd_configs:
+ - role: node
+ api_server: https://kubernetes.default.svc:443
+ tls_config:
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
relabel_configs:
- - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name]
- action: keep
- regex: default;kubernetes;https
- - job_name: 'kubernetes-nodes'
+ - action: labelmap
+ regex: __meta_kubernetes_node_label_(.+)
+ - target_label: __address__
+ replacement: kubernetes.default.svc:443
+ - source_labels:
+ - __meta_kubernetes_node_name
+ regex: "(.+)"
+ target_label: __metrics_path__
+ replacement: "/api/v1/nodes/${1}/proxy/metrics/cadvisor"
+ metric_relabel_configs:
+ - source_labels:
+ - pod_name
+ target_label: environment
+ regex: "(.+)-.+-.+"
+ - job_name: kubernetes-nodes
scheme: https
tls_config:
- ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
insecure_skip_verify: true
- bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
kubernetes_sd_configs:
- - role: node
+ - role: node
+ api_server: https://kubernetes.default.svc:443
+ tls_config:
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
relabel_configs:
- - action: labelmap
- regex: __meta_kubernetes_node_label_(.+)
- - target_label: __address__
- replacement: kubernetes.default.svc:443
- - source_labels: [__meta_kubernetes_node_name]
- regex: (.+)
- target_label: __metrics_path__
- replacement: /api/v1/nodes/${1}/proxy/metrics
-
- - job_name: 'kubernetes-service-endpoints'
- kubernetes_sd_configs:
- - role: endpoints
- relabel_configs: |
- - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape]
- action: keep
- regex: 'true'
- - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scheme]
- action: replace
- target_label: __scheme__
- regex: (https?)
- - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path]
- action: replace
- target_label: __metrics_path__
- regex: (.+)
- - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port]
- action: replace
- target_label: __address__
- regex: (.+)(?::\d+);(\d+)
- replacement: $1:$2
- - action: labelmap
- regex: __meta_kubernetes_service_label_(.+)
- - source_labels: [__meta_kubernetes_namespace]
- action: replace
- target_label: kubernetes_namespace
- - source_labels: [__meta_kubernetes_service_name]
- action: replace
- target_label: kubernetes_name
- - job_name: 'prometheus-pushgateway'
- honor_labels: true
- kubernetes_sd_configs: |
- - role: service
- relabel_configs: |
- - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
- action: keep
- regex: pushgateway
- - job_name: 'kubernetes-services'
- metrics_path: /probe
- params: |
- module: [http_2xx]
- kubernetes_sd_configs: |
- - role: service
- relabel_configs: |
- - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_probe]
- action: keep
- regex: 'true'
- - source_labels: [__address__]
- target_label: __param_target
- - target_label: __address__
- replacement: blackbox
- - source_labels: [__param_target]
- target_label: instance
- - action: labelmap
- regex: __meta_kubernetes_service_label_(.+)
- - source_labels: [__meta_kubernetes_namespace]
- target_label: kubernetes_namespace
- - source_labels: [__meta_kubernetes_service_name]
- target_label: kubernetes_name
- - job_name: 'kubernetes-pods'
+ - action: labelmap
+ regex: __meta_kubernetes_node_label_(.+)
+ - target_label: __address__
+ replacement: kubernetes.default.svc:443
+ - source_labels:
+ - __meta_kubernetes_node_name
+ regex: "(.+)"
+ target_label: __metrics_path__
+ replacement: "/api/v1/nodes/${1}/proxy/metrics"
+ metric_relabel_configs:
+ - source_labels:
+ - pod_name
+ target_label: environment
+ regex: "(.+)-.+-.+"
+ - job_name: kubernetes-pods
+ tls_config:
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ insecure_skip_verify: true
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
kubernetes_sd_configs:
- - role: pod
+ - role: pod
+ api_server: https://kubernetes.default.svc:443
+ tls_config:
+ ca_file: "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
+ bearer_token_file: "/var/run/secrets/kubernetes.io/serviceaccount/token"
relabel_configs:
- - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
- action: keep
- regex: 'true'
- - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
- action: replace
- target_label: __metrics_path__
- regex: (.+)
- - action: labelmap
- regex: __meta_kubernetes_pod_label_(.+)
- - source_labels: [__meta_kubernetes_namespace]
- action: replace
- target_label: kubernetes_namespace
- - source_labels: [__meta_kubernetes_pod_name]
- action: replace
- target_label: kubernetes_pod_name
+ - source_labels:
+ - __meta_kubernetes_pod_annotation_prometheus_io_scrape
+ action: keep
+ regex: 'true'
+ - source_labels:
+ - __meta_kubernetes_pod_annotation_prometheus_io_path
+ action: replace
+ target_label: __metrics_path__
+ regex: "(.+)"
+ - source_labels:
+ - __address__
+ - __meta_kubernetes_pod_annotation_prometheus_io_port
+ action: replace
+ regex: "([^:]+)(?::[0-9]+)?;([0-9]+)"
+ replacement: "$1:$2"
+ target_label: __address__
+ - action: labelmap
+ regex: __meta_kubernetes_pod_label_(.+)
+ - source_labels:
+ - __meta_kubernetes_namespace
+ action: replace
+ target_label: kubernetes_namespace
+ - source_labels:
+ - __meta_kubernetes_pod_name
+ action: replace
+ target_label: kubernetes_pod_name
diff --git a/yarn.lock b/yarn.lock
index 5d40e833889..64b66ee446a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4191,9 +4191,9 @@ map-stream@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/map-stream/-/map-stream-0.1.0.tgz#e56aa94c4c8055a16404a0674b78f215f7c8e194"
-marked@^0.3.6:
- version "0.3.6"
- resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.6.tgz#b2c6c618fccece4ef86c4fc6cb8a7cbf5aeda8d7"
+marked@^0.3.12:
+ version "0.3.12"
+ resolved "https://registry.yarnpkg.com/marked/-/marked-0.3.12.tgz#7cf25ff2252632f3fe2406bde258e94eee927519"
math-expression-evaluator@^1.2.14:
version "1.2.16"