summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG3
-rw-r--r--README.md4
-rw-r--r--app/assets/stylesheets/framework/avatar.scss1
-rw-r--r--app/assets/stylesheets/framework/blocks.scss35
-rw-r--r--app/assets/stylesheets/framework/header.scss4
-rw-r--r--app/assets/stylesheets/framework/mobile.scss2
-rw-r--r--app/assets/stylesheets/framework/nav.scss61
-rw-r--r--app/assets/stylesheets/framework/sidebar.scss13
-rw-r--r--app/assets/stylesheets/framework/variables.scss6
-rw-r--r--app/assets/stylesheets/pages/notes.scss5
-rw-r--r--app/assets/stylesheets/pages/profile.scss18
-rw-r--r--app/assets/stylesheets/pages/todos.scss9
-rw-r--r--app/helpers/blob_helper.rb2
-rw-r--r--app/helpers/nav_helper.rb13
-rw-r--r--app/models/appearance.rb13
-rw-r--r--app/models/application_setting.rb16
-rw-r--r--app/models/audit_event.rb4
-rw-r--r--app/models/broadcast_message.rb4
-rw-r--r--app/models/ci/build.rb14
-rw-r--r--app/models/ci/commit.rb10
-rw-r--r--app/models/ci/runner.rb14
-rw-r--r--app/models/ci/trigger.rb2
-rw-r--r--app/models/ci/variable.rb6
-rw-r--r--app/models/commit_status.rb17
-rw-r--r--app/models/concerns/issuable.rb5
-rw-r--r--app/models/deploy_key.rb6
-rw-r--r--app/models/email.rb2
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/generic_commit_status.rb17
-rw-r--r--app/models/group.rb21
-rw-r--r--app/models/hooks/project_hook.rb1
-rw-r--r--app/models/hooks/service_hook.rb1
-rw-r--r--app/models/hooks/system_hook.rb1
-rw-r--r--app/models/hooks/web_hook.rb1
-rw-r--r--app/models/identity.rb4
-rw-r--r--app/models/issue.rb9
-rw-r--r--app/models/key.rb6
-rw-r--r--app/models/label.rb16
-rw-r--r--app/models/label_link.rb2
-rw-r--r--app/models/lfs_object.rb4
-rw-r--r--app/models/member.rb8
-rw-r--r--app/models/members/group_member.rb8
-rw-r--r--app/models/members/project_member.rb8
-rw-r--r--app/models/merge_request.rb13
-rw-r--r--app/models/merge_request_diff.rb4
-rw-r--r--app/models/milestone.rb4
-rw-r--r--app/models/namespace.rb20
-rw-r--r--app/models/note.rb8
-rw-r--r--app/models/notification_setting.rb13
-rw-r--r--app/models/personal_snippet.rb6
-rw-r--r--app/models/project.rb82
-rw-r--r--app/models/project_group_link.rb12
-rw-r--r--app/models/project_import_data.rb9
-rw-r--r--app/models/project_services/asana_service.rb13
-rw-r--r--app/models/project_services/assembla_service.rb13
-rw-r--r--app/models/project_services/bamboo_service.rb13
-rw-r--r--app/models/project_services/buildkite_service.rb13
-rw-r--r--app/models/project_services/builds_email_service.rb13
-rw-r--r--app/models/project_services/campfire_service.rb13
-rw-r--r--app/models/project_services/ci_service.rb13
-rw-r--r--app/models/project_services/custom_issue_tracker_service.rb13
-rw-r--r--app/models/project_services/drone_ci_service.rb13
-rw-r--r--app/models/project_services/emails_on_push_service.rb13
-rw-r--r--app/models/project_services/external_wiki_service.rb13
-rw-r--r--app/models/project_services/flowdock_service.rb13
-rw-r--r--app/models/project_services/gemnasium_service.rb13
-rw-r--r--app/models/project_services/gitlab_ci_service.rb13
-rw-r--r--app/models/project_services/gitlab_issue_tracker_service.rb13
-rw-r--r--app/models/project_services/hipchat_service.rb13
-rw-r--r--app/models/project_services/irker_service.rb13
-rw-r--r--app/models/project_services/issue_tracker_service.rb13
-rw-r--r--app/models/project_services/jira_service.rb13
-rw-r--r--app/models/project_services/pivotaltracker_service.rb13
-rw-r--r--app/models/project_services/pushover_service.rb13
-rw-r--r--app/models/project_services/redmine_service.rb13
-rw-r--r--app/models/project_services/slack_service.rb13
-rw-r--r--app/models/project_services/teamcity_service.rb13
-rw-r--r--app/models/project_snippet.rb6
-rw-r--r--app/models/protected_branch.rb2
-rw-r--r--app/models/release.rb2
-rw-r--r--app/models/security_event.rb4
-rw-r--r--app/models/sent_notification.rb8
-rw-r--r--app/models/service.rb13
-rw-r--r--app/models/snippet.rb6
-rw-r--r--app/models/spam_log.rb17
-rw-r--r--app/models/subscription.rb2
-rw-r--r--app/models/user.rb49
-rw-r--r--app/services/merge_requests/build_service.rb36
-rw-r--r--app/services/projects/destroy_service.rb4
-rw-r--r--app/views/groups/activity.html.haml1
-rw-r--r--app/views/groups/edit.html.haml2
-rw-r--r--app/views/groups/group_members/index.html.haml1
-rw-r--r--app/views/groups/issues.html.haml1
-rw-r--r--app/views/groups/merge_requests.html.haml1
-rw-r--r--app/views/groups/milestones/index.html.haml1
-rw-r--r--app/views/groups/projects.html.haml1
-rw-r--r--app/views/groups/show.html.haml34
-rw-r--r--app/views/layouts/_page.html.haml2
-rw-r--r--app/views/layouts/group.html.haml2
-rw-r--r--app/views/layouts/group_settings.html.haml3
-rw-r--r--app/views/layouts/header/_default.html.haml1
-rw-r--r--app/views/layouts/nav/_dashboard.html.haml4
-rw-r--r--app/views/layouts/nav/_explore.html.haml2
-rw-r--r--app/views/layouts/nav/_group.html.haml20
-rw-r--r--app/views/layouts/nav/_group_settings.html.haml40
-rw-r--r--db/schema.rb18
-rw-r--r--doc/ci/docker/using_docker_build.md6
-rw-r--r--doc/ci/docker/using_docker_images.md8
-rw-r--r--doc/ci/examples/README.md4
-rw-r--r--doc/ci/examples/php.md6
-rw-r--r--doc/ci/examples/test-and-deploy-python-application-to-heroku.md10
-rw-r--r--doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md6
-rw-r--r--doc/ci/services/mysql.md4
-rw-r--r--doc/ci/services/postgres.md2
-rw-r--r--doc/ci/services/redis.md2
-rw-r--r--docker/README.md6
-rw-r--r--features/groups.feature4
-rw-r--r--features/steps/group/milestones.rb6
-rw-r--r--features/steps/groups.rb4
-rw-r--r--lib/gitlab/sanitizers/svg.rb37
-rw-r--r--lib/gitlab/sanitizers/svg/whitelist.rb107
-rw-r--r--lib/tasks/auto_annotate_models.rake44
-rw-r--r--spec/features/issues_spec.rb2
-rw-r--r--spec/fixtures/sanitized.svg50
-rw-r--r--spec/fixtures/unsanitized.svg50
-rw-r--r--spec/helpers/blob_helper_spec.rb12
-rw-r--r--spec/services/merge_requests/build_service_spec.rb181
127 files changed, 1254 insertions, 463 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 5b907fa217d..fed3caef7e8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -6,6 +6,7 @@ v 8.8.0 (unreleased)
- Log to application.log when an admin starts and stops impersonating a user
- Updated gitlab_git to 10.1.0
- GitAccess#protected_tag? no longer loads all tags just to check if a single one exists
+ - Reduce delay in destroying a project from 1-minute to immediately
- Make build status canceled if any of the jobs was canceled and none failed
- Upgrade Sidekiq to 4.1.2
- Sanitize repo paths in new project error message
@@ -15,6 +16,7 @@ v 8.8.0 (unreleased)
- Use ActionDispatch Remote IP for Akismet checking
- Fix error when visiting commit builds page before build was updated
- Add 'l' shortcut to open Label dropdown on issuables and 'i' to create new issue on a project
+ - Update SVG sanitizer to conform to SVG 1.1
- Updated search UI
- Display informative message when new milestone is created
- Allow "NEWS" and "CHANGES" as alternative names for CHANGELOG. !3768 (Connor Shea)
@@ -28,6 +30,7 @@ v 8.8.0 (unreleased)
- API support for the 'since' and 'until' operators on commit requests (Paco Guzman)
- Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko)
- Expire repository exists? and has_visible_content? caches after a push if necessary
+ - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi)
v 8.7.3
- Emails, Gitlab::Email::Message, Gitlab::Diff, and Premailer::Adapter::Nokogiri are now instrumented
diff --git a/README.md b/README.md
index c1a29c3bb1e..5e41665a6ba 100644
--- a/README.md
+++ b/README.md
@@ -20,6 +20,10 @@ To see how GitLab looks please see the [features page on our website](https://ab
- Completely free and open source (MIT Expat license)
- Powered by [Ruby on Rails](https://github.com/rails/rails)
+## Hiring
+
+We're hiring developers, support people, and production engineers all the time, please see our [jobs page](https://about.gitlab.com/jobs/).
+
## Editions
There are two editions of GitLab:
diff --git a/app/assets/stylesheets/framework/avatar.scss b/app/assets/stylesheets/framework/avatar.scss
index 5aa425dab6c..f5ce70b606b 100644
--- a/app/assets/stylesheets/framework/avatar.scss
+++ b/app/assets/stylesheets/framework/avatar.scss
@@ -28,6 +28,7 @@
&.s46 { width: 46px; height: 46px; margin-right: 15px; }
&.s48 { width: 48px; height: 48px; margin-right: 10px; }
&.s60 { width: 60px; height: 60px; margin-right: 12px; }
+ &.s70 { width: 70px; height: 70px; margin-right: 14px; }
&.s90 { width: 90px; height: 90px; margin-right: 15px; }
&.s110 { width: 110px; height: 110px; margin-right: 15px; }
&.s140 { width: 140px; height: 140px; margin-right: 20px; }
diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss
index af6f22da281..434a26d57c6 100644
--- a/app/assets/stylesheets/framework/blocks.scss
+++ b/app/assets/stylesheets/framework/blocks.scss
@@ -155,6 +155,41 @@
right: auto;
}
}
+
+ &.groups-cover-block {
+ background: $white-light;
+ border-bottom: 1px solid $border-color;
+ text-align: left;
+ padding: 24px 0;
+
+ .group-info {
+ .cover-title {
+ margin-top: 9px;
+ }
+
+ p {
+ margin-bottom: 0;
+ }
+ }
+
+ @media (max-width: $screen-xs-max) {
+ text-align: center;
+
+ .avatar {
+ float: none;
+ }
+ }
+ }
+
+ .group-info {
+
+ h1 {
+ display: inline;
+ font-weight: normal;
+ font-size: 24px;
+ color: $gl-title-color;
+ }
+ }
}
.block-connector {
diff --git a/app/assets/stylesheets/framework/header.scss b/app/assets/stylesheets/framework/header.scss
index 5fa10d29a87..97f9d582007 100644
--- a/app/assets/stylesheets/framework/header.scss
+++ b/app/assets/stylesheets/framework/header.scss
@@ -30,6 +30,10 @@ header {
border: none;
border-bottom: 1px solid $border-color;
+ &.with-horizontal-nav {
+ border-bottom: none;
+ }
+
.container-fluid {
width: 100% !important;
filter: none;
diff --git a/app/assets/stylesheets/framework/mobile.scss b/app/assets/stylesheets/framework/mobile.scss
index 7eb451c124e..33cbee85987 100644
--- a/app/assets/stylesheets/framework/mobile.scss
+++ b/app/assets/stylesheets/framework/mobile.scss
@@ -30,7 +30,7 @@
}
.rss-btn {
- display: none !important;
+ display: none;
}
.project-home-links {
diff --git a/app/assets/stylesheets/framework/nav.scss b/app/assets/stylesheets/framework/nav.scss
index 5fe687dcec3..7c18e93a261 100644
--- a/app/assets/stylesheets/framework/nav.scss
+++ b/app/assets/stylesheets/framework/nav.scss
@@ -26,8 +26,8 @@
}
&.active a {
- color: #000;
- border-bottom: 2px solid #4688f1;
+ border-bottom: 2px solid $link-underline-blue;
+ color: $black;
}
.badge {
@@ -140,6 +140,12 @@
}
}
+ .project-filter-form {
+ input {
+ background-color: $background-color;
+ }
+ }
+
@media (max-width: $screen-xs-max) {
padding-bottom: 0;
@@ -187,13 +193,31 @@
}
.layout-nav {
+ position: fixed;
+ top: $header-height;
+ width: 100%;
+ z-index: 1;
background: $background-color;
border-bottom: 1px solid $border-color;
+ transition-duration: .3s;
.controls {
float: right;
- position: relative;
- top: 10px;
+ padding: 7px 5px 0 0;
+
+ i {
+ color: $layout-link-gray;
+ }
+
+ .fa-rss,
+ .fa-cog {
+ font-size: 16px;
+ }
+
+ .fa-caret-down {
+ margin-left: 5px;
+ color: $gl-icon-color;
+ }
.dropdown {
margin-left: 7px;
@@ -202,5 +226,34 @@
.nav-links {
border-bottom: none;
+ height: 51px;
+ white-space: nowrap;
+ overflow-x: auto;
+
+ li {
+
+ a {
+ padding-top: 10px;
+ }
+
+ a, i {
+ color: $layout-link-gray;
+ }
+
+ &.active {
+ a, i {
+ color: $black;
+ }
+ }
+
+ .badge {
+ color: $gl-icon-color;
+ }
+ }
}
+
+}
+
+.page-with-layout-nav {
+ margin-top: 50px;
}
diff --git a/app/assets/stylesheets/framework/sidebar.scss b/app/assets/stylesheets/framework/sidebar.scss
index 18189e985c4..e940fd7286e 100644
--- a/app/assets/stylesheets/framework/sidebar.scss
+++ b/app/assets/stylesheets/framework/sidebar.scss
@@ -3,6 +3,7 @@
position: absolute;
width: 58px;
cursor: pointer;
+ margin-top: 8px;
}
.page-with-sidebar {
@@ -62,7 +63,7 @@
float: left;
height: $header-height;
width: 100%;
- padding: 11px 0 11px 22px;
+ padding-left: 22px;
overflow: hidden;
outline: none;
transition-duration: .3s;
@@ -85,7 +86,7 @@
margin: 0;
margin-left: 50px;
font-size: 19px;
- line-height: 41px;
+ line-height: 50px;
font-weight: normal;
}
}
@@ -254,6 +255,10 @@
}
}
}
+
+ .layout-nav {
+ padding-right: $sidebar_collapsed_width;
+ }
}
.page-sidebar-expanded {
@@ -280,6 +285,10 @@
}
}
}
+
+ .layout-nav {
+ padding-right: $sidebar_width;
+ }
}
.right-sidebar-collapsed {
diff --git a/app/assets/stylesheets/framework/variables.scss b/app/assets/stylesheets/framework/variables.scss
index 4227839eed3..ccb4e5381b7 100644
--- a/app/assets/stylesheets/framework/variables.scss
+++ b/app/assets/stylesheets/framework/variables.scss
@@ -66,7 +66,7 @@ $gl-padding-top: 10px;
$row-hover: #f4f8fe;
$progress-color: #c0392b;
$avatar_radius: 50%;
-$header-height: 58px;
+$header-height: 50px;
$fixed-layout-width: 1280px;
$gl-avatar-size: 40px;
$error-exclamation-point: #e62958;
@@ -75,6 +75,9 @@ $btn-transparent-color: #8f8f8f;
$settings-icon-size: 18px;
$provider-btn-group-border: #e5e5e5;
$provider-btn-not-active-color: #4688f1;
+$link-underline-blue: #4a8bee;
+$layout-link-gray: #7e7c7c;
+$todo-alert-blue: #428bca;
/*
* Color schema
@@ -109,6 +112,7 @@ $red-light: #e52c5a;
$red-normal: #d22852;
$red-dark: darken($red-normal, 5%);
+$black: #000;
$black-transparent: rgba(0, 0, 0, 0.3);
$border-white-light: #f1f2f4;
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 50ca755bcb6..624c8249f7e 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -168,6 +168,11 @@ ul.notes {
.notes {
background-color: $white-light;
}
+
+ a code {
+ top: 0;
+ margin-right: 0;
+ }
}
}
}
diff --git a/app/assets/stylesheets/pages/profile.scss b/app/assets/stylesheets/pages/profile.scss
index 01f98479623..abc5a0e9877 100644
--- a/app/assets/stylesheets/pages/profile.scss
+++ b/app/assets/stylesheets/pages/profile.scss
@@ -205,3 +205,21 @@
text-align: center;
}
}
+
+.user-profile {
+ @media (max-width: $screen-xs-max) {
+ .cover-block {
+ padding-top: 20px;
+ }
+
+ .cover-controls {
+ position: static;
+ margin-bottom: 20px;
+
+ .btn {
+ display: inline-block;
+ width: 48%;
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/pages/todos.scss b/app/assets/stylesheets/pages/todos.scss
index 75f78569e3c..e51c3491dae 100644
--- a/app/assets/stylesheets/pages/todos.scss
+++ b/app/assets/stylesheets/pages/todos.scss
@@ -6,9 +6,16 @@
.navbar-nav {
li {
.badge.todos-pending-count {
- background-color: $gl-icon-color;
margin-top: -5px;
font-weight: normal;
+ background: $todo-alert-blue;
+ margin-left: -17px;
+ font-size: 11px;
+ color: white;
+ padding: 3px;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ border-radius: 3px;
}
}
}
diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb
index 474c6f27374..93241b3afb7 100644
--- a/app/helpers/blob_helper.rb
+++ b/app/helpers/blob_helper.rb
@@ -131,7 +131,7 @@ module BlobHelper
# elements and attributes. Note that this whitelist is by no means complete
# and may omit some elements.
def sanitize_svg(blob)
- blob.data = Loofah.scrub_fragment(blob.data, :strip).to_xml
+ blob.data = Gitlab::Sanitizers::SVG.clean(blob.data)
blob
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 5d86bd490a8..3aa41030453 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -34,10 +34,13 @@ module NavHelper
end
def nav_header_class
- if nav_menu_collapsed?
- "header-collapsed"
- else
- "header-expanded"
- end
+ class_name =
+ if nav_menu_collapsed?
+ "header-collapsed"
+ else
+ "header-expanded"
+ end
+ class_name += " with-horizontal-nav" if defined?(nav) && nav
+ class_name
end
end
diff --git a/app/models/appearance.rb b/app/models/appearance.rb
index 4cf8dd9a8ce..4528760fefa 100644
--- a/app/models/appearance.rb
+++ b/app/models/appearance.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: appearances
+#
+# id :integer not null, primary key
+# title :string
+# description :text
+# header_logo :string
+# logo :string
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class Appearance < ActiveRecord::Base
validates :title, presence: true
validates :description, presence: true
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index 36f88154232..72ec91d2909 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -10,21 +10,20 @@
# sign_in_text :text
# created_at :datetime
# updated_at :datetime
-# home_page_url :string(255)
+# home_page_url :string
# default_branch_protection :integer default(2)
# restricted_visibility_levels :text
# version_check_enabled :boolean default(TRUE)
# max_attachment_size :integer default(10), not null
# default_project_visibility :integer
# default_snippet_visibility :integer
-# default_group_visibility :integer
# restricted_signup_domains :text
# user_oauth_applications :boolean default(TRUE)
-# after_sign_out_path :string(255)
+# after_sign_out_path :string
# session_expire_delay :integer default(10080), not null
# import_sources :text
# help_page_text :text
-# admin_notification_email :string(255)
+# admin_notification_email :string
# shared_runners_enabled :boolean default(TRUE), not null
# max_artifacts_size :integer default(100), not null
# runners_registration_token :string
@@ -32,8 +31,6 @@
# two_factor_grace_period :integer default(48)
# metrics_enabled :boolean default(FALSE)
# metrics_host :string default("localhost")
-# metrics_username :string
-# metrics_password :string
# metrics_pool_size :integer default(16)
# metrics_timeout :integer default(10)
# metrics_method_call_threshold :integer default(10)
@@ -41,9 +38,16 @@
# recaptcha_site_key :string
# recaptcha_private_key :string
# metrics_port :integer default(8089)
+# metrics_sample_interval :integer default(15)
# sentry_enabled :boolean default(FALSE)
# sentry_dsn :string
+# akismet_enabled :boolean default(FALSE)
+# akismet_api_key :string
# email_author_in_body :boolean default(FALSE)
+# default_group_visibility :integer
+# repository_checks_enabled :boolean default(FALSE)
+# metrics_packet_size :integer default(1)
+# shared_runners_text :text
#
class ApplicationSetting < ActiveRecord::Base
diff --git a/app/models/audit_event.rb b/app/models/audit_event.rb
index 0ed0dd98a59..44b090260e7 100644
--- a/app/models/audit_event.rb
+++ b/app/models/audit_event.rb
@@ -4,9 +4,9 @@
#
# id :integer not null, primary key
# author_id :integer not null
-# type :string(255) not null
+# type :string not null
# entity_id :integer not null
-# entity_type :string(255) not null
+# entity_type :string not null
# details :text
# created_at :datetime
# updated_at :datetime
diff --git a/app/models/broadcast_message.rb b/app/models/broadcast_message.rb
index 8a0a8a4c2a9..075ac733bfc 100644
--- a/app/models/broadcast_message.rb
+++ b/app/models/broadcast_message.rb
@@ -8,8 +8,8 @@
# ends_at :datetime
# created_at :datetime
# updated_at :datetime
-# color :string(255)
-# font :string(255)
+# color :string
+# font :string
#
class BroadcastMessage < ActiveRecord::Base
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 553cd447971..4bc3a225e2c 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
-# status :string(255)
+# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
@@ -15,19 +15,19 @@
# commit_id :integer
# commands :text
# job_id :integer
-# name :string(255)
+# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
-# stage :string(255)
+# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
-# ref :string(255)
+# ref :string
# user_id :integer
-# type :string(255)
-# target_url :string(255)
-# description :string(255)
+# type :string
+# target_url :string
+# description :string
# artifacts_file :text
# gl_project_id :integer
# artifacts_metadata :text
diff --git a/app/models/ci/commit.rb b/app/models/ci/commit.rb
index f2667e5476b..4ac4e0fb8b2 100644
--- a/app/models/ci/commit.rb
+++ b/app/models/ci/commit.rb
@@ -4,9 +4,9 @@
#
# id :integer not null, primary key
# project_id :integer
-# ref :string(255)
-# sha :string(255)
-# before_sha :string(255)
+# ref :string
+# sha :string
+# before_sha :string
# push_data :text
# created_at :datetime
# updated_at :datetime
@@ -14,6 +14,10 @@
# yaml_errors :text
# committed_at :datetime
# gl_project_id :integer
+# status :string
+# started_at :datetime
+# finished_at :datetime
+# duration :integer
#
module Ci
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 90349a07594..add59a08892 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -3,18 +3,18 @@
# Table name: ci_runners
#
# id :integer not null, primary key
-# token :string(255)
+# token :string
# created_at :datetime
# updated_at :datetime
-# description :string(255)
+# description :string
# contacted_at :datetime
# active :boolean default(TRUE), not null
# is_shared :boolean default(FALSE)
-# name :string(255)
-# version :string(255)
-# revision :string(255)
-# platform :string(255)
-# architecture :string(255)
+# name :string
+# version :string
+# revision :string
+# platform :string
+# architecture :string
#
module Ci
diff --git a/app/models/ci/trigger.rb b/app/models/ci/trigger.rb
index 2b9a457c8ab..4f3f4d79fac 100644
--- a/app/models/ci/trigger.rb
+++ b/app/models/ci/trigger.rb
@@ -3,7 +3,7 @@
# Table name: ci_triggers
#
# id :integer not null, primary key
-# token :string(255)
+# token :string
# project_id :integer
# deleted_at :datetime
# created_at :datetime
diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb
index e786bd7dd93..4229fe085a1 100644
--- a/app/models/ci/variable.rb
+++ b/app/models/ci/variable.rb
@@ -4,11 +4,11 @@
#
# id :integer not null, primary key
# project_id :integer
-# key :string(255)
+# key :string
# value :text
# encrypted_value :text
-# encrypted_value_salt :string(255)
-# encrypted_value_iv :string(255)
+# encrypted_value_salt :string
+# encrypted_value_iv :string
# gl_project_id :integer
#
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index aa56314aa16..1260c448de3 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
-# status :string(255)
+# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
@@ -15,21 +15,24 @@
# commit_id :integer
# commands :text
# job_id :integer
-# name :string(255)
+# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
-# stage :string(255)
+# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
-# ref :string(255)
+# ref :string
# user_id :integer
-# type :string(255)
-# target_url :string(255)
-# description :string(255)
+# type :string
+# target_url :string
+# description :string
# artifacts_file :text
# gl_project_id :integer
+# artifacts_metadata :text
+# erased_by_id :integer
+# erased_at :datetime
#
class CommitStatus < ActiveRecord::Base
diff --git a/app/models/concerns/issuable.rb b/app/models/concerns/issuable.rb
index d5166e81474..2e4efc4e8d8 100644
--- a/app/models/concerns/issuable.rb
+++ b/app/models/concerns/issuable.rb
@@ -35,13 +35,14 @@ module Issuable
scope :only_opened, -> { with_state(:opened) }
scope :only_reopened, -> { with_state(:reopened) }
scope :closed, -> { with_state(:closed) }
- scope :order_milestone_due_desc, -> { joins(:milestone).reorder('milestones.due_date DESC, milestones.id DESC') }
- scope :order_milestone_due_asc, -> { joins(:milestone).reorder('milestones.due_date ASC, milestones.id ASC') }
+ scope :order_milestone_due_desc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date DESC, milestones.id DESC') }
+ scope :order_milestone_due_asc, -> { outer_join_milestone.reorder('milestones.due_date IS NULL ASC, milestones.due_date ASC, milestones.id ASC') }
scope :without_label, -> { joins("LEFT OUTER JOIN label_links ON label_links.target_type = '#{name}' AND label_links.target_id = #{table_name}.id").where(label_links: { id: nil }) }
scope :join_project, -> { joins(:project) }
scope :references_project, -> { references(:project) }
scope :non_archived, -> { join_project.where(projects: { archived: false }) }
+ scope :outer_join_milestone, -> { joins("LEFT OUTER JOIN milestones ON milestones.id = #{table_name}.milestone_id") }
delegate :name,
:email,
diff --git a/app/models/deploy_key.rb b/app/models/deploy_key.rb
index 9ab663c04ad..43cf625f770 100644
--- a/app/models/deploy_key.rb
+++ b/app/models/deploy_key.rb
@@ -7,9 +7,9 @@
# created_at :datetime
# updated_at :datetime
# key :text
-# title :string(255)
-# type :string(255)
-# fingerprint :string(255)
+# title :string
+# type :string
+# fingerprint :string
# public :boolean default(FALSE), not null
#
diff --git a/app/models/email.rb b/app/models/email.rb
index b323d1edd10..eae2472f337 100644
--- a/app/models/email.rb
+++ b/app/models/email.rb
@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# user_id :integer not null
-# email :string(255) not null
+# email :string not null
# created_at :datetime
# updated_at :datetime
#
diff --git a/app/models/event.rb b/app/models/event.rb
index 897518aadc7..25c7c3e6dc7 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -3,9 +3,9 @@
# Table name: events
#
# id :integer not null, primary key
-# target_type :string(255)
+# target_type :string
# target_id :integer
-# title :string(255)
+# title :string
# data :text
# project_id :integer
# created_at :datetime
diff --git a/app/models/generic_commit_status.rb b/app/models/generic_commit_status.rb
index 97f4f03a9a5..d4afd8cbe84 100644
--- a/app/models/generic_commit_status.rb
+++ b/app/models/generic_commit_status.rb
@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer
-# status :string(255)
+# status :string
# finished_at :datetime
# trace :text
# created_at :datetime
@@ -15,21 +15,24 @@
# commit_id :integer
# commands :text
# job_id :integer
-# name :string(255)
+# name :string
# deploy :boolean default(FALSE)
# options :text
# allow_failure :boolean default(FALSE), not null
-# stage :string(255)
+# stage :string
# trigger_request_id :integer
# stage_idx :integer
# tag :boolean
-# ref :string(255)
+# ref :string
# user_id :integer
-# type :string(255)
-# target_url :string(255)
-# description :string(255)
+# type :string
+# target_url :string
+# description :string
# artifacts_file :text
# gl_project_id :integer
+# artifacts_metadata :text
+# erased_by_id :integer
+# erased_at :datetime
#
class GenericCommitStatus < CommitStatus
diff --git a/app/models/group.rb b/app/models/group.rb
index 1f8432e3320..cff76877958 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -2,16 +2,17 @@
#
# Table name: namespaces
#
-# id :integer not null, primary key
-# name :string(255) not null
-# path :string(255) not null
-# owner_id :integer
-# visibility_level :integer default(20), not null
-# created_at :datetime
-# updated_at :datetime
-# type :string(255)
-# description :string(255) default(""), not null
-# avatar :string(255)
+# id :integer not null, primary key
+# name :string not null
+# path :string not null
+# owner_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string
+# description :string default(""), not null
+# avatar :string
+# share_with_group_lock :boolean default(FALSE)
+# visibility_level :integer default(20), not null
#
require 'carrierwave/orm/activerecord'
diff --git a/app/models/hooks/project_hook.rb b/app/models/hooks/project_hook.rb
index d149511b868..2b8f34a0568 100644
--- a/app/models/hooks/project_hook.rb
+++ b/app/models/hooks/project_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
# token :string
#
diff --git a/app/models/hooks/service_hook.rb b/app/models/hooks/service_hook.rb
index f45145eeb3a..0e176de5ef8 100644
--- a/app/models/hooks/service_hook.rb
+++ b/app/models/hooks/service_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
# token :string
#
diff --git a/app/models/hooks/system_hook.rb b/app/models/hooks/system_hook.rb
index 012cc8ec005..ad508cbbcb8 100644
--- a/app/models/hooks/system_hook.rb
+++ b/app/models/hooks/system_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
# token :string
#
diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb
index 1e3b4815596..8e58c9583ab 100644
--- a/app/models/hooks/web_hook.rb
+++ b/app/models/hooks/web_hook.rb
@@ -16,6 +16,7 @@
# note_events :boolean default(FALSE), not null
# enable_ssl_verification :boolean default(TRUE)
# build_events :boolean default(FALSE), not null
+# wiki_page_events :boolean default(FALSE), not null
# token :string
#
diff --git a/app/models/identity.rb b/app/models/identity.rb
index e1915b079d4..ef4d5f99091 100644
--- a/app/models/identity.rb
+++ b/app/models/identity.rb
@@ -3,8 +3,8 @@
# Table name: identities
#
# id :integer not null, primary key
-# extern_uid :string(255)
-# provider :string(255)
+# extern_uid :string
+# provider :string
# user_id :integer
# created_at :datetime
# updated_at :datetime
diff --git a/app/models/issue.rb b/app/models/issue.rb
index ea1bfb776ee..abaa509707c 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -3,20 +3,23 @@
# Table name: issues
#
# id :integer not null, primary key
-# title :string(255)
+# title :string
# assignee_id :integer
# author_id :integer
# project_id :integer
# created_at :datetime
# updated_at :datetime
# position :integer default(0)
-# branch_name :string(255)
+# branch_name :string
# description :text
# milestone_id :integer
-# state :string(255)
+# state :string
# iid :integer
# updated_by_id :integer
# moved_to_id :integer
+# confidential :boolean default(FALSE)
+# deleted_at :datetime
+# due_date :date
#
require 'carrierwave/orm/activerecord'
diff --git a/app/models/key.rb b/app/models/key.rb
index 0282ad18139..b2b57849f8a 100644
--- a/app/models/key.rb
+++ b/app/models/key.rb
@@ -7,9 +7,9 @@
# created_at :datetime
# updated_at :datetime
# key :text
-# title :string(255)
-# type :string(255)
-# fingerprint :string(255)
+# title :string
+# type :string
+# fingerprint :string
# public :boolean default(FALSE), not null
#
diff --git a/app/models/label.rb b/app/models/label.rb
index 60bdce32952..9a22398d952 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -2,14 +2,14 @@
#
# Table name: labels
#
-# id :integer not null, primary key
-# title :string(255)
-# color :string(255)
-# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# template :boolean default(FALSE)
-# description :string(255)
+# id :integer not null, primary key
+# title :string
+# color :string
+# project_id :integer
+# created_at :datetime
+# updated_at :datetime
+# template :boolean default(FALSE)
+# description :string
#
class Label < ActiveRecord::Base
diff --git a/app/models/label_link.rb b/app/models/label_link.rb
index b94c9c777af..7b8e872b6dd 100644
--- a/app/models/label_link.rb
+++ b/app/models/label_link.rb
@@ -5,7 +5,7 @@
# id :integer not null, primary key
# label_id :integer
# target_id :integer
-# target_type :string(255)
+# target_type :string
# created_at :datetime
# updated_at :datetime
#
diff --git a/app/models/lfs_object.rb b/app/models/lfs_object.rb
index 86b1b7e2f99..927e764af92 100644
--- a/app/models/lfs_object.rb
+++ b/app/models/lfs_object.rb
@@ -3,11 +3,11 @@
# Table name: lfs_objects
#
# id :integer not null, primary key
-# oid :string(255) not null
+# oid :string not null
# size :integer not null
# created_at :datetime
# updated_at :datetime
-# file :string(255)
+# file :string
#
class LfsObject < ActiveRecord::Base
diff --git a/app/models/member.rb b/app/models/member.rb
index 60efafef211..cca82da89f1 100644
--- a/app/models/member.rb
+++ b/app/models/member.rb
@@ -5,15 +5,15 @@
# id :integer not null, primary key
# access_level :integer not null
# source_id :integer not null
-# source_type :string(255) not null
+# source_type :string not null
# user_id :integer
# notification_level :integer not null
-# type :string(255)
+# type :string
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
-# invite_email :string(255)
-# invite_token :string(255)
+# invite_email :string
+# invite_token :string
# invite_accepted_at :datetime
#
diff --git a/app/models/members/group_member.rb b/app/models/members/group_member.rb
index 9fb474a1a93..a48c1943e6f 100644
--- a/app/models/members/group_member.rb
+++ b/app/models/members/group_member.rb
@@ -5,15 +5,15 @@
# id :integer not null, primary key
# access_level :integer not null
# source_id :integer not null
-# source_type :string(255) not null
+# source_type :string not null
# user_id :integer
# notification_level :integer not null
-# type :string(255)
+# type :string
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
-# invite_email :string(255)
-# invite_token :string(255)
+# invite_email :string
+# invite_token :string
# invite_accepted_at :datetime
#
diff --git a/app/models/members/project_member.rb b/app/models/members/project_member.rb
index 07ddb02ae9d..143350a0b55 100644
--- a/app/models/members/project_member.rb
+++ b/app/models/members/project_member.rb
@@ -5,15 +5,15 @@
# id :integer not null, primary key
# access_level :integer not null
# source_id :integer not null
-# source_type :string(255) not null
+# source_type :string not null
# user_id :integer
# notification_level :integer not null
-# type :string(255)
+# type :string
# created_at :datetime
# updated_at :datetime
# created_by_id :integer
-# invite_email :string(255)
-# invite_token :string(255)
+# invite_email :string
+# invite_token :string
# invite_accepted_at :datetime
#
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index d00919c3b0c..4175e1e5fba 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -3,28 +3,29 @@
# Table name: merge_requests
#
# id :integer not null, primary key
-# target_branch :string(255) not null
-# source_branch :string(255) not null
+# target_branch :string not null
+# source_branch :string not null
# source_project_id :integer not null
# author_id :integer
# assignee_id :integer
-# title :string(255)
+# title :string
# created_at :datetime
# updated_at :datetime
# milestone_id :integer
-# state :string(255)
-# merge_status :string(255)
+# state :string
+# merge_status :string
# target_project_id :integer not null
# iid :integer
# description :text
# position :integer default(0)
# locked_at :datetime
# updated_by_id :integer
-# merge_error :string(255)
+# merge_error :string
# merge_params :text
# merge_when_build_succeeds :boolean default(FALSE), not null
# merge_user_id :integer
# merge_commit_sha :string
+# deleted_at :datetime
#
class MergeRequest < ActiveRecord::Base
diff --git a/app/models/merge_request_diff.rb b/app/models/merge_request_diff.rb
index 0580cafdd1b..8951e92a0b8 100644
--- a/app/models/merge_request_diff.rb
+++ b/app/models/merge_request_diff.rb
@@ -3,12 +3,14 @@
# Table name: merge_request_diffs
#
# id :integer not null, primary key
-# state :string(255)
+# state :string
# st_commits :text
# st_diffs :text
# merge_request_id :integer not null
# created_at :datetime
# updated_at :datetime
+# base_commit_sha :string
+# real_size :string
#
class MergeRequestDiff < ActiveRecord::Base
diff --git a/app/models/milestone.rb b/app/models/milestone.rb
index 986184dd301..5ee8a965ad8 100644
--- a/app/models/milestone.rb
+++ b/app/models/milestone.rb
@@ -3,13 +3,13 @@
# Table name: milestones
#
# id :integer not null, primary key
-# title :string(255) not null
+# title :string not null
# project_id :integer not null
# description :text
# due_date :date
# created_at :datetime
# updated_at :datetime
-# state :string(255)
+# state :string
# iid :integer
#
diff --git a/app/models/namespace.rb b/app/models/namespace.rb
index 55842df1e2d..741e912171d 100644
--- a/app/models/namespace.rb
+++ b/app/models/namespace.rb
@@ -2,15 +2,17 @@
#
# Table name: namespaces
#
-# id :integer not null, primary key
-# name :string(255) not null
-# path :string(255) not null
-# owner_id :integer
-# created_at :datetime
-# updated_at :datetime
-# type :string(255)
-# description :string(255) default(""), not null
-# avatar :string(255)
+# id :integer not null, primary key
+# name :string not null
+# path :string not null
+# owner_id :integer
+# created_at :datetime
+# updated_at :datetime
+# type :string
+# description :string default(""), not null
+# avatar :string
+# share_with_group_lock :boolean default(FALSE)
+# visibility_level :integer default(20), not null
#
class Namespace < ActiveRecord::Base
diff --git a/app/models/note.rb b/app/models/note.rb
index 71b4293d57a..deee2b9e885 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -4,14 +4,14 @@
#
# id :integer not null, primary key
# note :text
-# noteable_type :string(255)
+# noteable_type :string
# author_id :integer
# created_at :datetime
# updated_at :datetime
# project_id :integer
-# attachment :string(255)
-# line_code :string(255)
-# commit_id :string(255)
+# attachment :string
+# line_code :string
+# commit_id :string
# noteable_id :integer
# system :boolean default(FALSE), not null
# st_diff :text
diff --git a/app/models/notification_setting.rb b/app/models/notification_setting.rb
index 5001738f411..846773752a6 100644
--- a/app/models/notification_setting.rb
+++ b/app/models/notification_setting.rb
@@ -1,3 +1,16 @@
+# == Schema Information
+#
+# Table name: notification_settings
+#
+# id :integer not null, primary key
+# user_id :integer not null
+# source_id :integer not null
+# source_type :string not null
+# level :integer default(0), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class NotificationSetting < ActiveRecord::Base
enum level: { disabled: 0, participating: 1, watch: 2, global: 3, mention: 4 }
diff --git a/app/models/personal_snippet.rb b/app/models/personal_snippet.rb
index 452f3913eef..1d5f4c50254 100644
--- a/app/models/personal_snippet.rb
+++ b/app/models/personal_snippet.rb
@@ -3,14 +3,14 @@
# Table name: snippets
#
# id :integer not null, primary key
-# title :string(255)
+# title :string
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime
# updated_at :datetime
-# file_name :string(255)
-# type :string(255)
+# file_name :string
+# type :string
# visibility_level :integer default(0), not null
#
diff --git a/app/models/project.rb b/app/models/project.rb
index af62e8ecd90..dfd1e54ecf7 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2,41 +2,46 @@
#
# Table name: projects
#
-# id :integer not null, primary key
-# name :string(255)
-# path :string(255)
-# description :text
-# created_at :datetime
-# updated_at :datetime
-# creator_id :integer
-# issues_enabled :boolean default(TRUE), not null
-# wall_enabled :boolean default(TRUE), not null
-# merge_requests_enabled :boolean default(TRUE), not null
-# wiki_enabled :boolean default(TRUE), not null
-# namespace_id :integer
-# issues_tracker :string(255) default("gitlab"), not null
-# issues_tracker_id :string(255)
-# snippets_enabled :boolean default(TRUE), not null
-# last_activity_at :datetime
-# import_url :string(255)
-# visibility_level :integer default(0), not null
-# archived :boolean default(FALSE), not null
-# avatar :string(255)
-# import_status :string(255)
-# repository_size :float default(0.0)
-# star_count :integer default(0), not null
-# import_type :string(255)
-# import_source :string(255)
-# commit_count :integer default(0)
-# import_error :text
-# ci_id :integer
-# builds_enabled :boolean default(TRUE), not null
-# shared_runners_enabled :boolean default(TRUE), not null
-# runners_token :string
-# build_coverage_regex :string
-# build_allow_git_fetch :boolean default(TRUE), not null
-# build_timeout :integer default(3600), not null
-# pending_delete :boolean
+# id :integer not null, primary key
+# name :string
+# path :string
+# description :text
+# created_at :datetime
+# updated_at :datetime
+# creator_id :integer
+# issues_enabled :boolean default(TRUE), not null
+# wall_enabled :boolean default(TRUE), not null
+# merge_requests_enabled :boolean default(TRUE), not null
+# wiki_enabled :boolean default(TRUE), not null
+# namespace_id :integer
+# issues_tracker :string default("gitlab"), not null
+# issues_tracker_id :string
+# snippets_enabled :boolean default(TRUE), not null
+# last_activity_at :datetime
+# import_url :string
+# visibility_level :integer default(0), not null
+# archived :boolean default(FALSE), not null
+# avatar :string
+# import_status :string
+# repository_size :float default(0.0)
+# star_count :integer default(0), not null
+# import_type :string
+# import_source :string
+# commit_count :integer default(0)
+# import_error :text
+# ci_id :integer
+# builds_enabled :boolean default(TRUE), not null
+# shared_runners_enabled :boolean default(TRUE), not null
+# runners_token :string
+# build_coverage_regex :string
+# build_allow_git_fetch :boolean default(TRUE), not null
+# build_timeout :integer default(3600), not null
+# pending_delete :boolean default(FALSE)
+# public_builds :boolean default(TRUE), not null
+# main_language :string
+# pushes_since_gc :integer default(0)
+# last_repository_check_failed :boolean
+# last_repository_check_at :datetime
#
require 'carrierwave/orm/activerecord'
@@ -1034,4 +1039,11 @@ class Project < ActiveRecord::Base
def wiki
@wiki ||= ProjectWiki.new(self, self.owner)
end
+
+ def schedule_delete!(user_id, params)
+ # Queue this task for after the commit, so once we mark pending_delete it will run
+ run_after_commit { ProjectDestroyWorker.perform_async(id, user_id, params) }
+
+ update_attribute(:pending_delete, true)
+ end
end
diff --git a/app/models/project_group_link.rb b/app/models/project_group_link.rb
index e52a6bd7c84..66f5a609bf5 100644
--- a/app/models/project_group_link.rb
+++ b/app/models/project_group_link.rb
@@ -1,3 +1,15 @@
+# == Schema Information
+#
+# Table name: project_group_links
+#
+# id :integer not null, primary key
+# project_id :integer not null
+# group_id :integer not null
+# created_at :datetime
+# updated_at :datetime
+# group_access :integer default(30), not null
+#
+
class ProjectGroupLink < ActiveRecord::Base
GUEST = 10
REPORTER = 20
diff --git a/app/models/project_import_data.rb b/app/models/project_import_data.rb
index 2c0ae312f1b..7830f764ed3 100644
--- a/app/models/project_import_data.rb
+++ b/app/models/project_import_data.rb
@@ -2,9 +2,12 @@
#
# Table name: project_import_data
#
-# id :integer not null, primary key
-# project_id :integer
-# data :text
+# id :integer not null, primary key
+# project_id :integer
+# data :text
+# encrypted_credentials :text
+# encrypted_credentials_iv :string
+# encrypted_credentials_salt :string
#
require 'carrierwave/orm/activerecord'
diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb
index 792ad804575..368485a060a 100644
--- a/app/models/project_services/asana_service.rb
+++ b/app/models/project_services/asana_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
require 'asana'
diff --git a/app/models/project_services/assembla_service.rb b/app/models/project_services/assembla_service.rb
index 29d841faed8..ffb7455b014 100644
--- a/app/models/project_services/assembla_service.rb
+++ b/app/models/project_services/assembla_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class AssemblaService < Service
diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb
index 060062aaf7a..c36ee95e378 100644
--- a/app/models/project_services/bamboo_service.rb
+++ b/app/models/project_services/bamboo_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class BambooService < CiService
diff --git a/app/models/project_services/buildkite_service.rb b/app/models/project_services/buildkite_service.rb
index 861cc974ec4..f9f4897a065 100644
--- a/app/models/project_services/buildkite_service.rb
+++ b/app/models/project_services/buildkite_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
require "addressable/uri"
diff --git a/app/models/project_services/builds_email_service.rb b/app/models/project_services/builds_email_service.rb
index 6ab6d7417b7..20cdfcaffb2 100644
--- a/app/models/project_services/builds_email_service.rb
+++ b/app/models/project_services/builds_email_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class BuildsEmailService < Service
diff --git a/app/models/project_services/campfire_service.rb b/app/models/project_services/campfire_service.rb
index 6e8f0842524..28c969fe57f 100644
--- a/app/models/project_services/campfire_service.rb
+++ b/app/models/project_services/campfire_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class CampfireService < Service
diff --git a/app/models/project_services/ci_service.rb b/app/models/project_services/ci_service.rb
index d9f0849d147..9bc8f982da6 100644
--- a/app/models/project_services/ci_service.rb
+++ b/app/models/project_services/ci_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
# Base class for CI services
diff --git a/app/models/project_services/custom_issue_tracker_service.rb b/app/models/project_services/custom_issue_tracker_service.rb
index 88a3e9218cb..4d1319eb6f8 100644
--- a/app/models/project_services/custom_issue_tracker_service.rb
+++ b/app/models/project_services/custom_issue_tracker_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class CustomIssueTrackerService < IssueTrackerService
diff --git a/app/models/project_services/drone_ci_service.rb b/app/models/project_services/drone_ci_service.rb
index b4724bb647e..d8e00e018cc 100644
--- a/app/models/project_services/drone_ci_service.rb
+++ b/app/models/project_services/drone_ci_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class DroneCiService < CiService
diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb
index b831577cd97..2dbd29062df 100644
--- a/app/models/project_services/emails_on_push_service.rb
+++ b/app/models/project_services/emails_on_push_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class EmailsOnPushService < Service
diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb
index b402b68665a..5469049bb5e 100644
--- a/app/models/project_services/external_wiki_service.rb
+++ b/app/models/project_services/external_wiki_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class ExternalWikiService < Service
diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb
index 8605ce66e48..3dc1e0fbe8b 100644
--- a/app/models/project_services/flowdock_service.rb
+++ b/app/models/project_services/flowdock_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
require "flowdock-git-hook"
diff --git a/app/models/project_services/gemnasium_service.rb b/app/models/project_services/gemnasium_service.rb
index 61babe9cfe5..b4c311cf664 100644
--- a/app/models/project_services/gemnasium_service.rb
+++ b/app/models/project_services/gemnasium_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
require "gemnasium/gitlab_service"
diff --git a/app/models/project_services/gitlab_ci_service.rb b/app/models/project_services/gitlab_ci_service.rb
index 33f0d7ea01a..a92f7226083 100644
--- a/app/models/project_services/gitlab_ci_service.rb
+++ b/app/models/project_services/gitlab_ci_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
# TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed
diff --git a/app/models/project_services/gitlab_issue_tracker_service.rb b/app/models/project_services/gitlab_issue_tracker_service.rb
index eaa5654b9c6..1adaeeb3b2b 100644
--- a/app/models/project_services/gitlab_issue_tracker_service.rb
+++ b/app/models/project_services/gitlab_issue_tracker_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class GitlabIssueTrackerService < IssueTrackerService
diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb
index 064ef8e8674..f9ddf588722 100644
--- a/app/models/project_services/hipchat_service.rb
+++ b/app/models/project_services/hipchat_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class HipchatService < Service
diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb
index 04c714bfaad..b9a592d7096 100644
--- a/app/models/project_services/irker_service.rb
+++ b/app/models/project_services/irker_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
require 'uri'
diff --git a/app/models/project_services/issue_tracker_service.rb b/app/models/project_services/issue_tracker_service.rb
index c5501e06411..98a3a7c6b86 100644
--- a/app/models/project_services/issue_tracker_service.rb
+++ b/app/models/project_services/issue_tracker_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class IssueTrackerService < Service
diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb
index b4418ba9284..ba68658f0bd 100644
--- a/app/models/project_services/jira_service.rb
+++ b/app/models/project_services/jira_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class JiraService < IssueTrackerService
diff --git a/app/models/project_services/pivotaltracker_service.rb b/app/models/project_services/pivotaltracker_service.rb
index c9a890c7e3f..acaa0c39365 100644
--- a/app/models/project_services/pivotaltracker_service.rb
+++ b/app/models/project_services/pivotaltracker_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class PivotaltrackerService < Service
diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb
index e76d9eca2ab..a640c8cb440 100644
--- a/app/models/project_services/pushover_service.rb
+++ b/app/models/project_services/pushover_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class PushoverService < Service
diff --git a/app/models/project_services/redmine_service.rb b/app/models/project_services/redmine_service.rb
index de974354c77..e2137e92c62 100644
--- a/app/models/project_services/redmine_service.rb
+++ b/app/models/project_services/redmine_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class RedmineService < IssueTrackerService
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
index 7092b757549..83ffa53a407 100644
--- a/app/models/project_services/slack_service.rb
+++ b/app/models/project_services/slack_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class SlackService < Service
diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb
index 8dceee5e2c5..4015da31509 100644
--- a/app/models/project_services/teamcity_service.rb
+++ b/app/models/project_services/teamcity_service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
class TeamcityService < CiService
diff --git a/app/models/project_snippet.rb b/app/models/project_snippet.rb
index d48f0546159..b4b2807eba4 100644
--- a/app/models/project_snippet.rb
+++ b/app/models/project_snippet.rb
@@ -3,14 +3,14 @@
# Table name: snippets
#
# id :integer not null, primary key
-# title :string(255)
+# title :string
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime
# updated_at :datetime
-# file_name :string(255)
-# type :string(255)
+# file_name :string
+# type :string
# visibility_level :integer default(0), not null
#
diff --git a/app/models/protected_branch.rb b/app/models/protected_branch.rb
index 8ebd790a89e..3d2052c892c 100644
--- a/app/models/protected_branch.rb
+++ b/app/models/protected_branch.rb
@@ -4,7 +4,7 @@
#
# id :integer not null, primary key
# project_id :integer not null
-# name :string(255) not null
+# name :string not null
# created_at :datetime
# updated_at :datetime
# developers_can_push :boolean default(FALSE), not null
diff --git a/app/models/release.rb b/app/models/release.rb
index 89f70278af5..dc700d1ea5a 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -3,7 +3,7 @@
# Table name: releases
#
# id :integer not null, primary key
-# tag :string(255)
+# tag :string
# description :text
# project_id :integer
# created_at :datetime
diff --git a/app/models/security_event.rb b/app/models/security_event.rb
index 68c00adad59..0bee03974f1 100644
--- a/app/models/security_event.rb
+++ b/app/models/security_event.rb
@@ -4,9 +4,9 @@
#
# id :integer not null, primary key
# author_id :integer not null
-# type :string(255) not null
+# type :string not null
# entity_id :integer not null
-# entity_type :string(255) not null
+# entity_type :string not null
# details :text
# created_at :datetime
# updated_at :datetime
diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb
index 77115597d71..99279a2e083 100644
--- a/app/models/sent_notification.rb
+++ b/app/models/sent_notification.rb
@@ -5,11 +5,11 @@
# id :integer not null, primary key
# project_id :integer
# noteable_id :integer
-# noteable_type :string(255)
+# noteable_type :string
# recipient_id :integer
-# commit_id :string(255)
-# line_code :string(255)
-# reply_key :string(255) not null
+# commit_id :string
+# reply_key :string not null
+# line_code :string
#
class SentNotification < ActiveRecord::Base
diff --git a/app/models/service.rb b/app/models/service.rb
index 2645b8321d7..bf16a545307 100644
--- a/app/models/service.rb
+++ b/app/models/service.rb
@@ -3,12 +3,12 @@
# Table name: services
#
# id :integer not null, primary key
-# type :string(255)
-# title :string(255)
+# type :string
+# title :string
# project_id :integer
-# created_at :datetime
-# updated_at :datetime
-# active :boolean default(FALSE), not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# active :boolean not null
# properties :text
# template :boolean default(FALSE)
# push_events :boolean default(TRUE)
@@ -17,6 +17,9 @@
# tag_push_events :boolean default(TRUE)
# note_events :boolean default(TRUE), not null
# build_events :boolean default(FALSE), not null
+# category :string default("common"), not null
+# default :boolean default(FALSE)
+# wiki_page_events :boolean default(TRUE)
#
# To add new service you should build a class inherited from Service
diff --git a/app/models/snippet.rb b/app/models/snippet.rb
index 0fd08061925..2f905a90942 100644
--- a/app/models/snippet.rb
+++ b/app/models/snippet.rb
@@ -3,14 +3,14 @@
# Table name: snippets
#
# id :integer not null, primary key
-# title :string(255)
+# title :string
# content :text
# author_id :integer not null
# project_id :integer
# created_at :datetime
# updated_at :datetime
-# file_name :string(255)
-# type :string(255)
+# file_name :string
+# type :string
# visibility_level :integer default(0), not null
#
diff --git a/app/models/spam_log.rb b/app/models/spam_log.rb
index 12df68ef83b..f49eb7d88e2 100644
--- a/app/models/spam_log.rb
+++ b/app/models/spam_log.rb
@@ -1,3 +1,20 @@
+# == Schema Information
+#
+# Table name: spam_logs
+#
+# id :integer not null, primary key
+# user_id :integer
+# source_ip :string
+# user_agent :string
+# via_api :boolean
+# project_id :integer
+# noteable_type :string
+# title :string
+# description :text
+# created_at :datetime not null
+# updated_at :datetime not null
+#
+
class SpamLog < ActiveRecord::Base
belongs_to :user
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
index dd800ce110f..242faa7d32e 100644
--- a/app/models/subscription.rb
+++ b/app/models/subscription.rb
@@ -5,7 +5,7 @@
# id :integer not null, primary key
# user_id :integer
# subscribable_id :integer
-# subscribable_type :string(255)
+# subscribable_type :string
# subscribed :boolean
# created_at :datetime
# updated_at :datetime
diff --git a/app/models/user.rb b/app/models/user.rb
index ab48f8f1960..959b1f93758 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -3,55 +3,55 @@
# Table name: users
#
# id :integer not null, primary key
-# email :string(255) default(""), not null
-# encrypted_password :string(255) default(""), not null
-# reset_password_token :string(255)
+# email :string default(""), not null
+# encrypted_password :string default(""), not null
+# reset_password_token :string
# reset_password_sent_at :datetime
# remember_created_at :datetime
# sign_in_count :integer default(0)
# current_sign_in_at :datetime
# last_sign_in_at :datetime
-# current_sign_in_ip :string(255)
-# last_sign_in_ip :string(255)
+# current_sign_in_ip :string
+# last_sign_in_ip :string
# created_at :datetime
# updated_at :datetime
-# name :string(255)
+# name :string
# admin :boolean default(FALSE), not null
# projects_limit :integer default(10)
-# skype :string(255) default(""), not null
-# linkedin :string(255) default(""), not null
-# twitter :string(255) default(""), not null
-# authentication_token :string(255)
+# skype :string default(""), not null
+# linkedin :string default(""), not null
+# twitter :string default(""), not null
+# authentication_token :string
# theme_id :integer default(1), not null
-# bio :string(255)
+# bio :string
# failed_attempts :integer default(0)
# locked_at :datetime
-# username :string(255)
+# username :string
# can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null
-# state :string(255)
+# state :string
# color_scheme_id :integer default(1), not null
# notification_level :integer default(1), not null
# password_expires_at :datetime
# created_by_id :integer
# last_credential_check_at :datetime
-# avatar :string(255)
-# confirmation_token :string(255)
+# avatar :string
+# confirmation_token :string
# confirmed_at :datetime
# confirmation_sent_at :datetime
-# unconfirmed_email :string(255)
+# unconfirmed_email :string
# hide_no_ssh_key :boolean default(FALSE)
-# website_url :string(255) default(""), not null
-# notification_email :string(255)
+# website_url :string default(""), not null
+# notification_email :string
# hide_no_password :boolean default(FALSE)
# password_automatically_set :boolean default(FALSE)
-# location :string(255)
-# encrypted_otp_secret :string(255)
-# encrypted_otp_secret_iv :string(255)
-# encrypted_otp_secret_salt :string(255)
+# location :string
+# encrypted_otp_secret :string
+# encrypted_otp_secret_iv :string
+# encrypted_otp_secret_salt :string
# otp_required_for_login :boolean default(FALSE), not null
# otp_backup_codes :text
-# public_email :string(255) default(""), not null
+# public_email :string default(""), not null
# dashboard :integer default(0)
# project_view :integer default(0)
# consumed_timestep :integer
@@ -59,7 +59,8 @@
# hide_project_limit :boolean default(FALSE)
# unlock_token :string
# otp_grace_period_started_at :datetime
-# external :boolean default(FALSE)
+# ldap_email :boolean default(FALSE), not null
+# external :boolean default(FALSE)
#
require 'carrierwave/orm/activerecord'
diff --git a/app/services/merge_requests/build_service.rb b/app/services/merge_requests/build_service.rb
index 3544752d47a..cd4230aa5e4 100644
--- a/app/services/merge_requests/build_service.rb
+++ b/app/services/merge_requests/build_service.rb
@@ -41,21 +41,45 @@ module MergeRequests
merge_request.can_be_created = false
end
+ set_title_and_description(merge_request)
+ end
+
+ private
+
+ # When your branch name starts with an iid followed by a dash this pattern will be
+ # interpreted as the user wants to close that issue on this project.
+ #
+ # For example:
+ # - Issue 112 exists, title: Emoji don't show up in commit title
+ # - Source branch is: 112-fix-mep-mep
+ #
+ # Will lead to:
+ # - Appending `Closes #112` to the description
+ # - Setting the title as 'Resolves "Emoji don't show up in commit title"' if there is
+ # more than one commit in the MR
+ #
+ def set_title_and_description(merge_request)
+ if match = merge_request.source_branch.match(/\A(\d+)-/)
+ iid = match[1]
+ end
+
commits = merge_request.compare_commits
if commits && commits.count == 1
commit = commits.first
merge_request.title = commit.title
merge_request.description ||= commit.description.try(:strip)
+ elsif iid && (issue = merge_request.target_project.get_issue(iid)) && !issue.try(:confidential?)
+ case issue
+ when Issue
+ merge_request.title = "Resolve \"#{issue.title}\""
+ when ExternalIssue
+ merge_request.title = "Resolve #{issue.title}"
+ end
else
merge_request.title = merge_request.source_branch.titleize.humanize
end
- # When your branch name starts with an iid followed by a dash this pattern will
- # be interpreted as the use wants to close that issue on this project
- # Pattern example: 112-fix-mep-mep
- # Will lead to appending `Closes #112` to the description
- if match = merge_request.source_branch.match(/\A(\d+)-/)
- iid = match[1]
+ if iid
closes_issue = "Closes ##{iid}"
if merge_request.description.present?
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index df5054f08d7..19aab999e00 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -7,9 +7,7 @@ module Projects
DELETED_FLAG = '+deleted'
def pending_delete!
- project.update_attribute(:pending_delete, true)
-
- ProjectDestroyWorker.perform_in(1.minute, project.id, current_user.id, params)
+ project.schedule_delete!(current_user.id, params)
end
def execute
diff --git a/app/views/groups/activity.html.haml b/app/views/groups/activity.html.haml
index f73e1d9e865..aaad265b3ee 100644
--- a/app/views/groups/activity.html.haml
+++ b/app/views/groups/activity.html.haml
@@ -3,7 +3,6 @@
= auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity")
- page_title "Activity"
-- header_title group_title(@group, "Activity", activity_group_path(@group))
%section.activities
= render 'activities'
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index a698cbbe9db..92cd4c553d0 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -1,5 +1,3 @@
-- header_title group_title(@group, "Settings", edit_group_path(@group))
-
.panel.panel-default.prepend-top-default
.panel-heading
Group settings
diff --git a/app/views/groups/group_members/index.html.haml b/app/views/groups/group_members/index.html.haml
index 6b7fd5746d6..0eb6bbd4420 100644
--- a/app/views/groups/group_members/index.html.haml
+++ b/app/views/groups/group_members/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Members"
-- header_title group_title(@group, "Members", group_group_members_path(@group))
.group-members-page.prepend-top-default
- if current_user && current_user.can?(:admin_group_member, @group)
diff --git a/app/views/groups/issues.html.haml b/app/views/groups/issues.html.haml
index df6db8c23d3..4434f1cbd35 100644
--- a/app/views/groups/issues.html.haml
+++ b/app/views/groups/issues.html.haml
@@ -1,5 +1,4 @@
- page_title "Issues"
-- header_title group_title(@group, "Issues", issues_group_path(@group))
= content_for :meta_tags do
- if current_user
= auto_discovery_link_tag(:atom, issues_group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} issues")
diff --git a/app/views/groups/merge_requests.html.haml b/app/views/groups/merge_requests.html.haml
index 0cc2305b7d7..e6953d94531 100644
--- a/app/views/groups/merge_requests.html.haml
+++ b/app/views/groups/merge_requests.html.haml
@@ -1,5 +1,4 @@
- page_title "Merge Requests"
-- header_title group_title(@group, "Merge Requests", merge_requests_group_path(@group))
.top-area
= render 'shared/issuable/nav', type: :merge_requests
diff --git a/app/views/groups/milestones/index.html.haml b/app/views/groups/milestones/index.html.haml
index ddb8be0d496..121a7de3ad7 100644
--- a/app/views/groups/milestones/index.html.haml
+++ b/app/views/groups/milestones/index.html.haml
@@ -1,5 +1,4 @@
- page_title "Milestones"
-- header_title group_title(@group, "Milestones", group_milestones_path(@group))
.top-area
= render 'shared/milestones_filter'
diff --git a/app/views/groups/projects.html.haml b/app/views/groups/projects.html.haml
index dd75766121e..c2f2d9912f7 100644
--- a/app/views/groups/projects.html.haml
+++ b/app/views/groups/projects.html.haml
@@ -1,5 +1,4 @@
- page_title "Projects"
-- header_title group_title(@group, "Projects", projects_group_path(@group))
.panel.panel-default.prepend-top-default
.panel-heading
diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml
index 3d16ecb097a..77c297255b8 100644
--- a/app/views/groups/show.html.haml
+++ b/app/views/groups/show.html.haml
@@ -4,28 +4,20 @@
- if current_user
= auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity")
-.cover-block
- .cover-controls
- - if @group && can?(current_user, :admin_group, @group)
- = link_to icon('pencil'), edit_group_path(@group), class: 'btn'
- - if current_user
- = link_to icon('rss'), group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn'
-
- .avatar-holder
+.cover-block.groups-cover-block
+ .container-fluid.container-limited
= link_to group_icon(@group), target: '_blank' do
- = image_tag group_icon(@group), class: "avatar group-avatar s90"
- .cover-title
- %h1
- = @group.name
- %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
- = visibility_level_icon(@group.visibility_level, fw: false)
-
- .cover-desc.username
- @#{@group.path}
-
- - if @group.description.present?
- .cover-desc.description
- = markdown(@group.description, pipeline: :description)
+ = image_tag group_icon(@group), class: "avatar group-avatar s70"
+ .group-info
+ .cover-title
+ %h1
+ @#{@group.path}
+ %span.visibility-icon.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
+ = visibility_level_icon(@group.visibility_level, fw: false)
+
+ - if @group.description.present?
+ .cover-desc.description
+ = markdown(@group.description, pipeline: :description)
%div{ class: container_class }
.top-area
diff --git a/app/views/layouts/_page.html.haml b/app/views/layouts/_page.html.haml
index ad8a2e1e6c7..3c3bc41bf0e 100644
--- a/app/views/layouts/_page.html.haml
+++ b/app/views/layouts/_page.html.haml
@@ -26,7 +26,7 @@
.layout-nav
.container-fluid
= render "layouts/nav/#{nav}"
- .content-wrapper
+ .content-wrapper{ class: ('page-with-layout-nav' if defined?(nav) && nav) }
= render "layouts/flash"
= yield :flash_message
%div{ class: (container_class unless @no_container) }
diff --git a/app/views/layouts/group.html.haml b/app/views/layouts/group.html.haml
index 2e483b7148d..f06acc98ca1 100644
--- a/app/views/layouts/group.html.haml
+++ b/app/views/layouts/group.html.haml
@@ -1,6 +1,6 @@
- page_title @group.name
- page_description @group.description unless page_description
- header_title group_title(@group) unless header_title
-- sidebar "group" unless sidebar
+- nav "group"
= render template: "layouts/application"
diff --git a/app/views/layouts/group_settings.html.haml b/app/views/layouts/group_settings.html.haml
index a1a1fc2f858..66b115e36de 100644
--- a/app/views/layouts/group_settings.html.haml
+++ b/app/views/layouts/group_settings.html.haml
@@ -1,5 +1,4 @@
- page_title "Settings"
-- header_title group_title(@group, "Settings", edit_group_path(@group))
-- sidebar "group_settings"
+- nav "group"
= render template: "layouts/group"
diff --git a/app/views/layouts/header/_default.html.haml b/app/views/layouts/header/_default.html.haml
index cde9e1b918b..86930d4eaaf 100644
--- a/app/views/layouts/header/_default.html.haml
+++ b/app/views/layouts/header/_default.html.haml
@@ -23,6 +23,7 @@
= icon('wrench fw')
%li
= link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = icon('bell fw')
%span.badge.todos-pending-count
= todos_pending_count
- if current_user.can_create_project?
diff --git a/app/views/layouts/nav/_dashboard.html.haml b/app/views/layouts/nav/_dashboard.html.haml
index ca49c313ff7..fad4224e945 100644
--- a/app/views/layouts/nav/_dashboard.html.haml
+++ b/app/views/layouts/nav/_dashboard.html.haml
@@ -15,12 +15,12 @@
= icon('dashboard fw')
%span
Activity
- = nav_link(controller: :groups) do
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to dashboard_groups_path, title: 'Groups' do
= icon('group fw')
%span
Groups
- = nav_link(controller: :milestones) do
+ = nav_link(controller: 'dashboard/milestones') do
= link_to dashboard_milestones_path, title: 'Milestones' do
= icon('clock-o fw')
%span
diff --git a/app/views/layouts/nav/_explore.html.haml b/app/views/layouts/nav/_explore.html.haml
index f08c5edf99c..3b40006a0cc 100644
--- a/app/views/layouts/nav/_explore.html.haml
+++ b/app/views/layouts/nav/_explore.html.haml
@@ -4,7 +4,7 @@
= icon('bookmark fw')
%span
Projects
- = nav_link(controller: :groups) do
+ = nav_link(controller: [:groups, 'groups/milestones', 'groups/group_members']) do
= link_to explore_groups_path, title: 'Groups' do
= icon('group fw')
%span
diff --git a/app/views/layouts/nav/_group.html.haml b/app/views/layouts/nav/_group.html.haml
index 55940741dc0..3438005863a 100644
--- a/app/views/layouts/nav/_group.html.haml
+++ b/app/views/layouts/nav/_group.html.haml
@@ -1,12 +1,6 @@
-%ul.nav.nav-sidebar
- = nav_link do
- = link_to root_path, title: 'Go to dashboard', class: 'back-link' do
- = icon('caret-square-o-left fw')
- %span
- Go to dashboard
-
- %li.separate-item
+= render 'layouts/nav/group_settings'
+%ul.nav-links
= nav_link(path: 'groups#show', html_options: {class: 'home'}) do
= link_to group_path(@group), title: 'Home' do
= icon('group fw')
@@ -28,22 +22,16 @@
%span
Issues
- issues = IssuesFinder.new(current_user, group_id: @group.id, state: 'opened').execute
- %span.count= number_with_delimiter(issues.count)
+ %span.badge.count= number_with_delimiter(issues.count)
= nav_link(path: 'groups#merge_requests') do
= link_to merge_requests_group_path(@group), title: 'Merge Requests' do
= icon('tasks fw')
%span
Merge Requests
- merge_requests = MergeRequestsFinder.new(current_user, group_id: @group.id, state: 'opened').execute
- %span.count= number_with_delimiter(merge_requests.count)
+ %span.badge.count= number_with_delimiter(merge_requests.count)
= nav_link(controller: [:group_members]) do
= link_to group_group_members_path(@group), title: 'Members' do
= icon('users fw')
%span
Members
- - if can?(current_user, :admin_group, @group)
- = nav_link(html_options: { class: "separate-item" }) do
- = link_to edit_group_path(@group), title: 'Settings' do
- = icon ('cogs fw')
- %span
- Settings
diff --git a/app/views/layouts/nav/_group_settings.html.haml b/app/views/layouts/nav/_group_settings.html.haml
index 56a92fe9103..e391ec7f2b7 100644
--- a/app/views/layouts/nav/_group_settings.html.haml
+++ b/app/views/layouts/nav/_group_settings.html.haml
@@ -1,20 +1,20 @@
-%ul.nav.nav-sidebar
- = nav_link do
- = link_to group_path(@group), title: 'Go to group', class: 'back-link' do
- = icon('caret-square-o-left fw')
- %span
- Go to group
-
- %li.separate-item
-
- %ul.sidebar-subnav
- = nav_link(path: 'groups#edit') do
- = link_to edit_group_path(@group), title: 'Group Settings' do
- = icon ('pencil-square-o fw')
- %span
- Group Settings
- = nav_link(path: 'groups#projects') do
- = link_to projects_group_path(@group), title: 'Projects' do
- = icon('folder fw')
- %span
- Projects
+- if current_user
+ - if access = @group.users.find_by(id: current_user.id)
+ .controls
+ %span.dropdown.group-settings-dropdown
+ %a.dropdown-new.btn.btn-default#group-settings-button{href: '#', 'data-toggle' => 'dropdown'}
+ = icon('cog')
+ = icon('caret-down')
+ %ul.dropdown-menu.dropdown-menu-align-right
+ - if can?(current_user, :admin_group, @group)
+ = nav_link(path: 'groups#projects') do
+ = link_to projects_group_path(@group), title: 'Projects' do
+ Projects
+ %li.divider
+ %li
+ = link_to edit_group_path(@group) do
+ Edit Group
+ %li
+ = link_to leave_group_group_members_path(@group),
+ data: { confirm: leave_group_message(@group.name) }, method: :delete, title: 'Leave group' do
+ Leave Group
diff --git a/db/schema.rb b/db/schema.rb
index 04aee737e4c..7683aad968c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -70,16 +70,16 @@ ActiveRecord::Schema.define(version: 20160421130527) do
t.string "recaptcha_site_key"
t.string "recaptcha_private_key"
t.integer "metrics_port", default: 8089
+ t.boolean "akismet_enabled", default: false
+ t.string "akismet_api_key"
t.integer "metrics_sample_interval", default: 15
t.boolean "sentry_enabled", default: false
t.string "sentry_dsn"
- t.boolean "akismet_enabled", default: false
- t.string "akismet_api_key"
t.boolean "email_author_in_body", default: false
t.integer "default_group_visibility"
t.boolean "repository_checks_enabled", default: false
- t.integer "metrics_packet_size", default: 1
t.text "shared_runners_text"
+ t.integer "metrics_packet_size", default: 1
end
create_table "audit_events", force: :cascade do |t|
@@ -426,10 +426,10 @@ ActiveRecord::Schema.define(version: 20160421130527) do
t.string "state"
t.integer "iid"
t.integer "updated_by_id"
- t.integer "moved_to_id"
t.boolean "confidential", default: false
t.datetime "deleted_at"
t.date "due_date"
+ t.integer "moved_to_id"
end
add_index "issues", ["assignee_id"], name: "index_issues_on_assignee_id", using: :btree
@@ -716,8 +716,8 @@ ActiveRecord::Schema.define(version: 20160421130527) do
t.integer "project_id"
t.text "data"
t.text "encrypted_credentials"
- t.text "encrypted_credentials_iv"
- t.text "encrypted_credentials_salt"
+ t.string "encrypted_credentials_iv"
+ t.string "encrypted_credentials_salt"
end
create_table "projects", force: :cascade do |t|
@@ -816,9 +816,9 @@ ActiveRecord::Schema.define(version: 20160421130527) do
t.string "type"
t.string "title"
t.integer "project_id"
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.boolean "active", null: false
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.boolean "active", default: false, null: false
t.text "properties"
t.boolean "template", default: false
t.boolean "push_events", default: true
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index 5fb086b1dd9..ca52a483a59 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -41,9 +41,9 @@ GitLab Runner then executes build scripts as `gitlab-runner` user.
--description "My Runner"
```
-2. Install Docker on server.
+2. Install Docker Engine on server.
- For more information how to install Docker on different systems checkout the [Supported installations](https://docs.docker.com/installation/).
+ For more information how to install Docker Engine on different systems checkout the [Supported installations](https://docs.docker.com/engine/installation/).
3. Add `gitlab-runner` user to `docker` group:
@@ -151,4 +151,4 @@ In order to do that follow the steps:
An example project using this approach can be found here: https://gitlab.com/gitlab-examples/docker.
[docker-in-docker]: https://blog.docker.com/2013/09/docker-can-now-run-within-docker/
-[docker-cap]: https://docs.docker.com/reference/run/#runtime-privilege-and-linux-capabilities
+[docker-cap]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md
index 84212fb3c61..56ac2195c49 100644
--- a/doc/ci/docker/using_docker_images.md
+++ b/doc/ci/docker/using_docker_images.md
@@ -64,7 +64,7 @@ You can see some widely used services examples in the relevant documentation of
### How is service linked to the build
To better understand how the container linking works, read
-[Linking containers together](https://docs.docker.com/userguide/dockerlinks/).
+[Linking containers together][linking-containers].
To summarize, if you add `mysql` as service to your application, the image will
then be used to create a container that is linked to the build container.
@@ -273,7 +273,7 @@ creation.
[Docker Fundamentals]: https://docs.docker.com/engine/understanding-docker/
[hub]: https://hub.docker.com/
[linking-containers]: https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/
-[tutum/wordpress]: https://registry.hub.docker.com/u/tutum/wordpress/
-[postgres-hub]: https://registry.hub.docker.com/u/library/postgres/
-[mysql-hub]: https://registry.hub.docker.com/u/library/mysql/
+[tutum/wordpress]: https://hub.docker.com/r/tutum/wordpress/
+[postgres-hub]: https://hub.docker.com/r/_/postgres/
+[mysql-hub]: https://hub.docker.com/r/_/mysql/
[runner-priv-reg]: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/configuration/advanced-configuration.md#using-a-private-docker-registry
diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md
index cc059dc4376..61294be599d 100644
--- a/doc/ci/examples/README.md
+++ b/doc/ci/examples/README.md
@@ -4,12 +4,12 @@
- [Test and deploy a Ruby application to Heroku](test-and-deploy-ruby-application-to-heroku.md)
- [Test and deploy a Python application to Heroku](test-and-deploy-python-application-to-heroku.md)
- [Test a Clojure application](test-clojure-application.md)
-- [Using `dpl` as deployment tool](deployment/README.md)
+- [Using `dpl` as deployment tool](../deployment/README.md)
- Help your favorite programming language and GitLab by sending a merge request
with a guide for that language.
## Outside the documentation
-- [Blost post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
+- [Blog post about using GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/)
- [Repo's with examples for various languages](https://gitlab.com/groups/gitlab-examples)
- [The .gitlab-ci.yml file for GitLab itself](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/.gitlab-ci.yml)
diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md
index db077927126..26953014502 100644
--- a/doc/ci/examples/php.md
+++ b/doc/ci/examples/php.md
@@ -60,7 +60,7 @@ docker-php-ext-install pdo_mysql
You might wonder what `docker-php-ext-install` is. In short, it is a script
provided by the official php docker image that you can use to easilly install
extensions. For more information read the the documentation at
-<https://hub.docker.com/_/php/>.
+<https://hub.docker.com/r/_/php/>.
Now that we created the script that contains all prerequisites for our build
environment, let's add it in `.gitlab-ci.yml`:
@@ -92,7 +92,7 @@ Finally, commit your files and push them to GitLab to see your build succeeding
The final `.gitlab-ci.yml` should look similar to this:
```yaml
-# Select image from https://hub.docker.com/_/php/
+# Select image from https://hub.docker.com/r/_/php/
image: php:5.6
before_script:
@@ -278,7 +278,7 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the build will begin.
-[php-hub]: https://hub.docker.com/_/php/
+[php-hub]: https://hub.docker.com/r/_/php/
[phpenv]: https://github.com/phpenv/phpenv
[phpenv-installation]: https://github.com/phpenv/phpenv#installation
[php-example-repo]: https://gitlab.com/gitlab-examples/php
diff --git a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
index a236da53fe9..e4d3970deac 100644
--- a/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
+++ b/doc/ci/examples/test-and-deploy-python-application-to-heroku.md
@@ -8,7 +8,7 @@ This is what the `.gitlab-ci.yml` file looks like for this project:
```yaml
test:
script:
- # this configures django application to use attached postgres database that is run on `postgres` host
+ # this configures Django application to use attached postgres database that is run on `postgres` host
- export DATABASE_URL=postgres://postgres:@postgres:5432/python-test-app
- apt-get update -qy
- apt-get install -y python-dev python-pip
@@ -37,7 +37,7 @@ production:
```
This project has three jobs:
-1. `test` - used to test rails application,
+1. `test` - used to test Django application,
2. `staging` - used to automatically deploy staging environment every push to `master` branch
3. `production` - used to automatically deploy production environmnet for every created tag
@@ -61,12 +61,12 @@ gitlab-ci-multi-runner register \
--non-interactive \
--url "https://gitlab.com/ci/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
- --description "python-3.2" \
+ --description "python-3.5" \
--executor "docker" \
- --docker-image python:3.2 \
+ --docker-image python:3.5 \
--docker-postgres latest
```
-With the command above, you create a runner that uses [python:3.2](https://registry.hub.docker.com/u/library/python/) image and uses [postgres](https://registry.hub.docker.com/u/library/postgres/) database.
+With the command above, you create a runner that uses [python:3.5](https://hub.docker.com/r/_/python/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database.
To access PostgreSQL database you need to connect to `host: postgres` as user `postgres` without password.
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 f5645d586ae..08c10d391ea 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
@@ -1,5 +1,5 @@
## Test and Deploy a ruby application
-This example will guide you how to run tests in your Ruby application and deploy it automatically as Heroku application.
+This example will guide you how to run tests in your Ruby on Rails application and deploy it automatically as Heroku application.
You can checkout the example [source](https://gitlab.com/ayufan/ruby-getting-started) and check [CI status](https://gitlab.com/ayufan/ruby-getting-started/builds?scope=all).
@@ -32,7 +32,7 @@ production:
```
This project has three jobs:
-1. `test` - used to test rails application,
+1. `test` - used to test Rails application,
2. `staging` - used to automatically deploy staging environment every push to `master` branch
3. `production` - used to automatically deploy production environmnet for every created tag
@@ -62,6 +62,6 @@ gitlab-ci-multi-runner register \
--docker-postgres latest
```
-With the command above, you create a runner that uses [ruby:2.2](https://registry.hub.docker.com/u/library/ruby/) image and uses [postgres](https://registry.hub.docker.com/u/library/postgres/) database.
+With the command above, you create a runner that uses [ruby:2.2](https://hub.docker.com/r/_/ruby/) image and uses [postgres](https://hub.docker.com/r/_/postgres/) database.
To access PostgreSQL database you need to connect to `host: postgres` as user `postgres` without password.
diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md
index c66d77122b2..aaf3aa77837 100644
--- a/doc/ci/services/mysql.md
+++ b/doc/ci/services/mysql.md
@@ -16,7 +16,7 @@ services:
- mysql:latest
variables:
- # Configure mysql environment variables (https://hub.docker.com/_/mysql/)
+ # Configure mysql environment variables (https://hub.docker.com/r/_/mysql/)
MYSQL_DATABASE: el_duderino
MYSQL_ROOT_PASSWORD: mysql_strong_password
```
@@ -114,5 +114,5 @@ available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the build will begin.
-[hub-mysql]: https://hub.docker.com/_/mysql/
+[hub-mysql]: https://hub.docker.com/r/_/mysql/
[mysql-example-repo]: https://gitlab.com/gitlab-examples/mysql
diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md
index 17d21dbda1c..f787cc0a124 100644
--- a/doc/ci/services/postgres.md
+++ b/doc/ci/services/postgres.md
@@ -110,5 +110,5 @@ available [shared runners](../runners/README.md).
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the build will begin.
-[hub-pg]: https://hub.docker.com/_/postgres/
+[hub-pg]: https://hub.docker.com/r/_/postgres/
[postgres-example-repo]: https://gitlab.com/gitlab-examples/postgres
diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md
index b281e8f9f60..80705024d2f 100644
--- a/doc/ci/services/redis.md
+++ b/doc/ci/services/redis.md
@@ -65,5 +65,5 @@ that runs on [GitLab.com](https://gitlab.com) using our publicly available
Want to hack on it? Simply fork it, commit and push your changes. Within a few
moments the changes will be picked by a public runner and the build will begin.
-[hub-redis]: https://hub.docker.com/_/redis/
+[hub-redis]: https://hub.docker.com/r/_/redis/
[redis-example-repo]: https://gitlab.com/gitlab-examples/redis
diff --git a/docker/README.md b/docker/README.md
index 7514d610aec..ee1f32adc26 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -1,7 +1,7 @@
# GitLab Docker images
-* The official GitLab Community Edition Docker image is [available on Docker Hub](https://registry.hub.docker.com/u/gitlab/gitlab-ce/).
-* The official GitLab Enterprise Edition Docker image is [available on Docker Hub](https://registry.hub.docker.com/u/gitlab/gitlab-ee/).
+* The official GitLab Community Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ce/).
+* The official GitLab Enterprise Edition Docker image is [available on Docker Hub](https://hub.docker.com/r/gitlab/gitlab-ee/).
* The complete usage guide can be found in [Using GitLab Docker images](http://doc.gitlab.com/omnibus/docker/)
* The Dockerfile used for building public images is in [Omnibus Repository](https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/docker)
-* Check the guide for [creating Omnibus-based Docker Image](http://doc.gitlab.com/omnibus/build/README.html#Build-Docker-image)
+* Check the guide for [creating Omnibus-based Docker Image](http://doc.gitlab.com/omnibus/build/README.html#build-docker-image)
diff --git a/features/groups.feature b/features/groups.feature
index 419a5d3963d..49e939807b5 100644
--- a/features/groups.feature
+++ b/features/groups.feature
@@ -7,10 +7,6 @@ Feature: Groups
When I visit group "NonExistentGroup" page
Then page status code should be 404
- Scenario: I should have back to group button
- When I visit group "Owned" page
- Then I should see back to dashboard button
-
@javascript
Scenario: I should see group "Owned" dashboard list
When I visit group "Owned" page
diff --git a/features/steps/group/milestones.rb b/features/steps/group/milestones.rb
index a167d259837..f5fddab357d 100644
--- a/features/steps/group/milestones.rb
+++ b/features/steps/group/milestones.rb
@@ -5,7 +5,9 @@ class Spinach::Features::GroupMilestones < Spinach::FeatureSteps
include SharedUser
step 'I click on group milestones' do
- click_link 'Milestones'
+ page.within('.layout-nav') do
+ click_link 'Milestones'
+ end
end
step 'I should see group milestones index page has no milestones' do
@@ -84,7 +86,7 @@ class Spinach::Features::GroupMilestones < Spinach::FeatureSteps
end
step 'I click on the "Labels" tab' do
- page.within('.nav-links') do
+ page.within('.content .nav-links') do
page.find(:xpath, "//a[@href='#tab-labels']").click
end
end
diff --git a/features/steps/groups.rb b/features/steps/groups.rb
index e5b7db4c5e3..483370f41c6 100644
--- a/features/steps/groups.rb
+++ b/features/steps/groups.rb
@@ -4,10 +4,6 @@ class Spinach::Features::Groups < Spinach::FeatureSteps
include SharedGroup
include SharedUser
- step 'I should see back to dashboard button' do
- expect(page).to have_content 'Go to dashboard'
- end
-
step 'I should see group "Owned"' do
expect(page).to have_content '@owned'
end
diff --git a/lib/gitlab/sanitizers/svg.rb b/lib/gitlab/sanitizers/svg.rb
new file mode 100644
index 00000000000..b98589dff89
--- /dev/null
+++ b/lib/gitlab/sanitizers/svg.rb
@@ -0,0 +1,37 @@
+require_relative "svg/whitelist"
+
+module Gitlab
+ module Sanitizers
+ module SVG
+ def self.clean(data)
+ Loofah.xml_document(data).scrub!(Scrubber.new).to_s
+ end
+
+ class Scrubber < Loofah::Scrubber
+ # http://www.whatwg.org/specs/web-apps/current-work/multipage/elements.html#embedding-custom-non-visible-data-with-the-data-*-attributes
+ DATA_ATTR_PATTERN = /\Adata-(?!xml)[a-z_][\w.\u00E0-\u00F6\u00F8-\u017F\u01DD-\u02AF-]*\z/u
+
+ def scrub(node)
+ unless ALLOWED_ELEMENTS.include?(node.name)
+ node.unlink
+ else
+ node.attributes.each do |attr_name, attr|
+ valid_attributes = ALLOWED_ATTRIBUTES[node.name]
+
+ unless valid_attributes && valid_attributes.include?(attr_name)
+ if ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS.include?(node.name) &&
+ attr_name.start_with?('data-')
+ # Arbitrary data attributes are allowed. Verify that the attribute
+ # is a valid data attribute.
+ attr.unlink unless attr_name =~ DATA_ATTR_PATTERN
+ else
+ attr.unlink
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/sanitizers/svg/whitelist.rb b/lib/gitlab/sanitizers/svg/whitelist.rb
new file mode 100644
index 00000000000..917e795b29e
--- /dev/null
+++ b/lib/gitlab/sanitizers/svg/whitelist.rb
@@ -0,0 +1,107 @@
+# Generated from:
+# SVG element list: https://www.w3.org/TR/SVG/eltindex.html
+# SVG Attribute list: https://www.w3.org/TR/SVG/attindex.html
+module Gitlab
+ module Sanitizers
+ module SVG
+ ALLOWED_ELEMENTS = %w[
+ a altGlyph altGlyphDef altGlyphItem animate
+ animateColor animateMotion animateTransform circle clipPath color-profile
+ cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer
+ feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap
+ feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur
+ feImage feMerge feMergeNode feMorphology feOffset fePointLight
+ feSpecularLighting feSpotLight feTile feTurbulence filter font font-face
+ font-face-format font-face-name font-face-src font-face-uri foreignObject
+ g glyph glyphRef hkern image line linearGradient marker mask metadata
+ missing-glyph mpath path pattern polygon polyline radialGradient rect
+ script set stop style svg switch symbol text textPath title tref tspan use
+ view vkern].freeze
+
+ ALLOWED_DATA_ATTRIBUTES_IN_ELEMENTS = %w[svg].freeze
+
+ ALLOWED_ATTRIBUTES = {
+ 'a' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage target text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'altGlyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'altGlyphDef' => %w[id xml:base xml:lang xml:space],
+ 'altGlyphItem' => %w[id xml:base xml:lang xml:space],
+ 'animate' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateColor' => %w[accumulate additive alignment-baseline attributeName attributeType baseline-shift begin by calcMode clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dur enable-background end externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight from glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning keySplines keyTimes letter-spacing lighting-color marker-end marker-mid marker-start mask max min onbegin onend onload onrepeat opacity overflow pointer-events repeatCount repeatDur requiredExtensions requiredFeatures restart shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width systemLanguage text-anchor text-decoration text-rendering to unicode-bidi values visibility word-spacing writing-mode xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateMotion' => %w[accumulate additive begin by calcMode dur end externalResourcesRequired fill from id keyPoints keySplines keyTimes max min onbegin onend onload onrepeat origin path repeatCount repeatDur requiredExtensions requiredFeatures restart rotate systemLanguage to values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'animateTransform' => %w[accumulate additive attributeName attributeType begin by calcMode dur end externalResourcesRequired fill from id keySplines keyTimes max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to type values xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'circle' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events r requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'clipPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule clipPathUnits color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'color-profile' => %w[id local name rendering-intent xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'cursor' => %w[externalResourcesRequired id requiredExtensions requiredFeatures systemLanguage x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'defs' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'desc' => %w[class id style xml:base xml:lang xml:space],
+ 'ellipse' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'feBlend' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask mode opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feColorMatrix' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi values visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feComponentTransfer' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feComposite' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 k1 k2 k3 k4 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feConvolveMatrix' => %w[alignment-baseline baseline-shift bias class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display divisor dominant-baseline edgeMode enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelMatrix kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity order overflow pointer-events preserveAlpha result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style targetX targetY text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feDiffuseLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor diffuseConstant direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feDisplacementMap' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in in2 kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result scale shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xChannelSelector xml:base xml:lang xml:space y yChannelSelector],
+ 'feDistantLight' => %w[azimuth elevation id xml:base xml:lang xml:space],
+ 'feFlood' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feFuncA' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncB' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncG' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feFuncR' => %w[amplitude exponent id intercept offset slope tableValues type xml:base xml:lang xml:space],
+ 'feGaussianBlur' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stdDeviation stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feImage' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events preserveAspectRatio result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'feMerge' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feMergeNode' => %w[id xml:base xml:lang xml:space],
+ 'feMorphology' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity operator overflow pointer-events radius result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feOffset' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'fePointLight' => %w[id x xml:base xml:lang xml:space y z],
+ 'feSpecularLighting' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kernelUnitLength kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering specularConstant specularExponent stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style surfaceScale text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feSpotLight' => %w[id limitingConeAngle pointsAtX pointsAtY pointsAtZ specularExponent x xml:base xml:lang xml:space y z],
+ 'feTile' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering in kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events result shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'feTurbulence' => %w[alignment-baseline baseFrequency baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask numOctaves opacity overflow pointer-events result seed shape-rendering stitchTiles stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering type unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'filter' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter filterRes filterUnits flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events primitiveUnits shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'font' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x horiz-origin-y id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'font-face' => %w[accent-height alphabetic ascent bbox cap-height descent font-family font-size font-stretch font-style font-variant font-weight hanging id ideographic mathematical overline-position overline-thickness panose-1 slope stemh stemv strikethrough-position strikethrough-thickness underline-position underline-thickness unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical widths x-height xml:base xml:lang xml:space],
+ 'font-face-format' => %w[id string xml:base xml:lang xml:space],
+ 'font-face-name' => %w[id name xml:base xml:lang xml:space],
+ 'font-face-src' => %w[id xml:base xml:lang xml:space],
+ 'font-face-uri' => %w[id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'foreignObject' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'g' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'glyph' => %w[alignment-baseline arabic-form baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning lang letter-spacing lighting-color marker-end marker-mid marker-start mask opacity orientation overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'glyphRef' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight format glyph-orientation-horizontal glyph-orientation-vertical glyphRef id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'hkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space],
+ 'image' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'line' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode x1 x2 xml:base xml:lang xml:space y1 y2],
+ 'linearGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode x1 x2 xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y1 y2],
+ 'marker' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start markerHeight markerUnits markerWidth mask opacity orient overflow pointer-events preserveAspectRatio refX refY shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'mask' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask maskContentUnits maskUnits opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'metadata' => %w[id xml:base xml:lang xml:space],
+ 'missing-glyph' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi vert-adv-y vert-origin-x vert-origin-y visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'mpath' => %w[externalResourcesRequired id xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'path' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor d direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pathLength pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'pattern' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow patternContentUnits patternTransform patternUnits pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi viewBox visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'polygon' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'polyline' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events points requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'radialGradient' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor cx cy direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight fx fy glyph-orientation-horizontal glyph-orientation-vertical gradientTransform gradientUnits id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask opacity overflow pointer-events r shape-rendering spreadMethod stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
+ 'rect' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rx ry shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'script' => %w[externalResourcesRequired id type xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'set' => %w[attributeName attributeType begin dur end externalResourcesRequired fill id max min onbegin onend onload onrepeat repeatCount repeatDur requiredExtensions requiredFeatures restart systemLanguage to xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space],
+ 'stop' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask offset opacity overflow pointer-events shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'style' => %w[id media title type xml:base xml:lang xml:space],
+ 'svg' => %w[alignment-baseline baseProfile baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering contentScriptType contentStyleType cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onabort onactivate onclick onerror onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup onresize onscroll onunload onzoom opacity overflow pointer-events preserveAspectRatio requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering unicode-bidi version viewBox visibility width word-spacing writing-mode x xml:base xml:lang xml:space xmlns y zoomAndPan],
+ 'switch' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'symbol' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events preserveAspectRatio shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style text-anchor text-decoration text-rendering unicode-bidi viewBox visibility word-spacing writing-mode xml:base xml:lang xml:space],
+ 'text' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength transform unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'textPath' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask method onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering spacing startOffset stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space],
+ 'title' => %w[class id style xml:base xml:lang xml:space],
+ 'tref' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xlink:arcrole xlink:href xlink:role xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'tspan' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline dx dy enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical id image-rendering kerning lengthAdjust letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures rotate shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering textLength unicode-bidi visibility word-spacing writing-mode x xml:base xml:lang xml:space y],
+ 'use' => %w[alignment-baseline baseline-shift class clip clip-path clip-rule color color-interpolation color-interpolation-filters color-profile color-rendering cursor direction display dominant-baseline enable-background externalResourcesRequired fill fill-opacity fill-rule filter flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-orientation-horizontal glyph-orientation-vertical height id image-rendering kerning letter-spacing lighting-color marker-end marker-mid marker-start mask onactivate onclick onfocusin onfocusout onload onmousedown onmousemove onmouseout onmouseover onmouseup opacity overflow pointer-events requiredExtensions requiredFeatures shape-rendering stop-color stop-opacity stroke stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width style systemLanguage text-anchor text-decoration text-rendering transform unicode-bidi visibility width word-spacing writing-mode x xlink:actuate xlink:arcrole xlink:href xlink:role xlink:show xlink:title xlink:type xml:base xml:lang xml:space y],
+ 'view' => %w[externalResourcesRequired id preserveAspectRatio viewBox viewTarget xml:base xml:lang xml:space zoomAndPan],
+ 'vkern' => %w[g1 g2 id k u1 u2 xml:base xml:lang xml:space]
+ }.freeze
+ end
+ end
+end
diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake
new file mode 100644
index 00000000000..16bad4bd2bd
--- /dev/null
+++ b/lib/tasks/auto_annotate_models.rake
@@ -0,0 +1,44 @@
+if Rails.env.development?
+ task :set_annotation_options do
+ # You can override any of these by setting an environment variable of the
+ # same name.
+ Annotate.set_defaults(
+ 'routes' => 'false',
+ 'position_in_routes' => 'before',
+ 'position_in_class' => 'before',
+ 'position_in_test' => 'before',
+ 'position_in_fixture' => 'before',
+ 'position_in_factory' => 'before',
+ 'position_in_serializer' => 'before',
+ 'show_foreign_keys' => 'true',
+ 'show_indexes' => 'false',
+ 'simple_indexes' => 'false',
+ 'model_dir' => 'app/models',
+ 'root_dir' => '',
+ 'include_version' => 'false',
+ 'require' => '',
+ 'exclude_tests' => 'true',
+ 'exclude_fixtures' => 'true',
+ 'exclude_factories' => 'true',
+ 'exclude_serializers' => 'true',
+ 'exclude_scaffolds' => 'true',
+ 'exclude_controllers' => 'true',
+ 'exclude_helpers' => 'true',
+ 'ignore_model_sub_dir' => 'false',
+ 'ignore_columns' => nil,
+ 'ignore_unknown_models' => 'false',
+ 'hide_limit_column_types' => 'integer,boolean',
+ 'skip_on_db_migrate' => 'false',
+ 'format_bare' => 'true',
+ 'format_rdoc' => 'false',
+ 'format_markdown' => 'false',
+ 'sort' => 'false',
+ 'force' => 'false',
+ 'trace' => 'false',
+ 'wrapper_open' => nil,
+ 'wrapper_close' => nil,
+ )
+ end
+
+ Annotate.load_tasks
+end
diff --git a/spec/features/issues_spec.rb b/spec/features/issues_spec.rb
index b57131f68d5..d5755c293c5 100644
--- a/spec/features/issues_spec.rb
+++ b/spec/features/issues_spec.rb
@@ -264,12 +264,14 @@ describe 'Issues', feature: true do
visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_soon)
expect(first_issue).to include('foo')
+ expect(last_issue).to include('baz')
end
it 'sorts by least recently due milestone' do
visit namespace_project_issues_path(project.namespace, project, sort: sort_value_milestone_later)
expect(first_issue).to include('bar')
+ expect(last_issue).to include('baz')
end
end
diff --git a/spec/fixtures/sanitized.svg b/spec/fixtures/sanitized.svg
new file mode 100644
index 00000000000..8f84b8f5e20
--- /dev/null
+++ b/spec/fixtures/sanitized.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 622 682">
+
+ <defs>
+ <style>.cls-1{fill:#30353e;}.cls-2{fill:#8c929d;}.cls-3{fill:#fc6d26;}.cls-4{fill:#e24329;}.cls-5{fill:#fca326;}</style>
+ </defs>
+ <title>stacked_wm</title>
+ <path id="bg" class="cls-1" d="M622,681H0V-1H622V681h0Z"/>
+ <g id="g12">
+ <path id="path14" class="cls-2" d="M316.89,497.72h-19l0.06,141.74H375V621.93h-58l-0.06-124.22h0Z"/>
+ </g>
+ <g id="g24">
+ <path id="path26" class="cls-2" d="M448.32,614.57a32.46,32.46,0,0,1-23.59,10c-14.5,0-20.35-7.14-20.35-16.45,0-14.07,9.74-20.77,30.52-20.77a86.46,86.46,0,0,1,13.42,1.08v26.19h0Zm-19.7-85.91a63.45,63.45,0,0,0-40.5,14.53l6.73,11.66c7.79-4.54,17.32-9.09,31-9.09,15.58,0,22.51,8,22.51,21.42v6.93a81.48,81.48,0,0,0-13.2-1.08c-33.33,0-50.22,11.69-50.22,36.14,0,21.86,13.42,32.89,33.76,32.89,13.71,0,26.84-6.28,31.38-16.45l3.46,13.85h13.42V567c0-22.94-10-38.3-38.31-38.3h0Z"/>
+ </g>
+ <g id="g28">
+ <path id="path30" class="cls-2" d="M528.4,625.18c-7.14,0-13.42-.87-18.18-3V556.58c6.49-5.41,14.5-9.31,24.68-9.31,18.4,0,25.54,13,25.54,34,0,29.86-11.47,43.93-32,43.93m8-96.52a34.88,34.88,0,0,0-26.19,11.58V522l-0.06-24.24H491.54L491.6,636c9.31,3.9,22.08,6.06,35.93,6.06,35.5,0,52.6-22.72,52.6-61.89,0-30.95-15.8-51.51-43.73-51.51"/>
+ </g>
+ <g id="g32">
+ <path id="path34" class="cls-2" d="M109.84,513.08c16.88,0,27.7,5.63,34.85,11.25l8.19-14.18c-11.16-9.78-26.16-15-42.17-15-40.47,0-68.83,24.67-68.83,74.44,0,52.15,30.59,72.5,65.58,72.5a111,111,0,0,0,42.21-8.22l-0.4-55.72V560.58H97.32v17.53h33.12l0.4,42.31c-4.33,2.16-11.9,3.9-22.08,3.9-28.14,0-47-17.7-47-55,0-37.87,19.48-56.26,48.05-56.26"/>
+ </g>
+ <g id="g36">
+ <path id="path38" class="cls-2" d="M243.79,497.72H225.17l0.06,23.8v82.23c0,22.94,10,38.3,38.31,38.3A64.16,64.16,0,0,0,275,641V624.31a57,57,0,0,1-8.66.65c-15.58,0-22.51-8-22.51-21.42v-56.7H275V531.26H243.85l-0.06-33.54h0Z"/>
+ </g>
+ <path id="path40" class="cls-2" d="M177.94,639.46h18.61V531.26H177.94v108.2h0Z"/>
+ <path id="path42" class="cls-2" d="M177.94,516.33h18.61V497.72H177.94v18.61h0Z"/>
+ <g id="g44">
+ <path id="path46" class="cls-3" d="M525.05,266.23l-24-74L453.36,45.6a8.19,8.19,0,0,0-15.58,0L390.12,192.24H231.88L184.22,45.6a8.19,8.19,0,0,0-15.58,0L121,192.24l-24,74a16.38,16.38,0,0,0,6,18.31L311,435.71,519.1,284.54a16.38,16.38,0,0,0,6-18.31"/>
+ </g>
+ <g id="g48">
+ <path id="path50" class="cls-4" d="M311,435.71h0l79.12-243.47H231.88L311,435.71h0Z"/>
+ </g>
+ <g id="g56">
+ <path id="path58" class="cls-3" d="M311,435.71L231.88,192.24H121L311,435.71h0Z"/>
+ </g>
+ <g id="g64">
+ <path id="path66" class="cls-5" d="M121,192.24h0l-24,74a16.37,16.37,0,0,0,6,18.31L311,435.7,121,192.24h0Z"/>
+ </g>
+ <g id="g72">
+ <path id="path74" class="cls-4" d="M121,192.24H231.88L184.22,45.6a8.19,8.19,0,0,0-15.58,0L121,192.24h0Z"/>
+ </g>
+ <g id="g76">
+ <path id="path78" class="cls-3" d="M311,435.71l79.12-243.47H501L311,435.71h0Z"/>
+ </g>
+ <g id="g80">
+ <path id="path82" class="cls-5" d="M501,192.24h0l24,74a16.37,16.37,0,0,1-6,18.31L311,435.7,501,192.24h0Z"/>
+ </g>
+ <g id="g84">
+ <path id="path86" class="cls-4" d="M501,192.24H390.12L437.78,45.6a8.19,8.19,0,0,1,15.58,0L501,192.24h0Z"/>
+ </g>
+</svg>
diff --git a/spec/fixtures/unsanitized.svg b/spec/fixtures/unsanitized.svg
new file mode 100644
index 00000000000..3957557334b
--- /dev/null
+++ b/spec/fixtures/unsanitized.svg
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg" id="Layer_1" data-name="Layer 1" viewBox="0 0 622 682" filterMe="test">
+ <iframe src="http://www.google.com"></iframe>
+ <defs>
+ <style>.cls-1{fill:#30353e;}.cls-2{fill:#8c929d;}.cls-3{fill:#fc6d26;}.cls-4{fill:#e24329;}.cls-5{fill:#fca326;}</style>
+ </defs>
+ <title>stacked_wm</title>
+ <path id="bg" class="cls-1" d="M622,681H0V-1H622V681h0Z"/>
+ <g id="g12">
+ <path id="path14" class="cls-2" d="M316.89,497.72h-19l0.06,141.74H375V621.93h-58l-0.06-124.22h0Z"/>
+ </g>
+ <g id="g24">
+ <path id="path26" class="cls-2" d="M448.32,614.57a32.46,32.46,0,0,1-23.59,10c-14.5,0-20.35-7.14-20.35-16.45,0-14.07,9.74-20.77,30.52-20.77a86.46,86.46,0,0,1,13.42,1.08v26.19h0Zm-19.7-85.91a63.45,63.45,0,0,0-40.5,14.53l6.73,11.66c7.79-4.54,17.32-9.09,31-9.09,15.58,0,22.51,8,22.51,21.42v6.93a81.48,81.48,0,0,0-13.2-1.08c-33.33,0-50.22,11.69-50.22,36.14,0,21.86,13.42,32.89,33.76,32.89,13.71,0,26.84-6.28,31.38-16.45l3.46,13.85h13.42V567c0-22.94-10-38.3-38.31-38.3h0Z"/>
+ </g>
+ <g id="g28">
+ <path id="path30" class="cls-2" d="M528.4,625.18c-7.14,0-13.42-.87-18.18-3V556.58c6.49-5.41,14.5-9.31,24.68-9.31,18.4,0,25.54,13,25.54,34,0,29.86-11.47,43.93-32,43.93m8-96.52a34.88,34.88,0,0,0-26.19,11.58V522l-0.06-24.24H491.54L491.6,636c9.31,3.9,22.08,6.06,35.93,6.06,35.5,0,52.6-22.72,52.6-61.89,0-30.95-15.8-51.51-43.73-51.51"/>
+ </g>
+ <g id="g32">
+ <path id="path34" class="cls-2" d="M109.84,513.08c16.88,0,27.7,5.63,34.85,11.25l8.19-14.18c-11.16-9.78-26.16-15-42.17-15-40.47,0-68.83,24.67-68.83,74.44,0,52.15,30.59,72.5,65.58,72.5a111,111,0,0,0,42.21-8.22l-0.4-55.72V560.58H97.32v17.53h33.12l0.4,42.31c-4.33,2.16-11.9,3.9-22.08,3.9-28.14,0-47-17.7-47-55,0-37.87,19.48-56.26,48.05-56.26"/>
+ </g>
+ <g id="g36">
+ <path id="path38" class="cls-2" d="M243.79,497.72H225.17l0.06,23.8v82.23c0,22.94,10,38.3,38.31,38.3A64.16,64.16,0,0,0,275,641V624.31a57,57,0,0,1-8.66.65c-15.58,0-22.51-8-22.51-21.42v-56.7H275V531.26H243.85l-0.06-33.54h0Z"/>
+ </g>
+ <path id="path40" class="cls-2" d="M177.94,639.46h18.61V531.26H177.94v108.2h0Z"/>
+ <path id="path42" class="cls-2" d="M177.94,516.33h18.61V497.72H177.94v18.61h0Z"/>
+ <g id="g44">
+ <path id="path46" class="cls-3" d="M525.05,266.23l-24-74L453.36,45.6a8.19,8.19,0,0,0-15.58,0L390.12,192.24H231.88L184.22,45.6a8.19,8.19,0,0,0-15.58,0L121,192.24l-24,74a16.38,16.38,0,0,0,6,18.31L311,435.71,519.1,284.54a16.38,16.38,0,0,0,6-18.31"/>
+ </g>
+ <g id="g48">
+ <path id="path50" class="cls-4" d="M311,435.71h0l79.12-243.47H231.88L311,435.71h0Z"/>
+ </g>
+ <g id="g56">
+ <path id="path58" class="cls-3" d="M311,435.71L231.88,192.24H121L311,435.71h0Z"/>
+ </g>
+ <g id="g64">
+ <path id="path66" class="cls-5" d="M121,192.24h0l-24,74a16.37,16.37,0,0,0,6,18.31L311,435.7,121,192.24h0Z"/>
+ </g>
+ <g id="g72">
+ <path id="path74" class="cls-4" d="M121,192.24H231.88L184.22,45.6a8.19,8.19,0,0,0-15.58,0L121,192.24h0Z"/>
+ </g>
+ <g id="g76">
+ <path id="path78" class="cls-3" d="M311,435.71l79.12-243.47H501L311,435.71h0Z"/>
+ </g>
+ <g id="g80">
+ <path id="path82" class="cls-5" d="M501,192.24h0l24,74a16.37,16.37,0,0,1-6,18.31L311,435.7,501,192.24h0Z"/>
+ </g>
+ <g id="g84">
+ <path id="path86" class="cls-4" d="M501,192.24H390.12L437.78,45.6a8.19,8.19,0,0,1,15.58,0L501,192.24h0Z"/>
+ </g>
+</svg>
diff --git a/spec/helpers/blob_helper_spec.rb b/spec/helpers/blob_helper_spec.rb
index 87849230dbe..6d1c02db297 100644
--- a/spec/helpers/blob_helper_spec.rb
+++ b/spec/helpers/blob_helper_spec.rb
@@ -67,4 +67,16 @@ describe BlobHelper do
expect(result).to eq(expected)
end
end
+
+ describe "#sanitize_svg" do
+ let(:input_svg_path) { File.join(Rails.root, 'spec', 'fixtures', 'unsanitized.svg') }
+ let(:data) { open(input_svg_path).read }
+ let(:expected_svg_path) { File.join(Rails.root, 'spec', 'fixtures', 'sanitized.svg') }
+ let(:expected) { open(expected_svg_path).read }
+
+ it 'should retain essential elements' do
+ blob = OpenStruct.new(data: data)
+ expect(sanitize_svg(blob).data).to eq(expected)
+ end
+ end
end
diff --git a/spec/services/merge_requests/build_service_spec.rb b/spec/services/merge_requests/build_service_spec.rb
new file mode 100644
index 00000000000..782d74ec5ec
--- /dev/null
+++ b/spec/services/merge_requests/build_service_spec.rb
@@ -0,0 +1,181 @@
+require 'spec_helper'
+
+describe MergeRequests::BuildService, services: true do
+ include RepoHelpers
+
+ let(:project) { create(:project) }
+ let(:user) { create(:user) }
+ let(:issue_confidential) { false }
+ let(:issue) { create(:issue, project: project, title: 'A bug', confidential: issue_confidential) }
+ let(:description) { nil }
+ let(:source_branch) { 'feature-branch' }
+ let(:target_branch) { 'master' }
+ let(:merge_request) { service.execute }
+ let(:compare) { double(:compare, commits: commits) }
+ let(:commit_1) { double(:commit_1, safe_message: "Initial commit\n\nCreate the app") }
+ let(:commit_2) { double(:commit_2, safe_message: 'This is a bad commit message!') }
+ let(:commits) { nil }
+
+ let(:service) do
+ MergeRequests::BuildService.new(project, user,
+ description: description,
+ source_branch: source_branch,
+ target_branch: target_branch)
+ end
+
+ before do
+ allow(CompareService).to receive_message_chain(:new, :execute).and_return(compare)
+ end
+
+ describe 'execute' do
+ context 'missing source branch' do
+ let(:source_branch) { '' }
+
+ it 'forbids the merge request from being created' do
+ expect(merge_request.can_be_created).to eq(false)
+ end
+
+ it 'adds an error message to the merge request' do
+ expect(merge_request.errors).to contain_exactly('You must select source and target branch')
+ end
+ end
+
+ context 'missing target branch' do
+ let(:target_branch) { '' }
+
+ it 'forbids the merge request from being created' do
+ expect(merge_request.can_be_created).to eq(false)
+ end
+
+ it 'adds an error message to the merge request' do
+ expect(merge_request.errors).to contain_exactly('You must select source and target branch')
+ end
+ end
+
+ context 'no commits in the diff' do
+ let(:commits) { [] }
+
+ it 'forbids the merge request from being created' do
+ expect(merge_request.can_be_created).to eq(false)
+ end
+ end
+
+ context 'one commit in the diff' do
+ let(:commits) { [commit_1] }
+
+ it 'allows the merge request to be created' do
+ expect(merge_request.can_be_created).to eq(true)
+ end
+
+ it 'uses the title of the commit as the title of the merge request' do
+ expect(merge_request.title).to eq(commit_1.safe_message.split("\n").first)
+ end
+
+ it 'uses the description of the commit as the description of the merge request' do
+ expect(merge_request.description).to eq(commit_1.safe_message.split(/\n+/, 2).last)
+ end
+
+ context 'merge request already has a description set' do
+ let(:description) { 'Merge request description' }
+
+ it 'keeps the description from the initial params' do
+ expect(merge_request.description).to eq(description)
+ end
+ end
+
+ context 'commit has no description' do
+ let(:commits) { [commit_2] }
+
+ it 'uses the title of the commit as the title of the merge request' do
+ expect(merge_request.title).to eq(commit_2.safe_message)
+ end
+
+ it 'sets the description to nil' do
+ expect(merge_request.description).to be_nil
+ end
+ end
+
+ context 'branch starts with issue IID followed by a hyphen' do
+ let(:source_branch) { "#{issue.iid}-fix-issue" }
+
+ it 'appends "Closes #$issue-iid" to the description' do
+ expect(merge_request.description).to eq("#{commit_1.safe_message.split(/\n+/, 2).last}\nCloses ##{issue.iid}")
+ end
+
+ context 'merge request already has a description set' do
+ let(:description) { 'Merge request description' }
+
+ it 'appends "Closes #$issue-iid" to the description' do
+ expect(merge_request.description).to eq("#{description}\nCloses ##{issue.iid}")
+ end
+ end
+
+ context 'commit has no description' do
+ let(:commits) { [commit_2] }
+
+ it 'sets the description to "Closes #$issue-iid"' do
+ expect(merge_request.description).to eq("Closes ##{issue.iid}")
+ end
+ end
+ end
+ end
+
+ context 'more than one commit in the diff' do
+ let(:commits) { [commit_1, commit_2] }
+
+ it 'allows the merge request to be created' do
+ expect(merge_request.can_be_created).to eq(true)
+ end
+
+ it 'uses the title of the branch as the merge request title' do
+ expect(merge_request.title).to eq('Feature branch')
+ end
+
+ it 'does not add a description' do
+ expect(merge_request.description).to be_nil
+ end
+
+ context 'merge request already has a description set' do
+ let(:description) { 'Merge request description' }
+
+ it 'keeps the description from the initial params' do
+ expect(merge_request.description).to eq(description)
+ end
+ end
+
+ context 'branch starts with GitLab issue IID followed by a hyphen' do
+ let(:source_branch) { "#{issue.iid}-fix-issue" }
+
+ it 'sets the title to: Resolves "$issue-title"' do
+ expect(merge_request.title).to eq("Resolve \"#{issue.title}\"")
+ end
+
+ context 'issue does not exist' do
+ let(:source_branch) { "#{issue.iid.succ}-fix-issue" }
+
+ it 'uses the title of the branch as the merge request title' do
+ expect(merge_request.title).to eq("#{issue.iid.succ} fix issue")
+ end
+ end
+
+ context 'issue is confidential' do
+ let(:issue_confidential) { true }
+
+ it 'uses the title of the branch as the merge request title' do
+ expect(merge_request.title).to eq("#{issue.iid} fix issue")
+ end
+ end
+ end
+
+ context 'branch starts with external issue IID followed by a hyphen' do
+ let(:source_branch) { '12345-fix-issue' }
+
+ before { allow(project).to receive(:default_issues_tracker?).and_return(false) }
+
+ it 'sets the title to: Resolves External Issue $issue-iid' do
+ expect(merge_request.title).to eq('Resolve External Issue 12345')
+ end
+ end
+ end
+ end
+end