summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG27
-rw-r--r--GITLAB_SHELL_VERSION2
-rw-r--r--app/assets/javascripts/gfm_auto_complete.js.coffee2
-rw-r--r--app/assets/javascripts/labels_select.js.coffee6
-rw-r--r--app/assets/javascripts/notes.js.coffee48
-rw-r--r--app/assets/stylesheets/framework/dropdowns.scss3
-rw-r--r--app/models/event.rb4
-rw-r--r--app/models/label.rb14
-rw-r--r--app/models/project.rb6
-rw-r--r--app/services/projects/housekeeping_service.rb10
-rw-r--r--app/services/projects/import_export/export_service.rb4
-rw-r--r--app/validators/addressable_url_validator.rb45
-rw-r--r--app/views/projects/commit/_ci_stage.html.haml2
-rw-r--r--app/views/projects/pipelines/index.html.haml2
-rw-r--r--app/views/shared/_labels_row.html.haml7
-rw-r--r--db/migrate/20160620110927_fix_no_validatable_import_url.rb86
-rw-r--r--doc/administration/auth/ldap.md42
-rw-r--r--lib/banzai/filter/label_reference_filter.rb8
-rw-r--r--lib/gitlab/github_import/branch_formatter.rb12
-rw-r--r--lib/gitlab/github_import/importer.rb4
-rw-r--r--lib/gitlab/import_export/command_line_util.rb3
-rw-r--r--lib/gitlab/import_export/saver.rb1
-rw-r--r--lib/gitlab/sidekiq_middleware/memory_killer.rb4
-rw-r--r--lib/gitlab/url_sanitizer.rb10
-rw-r--r--spec/features/pipelines_spec.rb2
-rw-r--r--spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb6
-rw-r--r--spec/lib/banzai/filter/label_reference_filter_spec.rb50
-rw-r--r--spec/lib/gitlab/github_import/branch_formatter_spec.rb19
-rw-r--r--spec/lib/gitlab/github_import/pull_request_formatter_spec.rb18
-rw-r--r--spec/models/event_spec.rb32
-rw-r--r--spec/models/label_spec.rb13
-rw-r--r--spec/models/project_spec.rb12
-rw-r--r--spec/requests/api/issues_spec.rb40
-rw-r--r--spec/requests/api/labels_spec.rb10
-rw-r--r--spec/requests/api/merge_requests_spec.rb26
-rw-r--r--vendor/gitignore/Android.gitignore1
-rw-r--r--vendor/gitignore/C++.gitignore3
-rw-r--r--vendor/gitignore/C.gitignore3
-rw-r--r--vendor/gitignore/Gradle.gitignore2
-rw-r--r--vendor/gitignore/LICENSE140
-rw-r--r--vendor/gitignore/Node.gitignore1
-rw-r--r--vendor/gitignore/TeX.gitignore3
-rw-r--r--vendor/gitlab-ci-yml/Maven.gitlab-ci.yml102
-rw-r--r--vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/brunch.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml (renamed from vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml)0
-rw-r--r--vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml15
-rw-r--r--vendor/gitlab-ci-yml/Rust.gitlab-ci.yml23
-rw-r--r--vendor/gitlab-ci-yml/Scala.gitlab-ci.yml22
60 files changed, 740 insertions, 155 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 8ef934bf80d..9627c08d428 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -26,6 +26,7 @@ v 8.10.0 (unreleased)
- Add "Enabled Git access protocols" to Application Settings
- Fix user creation with stronger minimum password requirements !4054 (nathan-pmt)
- PipelinesFinder uses git cache data
+ - Throttle the update of `project.pushes_since_gc` to 1 minute.
- Check for conflicts with existing Project's wiki path when creating a new project.
- Don't instantiate a git tree on Projects show default view
- Bump Rinku to 2.0.0
@@ -37,20 +38,28 @@ v 8.10.0 (unreleased)
- Metrics for Rouge::Plugins::Redcarpet and Rouge::Formatters::HTMLGitlab
- RailsCache metris now includes fetch_hit/fetch_miss and read_hit/read_miss info.
- Allow [ci skip] to be in any case and allow [skip ci]. !4785 (simon_w)
+ - Set import_url validation to be more strict
- Add basic system information like memory and disk usage to the admin panel
- Don't garbage collect commits that have related DB records like comments
- More descriptive message for git hooks and file locks
- Handle custom Git hook result in GitLab UI
-
-v 8.9.5 (unreleased)
+ - Allow '?', or '&' for label names
+ - Fix importer for GitHub Pull Requests when a branch was reused across Pull Requests
+
+v 8.9.5
+ - Add more debug info to import/export and memory killer. !5108
+ - Fixed avatar alignment in new MR view. !5095
+ - Fix diff comments not showing up in activity feed. !5069
+ - Add index on both Award Emoji user and name. !5061
+ - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq. !5056
+ - Re-enable import button when import process fails due to namespace already being taken. !5053
+ - Fix snippets comments not displayed. !5045
+ - Fix emoji paths in relative root configurations. !5027
+ - Fix issues importing events in Import/Export. !4987
+ - Fixed 'use shortcuts' button on docs. !4979
+ - Admin should be able to turn shared runners into specific ones. !4961
+ - Update RedCloth to 4.3.2 for CVE-2012-6684. !4929 (Takuya Noguchi)
- Improve the request / withdraw access button. !4860
- - Fix assigning shared runners as admins. !4961
- - Show "locked" label for locked runners on runners admin. !4961
- - Downgrade to Redis 3.2.2 due to massive memory leak with Sidekiq
- - Add index on the user and emoji name on AwardEmoji table !5061
- - Fixes issues importing events in Import/Export. Import/Export version bumped to 0.1.1
- - Fix import button disabled when import process fail due to the namespace already been taken.
- - Security: Update RedCloth to 4.3.2 (Takuya Noguchi)
v 8.9.4
- Fix privilege escalation issue with OAuth external users.
diff --git a/GITLAB_SHELL_VERSION b/GITLAB_SHELL_VERSION
index fd2a01863fd..944880fa15e 100644
--- a/GITLAB_SHELL_VERSION
+++ b/GITLAB_SHELL_VERSION
@@ -1 +1 @@
-3.1.0
+3.2.0
diff --git a/app/assets/javascripts/gfm_auto_complete.js.coffee b/app/assets/javascripts/gfm_auto_complete.js.coffee
index b7d040bae85..4a851d9c9fb 100644
--- a/app/assets/javascripts/gfm_auto_complete.js.coffee
+++ b/app/assets/javascripts/gfm_auto_complete.js.coffee
@@ -190,7 +190,7 @@ GitLab.GfmAutoComplete =
callbacks:
beforeSave: (merges) ->
sanitizeLabelTitle = (title)->
- if /\w+\s+\w+/g.test(title)
+ if /[\w\?&]+\s+[\w\?&]+/g.test(title)
"\"#{sanitize(title)}\""
else
sanitize(title)
diff --git a/app/assets/javascripts/labels_select.js.coffee b/app/assets/javascripts/labels_select.js.coffee
index ce859fedb2d..7688609b301 100644
--- a/app/assets/javascripts/labels_select.js.coffee
+++ b/app/assets/javascripts/labels_select.js.coffee
@@ -32,7 +32,7 @@ class @LabelsSelect
if issueUpdateURL
labelHTMLTemplate = _.template(
'<% _.each(labels, function(label){ %>
- <a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- label.title %>">
+ <a href="<%- ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name[]=<%- encodeURIComponent(label.title) %>">
<span class="label has-tooltip color-label" title="<%- label.description %>" style="background-color: <%- label.color %>; color: <%- label.text_color %>;">
<%- label.title %>
</span>
@@ -261,7 +261,7 @@ class @LabelsSelect
$a.attr('data-label-id', label.id)
$a.addClass(selectedClass.join(' '))
- .html("#{colorEl} #{_.escape(label.title)}")
+ .html("#{colorEl} #{label.title}")
# Return generated html
$li.html($a).prop('outerHTML')
@@ -288,7 +288,7 @@ class @LabelsSelect
fieldName: $dropdown.data('field-name')
id: (label) ->
if $dropdown.hasClass("js-filter-submit") and not label.isAny?
- _.escape label.title
+ label.title
else
label.id
diff --git a/app/assets/javascripts/notes.js.coffee b/app/assets/javascripts/notes.js.coffee
index 17f7e180127..7c1d943667b 100644
--- a/app/assets/javascripts/notes.js.coffee
+++ b/app/assets/javascripts/notes.js.coffee
@@ -100,13 +100,40 @@ class @Notes
$('.note .js-task-list-container').taskList('disable')
$(document).off 'tasklist:changed', '.note .js-task-list-container'
- keydownNoteText: (e) ->
- $this = $(this)
- if $this.val() is '' and e.which is 38 and not isMetaKey e
- myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
- if myLastNote.length
- myLastNoteEditBtn = myLastNote.find('.js-note-edit')
- myLastNoteEditBtn.trigger('click', [true, myLastNote])
+ keydownNoteText: (e) =>
+ return if isMetaKey e
+
+ $textarea = $(e.target)
+
+ # Edit previous note when UP arrow is hit
+ switch e.which
+ when 38
+ return unless $textarea.val() is ''
+
+ myLastNote = $("li.note[data-author-id='#{gon.current_user_id}'][data-editable]:last")
+ if myLastNote.length
+ myLastNoteEditBtn = myLastNote.find('.js-note-edit')
+ myLastNoteEditBtn.trigger('click', [true, myLastNote])
+
+ # Cancel creating diff note or editing any note when ESCAPE is hit
+ when 27
+ discussionNoteForm = $textarea.closest('.js-discussion-note-form')
+ if discussionNoteForm.length
+ if $textarea.val() isnt ''
+ return unless confirm('Are you sure you want to cancel creating this comment?')
+
+ @removeDiscussionNoteForm(discussionNoteForm)
+ return
+
+ editNote = $textarea.closest('.note')
+ if editNote.length
+ originalText = $textarea.closest('form').data('original-note')
+ newText = $textarea.val()
+ if originalText isnt newText
+ return unless confirm('Are you sure you want to cancel editing this comment?')
+
+ @removeNoteEditForm(editNote)
+
isMetaKey = (e) ->
(e.metaKey or e.ctrlKey or e.altKey or e.shiftKey)
@@ -401,9 +428,12 @@ class @Notes
Hides edit form and restores the original note text to the editor textarea.
###
- cancelEdit: (e) ->
+ cancelEdit: (e) =>
e.preventDefault()
- note = $(this).closest(".note")
+ note = $(e.target).closest('.note')
+ @removeNoteEditForm(note)
+
+ removeNoteEditForm: (note) ->
form = note.find(".current-note-edit-form")
note.removeClass "is-editting"
form.removeClass("current-note-edit-form")
diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss
index 2a90a1fef37..f36736c475e 100644
--- a/app/assets/stylesheets/framework/dropdowns.scss
+++ b/app/assets/stylesheets/framework/dropdowns.scss
@@ -23,6 +23,9 @@
.dropdown-menu,
.dropdown-menu-nav {
display: block;
+ @media (max-width: $screen-xs-max) {
+ width: 100%;
+ }
}
.dropdown-menu-toggle {
diff --git a/app/models/event.rb b/app/models/event.rb
index d7d23c7ae6d..fd736d12359 100644
--- a/app/models/event.rb
+++ b/app/models/event.rb
@@ -67,7 +67,7 @@ class Event < ActiveRecord::Base
elsif issue? || issue_note?
Ability.abilities.allowed?(user, :read_issue, note? ? note_target : target)
else
- ((merge_request? || note?) && target) || milestone?
+ ((merge_request? || note?) && target.present?) || milestone?
end
end
@@ -136,7 +136,7 @@ class Event < ActiveRecord::Base
end
def note?
- target_type == "Note"
+ target.is_a?(Note)
end
def issue?
diff --git a/app/models/label.rb b/app/models/label.rb
index 49c352cc239..dc5586f5756 100644
--- a/app/models/label.rb
+++ b/app/models/label.rb
@@ -20,10 +20,10 @@ class Label < ActiveRecord::Base
validates :color, color: true, allow_blank: false
validates :project, presence: true, unless: Proc.new { |service| service.template? }
- # Don't allow '?', '&', and ',' for label titles
+ # Don't allow ',' for label titles
validates :title,
presence: true,
- format: { with: /\A[^&\?,]+\z/ },
+ format: { with: /\A[^,]+\z/ },
uniqueness: { scope: :project_id }
before_save :nullify_priority
@@ -58,8 +58,8 @@ class Label < ActiveRecord::Base
(?:
(?<label_id>\d+) | # Integer-based label ID, or
(?<label_name>
- [A-Za-z0-9_-]+ | # String-based single-word label title, or
- "[^&\?,]+" # String-based multi-word label surrounded in quotes
+ [A-Za-z0-9_\-\?&]+ | # String-based single-word label title, or
+ "[^,]+" # String-based multi-word label surrounded in quotes
)
)
}x
@@ -114,7 +114,7 @@ class Label < ActiveRecord::Base
end
def title=(value)
- write_attribute(:title, Sanitize.clean(value.to_s)) if value.present?
+ write_attribute(:title, sanitize_title(value)) if value.present?
end
private
@@ -132,4 +132,8 @@ class Label < ActiveRecord::Base
def nullify_priority
self.priority = nil if priority.blank?
end
+
+ def sanitize_title(value)
+ CGI.unescapeHTML(Sanitize.clean(value.to_s))
+ end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index e5fae15cb19..029026a4e56 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -162,9 +162,7 @@ class Project < ActiveRecord::Base
validates :namespace, presence: true
validates_uniqueness_of :name, scope: :namespace_id
validates_uniqueness_of :path, scope: :namespace_id
- validates :import_url,
- url: { protocols: %w(ssh git http https) },
- if: :external_import?
+ validates :import_url, addressable_url: true, if: :external_import?
validates :star_count, numericality: { greater_than_or_equal_to: 0 }
validate :check_limit, on: :create
validate :avatar_type,
@@ -463,6 +461,8 @@ class Project < ActiveRecord::Base
end
def import_url=(value)
+ return super(value) unless Gitlab::UrlSanitizer.valid?(value)
+
import_url = Gitlab::UrlSanitizer.new(value)
create_or_update_import_data(credentials: import_url.credentials)
super(import_url.sanitized_url)
diff --git a/app/services/projects/housekeeping_service.rb b/app/services/projects/housekeeping_service.rb
index a47df22f1ba..752c11d7ae6 100644
--- a/app/services/projects/housekeeping_service.rb
+++ b/app/services/projects/housekeeping_service.rb
@@ -27,7 +27,7 @@ module Projects
GitlabShellOneShotWorker.perform_async(:gc, @project.repository_storage_path, @project.path_with_namespace)
ensure
Gitlab::Metrics.measure(:reset_pushes_since_gc) do
- @project.update_column(:pushes_since_gc, 0)
+ update_pushes_since_gc(0)
end
end
@@ -37,12 +37,18 @@ module Projects
def increment!
Gitlab::Metrics.measure(:increment_pushes_since_gc) do
- @project.increment!(:pushes_since_gc)
+ update_pushes_since_gc(@project.pushes_since_gc + 1)
end
end
private
+ def update_pushes_since_gc(new_value)
+ if Gitlab::ExclusiveLease.new("project_housekeeping:update_pushes_since_gc:#{project.id}", timeout: 60).try_obtain
+ @project.update_column(:pushes_since_gc, new_value)
+ end
+ end
+
def try_obtain_lease
Gitlab::Metrics.measure(:obtain_housekeeping_lease) do
lease = ::Gitlab::ExclusiveLease.new("project_housekeeping:#{@project.id}", timeout: LEASE_TIMEOUT)
diff --git a/app/services/projects/import_export/export_service.rb b/app/services/projects/import_export/export_service.rb
index 3f507d5c400..6afc048576d 100644
--- a/app/services/projects/import_export/export_service.rb
+++ b/app/services/projects/import_export/export_service.rb
@@ -38,6 +38,8 @@ module Projects
end
def cleanup_and_notify
+ Rails.logger.error("Import/Export - Project #{project.name} with ID: #{project.id} export error - #{@shared.errors.join(', ')}")
+
FileUtils.rm_rf(@shared.export_path)
notify_error
@@ -45,6 +47,8 @@ module Projects
end
def notify_success
+ Rails.logger.info("Import/Export - Project #{project.name} with ID: #{project.id} successfully exported")
+
notification_service.project_exported(@project, @current_user)
end
diff --git a/app/validators/addressable_url_validator.rb b/app/validators/addressable_url_validator.rb
new file mode 100644
index 00000000000..09bfa613cbe
--- /dev/null
+++ b/app/validators/addressable_url_validator.rb
@@ -0,0 +1,45 @@
+# AddressableUrlValidator
+#
+# Custom validator for URLs. This is a stricter version of UrlValidator - it also checks
+# for using the right protocol, but it actually parses the URL checking for any syntax errors.
+# The regex is also different from `URI` as we use `Addressable::URI` here.
+#
+# By default, only URLs for http, https, ssh, and git protocols will be considered valid.
+# Provide a `:protocols` option to configure accepted protocols.
+#
+# Example:
+#
+# class User < ActiveRecord::Base
+# validates :personal_url, addressable_url: true
+#
+# validates :ftp_url, addressable_url: { protocols: %w(ftp) }
+#
+# validates :git_url, addressable_url: { protocols: %w(http https ssh git) }
+# end
+#
+class AddressableUrlValidator < ActiveModel::EachValidator
+ DEFAULT_OPTIONS = { protocols: %w(http https ssh git) }
+
+ def validate_each(record, attribute, value)
+ unless valid_url?(value)
+ record.errors.add(attribute, "must be a valid URL")
+ end
+ end
+
+ private
+
+ def valid_url?(value)
+ return false unless value
+
+ valid_protocol?(value) && valid_uri?(value)
+ end
+
+ def valid_uri?(value)
+ Gitlab::UrlSanitizer.valid?(value)
+ end
+
+ def valid_protocol?(value)
+ options = DEFAULT_OPTIONS.merge(self.options)
+ value =~ /\A#{URI.regexp(options[:protocols])}\z/
+ end
+end
diff --git a/app/views/projects/commit/_ci_stage.html.haml b/app/views/projects/commit/_ci_stage.html.haml
index ae7bb01223e..9d925cacc0d 100644
--- a/app/views/projects/commit/_ci_stage.html.haml
+++ b/app/views/projects/commit/_ci_stage.html.haml
@@ -7,7 +7,7 @@
= ci_icon_for_status(status)
- if stage
&nbsp;
- = stage.titleize.pluralize
+ = stage.titleize
= render statuses.latest.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, allow_retry: true
= render statuses.retried.ordered, coverage: @project.build_coverage_enabled?, stage: false, ref: false, retried: true
%tr
diff --git a/app/views/projects/pipelines/index.html.haml b/app/views/projects/pipelines/index.html.haml
index 28b475d5c2f..6a127afa410 100644
--- a/app/views/projects/pipelines/index.html.haml
+++ b/app/views/projects/pipelines/index.html.haml
@@ -50,7 +50,7 @@
- stages.each do |stage|
%th.stage
%span.has-tooltip{ title: "#{stage.titleize}" }
- = stage.titleize.pluralize
+ = stage.titleize
%th Duration
%th
= render @pipelines, commit_sha: true, stage: true, allow_retry: true, stages: stages
diff --git a/app/views/shared/_labels_row.html.haml b/app/views/shared/_labels_row.html.haml
index 5507a05f6c1..dce492352ac 100644
--- a/app/views/shared/_labels_row.html.haml
+++ b/app/views/shared/_labels_row.html.haml
@@ -1,10 +1,9 @@
- labels.each do |label|
- %span.label-row.btn-group{ role: "group", aria: { label: escape_once(label.name) }, style: "color: #{text_color_for_bg(label.color)}" }
- = link_to label_filter_path(@project, label, type: controller.controller_name),
+ %span.label-row.btn-group{ role: "group", aria: { label: label.name }, style: "color: #{text_color_for_bg(label.color)}" }
+ = link_to label.name, label_filter_path(@project, label, type: controller.controller_name),
class: "btn btn-transparent has-tooltip",
style: "background-color: #{label.color};",
title: escape_once(label.description),
- data: { container: "body" } do
- = escape_once label.name
+ data: { container: "body" }
%button.btn.btn-transparent.label-remove.js-label-filter-remove{ type: "button", style: "background-color: #{label.color};", data: { label: label.title } }
= icon("times")
diff --git a/db/migrate/20160620110927_fix_no_validatable_import_url.rb b/db/migrate/20160620110927_fix_no_validatable_import_url.rb
new file mode 100644
index 00000000000..82a616c62d9
--- /dev/null
+++ b/db/migrate/20160620110927_fix_no_validatable_import_url.rb
@@ -0,0 +1,86 @@
+# Updates project records containing invalid URLs using the AddressableUrlValidator.
+# This is optimized assuming the number of invalid records is low, but
+# we still need to loop through all the projects with an +import_url+
+# so we use batching for the latter.
+#
+# This migration is non-reversible as we would have to keep the old data.
+
+class FixNoValidatableImportUrl < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+ class SqlBatches
+
+ attr_reader :results, :query
+
+ def initialize(batch_size: 100, query:)
+ @offset = 0
+ @batch_size = batch_size
+ @query = query
+ @results = []
+ end
+
+ def next?
+ @results = ActiveRecord::Base.connection.exec_query(batched_sql)
+ @offset += @batch_size
+ @results.any?
+ end
+
+ private
+
+ def batched_sql
+ "#{@query} LIMIT #{@batch_size} OFFSET #{@offset}"
+ end
+ end
+
+ # AddressableValidator - Snapshot of AddressableUrlValidator
+ module AddressableUrlValidatorSnap
+ extend self
+
+ def valid_url?(value)
+ return false unless value
+
+ valid_uri?(value) && valid_protocol?(value)
+ rescue Addressable::URI::InvalidURIError
+ false
+ end
+
+ def valid_uri?(value)
+ Addressable::URI.parse(value).is_a?(Addressable::URI)
+ end
+
+ def valid_protocol?(value)
+ value =~ /\A#{URI.regexp(%w(http https ssh git))}\z/
+ end
+ end
+
+ def up
+ unless defined?(Addressable::URI::InvalidURIError)
+ say('Skipping cleaning up invalid import URLs as class from Addressable is missing')
+ return
+ end
+
+ say('Cleaning up invalid import URLs... This may take a few minutes if we have a large number of imported projects.')
+
+ invalid_import_url_project_ids.each { |project_id| cleanup_import_url(project_id) }
+ end
+
+ def invalid_import_url_project_ids
+ ids = []
+ batches = SqlBatches.new(query: "SELECT id, import_url FROM projects WHERE import_url IS NOT NULL")
+
+ while batches.next?
+ batches.results.each do |result|
+ ids << result['id'] unless valid_url?(result['import_url'])
+ end
+ end
+
+ ids
+ end
+
+ def valid_url?(url)
+ AddressableUrlValidatorSnap.valid_url?(url)
+ end
+
+ def cleanup_import_url(project_id)
+ execute("UPDATE projects SET import_url = NULL WHERE id = #{project_id}")
+ end
+end
diff --git a/doc/administration/auth/ldap.md b/doc/administration/auth/ldap.md
index 10096779844..7186f707ad6 100644
--- a/doc/administration/auth/ldap.md
+++ b/doc/administration/auth/ldap.md
@@ -130,27 +130,27 @@ main: # 'main' is the GitLab 'provider ID' of this LDAP server
first_name: 'givenName'
last_name: 'sn'
- ## EE only
-
- # Base where we can search for groups
- #
- # Ex. ou=groups,dc=gitlab,dc=example
- #
- group_base: ''
-
- # The CN of a group containing GitLab administrators
- #
- # Ex. administrators
- #
- # Note: Not `cn=administrators` or the full DN
- #
- admin_group: ''
-
- # The LDAP attribute containing a user's public SSH key
- #
- # Ex. ssh_public_key
- #
- sync_ssh_keys: false
+ ## EE only
+
+ # Base where we can search for groups
+ #
+ # Ex. ou=groups,dc=gitlab,dc=example
+ #
+ group_base: ''
+
+ # The CN of a group containing GitLab administrators
+ #
+ # Ex. administrators
+ #
+ # Note: Not `cn=administrators` or the full DN
+ #
+ admin_group: ''
+
+ # The LDAP attribute containing a user's public SSH key
+ #
+ # Ex. ssh_public_key
+ #
+ sync_ssh_keys: false
# GitLab EE only: add more LDAP servers
# Choose an ID made of a-z and 0-9 . This ID will be stored in the database
diff --git a/lib/banzai/filter/label_reference_filter.rb b/lib/banzai/filter/label_reference_filter.rb
index e4d3f87d0aa..e258dc8e2bf 100644
--- a/lib/banzai/filter/label_reference_filter.rb
+++ b/lib/banzai/filter/label_reference_filter.rb
@@ -13,13 +13,13 @@ module Banzai
end
def self.references_in(text, pattern = Label.reference_pattern)
- text.gsub(pattern) do |match|
+ unescape_html_entities(text).gsub(pattern) do |match|
yield match, $~[:label_id].to_i, $~[:label_name], $~[:project], $~
end
end
def references_in(text, pattern = Label.reference_pattern)
- text.gsub(pattern) do |match|
+ unescape_html_entities(text).gsub(pattern) do |match|
label = find_label($~[:project], $~[:label_id], $~[:label_name])
if label
@@ -66,6 +66,10 @@ module Banzai
LabelsHelper.render_colored_cross_project_label(object)
end
end
+
+ def unescape_html_entities(text)
+ CGI.unescapeHTML(text.to_s)
+ end
end
end
end
diff --git a/lib/gitlab/github_import/branch_formatter.rb b/lib/gitlab/github_import/branch_formatter.rb
index a15fc84b418..7d2d545b84e 100644
--- a/lib/gitlab/github_import/branch_formatter.rb
+++ b/lib/gitlab/github_import/branch_formatter.rb
@@ -4,7 +4,7 @@ module Gitlab
delegate :repo, :sha, :ref, to: :raw_data
def exists?
- project.repository.branch_exists?(ref)
+ branch_exists? && commit_exists?
end
def name
@@ -15,11 +15,15 @@ module Gitlab
repo.present?
end
- def valid?
- repo.present?
+ private
+
+ def branch_exists?
+ project.repository.branch_exists?(ref)
end
- private
+ def commit_exists?
+ project.repository.commit(sha).present?
+ end
def short_id
sha.to_s[0..7]
diff --git a/lib/gitlab/github_import/importer.rb b/lib/gitlab/github_import/importer.rb
index 730978d502b..3932fcb1eda 100644
--- a/lib/gitlab/github_import/importer.rb
+++ b/lib/gitlab/github_import/importer.rb
@@ -131,8 +131,10 @@ module Gitlab
def clean_up_restored_branches(branches)
branches.each do |name, _|
client.delete_ref(repo, "heads/#{name}")
- project.repository.rm_branch(project.creator, name)
+ project.repository.delete_branch(name) rescue Rugged::ReferenceError
end
+
+ project.repository.after_remove_branch
end
def apply_labels(issuable)
diff --git a/lib/gitlab/import_export/command_line_util.rb b/lib/gitlab/import_export/command_line_util.rb
index 78664f076eb..62c736451b7 100644
--- a/lib/gitlab/import_export/command_line_util.rb
+++ b/lib/gitlab/import_export/command_line_util.rb
@@ -28,7 +28,8 @@ module Gitlab
end
def execute(cmd)
- _output, status = Gitlab::Popen.popen(cmd)
+ output, status = Gitlab::Popen.popen(cmd)
+ @shared.error(output.to_s) unless status.zero?
status.zero?
end
diff --git a/lib/gitlab/import_export/saver.rb b/lib/gitlab/import_export/saver.rb
index f38229c6c59..dd4fdf37309 100644
--- a/lib/gitlab/import_export/saver.rb
+++ b/lib/gitlab/import_export/saver.rb
@@ -17,6 +17,7 @@ module Gitlab
Rails.logger.info("Saved project export #{archive_file}")
archive_file
else
+ @shared.error("Unable to save #{archive_file} into #{@shared.export_path}")
false
end
rescue => e
diff --git a/lib/gitlab/sidekiq_middleware/memory_killer.rb b/lib/gitlab/sidekiq_middleware/memory_killer.rb
index 4831c46c4be..104280f520a 100644
--- a/lib/gitlab/sidekiq_middleware/memory_killer.rb
+++ b/lib/gitlab/sidekiq_middleware/memory_killer.rb
@@ -29,11 +29,11 @@ module Gitlab
"in #{GRACE_TIME} seconds"
sleep(GRACE_TIME)
- Sidekiq.logger.warn "sending SIGTERM to PID #{Process.pid}"
+ Sidekiq.logger.warn "sending SIGTERM to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
Process.kill('SIGTERM', Process.pid)
Sidekiq.logger.warn "waiting #{SHUTDOWN_WAIT} seconds before sending "\
- "#{SHUTDOWN_SIGNAL} to PID #{Process.pid}"
+ "#{SHUTDOWN_SIGNAL} to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
sleep(SHUTDOWN_WAIT)
Sidekiq.logger.warn "sending #{SHUTDOWN_SIGNAL} to PID #{Process.pid} - Worker #{worker.class} - JID-#{job['jid']}"
diff --git a/lib/gitlab/url_sanitizer.rb b/lib/gitlab/url_sanitizer.rb
index 7d02fe3c971..86ed18fb50d 100644
--- a/lib/gitlab/url_sanitizer.rb
+++ b/lib/gitlab/url_sanitizer.rb
@@ -6,8 +6,16 @@ module Gitlab
content.gsub(regexp) { |url| new(url).masked_url }
end
+ def self.valid?(url)
+ Addressable::URI.parse(url.strip)
+
+ true
+ rescue Addressable::URI::InvalidURIError
+ false
+ end
+
def initialize(url, credentials: nil)
- @url = Addressable::URI.parse(url)
+ @url = Addressable::URI.parse(url.strip)
@credentials = credentials
end
diff --git a/spec/features/pipelines_spec.rb b/spec/features/pipelines_spec.rb
index 98703ef3ac4..e7ee0aaea3c 100644
--- a/spec/features/pipelines_spec.rb
+++ b/spec/features/pipelines_spec.rb
@@ -123,7 +123,7 @@ describe "Pipelines" do
before { visit namespace_project_pipeline_path(project.namespace, project, pipeline) }
it 'showing a list of builds' do
- expect(page).to have_content('Tests')
+ expect(page).to have_content('Test')
expect(page).to have_content(@success.id)
expect(page).to have_content('Deploy')
expect(page).to have_content(@failed.id)
diff --git a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
index b8c06c383fb..fca40f68b01 100644
--- a/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
+++ b/spec/features/projects/files/gitlab_ci_yml_dropdown_spec.rb
@@ -19,12 +19,12 @@ feature 'User wants to add a .gitlab-ci.yml file', feature: true do
find('.js-gitlab-ci-yml-selector').click
wait_for_ajax
within '.gitlab-ci-yml-selector' do
- find('.dropdown-input-field').set('jekyll')
- find('.dropdown-content li', text: 'jekyll').click
+ find('.dropdown-input-field').set('Jekyll')
+ find('.dropdown-content li', text: 'Jekyll').click
end
wait_for_ajax
- expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'jekyll')
+ expect(page).to have_css('.gitlab-ci-yml-selector .dropdown-toggle-text', text: 'Jekyll')
expect(page).to have_content('This file is a template, and might need editing before it works on your project')
expect(page).to have_content('jekyll build -d test')
end
diff --git a/spec/lib/banzai/filter/label_reference_filter_spec.rb b/spec/lib/banzai/filter/label_reference_filter_spec.rb
index f1064a701d8..9e3d2f5825d 100644
--- a/spec/lib/banzai/filter/label_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/label_reference_filter_spec.rb
@@ -104,6 +104,31 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
end
end
+ context 'String-based single-word references with special characters' do
+ let(:label) { create(:label, name: '?gfm&', project: project) }
+ let(:reference) { "#{Label.reference_prefix}#{label.name}" }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.
+ namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ expect(doc.text).to eq 'See ?gfm&'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+><span.+>\?gfm&amp;</span></a>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ act = "Label #{Label.reference_prefix}#{label.name.reverse}"
+ exp = "Label #{Label.reference_prefix}&amp;mfg?"
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
context 'String-based multi-word references in quotes' do
let(:label) { create(:label, name: 'gfm references', project: project) }
let(:reference) { label.to_reference(format: :name) }
@@ -128,6 +153,31 @@ describe Banzai::Filter::LabelReferenceFilter, lib: true do
end
end
+ context 'String-based multi-word references with special characters in quotes' do
+ let(:label) { create(:label, name: 'gfm & references?', project: project) }
+ let(:reference) { label.to_reference(format: :name) }
+
+ it 'links to a valid reference' do
+ doc = reference_filter("See #{reference}")
+
+ expect(doc.css('a').first.attr('href')).to eq urls.
+ namespace_project_issues_url(project.namespace, project, label_name: label.name)
+ expect(doc.text).to eq 'See gfm & references?'
+ end
+
+ it 'links with adjacent text' do
+ doc = reference_filter("Label (#{reference}.)")
+ expect(doc.to_html).to match(%r(\(<a.+><span.+>gfm &amp; references\?</span></a>\.\)))
+ end
+
+ it 'ignores invalid label names' do
+ act = %(Label #{Label.reference_prefix}"#{label.name.reverse}")
+ exp = %(Label #{Label.reference_prefix}"?secnerefer &amp; mfg\")
+
+ expect(reference_filter(act).to_html).to eq exp
+ end
+ end
+
describe 'edge cases' do
it 'gracefully handles non-references matching the pattern' do
exp = act = '(format nil "~0f" 3.0) ; 3.0'
diff --git a/spec/lib/gitlab/github_import/branch_formatter_spec.rb b/spec/lib/gitlab/github_import/branch_formatter_spec.rb
index 3cb634ba010..fc9d5204148 100644
--- a/spec/lib/gitlab/github_import/branch_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/branch_formatter_spec.rb
@@ -2,17 +2,18 @@ require 'spec_helper'
describe Gitlab::GithubImport::BranchFormatter, lib: true do
let(:project) { create(:project) }
+ let(:commit) { create(:commit, project: project) }
let(:repo) { double }
let(:raw) do
{
ref: 'feature',
repo: repo,
- sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
+ sha: commit.id
}
end
describe '#exists?' do
- it 'returns true when branch exists' do
+ it 'returns true when both branch, and commit exists' do
branch = described_class.new(project, double(raw))
expect(branch.exists?).to eq true
@@ -23,6 +24,12 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
expect(branch.exists?).to eq false
end
+
+ it 'returns false when commit does not exist' do
+ branch = described_class.new(project, double(raw.merge(sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b')))
+
+ expect(branch.exists?).to eq false
+ end
end
describe '#name' do
@@ -33,7 +40,7 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
end
it 'returns formatted ref when branch does not exist' do
- branch = described_class.new(project, double(raw.merge(ref: 'removed-branch')))
+ branch = described_class.new(project, double(raw.merge(ref: 'removed-branch', sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b')))
expect(branch.name).to eq 'removed-branch-2e5d3239'
end
@@ -51,18 +58,18 @@ describe Gitlab::GithubImport::BranchFormatter, lib: true do
it 'returns raw sha' do
branch = described_class.new(project, double(raw))
- expect(branch.sha).to eq '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b'
+ expect(branch.sha).to eq commit.id
end
end
describe '#valid?' do
- it 'returns true when repository exists' do
+ it 'returns true when raw repo is present' do
branch = described_class.new(project, double(raw))
expect(branch.valid?).to eq true
end
- it 'returns false when repository does not exist' do
+ it 'returns false when raw repo is blank' do
branch = described_class.new(project, double(raw.merge(repo: nil)))
expect(branch.valid?).to eq false
diff --git a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
index 120f59e6e71..9587252b990 100644
--- a/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/github_import/pull_request_formatter_spec.rb
@@ -2,11 +2,13 @@ require 'spec_helper'
describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
let(:project) { create(:project) }
+ let(:source_sha) { create(:commit, project: project).id }
+ let(:target_sha) { create(:commit, project: project, git_commit: RepoHelpers.another_sample_commit).id }
let(:repository) { double(id: 1, fork: false) }
let(:source_repo) { repository }
- let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b') }
+ let(:source_branch) { double(ref: 'feature', repo: source_repo, sha: source_sha) }
let(:target_repo) { repository }
- let(:target_branch) { double(ref: 'master', repo: target_repo, sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7') }
+ let(:target_branch) { double(ref: 'master', repo: target_repo, sha: target_sha) }
let(:octocat) { double(id: 123456, login: 'octocat') }
let(:created_at) { DateTime.strptime('2011-01-26T19:01:12Z') }
let(:updated_at) { DateTime.strptime('2011-01-27T19:01:12Z') }
@@ -41,10 +43,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ head_source_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ base_target_sha: target_sha,
state: 'opened',
milestone: nil,
author_id: project.creator_id,
@@ -68,10 +70,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ head_source_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ base_target_sha: target_sha,
state: 'closed',
milestone: nil,
author_id: project.creator_id,
@@ -95,10 +97,10 @@ describe Gitlab::GithubImport::PullRequestFormatter, lib: true do
description: "*Created by: octocat*\n\nPlease pull these awesome changes",
source_project: project,
source_branch: 'feature',
- head_source_sha: '2e5d3239642f9161dcbbc4b70a211a68e5e45e2b',
+ head_source_sha: source_sha,
target_project: project,
target_branch: 'master',
- base_target_sha: '8ffb3c15a5475e59ae909384297fede4badcb4c7',
+ base_target_sha: target_sha,
state: 'merged',
milestone: nil,
author_id: project.creator_id,
diff --git a/spec/models/event_spec.rb b/spec/models/event_spec.rb
index 166a1dc4ddb..6ac19756f15 100644
--- a/spec/models/event_spec.rb
+++ b/spec/models/event_spec.rb
@@ -46,6 +46,22 @@ describe Event, models: true do
it { expect(@event.author).to eq(@user) }
end
+ describe '#note?' do
+ subject { Event.new(project: target.project, target: target) }
+
+ context 'issue note event' do
+ let(:target) { create(:note_on_issue) }
+
+ it { is_expected.to be_note }
+ end
+
+ context 'merge request diff note event' do
+ let(:target) { create(:note_on_merge_request_diff) }
+
+ it { is_expected.to be_note }
+ end
+ end
+
describe '#visible_to_user?' do
let(:project) { create(:empty_project, :public) }
let(:non_member) { create(:user) }
@@ -89,7 +105,7 @@ describe Event, models: true do
end
end
- context 'note event' do
+ context 'issue note event' do
context 'on non confidential issues' do
let(:target) { note_on_issue }
@@ -112,6 +128,20 @@ describe Event, models: true do
it { expect(event.visible_to_user?(admin)).to eq true }
end
end
+
+ context 'merge request diff note event' do
+ let(:project) { create(:project, :public) }
+ let(:merge_request) { create(:merge_request, source_project: project, author: author, assignee: assignee) }
+ let(:note_on_merge_request) { create(:note_on_merge_request_diff, noteable: merge_request, project: project) }
+ let(:target) { note_on_merge_request }
+
+ it { expect(event.visible_to_user?(non_member)).to eq true }
+ it { expect(event.visible_to_user?(author)).to eq true }
+ it { expect(event.visible_to_user?(assignee)).to eq true }
+ it { expect(event.visible_to_user?(member)).to eq true }
+ it { expect(event.visible_to_user?(guest)).to eq true }
+ it { expect(event.visible_to_user?(admin)).to eq true }
+ end
end
describe '.limit_recent' do
diff --git a/spec/models/label_spec.rb b/spec/models/label_spec.rb
index dad2628651b..f37f44a608e 100644
--- a/spec/models/label_spec.rb
+++ b/spec/models/label_spec.rb
@@ -32,21 +32,20 @@ describe Label, models: true do
it 'should validate title' do
expect(label).not_to allow_value('G,ITLAB').for(:title)
- expect(label).not_to allow_value('G?ITLAB').for(:title)
- expect(label).not_to allow_value('G&ITLAB').for(:title)
expect(label).not_to allow_value('').for(:title)
expect(label).to allow_value('GITLAB').for(:title)
expect(label).to allow_value('gitlab').for(:title)
+ expect(label).to allow_value('G?ITLAB').for(:title)
+ expect(label).to allow_value('G&ITLAB').for(:title)
expect(label).to allow_value("customer's request").for(:title)
end
end
- describe "#title" do
- let(:label) { create(:label, title: "<b>test</b>") }
-
- it "sanitizes title" do
- expect(label.title).to eq("test")
+ describe '#title' do
+ it 'sanitizes title' do
+ label = described_class.new(title: '<b>foo & bar?</b>')
+ expect(label.title).to eq('foo & bar?')
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index a8c777d1e3e..2e89d6de3a2 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -129,6 +129,18 @@ describe Project, models: true do
expect(project2.errors[:repository_storage].first).to match(/is not included in the list/)
end
end
+
+ it 'should not allow an invalid URI as import_url' do
+ project2 = build(:project, import_url: 'invalid://')
+
+ expect(project2).not_to be_valid
+ end
+
+ it 'should allow a valid URI as import_url' do
+ project2 = build(:project, import_url: 'ssh://test@gitlab.com/project.git')
+
+ expect(project2).to be_valid
+ end
end
describe 'default_scope' do
diff --git a/spec/requests/api/issues_spec.rb b/spec/requests/api/issues_spec.rb
index 2cf130df328..6adccb4ebae 100644
--- a/spec/requests/api/issues_spec.rb
+++ b/spec/requests/api/issues_spec.rb
@@ -482,12 +482,16 @@ describe API::API, api: true do
expect(response).to have_http_status(400)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
post api("/projects/#{project.id}/issues", user),
title: 'new issue',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
it 'should return 400 if title is too long' do
@@ -557,12 +561,17 @@ describe API::API, api: true do
expect(response).to have_http_status(404)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
title: 'updated title',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
context 'confidential issues' do
@@ -627,21 +636,18 @@ describe API::API, api: true do
expect(json_response['labels']).to include 'bar'
end
- it 'should return 400 on invalid label names' do
- put api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
- end
-
it 'should allow special label names' do
put api("/projects/#{project.id}/issues/#{issue.id}", user),
- labels: 'label:foo, label-bar,label_bar,label/bar'
- expect(response).to have_http_status(200)
+ labels: 'label:foo, label-bar,label_bar,label/bar,label?bar,label&bar,?,&'
+ expect(response.status).to eq(200)
expect(json_response['labels']).to include 'label:foo'
expect(json_response['labels']).to include 'label-bar'
expect(json_response['labels']).to include 'label_bar'
expect(json_response['labels']).to include 'label/bar'
+ expect(json_response['labels']).to include 'label?bar'
+ expect(json_response['labels']).to include 'label&bar'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
it 'should return 400 if title is too long' do
diff --git a/spec/requests/api/labels_spec.rb b/spec/requests/api/labels_spec.rb
index 0404cf31ff7..63636b4a1b6 100644
--- a/spec/requests/api/labels_spec.rb
+++ b/spec/requests/api/labels_spec.rb
@@ -35,10 +35,10 @@ describe API::API, api: true do
it 'should return created label when only required params' do
post api("/projects/#{project.id}/labels", user),
- name: 'Foo',
+ name: 'Foo & Bar',
color: '#FFAABB'
- expect(response).to have_http_status(201)
- expect(json_response['name']).to eq('Foo')
+ expect(response.status).to eq(201)
+ expect(json_response['name']).to eq('Foo & Bar')
expect(json_response['color']).to eq('#FFAABB')
expect(json_response['description']).to be_nil
end
@@ -71,7 +71,7 @@ describe API::API, api: true do
it 'should return 400 for invalid name' do
post api("/projects/#{project.id}/labels", user),
- name: '?',
+ name: ',',
color: '#FFAABB'
expect(response).to have_http_status(400)
expect(json_response['message']['title']).to eq(['is invalid'])
@@ -167,7 +167,7 @@ describe API::API, api: true do
it 'should return 400 for invalid name' do
put api("/projects/#{project.id}/labels", user),
name: 'label1',
- new_name: '?',
+ new_name: ',',
color: '#FFFFFF'
expect(response).to have_http_status(400)
expect(json_response['message']['title']).to eq(['is invalid'])
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 61e897edf87..5d81844fb84 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -243,17 +243,19 @@ describe API::API, api: true do
expect(response).to have_http_status(400)
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
post api("/projects/#{project.id}/merge_requests", user),
title: 'Test merge_request',
source_branch: 'markdown',
target_branch: 'master',
author: user,
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(
- ['is invalid']
- )
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(201)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
context 'with existing MR' do
@@ -492,13 +494,17 @@ describe API::API, api: true do
expect(json_response['target_branch']).to eq('wiki')
end
- it 'should return 400 on invalid label names' do
+ it 'should allow special label names' do
put api("/projects/#{project.id}/merge_requests/#{merge_request.id}",
user),
title: 'new issue',
- labels: 'label, ?'
- expect(response).to have_http_status(400)
- expect(json_response['message']['labels']['?']['title']).to eq(['is invalid'])
+ labels: 'label, label?, label&foo, ?, &'
+ expect(response.status).to eq(200)
+ expect(json_response['labels']).to include 'label'
+ expect(json_response['labels']).to include 'label?'
+ expect(json_response['labels']).to include 'label&foo'
+ expect(json_response['labels']).to include '?'
+ expect(json_response['labels']).to include '&'
end
end
diff --git a/vendor/gitignore/Android.gitignore b/vendor/gitignore/Android.gitignore
index f6b286cea98..e5df7b9150e 100644
--- a/vendor/gitignore/Android.gitignore
+++ b/vendor/gitignore/Android.gitignore
@@ -35,6 +35,7 @@ captures/
# Intellij
*.iml
.idea/workspace.xml
+.idea/libraries
# Keystore files
*.jks
diff --git a/vendor/gitignore/C++.gitignore b/vendor/gitignore/C++.gitignore
index 4581ef2eeef..259148fa18f 100644
--- a/vendor/gitignore/C++.gitignore
+++ b/vendor/gitignore/C++.gitignore
@@ -1,3 +1,6 @@
+# Prerequisites
+*.d
+
# Compiled Object files
*.slo
*.lo
diff --git a/vendor/gitignore/C.gitignore b/vendor/gitignore/C.gitignore
index f805e810e5c..7a065c709c7 100644
--- a/vendor/gitignore/C.gitignore
+++ b/vendor/gitignore/C.gitignore
@@ -1,3 +1,6 @@
+# Prerequisites
+*.d
+
# Object files
*.o
*.ko
diff --git a/vendor/gitignore/Gradle.gitignore b/vendor/gitignore/Gradle.gitignore
index 77617a15c38..a1fc39c070f 100644
--- a/vendor/gitignore/Gradle.gitignore
+++ b/vendor/gitignore/Gradle.gitignore
@@ -1,5 +1,5 @@
.gradle
-build/
+/build/
# Ignore Gradle GUI config
gradle-app.setting
diff --git a/vendor/gitignore/LICENSE b/vendor/gitignore/LICENSE
index b8a103ac9b1..0e259d42c99 100644
--- a/vendor/gitignore/LICENSE
+++ b/vendor/gitignore/LICENSE
@@ -1,19 +1,121 @@
-Copyright (c) 2016 GitHub, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
+Creative Commons Legal Code
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
diff --git a/vendor/gitignore/Node.gitignore b/vendor/gitignore/Node.gitignore
index 5148e527a7e..aea5294de9d 100644
--- a/vendor/gitignore/Node.gitignore
+++ b/vendor/gitignore/Node.gitignore
@@ -7,6 +7,7 @@ npm-debug.log*
pids
*.pid
*.seed
+*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
diff --git a/vendor/gitignore/TeX.gitignore b/vendor/gitignore/TeX.gitignore
index 4123a577c47..3cb097c9d5e 100644
--- a/vendor/gitignore/TeX.gitignore
+++ b/vendor/gitignore/TeX.gitignore
@@ -152,6 +152,9 @@ pythontex-files-*/
# todonotes
*.tdo
+# easy-todo
+*.lod
+
# xindy
*.xdy
diff --git a/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml
new file mode 100644
index 00000000000..1678a47f9ac
--- /dev/null
+++ b/vendor/gitlab-ci-yml/Maven.gitlab-ci.yml
@@ -0,0 +1,102 @@
+---
+# Build JAVA applications using Apache Maven (http://maven.apache.org)
+# For docker image tags see https://hub.docker.com/_/maven/
+#
+# For general lifecycle information see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
+#
+# This template will build and test your projects as well as create the documentation.
+#
+# * Caches downloaded dependencies and plugins between invocation.
+# * Does only verify merge requests but deploy built artifacts of the
+# master branch.
+# * Shows how to use multiple jobs in test stage for verifying functionality
+# with multiple JDKs.
+# * Uses site:stage to collect the documentation for multi-module projects.
+# * Publishes the documentation for `master` branch.
+
+variables:
+ # This will supress any download for dependencies and plugins or upload messages which would clutter the console log.
+ # `showDateTime` will show the passed time in milliseconds. You need to specify `--batch-mode` to make this work.
+ MAVEN_OPTS: "-Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=WARN -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
+ # As of Maven 3.3.0 instead of this you may define these options in `.mvn/maven.config` so the same config is used
+ # when running from the command line.
+ # `installAtEnd` and `deployAtEnd`are only effective with recent version of the corresponding plugins.
+ MAVEN_CLI_OPTS: "--batch-mode --errors --fail-at-end --show-version -DinstallAtEnd=true -DdeployAtEnd=true"
+
+# Cache downloaded dependencies and plugins between builds.
+cache:
+ paths:
+ - /root/.m2/repository/
+
+# This will only validate and compile stuff and run e.g. maven-enforcer-plugin.
+# Because some enforcer rules might check dependency convergence and class duplications
+# we use `test-compile` here instead of `validate`, so the correct classpath is picked up.
+.validate: &validate
+ stage: build
+ script:
+ - 'mvn $MAVEN_CLI_OPTS test-compile'
+
+# For merge requests do not `deploy` but only run `verify`.
+# See https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
+.verify: &verify
+ stage: test
+ script:
+ - 'mvn $MAVEN_CLI_OPTS verify site site:stage'
+ except:
+ - master
+
+# Validate merge requests using JDK7
+validate:jdk7:
+ <<: *validate
+ image: maven:3.3.9-jdk-7
+
+# Validate merge requests using JDK8
+validate:jdk8:
+ <<: *validate
+ image: maven:3.3.9-jdk-8
+
+# Verify merge requests using JDK7
+verify:jdk7:
+ <<: *verify
+ image: maven:3.3.9-jdk-7
+
+# Verify merge requests using JDK8
+verify:jdk8:
+ <<: *verify
+ image: maven:3.3.9-jdk-8
+
+
+# For `master` branch run `mvn deploy` automatically.
+# Here you need to decide whether you want to use JDK7 or 8.
+# To get this working you need to define a volume while configuring your gitlab-ci-multi-runner.
+# Mount your `settings.xml` as `/root/.m2/settings.xml` which holds your secrets.
+# See https://maven.apache.org/settings.html
+deploy:jdk8:
+ # Use stage test here, so the pages job may later pickup the created site.
+ stage: test
+ script:
+ - 'mvn $MAVEN_CLI_OPTS deploy site site:stage'
+ only:
+ - master
+ # Archive up the built documentation site.
+ artifacts:
+ paths:
+ - target/staging
+ image: maven:3.3.9-jdk-8
+
+
+pages:
+ image: busybox:latest
+ stage: deploy
+ script:
+ # Because Maven appends the artifactId automatically to the staging path if you did define a parent pom,
+ # you might need to use `mv target/staging/YOUR_ARTIFACT_ID public` instead.
+ - mv target/staging public
+ dependencies:
+ - deploy:jdk8
+ artifacts:
+ paths:
+ - public
+ only:
+ - master
+
diff --git a/vendor/gitlab-ci-yml/Pages/brunch.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml
index 7fcc0b436b5..7fcc0b436b5 100644
--- a/vendor/gitlab-ci-yml/Pages/brunch.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml
index 791afdd23f1..791afdd23f1 100644
--- a/vendor/gitlab-ci-yml/Pages/doxygen.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml
index 249a168aa33..249a168aa33 100644
--- a/vendor/gitlab-ci-yml/Pages/html.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml
index dd3ef149668..dd3ef149668 100644
--- a/vendor/gitlab-ci-yml/Pages/harp.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml
index b468d79bcad..b468d79bcad 100644
--- a/vendor/gitlab-ci-yml/Pages/hexo.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml
index 45df6975259..45df6975259 100644
--- a/vendor/gitlab-ci-yml/Pages/hugo.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml
index f5b40f2b9f1..f5b40f2b9f1 100644
--- a/vendor/gitlab-ci-yml/Pages/hyde.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml
index 36918fc005a..36918fc005a 100644
--- a/vendor/gitlab-ci-yml/Pages/jekyll.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml
index c5c44a5d86c..c5c44a5d86c 100644
--- a/vendor/gitlab-ci-yml/Pages/lektor.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml
index 50e8b7ccd46..50e8b7ccd46 100644
--- a/vendor/gitlab-ci-yml/Pages/metalsmith.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml
index 9f4cc0574d6..9f4cc0574d6 100644
--- a/vendor/gitlab-ci-yml/Pages/middleman.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml
index b469b316ba5..b469b316ba5 100644
--- a/vendor/gitlab-ci-yml/Pages/nanoc.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml
index 4762ec9acfd..4762ec9acfd 100644
--- a/vendor/gitlab-ci-yml/Pages/octopress.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml
index c5f3154f587..c5f3154f587 100644
--- a/vendor/gitlab-ci-yml/Pages/pelican.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml
diff --git a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
index 78f3e39949f..2a761bbd127 100644
--- a/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Ruby.gitlab-ci.yml
@@ -10,12 +10,19 @@ services:
- redis:latest
- postgres:latest
+# Cache gems in between builds
+cache:
+ paths:
+ - vendor/ruby
+
# This is a basic example for a gem or script which doesn't use
# services such as redis or postgres
before_script:
- - gem install bundler # Bundler is not installed with the image
- - bundle install -j $(nproc) # Install dependencies
+ - ruby -v # Print out ruby version for debugging
+ - gem install bundler --no-ri --no-rdoc # Bundler is not installed with the image
+ - bundle install -j $(nproc) --path vendor # Install dependencies into ./vendor/ruby
+# Optional - Delete if not using `rubocop`
rubocop:
script:
- rubocop
@@ -26,5 +33,5 @@ rspec:
rails:
script:
- - rake db:migrate
- - rspec spec
+ - bundle exec rake db:migrate
+ - bundle exec rake test
diff --git a/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
new file mode 100644
index 00000000000..ae3f7405ea3
--- /dev/null
+++ b/vendor/gitlab-ci-yml/Rust.gitlab-ci.yml
@@ -0,0 +1,23 @@
+# Unofficial language image. Look for the different tagged releases at:
+# https://hub.docker.com/r/scorpil/rust/tags/
+image: "scorpil/rust:stable"
+
+# Optional: Pick zero or more services to be used on all builds.
+# Only needed when using a docker container to run your tests in.
+# Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-service
+#services:
+# - mysql:latest
+# - redis:latest
+# - postgres:latest
+
+# Optional: Install a C compiler, cmake and git into the container.
+# You will often need this when you (or any of your dependencies) depends on C code.
+#before_script:
+#- apt-get update -yqq
+#- apt-get install -yqq --no-install-recommends build-essential
+
+# Use cargo to test the project
+test:cargo:
+ script:
+ - rustc --version && cargo --version # Print version info for debugging
+ - cargo test --verbose --jobs 1 --release # Don't paralize to make errors more readable
diff --git a/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml b/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml
new file mode 100644
index 00000000000..443ba42e38c
--- /dev/null
+++ b/vendor/gitlab-ci-yml/Scala.gitlab-ci.yml
@@ -0,0 +1,22 @@
+# Official Java image. Look for the different tagged releases at
+# https://hub.docker.com/r/library/java/tags/ . A Java image is not required
+# but an image with a JVM speeds up the build a bit.
+image: java:8
+
+before_script:
+ # Enable the usage of sources over https
+ - apt-get update -yqq
+ - apt-get install apt-transport-https -yqq
+ # Add keyserver for SBT
+ - echo "deb http://dl.bintray.com/sbt/debian /" | tee -a /etc/apt/sources.list.d/sbt.list
+ - apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 642AC823
+ # Install SBT
+ - apt-get update -yqq
+ - apt-get install sbt -yqq
+ # Log the sbt version
+ - sbt sbt-version
+
+test:
+ script:
+ # Execute your project's tests
+ - sbt clean test