diff options
45 files changed, 814 insertions, 85 deletions
diff --git a/CHANGELOG b/CHANGELOG index 8ef934bf80d..40bccaabb39 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,10 +37,12 @@ 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 + - Allow '?', or '&' for label names v 8.9.5 (unreleased) - Improve the request / withdraw access button. !4860 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/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/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/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/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/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/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&</span></a>\.\))) + end + + it 'ignores invalid label names' do + act = "Label #{Label.reference_prefix}#{label.name.reverse}" + exp = "Label #{Label.reference_prefix}&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 & references\?</span></a>\.\))) + end + + it 'ignores invalid label names' do + act = %(Label #{Label.reference_prefix}"#{label.name.reverse}") + exp = %(Label #{Label.reference_prefix}"?secnerefer & 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/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 new file mode 100644 index 00000000000..7fcc0b436b5 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Brunch.gitlab-ci.yml @@ -0,0 +1,16 @@ +# Full project: https://gitlab.com/pages/brunch +image: node:4.2.2 + +pages: + cache: + paths: + - node_modules/ + + script: + - npm install -g brunch + - brunch build --production + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml new file mode 100644 index 00000000000..791afdd23f1 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Doxygen.gitlab-ci.yml @@ -0,0 +1,13 @@ +# Full project: https://gitlab.com/pages/doxygen +image: alpine + +pages: + script: + - apk update && apk add doxygen + - doxygen doxygen/Doxyfile + - mv doxygen/documentation/html/ public/ + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml new file mode 100644 index 00000000000..249a168aa33 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/HTML.gitlab-ci.yml @@ -0,0 +1,12 @@ +# Full project: https://gitlab.com/pages/plain-html +pages: + stage: deploy + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml new file mode 100644 index 00000000000..dd3ef149668 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Harp.gitlab-ci.yml @@ -0,0 +1,16 @@ +# Full project: https://gitlab.com/pages/harp +image: node:4.2.2 + +pages: + cache: + paths: + - node_modules + + script: + - npm install -g harp + - harp compile ./ public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml new file mode 100644 index 00000000000..b468d79bcad --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Hexo.gitlab-ci.yml @@ -0,0 +1,25 @@ +# Full project: https://gitlab.com/pages/hexo +image: python:2.7 + +cache: + paths: + - vendor/ + +test: + stage: test + script: + - pip install hyde + - hyde gen + except: + - master + +pages: + stage: deploy + script: + - pip install hyde + - hyde gen -d public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml new file mode 100644 index 00000000000..45df6975259 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Hugo.gitlab-ci.yml @@ -0,0 +1,11 @@ +# Full project: https://gitlab.com/pages/hugo +image: publysher/hugo + +pages: + script: + - hugo + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml new file mode 100644 index 00000000000..f5b40f2b9f1 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Hyde.gitlab-ci.yml @@ -0,0 +1,25 @@ +# Full project: https://gitlab.com/pages/hyde +image: python:2.7 + +cache: + paths: + - vendor/ + +test: + stage: test + script: + - pip install hyde + - hyde gen + except: + - master + +pages: + stage: deploy + script: + - pip install hyde + - hyde gen -d public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml new file mode 100644 index 00000000000..36918fc005a --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Jekyll.gitlab-ci.yml @@ -0,0 +1,24 @@ +# Full project: https://gitlab.com/pages/jekyll +image: ruby:2.3 + +test: + stage: test + script: + - gem install jekyll + - jekyll build -d test + artifacts: + paths: + - test + except: + - master + +pages: + stage: deploy + script: + - gem install jekyll + - jekyll build -d public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml new file mode 100644 index 00000000000..c5c44a5d86c --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Lektor.gitlab-ci.yml @@ -0,0 +1,12 @@ +# Full project: https://gitlab.com/pages/hyde +image: python:2.7 + +pages: + script: + - pip install lektor + - lektor build --output-path public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml new file mode 100644 index 00000000000..50e8b7ccd46 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Metalsmith.gitlab-ci.yml @@ -0,0 +1,17 @@ +# Full project: https://gitlab.com/pages/metalsmith +image: node:4.2.2 + +pages: + cache: + paths: + - node_modules/ + + script: + - npm install -g metalsmith + - npm install + - make build + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml new file mode 100644 index 00000000000..9f4cc0574d6 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Middleman.gitlab-ci.yml @@ -0,0 +1,27 @@ +# Full project: https://gitlab.com/pages/middleman +image: ruby:2.3 + +cache: + paths: + - vendor + +test: + script: + - apt-get update -yqqq + - apt-get install -y nodejs + - bundle install --path vendor + - bundle exec middleman build + except: + - master + +pages: + script: + - apt-get update -yqqq + - apt-get install -y nodejs + - bundle install --path vendor + - bundle exec middleman build + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml new file mode 100644 index 00000000000..b469b316ba5 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Nanoc.gitlab-ci.yml @@ -0,0 +1,12 @@ +# Full project: https://gitlab.com/pages/nanoc +image: ruby:2.3 + +pages: + script: + - bundle install -j4 + - nanoc + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml new file mode 100644 index 00000000000..4762ec9acfd --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Octopress.gitlab-ci.yml @@ -0,0 +1,15 @@ +# Full project: https://gitlab.com/pages/octopress +image: ruby:2.3 + +pages: + script: + - apt-get update -qq && apt-get install -qq nodejs + - bundle install -j4 + - bundle exec rake generate + - mv public .public + - mv .public/octopress public + artifacts: + paths: + - public + only: + - master diff --git a/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml new file mode 100644 index 00000000000..c5f3154f587 --- /dev/null +++ b/vendor/gitlab-ci-yml/Pages/Pelican.gitlab-ci.yml @@ -0,0 +1,10 @@ +# Full project: https://gitlab.com/pages/pelican +image: python:2.7-alpine + +pages: + script: + - pip install -r requirements.txt + - pelican -s publishconf.py + artifacts: + paths: + - public/ 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 |