From df5841a518930006549696ad143d2f571c508085 Mon Sep 17 00:00:00 2001 From: Kevin Nesmith Date: Mon, 1 May 2017 22:20:41 +0000 Subject: Update getting_started_part_one.md. Minor spelling error. --- doc/user/project/pages/getting_started_part_one.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md index e92549aa0df..8a8a73a156c 100644 --- a/doc/user/project/pages/getting_started_part_one.md +++ b/doc/user/project/pages/getting_started_part_one.md @@ -9,7 +9,7 @@ - [Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](getting_started_part_three.md) - [Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](getting_started_part_four.md) -## GitLab Pages form A to Z +## GitLab Pages from A to Z This is a comprehensive guide, made for those who want to publish a website with GitLab Pages but aren't familiar with -- cgit v1.2.1 From 4e06e833b370d736ecad32bf7707683c08c26a8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Fri, 5 May 2017 12:05:58 +0200 Subject: Fix a broken link for the "How to Configure LDAP with GitLab EE" article MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémy Coutable --- doc/topics/authentication/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/topics/authentication/index.md b/doc/topics/authentication/index.md index 3e756d96ed2..0c0d482499a 100644 --- a/doc/topics/authentication/index.md +++ b/doc/topics/authentication/index.md @@ -19,7 +19,7 @@ This page gathers all the resources for the topic **Authentication** within GitL - [Enforce Two-factor Authentication (2FA)](../../security/two_factor_authentication.md#enforce-two-factor-authentication-2fa) - **Articles:** - [How to Configure LDAP with GitLab CE](../../articles/how_to_configure_ldap_gitlab_ce/index.md) - - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/articles/how_to_configure_ldap_gitlab_ee/) + - [How to Configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) - [Feature Highlight: LDAP Integration](https://about.gitlab.com/2014/07/10/feature-highlight-ldap-sync/) - [Debugging LDAP](https://about.gitlab.com/handbook/support/workflows/ldap/debugging_ldap.html) - **Integrations:** -- cgit v1.2.1 From f2a4420d66216e3a9172f4ab45c6b4fa96578117 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Sun, 16 Apr 2017 13:14:39 +0200 Subject: Store retried in database for CI builds --- app/models/ci/build.rb | 4 +-- app/models/commit_status.rb | 11 ++----- app/services/ci/process_pipeline_service.rb | 20 +++++++++++++ app/services/ci/retry_build_service.rb | 13 +++++++-- app/services/ci/retry_pipeline_service.rb | 2 +- .../store-retried-in-database-for-ci-builds.yml | 4 +++ .../20170503004426_add_retried_to_ci_build.rb | 15 ++++++++++ .../20170503004427_upate_retried_for_ci_build.rb | 29 ++++++++++++++++++ db/schema.rb | 1 + .../gitlab/import_export/safe_model_attributes.yml | 1 + spec/models/ci/pipeline_spec.rb | 34 +++++++++++++--------- spec/models/ci/stage_spec.rb | 4 +++ spec/models/commit_status_spec.rb | 24 ++++++++++++--- spec/requests/api/commit_statuses_spec.rb | 4 +-- spec/services/ci/process_pipeline_service_spec.rb | 15 ++++++++++ spec/services/ci/retry_build_service_spec.rb | 11 +++++-- spec/services/ci/retry_pipeline_service_spec.rb | 2 +- .../projects/pipelines/_stage.html.haml_spec.rb | 5 ++-- 18 files changed, 158 insertions(+), 41 deletions(-) create mode 100644 changelogs/unreleased/store-retried-in-database-for-ci-builds.yml create mode 100644 db/migrate/20170503004426_add_retried_to_ci_build.rb create mode 100644 db/post_migrate/20170503004427_upate_retried_for_ci_build.rb diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 971ab7cb0ee..3c4a4d93349 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -124,8 +124,8 @@ module Ci success? || failed? || canceled? end - def retried? - !self.pipeline.statuses.latest.include?(self) + def latest? + !retried? end def expanded_environment_name diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 2c4033146bf..528bf4d87ac 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -18,13 +18,7 @@ class CommitStatus < ActiveRecord::Base validates :name, presence: true alias_attribute :author, :user - - scope :latest, -> do - max_id = unscope(:select).select("max(#{quoted_table_name}.id)") - - where(id: max_id.group(:name, :commit_id)) - end - + scope :failed_but_allowed, -> do where(allow_failure: true, status: [:failed, :canceled]) end @@ -37,7 +31,8 @@ class CommitStatus < ActiveRecord::Base false, all_state_names - [:failed, :canceled, :manual]) end - scope :retried, -> { where.not(id: latest) } + scope :latest, -> { where(retried: false) } + scope :retried, -> { where(retried: true) } scope :ordered, -> { order(:name) } scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) } scope :retried_ordered, -> { retried.ordered.includes(project: :namespace) } diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb index 33edcd60944..647836de384 100644 --- a/app/services/ci/process_pipeline_service.rb +++ b/app/services/ci/process_pipeline_service.rb @@ -5,6 +5,8 @@ module Ci def execute(pipeline) @pipeline = pipeline + update_retried + new_builds = stage_indexes_of_created_builds.map do |index| process_stage(index) @@ -71,5 +73,23 @@ module Ci def created_builds pipeline.builds.created end + + # This method is for compatibility and data consistency and should be removed with 9.3 version of GitLab + # This replicates what is db/post_migrate/20170416103934_upate_retried_for_ci_build.rb + # and ensures that functionality will not be broken before migration is run + # this updates only when there are data that needs to be updated, there are two groups with no retried flag + def update_retried + # find the latest builds for each name + latest_statuses = pipeline.statuses.latest + .group(:name) + .having('count(*) > 1') + .pluck('max(id)', 'name') + + # mark builds that are retried + pipeline.statuses.latest + .where(name: latest_statuses.map(&:second)) + .where.not(id: latest_statuses.map(&:first)) + .update_all(retried: true) if latest_statuses.any? + end end end diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb index 89da05b72bb..9c532b585a1 100644 --- a/app/services/ci/retry_build_service.rb +++ b/app/services/ci/retry_build_service.rb @@ -6,7 +6,7 @@ module Ci description tag_list].freeze def execute(build) - reprocess(build).tap do |new_build| + reprocess!(build).tap do |new_build| build.pipeline.mark_as_processable_after_stage(build.stage_idx) new_build.enqueue! @@ -17,7 +17,7 @@ module Ci end end - def reprocess(build) + def reprocess!(build) unless can?(current_user, :update_build, build) raise Gitlab::Access::AccessDeniedError end @@ -28,7 +28,14 @@ module Ci attributes.push([:user, current_user]) - project.builds.create(Hash[attributes]) + Ci::Build.transaction do + # mark all other builds of that name as retried + build.pipeline.builds.where(name: build.name) + .where.not(retried: true) + .update_all(retried: true) + + project.builds.create!(Hash[attributes]) + end end end end diff --git a/app/services/ci/retry_pipeline_service.rb b/app/services/ci/retry_pipeline_service.rb index 5b207157345..c5a43869990 100644 --- a/app/services/ci/retry_pipeline_service.rb +++ b/app/services/ci/retry_pipeline_service.rb @@ -11,7 +11,7 @@ module Ci next unless can?(current_user, :update_build, build) Ci::RetryBuildService.new(project, current_user) - .reprocess(build) + .reprocess!(build) end pipeline.builds.latest.skipped.find_each do |skipped| diff --git a/changelogs/unreleased/store-retried-in-database-for-ci-builds.yml b/changelogs/unreleased/store-retried-in-database-for-ci-builds.yml new file mode 100644 index 00000000000..9185113f51c --- /dev/null +++ b/changelogs/unreleased/store-retried-in-database-for-ci-builds.yml @@ -0,0 +1,4 @@ +--- +title: Store retried in database for CI Builds +merge_request: +author: diff --git a/db/migrate/20170503004426_add_retried_to_ci_build.rb b/db/migrate/20170503004426_add_retried_to_ci_build.rb new file mode 100644 index 00000000000..9f509f97f14 --- /dev/null +++ b/db/migrate/20170503004426_add_retried_to_ci_build.rb @@ -0,0 +1,15 @@ +class AddRetriedToCiBuild < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + add_column_with_default(:ci_builds, :retried, :boolean, default: false) + end + + def down + remove_column(:ci_builds, :retried) + end +end diff --git a/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb b/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb new file mode 100644 index 00000000000..e12180930a7 --- /dev/null +++ b/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb @@ -0,0 +1,29 @@ +class UpateRetriedForCiBuild < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + disable_statement_timeout + + latest_id = <<-SQL.strip_heredoc + SELECT MAX(ci_builds2.id) + FROM ci_builds ci_builds2 + WHERE ci_builds.commit_id=ci_builds2.commit_id + AND ci_builds.name=ci_builds2.name + SQL + + # This is slow update as it does single-row query + # This is designed to be run as idle, or a post deployment migration + is_retried = Arel.sql("((#{latest_id}) != ci_builds.id)") + + update_column_in_batches(:ci_builds, :retried, is_retried) do |table, query| + query.where(table[:retried].eq(false)) + end + end + + def down + end +end diff --git a/db/schema.rb b/db/schema.rb index 61af066ed3b..8046e9b48a7 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -232,6 +232,7 @@ ActiveRecord::Schema.define(version: 20170504102911) do t.integer "lock_version" t.string "coverage_regex" t.integer "auto_canceled_by_id" + t.boolean "retried", default: false, null: false end add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index a66086f8b47..56b9729a870 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -229,6 +229,7 @@ CommitStatus: - lock_version - coverage_regex - auto_canceled_by_id +- retried Ci::Variable: - id - project_id diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 3b222ea1c3d..d79f1e22f32 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -59,8 +59,8 @@ describe Ci::Pipeline, models: true do subject { pipeline.retried } before do - @build1 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy' - @build2 = FactoryGirl.create :ci_build, pipeline: pipeline, name: 'deploy' + @build1 = create(:ci_build, pipeline: pipeline, name: 'deploy', retried: true) + @build2 = create(:ci_build, pipeline: pipeline, name: 'deploy') end it 'returns old builds' do @@ -69,31 +69,31 @@ describe Ci::Pipeline, models: true do end describe "coverage" do - let(:project) { FactoryGirl.create :empty_project, build_coverage_regex: "/.*/" } - let(:pipeline) { FactoryGirl.create :ci_empty_pipeline, project: project } + let(:project) { create(:empty_project, build_coverage_regex: "/.*/") } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } it "calculates average when there are two builds with coverage" do - FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline - FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline + create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) + create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) expect(pipeline.coverage).to eq("35.00") end it "calculates average when there are two builds with coverage and one with nil" do - FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline - FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline - FactoryGirl.create :ci_build, pipeline: pipeline + create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) + create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) + create(:ci_build, pipeline: pipeline) expect(pipeline.coverage).to eq("35.00") end it "calculates average when there are two builds with coverage and one is retried" do - FactoryGirl.create :ci_build, name: "rspec", coverage: 30, pipeline: pipeline - FactoryGirl.create :ci_build, name: "rubocop", coverage: 30, pipeline: pipeline - FactoryGirl.create :ci_build, name: "rubocop", coverage: 40, pipeline: pipeline + create(:ci_build, name: "rspec", coverage: 30, pipeline: pipeline) + create(:ci_build, name: "rubocop", coverage: 30, pipeline: pipeline, retried: true) + create(:ci_build, name: "rubocop", coverage: 40, pipeline: pipeline) expect(pipeline.coverage).to eq("35.00") end it "calculates average when there is one build without coverage" do - FactoryGirl.create :ci_build, pipeline: pipeline + FactoryGirl.create(:ci_build, pipeline: pipeline) expect(pipeline.coverage).to be_nil end end @@ -221,13 +221,15 @@ describe Ci::Pipeline, models: true do %w(deploy running)]) end - context 'when commit status is retried' do + context 'when commit status is retried' do before do create(:commit_status, pipeline: pipeline, stage: 'build', name: 'mac', stage_idx: 0, status: 'success') + + pipeline.process! end it 'ignores the previous state' do @@ -488,6 +490,10 @@ describe Ci::Pipeline, models: true do context 'there are multiple of the same name' do let!(:manual2) { create(:ci_build, :manual, pipeline: pipeline, name: 'deploy') } + before do + manual.update(retried: true) + end + it 'returns latest one' do is_expected.to contain_exactly(manual2) end diff --git a/spec/models/ci/stage_spec.rb b/spec/models/ci/stage_spec.rb index 372b662fab2..8f6ab908987 100644 --- a/spec/models/ci/stage_spec.rb +++ b/spec/models/ci/stage_spec.rb @@ -102,6 +102,10 @@ describe Ci::Stage, models: true do context 'and builds are retried' do let!(:new_build) { create_job(:ci_build, status: :success) } + before do + stage_build.update(retried: true) + end + it "returns status of latest build" do is_expected.to eq('success') end diff --git a/spec/models/commit_status_spec.rb b/spec/models/commit_status_spec.rb index 0ee85489574..6947affcc1e 100644 --- a/spec/models/commit_status_spec.rb +++ b/spec/models/commit_status_spec.rb @@ -157,9 +157,9 @@ describe CommitStatus, :models do subject { described_class.latest.order(:id) } let(:statuses) do - [create_status(name: 'aa', ref: 'bb', status: 'running'), - create_status(name: 'cc', ref: 'cc', status: 'pending'), - create_status(name: 'aa', ref: 'cc', status: 'success'), + [create_status(name: 'aa', ref: 'bb', status: 'running', retried: true), + create_status(name: 'cc', ref: 'cc', status: 'pending', retried: true), + create_status(name: 'aa', ref: 'cc', status: 'success', retried: true), create_status(name: 'cc', ref: 'bb', status: 'success'), create_status(name: 'aa', ref: 'bb', status: 'success')] end @@ -169,6 +169,22 @@ describe CommitStatus, :models do end end + describe '.retried' do + subject { described_class.retried.order(:id) } + + let(:statuses) do + [create_status(name: 'aa', ref: 'bb', status: 'running', retried: true), + create_status(name: 'cc', ref: 'cc', status: 'pending', retried: true), + create_status(name: 'aa', ref: 'cc', status: 'success', retried: true), + create_status(name: 'cc', ref: 'bb', status: 'success'), + create_status(name: 'aa', ref: 'bb', status: 'success')] + end + + it 'returns unique statuses' do + is_expected.to contain_exactly(*statuses.values_at(0, 1, 2)) + end + end + describe '.running_or_pending' do subject { described_class.running_or_pending.order(:id) } @@ -181,7 +197,7 @@ describe CommitStatus, :models do end it 'returns statuses that are running or pending' do - is_expected.to eq(statuses.values_at(0, 1)) + is_expected.to contain_exactly(*statuses.values_at(0, 1)) end end diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index 1233cdc64c4..1c163cee152 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -26,8 +26,8 @@ describe API::CommitStatuses do create(:commit_status, { pipeline: commit, ref: commit.ref }.merge(opts)) end - let!(:status1) { create_status(master, status: 'running') } - let!(:status2) { create_status(master, name: 'coverage', status: 'pending') } + let!(:status1) { create_status(master, status: 'running', retried: true) } + let!(:status2) { create_status(master, name: 'coverage', status: 'pending', retried: true) } let!(:status3) { create_status(develop, status: 'running', allow_failure: true) } let!(:status4) { create_status(master, name: 'coverage', status: 'success') } let!(:status5) { create_status(develop, name: 'coverage', status: 'success') } diff --git a/spec/services/ci/process_pipeline_service_spec.rb b/spec/services/ci/process_pipeline_service_spec.rb index cf773866a6f..f1e1e1b6067 100644 --- a/spec/services/ci/process_pipeline_service_spec.rb +++ b/spec/services/ci/process_pipeline_service_spec.rb @@ -425,6 +425,21 @@ describe Ci::ProcessPipelineService, '#execute', :services do end end + context 'updates a list of retried builds' do + subject { described_class.retried.order(:id) } + + let!(:build_retried) { create_build('build') } + let!(:build) { create_build('build') } + let!(:test) { create_build('test') } + + it 'returns unique statuses' do + process_pipeline + + expect(all_builds.latest).to contain_exactly(build, test) + expect(all_builds.retried).to contain_exactly(build_retried) + end + end + def process_pipeline described_class.new(pipeline.project, user).execute(pipeline) end diff --git a/spec/services/ci/retry_build_service_spec.rb b/spec/services/ci/retry_build_service_spec.rb index b2d37657770..7254e6b357a 100644 --- a/spec/services/ci/retry_build_service_spec.rb +++ b/spec/services/ci/retry_build_service_spec.rb @@ -22,7 +22,7 @@ describe Ci::RetryBuildService, :services do %i[type lock_version target_url base_tags commit_id deployments erased_by_id last_deployment project_id runner_id tag_taggings taggings tags trigger_request_id - user_id auto_canceled_by_id].freeze + user_id auto_canceled_by_id retried].freeze shared_examples 'build duplication' do let(:build) do @@ -115,7 +115,7 @@ describe Ci::RetryBuildService, :services do end describe '#reprocess' do - let(:new_build) { service.reprocess(build) } + let(:new_build) { service.reprocess!(build) } context 'when user has ability to execute build' do before do @@ -131,11 +131,16 @@ describe Ci::RetryBuildService, :services do it 'does not enqueue the new build' do expect(new_build).to be_created end + + it 'does mark old build as retried' do + expect(new_build).to be_latest + expect(build.reload).to be_retried + end end context 'when user does not have ability to execute build' do it 'raises an error' do - expect { service.reprocess(build) } + expect { service.reprocess!(build) } .to raise_error Gitlab::Access::AccessDeniedError end end diff --git a/spec/services/ci/retry_pipeline_service_spec.rb b/spec/services/ci/retry_pipeline_service_spec.rb index 40e151545c9..d941d56c0d8 100644 --- a/spec/services/ci/retry_pipeline_service_spec.rb +++ b/spec/services/ci/retry_pipeline_service_spec.rb @@ -13,7 +13,7 @@ describe Ci::RetryPipelineService, '#execute', :services do context 'when there are already retried jobs present' do before do - create_build('rspec', :canceled, 0) + create_build('rspec', :canceled, 0, retried: true) create_build('rspec', :failed, 0) end diff --git a/spec/views/projects/pipelines/_stage.html.haml_spec.rb b/spec/views/projects/pipelines/_stage.html.haml_spec.rb index 10095ad7694..9c91c4e0fbd 100644 --- a/spec/views/projects/pipelines/_stage.html.haml_spec.rb +++ b/spec/views/projects/pipelines/_stage.html.haml_spec.rb @@ -39,9 +39,8 @@ describe 'projects/pipelines/_stage', :view do context 'when there are retried builds present' do before do - create_list(:ci_build, 2, name: 'test:build', - stage: stage.name, - pipeline: pipeline) + create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline, retried: true) + create(:ci_build, name: 'test:build', stage: stage.name, pipeline: pipeline) end it 'shows only latest builds' do -- cgit v1.2.1 From 62e130657bf05c048e180c991c8774200674860a Mon Sep 17 00:00:00 2001 From: Toni Date: Mon, 8 May 2017 10:05:59 +0000 Subject: Update README.md with projects example --- doc/api/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/api/README.md b/doc/api/README.md index d444ce94573..1b0f6470b13 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -61,8 +61,9 @@ The following documentation is for the [internal CI API](ci/README.md): ## Authentication -All API requests require authentication via a session cookie or token. There are -three types of tokens available: private tokens, OAuth 2 tokens, and personal +Most API requests require authentication via a session cookie or token. For those cases where it is not required, this will be mentioned in the documentation +for each individual endpoint. For example, the [`/projects/:id` endpoint](projects.md). +There are three types of tokens available: private tokens, OAuth 2 tokens, and personal access tokens. If authentication information is invalid or omitted, an error message will be -- cgit v1.2.1 From 1e0df21a74017deb780023ed83f04dbbeed13899 Mon Sep 17 00:00:00 2001 From: Achilleas Pipinellis Date: Tue, 9 May 2017 16:59:20 +0200 Subject: Hide GCP install guide from index page until our image is added --- doc/install/README.md | 2 -- doc/install/google_cloud_platform/index.md | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/install/README.md b/doc/install/README.md index 58cc7d312fd..eabea002af9 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -18,8 +18,6 @@ the hardware requirements. Useful for unsupported systems like *BSD. For an overview of the directory structure, read the [structure documentation](structure.md). - [Docker](https://docs.gitlab.com/omnibus/docker/) - Install GitLab using Docker. -- [Installation on Google Cloud Platform](google_cloud_platform/index.md) - Install - GitLab on Google Cloud Platform using our official image. - Testing only! [DigitalOcean and Docker Machine](digitaloceandocker.md) - Quickly test any version of GitLab on DigitalOcean using Docker Machine. diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md index 26506111548..35220119e9b 100644 --- a/doc/install/google_cloud_platform/index.md +++ b/doc/install/google_cloud_platform/index.md @@ -2,6 +2,10 @@ ![GCP landing page](img/gcp_landing.png) +>**Important note:** +GitLab has no official images in Google Cloud Platform yet. This guide serves +as a template for when the GitLab VM will be available. + The fastest way to get started on [Google Cloud Platform (GCP)][gcp] is through the [Google Cloud Launcher][launcher] program. -- cgit v1.2.1 From f09dcbd9bd2590bb66ee49b65637525a3c71a307 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 9 May 2017 13:14:45 +0200 Subject: Make retried to be nullable --- app/models/commit_status.rb | 2 +- app/models/concerns/has_status.rb | 2 +- app/services/ci/retry_build_service.rb | 4 ++-- db/migrate/20170503004426_add_retried_to_ci_build.rb | 10 ++-------- db/post_migrate/20170503004427_upate_retried_for_ci_build.rb | 2 +- db/schema.rb | 2 +- 6 files changed, 8 insertions(+), 14 deletions(-) diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb index 528bf4d87ac..7855c16ee5b 100644 --- a/app/models/commit_status.rb +++ b/app/models/commit_status.rb @@ -31,7 +31,7 @@ class CommitStatus < ActiveRecord::Base false, all_state_names - [:failed, :canceled, :manual]) end - scope :latest, -> { where(retried: false) } + scope :latest, -> { where(retried: [false, nil]) } scope :retried, -> { where(retried: true) } scope :ordered, -> { order(:name) } scope :latest_ordered, -> { latest.ordered.includes(project: :namespace) } diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb index dff7b6e3523..3e4f8e6bff8 100644 --- a/app/models/concerns/has_status.rb +++ b/app/models/concerns/has_status.rb @@ -22,7 +22,7 @@ module HasStatus skipped = scope.skipped.select('count(*)').to_sql canceled = scope.canceled.select('count(*)').to_sql - "(CASE + "(CASE WHEN (#{builds})=(#{skipped}) THEN 'skipped' WHEN (#{builds})=(#{success}) THEN 'success' WHEN (#{builds})=(#{created}) THEN 'created' diff --git a/app/services/ci/retry_build_service.rb b/app/services/ci/retry_build_service.rb index 9c532b585a1..f51e9fd1d54 100644 --- a/app/services/ci/retry_build_service.rb +++ b/app/services/ci/retry_build_service.rb @@ -30,8 +30,8 @@ module Ci Ci::Build.transaction do # mark all other builds of that name as retried - build.pipeline.builds.where(name: build.name) - .where.not(retried: true) + build.pipeline.builds.latest + .where(name: build.name) .update_all(retried: true) project.builds.create!(Hash[attributes]) diff --git a/db/migrate/20170503004426_add_retried_to_ci_build.rb b/db/migrate/20170503004426_add_retried_to_ci_build.rb index 9f509f97f14..2851e3de473 100644 --- a/db/migrate/20170503004426_add_retried_to_ci_build.rb +++ b/db/migrate/20170503004426_add_retried_to_ci_build.rb @@ -3,13 +3,7 @@ class AddRetriedToCiBuild < ActiveRecord::Migration DOWNTIME = false - disable_ddl_transaction! - - def up - add_column_with_default(:ci_builds, :retried, :boolean, default: false) - end - - def down - remove_column(:ci_builds, :retried) + def change + add_column(:ci_builds, :retried, :boolean) end end diff --git a/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb b/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb index e12180930a7..80215d662e4 100644 --- a/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb +++ b/db/post_migrate/20170503004427_upate_retried_for_ci_build.rb @@ -20,7 +20,7 @@ class UpateRetriedForCiBuild < ActiveRecord::Migration is_retried = Arel.sql("((#{latest_id}) != ci_builds.id)") update_column_in_batches(:ci_builds, :retried, is_retried) do |table, query| - query.where(table[:retried].eq(false)) + query.where(table[:retried].eq(nil)) end end diff --git a/db/schema.rb b/db/schema.rb index 8046e9b48a7..a54a57bd4da 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -232,7 +232,7 @@ ActiveRecord::Schema.define(version: 20170504102911) do t.integer "lock_version" t.string "coverage_regex" t.integer "auto_canceled_by_id" - t.boolean "retried", default: false, null: false + t.boolean "retried" end add_index "ci_builds", ["commit_id", "stage_idx", "created_at"], name: "index_ci_builds_on_commit_id_and_stage_idx_and_created_at", using: :btree -- cgit v1.2.1 From 7eaab72b983a89040a01b9f32184fef258fb29f2 Mon Sep 17 00:00:00 2001 From: Kamil Trzcinski Date: Tue, 9 May 2017 23:03:50 +0200 Subject: Fix rubocop failure --- app/models/concerns/has_status.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/concerns/has_status.rb b/app/models/concerns/has_status.rb index 3e4f8e6bff8..dff7b6e3523 100644 --- a/app/models/concerns/has_status.rb +++ b/app/models/concerns/has_status.rb @@ -22,7 +22,7 @@ module HasStatus skipped = scope.skipped.select('count(*)').to_sql canceled = scope.canceled.select('count(*)').to_sql - "(CASE + "(CASE WHEN (#{builds})=(#{skipped}) THEN 'skipped' WHEN (#{builds})=(#{success}) THEN 'success' WHEN (#{builds})=(#{created}) THEN 'created' -- cgit v1.2.1 From 5b376e654ac656088e0a6e5c3e63c341cac97043 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 10 May 2017 10:10:57 -0400 Subject: Include blob content when printing page --- app/assets/stylesheets/print.scss | 8 +++++--- changelogs/unreleased/31781-print-rendered-files-not-possible.yml | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/31781-print-rendered-files-not-possible.yml diff --git a/app/assets/stylesheets/print.scss b/app/assets/stylesheets/print.scss index 6cc1cc8e263..136d0c79467 100644 --- a/app/assets/stylesheets/print.scss +++ b/app/assets/stylesheets/print.scss @@ -28,9 +28,6 @@ nav.navbar-collapse.collapse, .profiler-results, .tree-ref-holder, .tree-holder .breadcrumb, -.blob-commit-info, -.file-title, -.file-holder, .nav, .btn, ul.notes-form, @@ -43,6 +40,11 @@ ul.notes-form, display: none!important; } +pre { + page-break-before: avoid; + page-break-inside: auto; +} + .page-gutter { padding-top: 0; padding-left: 0; diff --git a/changelogs/unreleased/31781-print-rendered-files-not-possible.yml b/changelogs/unreleased/31781-print-rendered-files-not-possible.yml new file mode 100644 index 00000000000..14915823ff7 --- /dev/null +++ b/changelogs/unreleased/31781-print-rendered-files-not-possible.yml @@ -0,0 +1,4 @@ +--- +title: Include the blob content when printing a blob page +merge_request: 11247 +author: -- cgit v1.2.1 From 262876a043a31cfa24dd620b85d13c1fc2c7ef8e Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 10 May 2017 14:22:56 +0000 Subject: Remove balsamiq module from common_vue bundle --- config/webpack.config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/config/webpack.config.js b/config/webpack.config.js index 7e413c8493e..2b833c21f58 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -147,7 +147,6 @@ var config = { 'notebook_viewer', 'pdf_viewer', 'pipelines', - 'balsamiq_viewer', 'pipelines_graph', ], minChunks: function(module, count) { -- cgit v1.2.1 From ca9033bd5dcf8c3abc9fe17c2a23da495d6e60d4 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 10 May 2017 15:09:36 +0000 Subject: Find the nothing-here-block before asserting page content when on explore page of shortcuts_spec.rb --- spec/features/dashboard/shortcuts_spec.rb | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index 4c9adcabe34..af7ef55a57e 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -1,6 +1,6 @@ require 'spec_helper' -feature 'Dashboard shortcuts', feature: true, js: true do +feature 'Dashboard shortcuts', :feature, :js do context 'logged in' do before do login_as :user @@ -8,21 +8,21 @@ feature 'Dashboard shortcuts', feature: true, js: true do end scenario 'Navigate to tabs' do - find('body').native.send_keys([:shift, 'P']) - - check_page_title('Projects') - - find('body').native.send_key([:shift, 'I']) + find('body').send_key([:shift, 'I']) check_page_title('Issues') - find('body').native.send_key([:shift, 'M']) + find('body').send_key([:shift, 'M']) check_page_title('Merge Requests') - find('body').native.send_keys([:shift, 'T']) + find('body').send_keys([:shift, 'T']) check_page_title('Todos') + + find('body').send_keys([:shift, 'P']) + + check_page_title('Projects') end end @@ -32,21 +32,24 @@ feature 'Dashboard shortcuts', feature: true, js: true do end scenario 'Navigate to tabs' do - find('body').native.send_keys([:shift, 'P']) - - expect(page).to have_content('No projects found') - - find('body').native.send_keys([:shift, 'G']) + find('body').send_keys([:shift, 'G']) + find('.nothing-here-block') expect(page).to have_content('No public groups') - find('body').native.send_keys([:shift, 'S']) + find('body').send_keys([:shift, 'S']) + find('.nothing-here-block') expect(page).to have_selector('.snippets-list-holder') + + find('body').send_keys([:shift, 'P']) + + find('.nothing-here-block') + expect(page).to have_content('No projects found') end end def check_page_title(title) expect(find('.header-content .title')).to have_content(title) end -end +end \ No newline at end of file -- cgit v1.2.1 From 26f5713fcfe20188d095e520de672376e99690e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Pedro=20Algarvio?= Date: Wed, 10 May 2017 15:34:48 +0000 Subject: Update installation.md - Updated the Ruby section. Fixes my previous my old obsolete/forgotten pull request / patch (sorry about that): #6262 https://github.com/lpalgarvio/gitlabhq/tree/patch-1 --- doc/install/installation.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/doc/install/installation.md b/doc/install/installation.md index 5615b2a534b..5bba405f159 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -109,14 +109,19 @@ Then select 'Internet Site' and press enter to confirm the hostname. ## 2. Ruby -**Note:** The current supported Ruby version is 2.3.x. GitLab 9.0 dropped support -for Ruby 2.1.x. +The Ruby interpreter is required to run GitLab. + +**Note:** The current supported Ruby (MRI) version is 2.3.x. GitLab 9.0 dropped +support for Ruby 2.1.x. The use of Ruby version managers such as [RVM], [rbenv] or [chruby] with GitLab in production, frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH, and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly -advise everyone to follow the instructions below to use a system Ruby. +advise everyone to follow the instructions below to use a system Ruby. + +Linux distributions generally have older versions of Ruby available, so these +instructions are designed to install Ruby from the official source code. Remove the old Ruby 1.8 if present: @@ -132,7 +137,7 @@ Download Ruby and compile it: make sudo make install -Install the Bundler Gem: +Then install the Bundler Gem: sudo gem install bundler --no-ri --no-rdoc -- cgit v1.2.1 From 8480118d2baeec3113709febb6a54735c3758be2 Mon Sep 17 00:00:00 2001 From: "Luke \"Jared\" Bennett" Date: Wed, 10 May 2017 15:53:11 +0000 Subject: Fix `send_key` to `send_keys` and add EOF newline --- spec/features/dashboard/shortcuts_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/features/dashboard/shortcuts_spec.rb b/spec/features/dashboard/shortcuts_spec.rb index af7ef55a57e..349b948eaee 100644 --- a/spec/features/dashboard/shortcuts_spec.rb +++ b/spec/features/dashboard/shortcuts_spec.rb @@ -8,11 +8,11 @@ feature 'Dashboard shortcuts', :feature, :js do end scenario 'Navigate to tabs' do - find('body').send_key([:shift, 'I']) + find('body').send_keys([:shift, 'I']) check_page_title('Issues') - find('body').send_key([:shift, 'M']) + find('body').send_keys([:shift, 'M']) check_page_title('Merge Requests') @@ -52,4 +52,4 @@ feature 'Dashboard shortcuts', :feature, :js do def check_page_title(title) expect(find('.header-content .title')).to have_content(title) end -end \ No newline at end of file +end -- cgit v1.2.1 From a7a53cd012a792828b0832242f15c33c4bb21d0e Mon Sep 17 00:00:00 2001 From: winh Date: Fri, 5 May 2017 12:34:42 +0200 Subject: Replace pipeline mock data with JSON fixture --- spec/javascripts/commit/pipelines/mock_data.js | 90 ----------------- .../javascripts/commit/pipelines/pipelines_spec.js | 7 +- spec/javascripts/fixtures/pipelines.rb | 35 +++++++ spec/javascripts/pipelines/mock_data.js | 107 --------------------- spec/javascripts/pipelines/pipelines_spec.js | 9 +- .../components/pipelines_table_row_spec.js | 8 +- .../vue_shared/components/pipelines_table_spec.js | 8 +- 7 files changed, 62 insertions(+), 202 deletions(-) delete mode 100644 spec/javascripts/commit/pipelines/mock_data.js create mode 100644 spec/javascripts/fixtures/pipelines.rb delete mode 100644 spec/javascripts/pipelines/mock_data.js diff --git a/spec/javascripts/commit/pipelines/mock_data.js b/spec/javascripts/commit/pipelines/mock_data.js deleted file mode 100644 index 10a60620f49..00000000000 --- a/spec/javascripts/commit/pipelines/mock_data.js +++ /dev/null @@ -1,90 +0,0 @@ -export default { - id: 73, - user: { - name: 'Administrator', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', - web_url: 'http://localhost:3000/root', - }, - path: '/root/review-app/pipelines/73', - details: { - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/73', - }, - duration: null, - finished_at: '2017-01-25T00:00:17.130Z', - stages: [{ - name: 'build', - title: 'build: failed', - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/73#build', - }, - path: '/root/review-app/pipelines/73#build', - dropdown_path: '/root/review-app/pipelines/73/stage.json?stage=build', - }], - artifacts: [], - manual_actions: [ - { - name: 'stop_review', - path: '/root/review-app/builds/1463/play', - }, - { - name: 'name', - path: '/root/review-app/builds/1490/play', - }, - ], - }, - flags: { - latest: true, - triggered: false, - stuck: false, - yaml_errors: false, - retryable: true, - cancelable: false, - }, - ref: - { - name: 'master', - path: '/root/review-app/tree/master', - tag: false, - branch: true, - }, - coverage: '42.21', - commit: { - id: 'fbd79f04fa98717641deaaeb092a4d417237c2e4', - short_id: 'fbd79f04', - title: 'Update .gitlab-ci.yml', - author_name: 'Administrator', - author_email: 'admin@example.com', - created_at: '2017-01-16T12:13:57.000-05:00', - committer_name: 'Administrator', - committer_email: 'admin@example.com', - message: 'Update .gitlab-ci.yml', - author: { - name: 'Administrator', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', - web_url: 'http://localhost:3000/root', - }, - author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon', - commit_url: 'http://localhost:3000/root/review-app/commit/fbd79f04fa98717641deaaeb092a4d417237c2e4', - commit_path: '/root/review-app/commit/fbd79f04fa98717641deaaeb092a4d417237c2e4', - }, - retry_path: '/root/review-app/pipelines/73/retry', - created_at: '2017-01-16T17:13:59.800Z', - updated_at: '2017-01-25T00:00:17.132Z', -}; diff --git a/spec/javascripts/commit/pipelines/pipelines_spec.js b/spec/javascripts/commit/pipelines/pipelines_spec.js index ad31448f81c..398c593eec2 100644 --- a/spec/javascripts/commit/pipelines/pipelines_spec.js +++ b/spec/javascripts/commit/pipelines/pipelines_spec.js @@ -1,12 +1,17 @@ import Vue from 'vue'; import PipelinesTable from '~/commit/pipelines/pipelines_table'; -import pipeline from './mock_data'; describe('Pipelines table in Commits and Merge requests', () => { + const jsonFixtureName = 'pipelines/pipelines.json'; + let pipeline; + preloadFixtures('static/pipelines_table.html.raw'); + preloadFixtures(jsonFixtureName); beforeEach(() => { loadFixtures('static/pipelines_table.html.raw'); + const pipelines = getJSONFixture(jsonFixtureName).pipelines; + pipeline = pipelines.find(p => p.id === 1); }); describe('successful request', () => { diff --git a/spec/javascripts/fixtures/pipelines.rb b/spec/javascripts/fixtures/pipelines.rb new file mode 100644 index 00000000000..daafbac86db --- /dev/null +++ b/spec/javascripts/fixtures/pipelines.rb @@ -0,0 +1,35 @@ +require 'spec_helper' + +describe Projects::PipelinesController, '(JavaScript fixtures)', type: :controller do + include JavaScriptFixturesHelpers + + let(:admin) { create(:admin) } + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project, :repository, namespace: namespace, path: 'pipelines-project') } + let(:commit) { create(:commit, project: project) } + let(:commit_without_author) { RepoHelpers.another_sample_commit } + let!(:user) { create(:user, email: commit.author_email) } + let!(:pipeline) { create(:ci_pipeline, project: project, sha: commit.id, user: user) } + let!(:pipeline_without_author) { create(:ci_pipeline, project: project, sha: commit_without_author.id) } + let!(:pipeline_without_commit) { create(:ci_pipeline, project: project, sha: '0000') } + + render_views + + before(:all) do + clean_frontend_fixtures('pipelines/') + end + + before(:each) do + sign_in(admin) + end + + it 'pipelines/pipelines.json' do |example| + get :index, + namespace_id: namespace, + project_id: project, + format: :json + + expect(response).to be_success + store_frontend_fixture(response, example.description) + end +end diff --git a/spec/javascripts/pipelines/mock_data.js b/spec/javascripts/pipelines/mock_data.js deleted file mode 100644 index 2365a662b9f..00000000000 --- a/spec/javascripts/pipelines/mock_data.js +++ /dev/null @@ -1,107 +0,0 @@ -export default { - pipelines: [{ - id: 115, - user: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - web_url: 'http://localhost:3000/root', - }, - path: '/root/review-app/pipelines/115', - details: { - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/115', - }, - duration: null, - finished_at: '2017-03-17T19:00:15.996Z', - stages: [{ - name: 'build', - title: 'build: failed', - status: { - icon: 'icon_status_failed', - text: 'failed', - label: 'failed', - group: 'failed', - has_details: true, - details_path: '/root/review-app/pipelines/115#build', - }, - path: '/root/review-app/pipelines/115#build', - dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=build', - }, - { - name: 'review', - title: 'review: skipped', - status: { - icon: 'icon_status_skipped', - text: 'skipped', - label: 'skipped', - group: 'skipped', - has_details: true, - details_path: '/root/review-app/pipelines/115#review', - }, - path: '/root/review-app/pipelines/115#review', - dropdown_path: '/root/review-app/pipelines/115/stage.json?stage=review', - }], - artifacts: [], - manual_actions: [{ - name: 'stop_review', - path: '/root/review-app/builds/3766/play', - }], - }, - flags: { - latest: true, - triggered: false, - stuck: false, - yaml_errors: false, - retryable: true, - cancelable: false, - }, - ref: { - name: 'thisisabranch', - path: '/root/review-app/tree/thisisabranch', - tag: false, - branch: true, - }, - commit: { - id: '9e87f87625b26c42c59a2ee0398f81d20cdfe600', - short_id: '9e87f876', - title: 'Update README.md', - created_at: '2017-03-15T22:58:28.000+00:00', - parent_ids: ['3744f9226e699faec2662a8b267e5d3fd0bfff0e'], - message: 'Update README.md', - author_name: 'Root', - author_email: 'admin@example.com', - authored_date: '2017-03-15T22:58:28.000+00:00', - committer_name: 'Root', - committer_email: 'admin@example.com', - committed_date: '2017-03-15T22:58:28.000+00:00', - author: { - name: 'Root', - username: 'root', - id: 1, - state: 'active', - avatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - web_url: 'http://localhost:3000/root', - }, - author_gravatar_url: 'http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon', - commit_url: 'http://localhost:3000/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', - commit_path: '/root/review-app/commit/9e87f87625b26c42c59a2ee0398f81d20cdfe600', - }, - retry_path: '/root/review-app/pipelines/115/retry', - created_at: '2017-03-15T22:58:33.436Z', - updated_at: '2017-03-17T19:00:15.997Z', - }], - count: { - all: 52, - running: 0, - pending: 0, - finished: 52, - }, -}; diff --git a/spec/javascripts/pipelines/pipelines_spec.js b/spec/javascripts/pipelines/pipelines_spec.js index e9c05f74ce6..3a56156358b 100644 --- a/spec/javascripts/pipelines/pipelines_spec.js +++ b/spec/javascripts/pipelines/pipelines_spec.js @@ -1,15 +1,20 @@ import Vue from 'vue'; import pipelinesComp from '~/pipelines/pipelines'; import Store from '~/pipelines/stores/pipelines_store'; -import pipelinesData from './mock_data'; describe('Pipelines', () => { + const jsonFixtureName = 'pipelines/pipelines.json'; + preloadFixtures('static/pipelines.html.raw'); + preloadFixtures(jsonFixtureName); let PipelinesComponent; + let pipeline; beforeEach(() => { loadFixtures('static/pipelines.html.raw'); + const pipelines = getJSONFixture(jsonFixtureName).pipelines; + pipeline = pipelines.find(p => p.id === 1); PipelinesComponent = Vue.extend(pipelinesComp); }); @@ -17,7 +22,7 @@ describe('Pipelines', () => { describe('successfull request', () => { describe('with pipelines', () => { const pipelinesInterceptor = (request, next) => { - next(request.respondWith(JSON.stringify(pipelinesData), { + next(request.respondWith(JSON.stringify(pipeline), { status: 200, })); }; diff --git a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js index 699625cdbb7..3036a98d0b9 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js +++ b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js @@ -1,11 +1,17 @@ import Vue from 'vue'; import tableRowComp from '~/vue_shared/components/pipelines_table_row'; -import pipeline from '../../commit/pipelines/mock_data'; describe('Pipelines Table Row', () => { + const jsonFixtureName = 'pipelines/pipelines.json'; + let component; + let pipeline; + + preloadFixtures(jsonFixtureName); beforeEach(() => { + const pipelines = getJSONFixture(jsonFixtureName).pipelines; + pipeline = pipelines.find(p => p.id === 1); const PipelinesTableRowComponent = Vue.extend(tableRowComp); component = new PipelinesTableRowComponent({ diff --git a/spec/javascripts/vue_shared/components/pipelines_table_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_spec.js index 4d3ced944d7..6cc178b8f1d 100644 --- a/spec/javascripts/vue_shared/components/pipelines_table_spec.js +++ b/spec/javascripts/vue_shared/components/pipelines_table_spec.js @@ -1,13 +1,19 @@ import Vue from 'vue'; import pipelinesTableComp from '~/vue_shared/components/pipelines_table'; import '~/lib/utils/datetime_utility'; -import pipeline from '../../commit/pipelines/mock_data'; describe('Pipelines Table', () => { + const jsonFixtureName = 'pipelines/pipelines.json'; + + let pipeline; let PipelinesTableComponent; + preloadFixtures(jsonFixtureName); + beforeEach(() => { PipelinesTableComponent = Vue.extend(pipelinesTableComp); + const pipelines = getJSONFixture(jsonFixtureName).pipelines; + pipeline = pipelines.find(p => p.id === 1); }); describe('table', () => { -- cgit v1.2.1 From d40e1f547ea9e31e822229bb808aaa6b9201f473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 3 May 2017 13:22:03 +0200 Subject: Enable the Style/TrailingCommaInLiteral cop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the EnforcedStyleForMultiline: no_comma option. Signed-off-by: Rémy Coutable --- .rubocop.yml | 3 ++- app/controllers/autocomplete_controller.rb | 2 +- app/controllers/concerns/lfs_request.rb | 6 +++--- app/controllers/health_controller.rb | 2 +- app/controllers/jwt_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 2 +- app/controllers/projects/lfs_api_controller.rb | 4 ++-- app/controllers/projects/pipelines_controller.rb | 2 +- app/controllers/projects/tree_controller.rb | 2 +- app/controllers/projects_controller.rb | 2 +- app/helpers/diff_helper.rb | 2 +- app/helpers/emails_helper.rb | 2 +- app/helpers/events_helper.rb | 2 +- app/helpers/explore_helper.rb | 2 +- app/helpers/markup_helper.rb | 2 +- app/helpers/merge_requests_helper.rb | 2 +- app/helpers/notes_helper.rb | 4 ++-- app/helpers/search_helper.rb | 6 +++--- app/helpers/selects_helper.rb | 2 +- app/helpers/sorting_helper.rb | 2 +- app/helpers/todos_helper.rb | 2 +- app/models/blob.rb | 2 +- app/models/commit.rb | 2 +- app/models/environment.rb | 2 +- app/models/hooks/web_hook.rb | 2 +- app/models/project.rb | 2 +- app/models/project_services/bamboo_service.rb | 2 +- app/models/project_services/chat_notification_service.rb | 2 +- app/models/project_services/emails_on_push_service.rb | 2 +- app/models/project_services/external_wiki_service.rb | 2 +- app/models/project_services/hipchat_service.rb | 2 +- app/models/project_services/irker_service.rb | 2 +- app/models/project_services/jira_service.rb | 2 +- app/models/project_services/kubernetes_service.rb | 2 +- app/models/project_services/microsoft_teams_service.rb | 2 +- app/models/project_services/mock_ci_service.rb | 2 +- app/models/project_services/pipelines_email_service.rb | 2 +- app/models/project_services/pushover_service.rb | 2 +- app/models/project_services/teamcity_service.rb | 4 ++-- app/services/akismet_service.rb | 2 +- app/services/audit_event_service.rb | 2 +- .../projects/update_pages_configuration_service.rb | 2 +- app/services/system_hooks_service.rb | 2 +- config/initializers/static_files.rb | 2 +- db/migrate/20160810142633_remove_redundant_indexes.rb | 2 +- db/migrate/20160829114652_add_markdown_cache_columns.rb | 2 +- lib/api/internal.rb | 2 +- lib/api/projects.rb | 2 +- lib/api/services.rb | 6 +++--- lib/api/subscriptions.rb | 2 +- lib/api/v3/services.rb | 2 +- lib/api/v3/subscriptions.rb | 2 +- lib/ci/ansi2html.rb | 2 +- lib/ci/gitlab_ci_yaml_processor.rb | 2 +- lib/gitlab/access.rb | 6 +++--- lib/gitlab/chat_commands/command.rb | 2 +- lib/gitlab/cycle_analytics/permissions.rb | 2 +- lib/gitlab/data_builder/build.rb | 6 +++--- lib/gitlab/etag_caching/router.rb | 2 +- lib/gitlab/git/repository.rb | 2 +- lib/gitlab/kubernetes.rb | 4 ++-- lib/gitlab/workhorse.rb | 8 ++++---- lib/tasks/gemojione.rake | 2 +- lib/tasks/gitlab/update_templates.rake | 2 +- lib/tasks/spec.rake | 2 +- scripts/trigger-build | 2 +- spec/factories/services.rb | 2 +- spec/features/auto_deploy_spec.rb | 2 +- spec/features/merge_requests/conflicts_spec.rb | 2 +- spec/features/projects/features_visibility_spec.rb | 2 +- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 6 +++--- spec/lib/expand_variables_spec.rb | 6 +++--- spec/lib/gitlab/backup/manager_spec.rb | 2 +- spec/lib/gitlab/diff/position_tracer_spec.rb | 8 ++++---- spec/lib/gitlab/git/encoding_helper_spec.rb | 16 ++++++++-------- spec/lib/gitlab/git/util_spec.rb | 2 +- spec/lib/gitlab/import_export/relation_factory_spec.rb | 2 +- spec/lib/gitlab/repo_path_spec.rb | 2 +- spec/lib/gitlab/workhorse_spec.rb | 4 ++-- spec/models/application_setting_spec.rb | 2 +- spec/models/ci/build_spec.rb | 4 ++-- spec/models/environment_spec.rb | 2 +- spec/models/global_milestone_spec.rb | 2 +- spec/models/project_authorization_spec.rb | 2 +- spec/models/project_services/asana_service_spec.rb | 2 +- .../project_services/chat_message/issue_message_spec.rb | 2 +- .../project_services/chat_message/merge_message_spec.rb | 2 +- .../project_services/chat_message/note_message_spec.rb | 2 +- .../project_services/chat_message/push_message_spec.rb | 4 ++-- .../chat_message/wiki_page_message_spec.rb | 4 ++-- spec/models/project_services/kubernetes_service_spec.rb | 2 +- .../project_services/pivotaltracker_service_spec.rb | 2 +- spec/models/project_spec.rb | 2 +- spec/models/user_spec.rb | 2 +- spec/requests/api/files_spec.rb | 2 +- spec/requests/api/groups_spec.rb | 2 +- spec/requests/api/projects_spec.rb | 2 +- spec/requests/api/v3/files_spec.rb | 4 ++-- spec/requests/api/v3/groups_spec.rb | 2 +- spec/requests/api/v3/projects_spec.rb | 4 ++-- spec/requests/lfs_http_spec.rb | 6 +++--- spec/requests/openid_connect_spec.rb | 2 +- spec/serializers/analytics_issue_entity_spec.rb | 2 +- spec/serializers/analytics_issue_serializer_spec.rb | 2 +- spec/services/cohorts_service_spec.rb | 2 +- spec/services/create_deployment_service_spec.rb | 2 +- spec/services/issuable/bulk_update_service_spec.rb | 2 +- spec/services/merge_requests/refresh_service_spec.rb | 2 +- spec/services/notification_service_spec.rb | 2 +- spec/support/kubernetes_helpers.rb | 8 ++++---- spec/support/repo_helpers.rb | 4 ++-- spec/support/workhorse_helpers.rb | 2 +- spec/tasks/gitlab/gitaly_rake_spec.rb | 2 +- 113 files changed, 157 insertions(+), 156 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index e53af97a92c..7438763984d 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -494,7 +494,8 @@ Style/TrailingBlankLines: # This cop checks for trailing comma in array and hash literals. Style/TrailingCommaInLiteral: - Enabled: false + Enabled: true + EnforcedStyleForMultiline: no_comma # Checks for %W when interpolation is not needed. Style/UnneededCapitalW: diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index b79ca034c5b..e2f5aa8508e 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -41,7 +41,7 @@ class AutocompleteController < ApplicationController no_project = { id: 0, - name_with_namespace: 'No project', + name_with_namespace: 'No project' } projects.unshift(no_project) unless params[:offset_id].present? diff --git a/app/controllers/concerns/lfs_request.rb b/app/controllers/concerns/lfs_request.rb index ed22b1e5470..ae91e02488a 100644 --- a/app/controllers/concerns/lfs_request.rb +++ b/app/controllers/concerns/lfs_request.rb @@ -23,7 +23,7 @@ module LfsRequest render( json: { message: 'Git LFS is not enabled on this GitLab server, contact your admin.', - documentation_url: help_url, + documentation_url: help_url }, status: 501 ) @@ -48,7 +48,7 @@ module LfsRequest render( json: { message: 'Access forbidden. Check your access level.', - documentation_url: help_url, + documentation_url: help_url }, content_type: "application/vnd.git-lfs+json", status: 403 @@ -59,7 +59,7 @@ module LfsRequest render( json: { message: 'Not found.', - documentation_url: help_url, + documentation_url: help_url }, content_type: "application/vnd.git-lfs+json", status: 404 diff --git a/app/controllers/health_controller.rb b/app/controllers/health_controller.rb index df0fc3132ed..125746d0426 100644 --- a/app/controllers/health_controller.rb +++ b/app/controllers/health_controller.rb @@ -5,7 +5,7 @@ class HealthController < ActionController::Base CHECKS = [ Gitlab::HealthChecks::DbCheck, Gitlab::HealthChecks::RedisCheck, - Gitlab::HealthChecks::FsShardsCheck, + Gitlab::HealthChecks::FsShardsCheck ].freeze def readiness diff --git a/app/controllers/jwt_controller.rb b/app/controllers/jwt_controller.rb index 3109439b2ff..1c01be06451 100644 --- a/app/controllers/jwt_controller.rb +++ b/app/controllers/jwt_controller.rb @@ -4,7 +4,7 @@ class JwtController < ApplicationController before_action :authenticate_project_or_user SERVICES = { - Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService, + Auth::ContainerRegistryAuthenticationService::AUDIENCE => Auth::ContainerRegistryAuthenticationService }.freeze def auth diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 58d41e0478d..c376bc8a785 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -209,7 +209,7 @@ class Projects::IssuesController < Projects::ApplicationController description_text: @issue.description, task_status: @issue.task_status, issue_number: @issue.iid, - updated_at: @issue.updated_at, + updated_at: @issue.updated_at } end diff --git a/app/controllers/projects/lfs_api_controller.rb b/app/controllers/projects/lfs_api_controller.rb index 8a5a645ed0e..1b0d3aab3fa 100644 --- a/app/controllers/projects/lfs_api_controller.rb +++ b/app/controllers/projects/lfs_api_controller.rb @@ -22,7 +22,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController render( json: { message: 'Server supports batch API only, please update your Git LFS client to version 1.0.1 and up.', - documentation_url: "#{Gitlab.config.gitlab.url}/help", + documentation_url: "#{Gitlab.config.gitlab.url}/help" }, status: 501 ) @@ -55,7 +55,7 @@ class Projects::LfsApiController < Projects::GitHttpClientController else object[:error] = { code: 404, - message: "Object does not exist on the server or you don't have permissions to access it", + message: "Object does not exist on the server or you don't have permissions to access it" } end end diff --git a/app/controllers/projects/pipelines_controller.rb b/app/controllers/projects/pipelines_controller.rb index 7fe3c3c116c..602d3dd8c1c 100644 --- a/app/controllers/projects/pipelines_controller.rb +++ b/app/controllers/projects/pipelines_controller.rb @@ -44,7 +44,7 @@ class Projects::PipelinesController < Projects::ApplicationController all: @pipelines_count, running: @running_count, pending: @pending_count, - finished: @finished_count, + finished: @finished_count } } end diff --git a/app/controllers/projects/tree_controller.rb b/app/controllers/projects/tree_controller.rb index 5e2182c883e..3ce65b29b3c 100644 --- a/app/controllers/projects/tree_controller.rb +++ b/app/controllers/projects/tree_controller.rb @@ -48,7 +48,7 @@ class Projects::TreeController < Projects::ApplicationController @dir_name = File.join(@path, params[:dir_name]) @commit_params = { file_path: @dir_name, - commit_message: params[:commit_message], + commit_message: params[:commit_message] } end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 69310b26e76..63d018c8cbf 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -220,7 +220,7 @@ class ProjectsController < Projects::ApplicationController branches = BranchesFinder.new(@repository, params).execute.map(&:name) options = { - 'Branches' => branches.take(100), + 'Branches' => branches.take(100) } unless @repository.tag_count.zero? diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index dc144906548..63bc3b11b56 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -98,7 +98,7 @@ module DiffHelper [ content_tag(:span, link_to(truncate(blob.name, length: 40), tree)), '@', - content_tag(:span, commit_id, class: 'monospace'), + content_tag(:span, commit_id, class: 'monospace') ].join(' ').html_safe end diff --git a/app/helpers/emails_helper.rb b/app/helpers/emails_helper.rb index f927cfc998f..3b24f183785 100644 --- a/app/helpers/emails_helper.rb +++ b/app/helpers/emails_helper.rb @@ -12,7 +12,7 @@ module EmailsHelper "action" => { "@type" => "ViewAction", "name" => name, - "url" => url, + "url" => url } } diff --git a/app/helpers/events_helper.rb b/app/helpers/events_helper.rb index 960111ca045..c14438da281 100644 --- a/app/helpers/events_helper.rb +++ b/app/helpers/events_helper.rb @@ -41,7 +41,7 @@ module EventsHelper link_opts = { class: "event-filter-link", id: "#{key}_event_filter", - title: "Filter by #{tooltip.downcase}", + title: "Filter by #{tooltip.downcase}" } content_tag :li, class: active do diff --git a/app/helpers/explore_helper.rb b/app/helpers/explore_helper.rb index 7bd212a3ef9..b981a1e8242 100644 --- a/app/helpers/explore_helper.rb +++ b/app/helpers/explore_helper.rb @@ -10,7 +10,7 @@ module ExploreHelper personal: params[:personal], archived: params[:archived], shared: params[:shared], - namespace_id: params[:namespace_id], + namespace_id: params[:namespace_id] } options = exist_opts.merge(options).delete_if { |key, value| value.blank? } diff --git a/app/helpers/markup_helper.rb b/app/helpers/markup_helper.rb index b241a14740b..752d0079818 100644 --- a/app/helpers/markup_helper.rb +++ b/app/helpers/markup_helper.rb @@ -32,7 +32,7 @@ module MarkupHelper context = { project: @project, current_user: (current_user if defined?(current_user)), - pipeline: :single_line, + pipeline: :single_line } gfm_body = Banzai.render(body, context) diff --git a/app/helpers/merge_requests_helper.rb b/app/helpers/merge_requests_helper.rb index 23e55539f0a..39d30631646 100644 --- a/app/helpers/merge_requests_helper.rb +++ b/app/helpers/merge_requests_helper.rb @@ -54,7 +54,7 @@ module MergeRequestsHelper source_project_id: merge_request.source_project_id, target_project_id: merge_request.target_project_id, source_branch: merge_request.source_branch, - target_branch: merge_request.target_branch, + target_branch: merge_request.target_branch }, change_branches: true ) diff --git a/app/helpers/notes_helper.rb b/app/helpers/notes_helper.rb index 52403640c05..375110b77e2 100644 --- a/app/helpers/notes_helper.rb +++ b/app/helpers/notes_helper.rb @@ -19,7 +19,7 @@ module NotesHelper id: noteable.id, class: noteable.class.name, resources: noteable.class.table_name, - project_id: noteable.project.id, + project_id: noteable.project.id }.to_json end @@ -34,7 +34,7 @@ module NotesHelper data = { line_code: line_code, - line_type: line_type, + line_type: line_type } if @use_legacy_diff_notes diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb index 8ff8db16514..9c46035057f 100644 --- a/app/helpers/search_helper.rb +++ b/app/helpers/search_helper.rb @@ -42,7 +42,7 @@ module SearchHelper { category: "Settings", label: "User settings", url: profile_path }, { category: "Settings", label: "SSH Keys", url: profile_keys_path }, { category: "Settings", label: "Dashboard", url: root_path }, - { category: "Settings", label: "Admin Section", url: admin_root_path }, + { category: "Settings", label: "Admin Section", url: admin_root_path } ] end @@ -57,7 +57,7 @@ module SearchHelper { category: "Help", label: "SSH Keys Help", url: help_page_path("ssh/README") }, { category: "Help", label: "System Hooks Help", url: help_page_path("system_hooks/system_hooks") }, { category: "Help", label: "Webhooks Help", url: help_page_path("user/project/integrations/webhooks") }, - { category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") }, + { category: "Help", label: "Workflow Help", url: help_page_path("workflow/README") } ] end @@ -76,7 +76,7 @@ module SearchHelper { category: "Current Project", label: "Milestones", url: namespace_project_milestones_path(@project.namespace, @project) }, { category: "Current Project", label: "Snippets", url: namespace_project_snippets_path(@project.namespace, @project) }, { category: "Current Project", label: "Members", url: namespace_project_settings_members_path(@project.namespace, @project) }, - { category: "Current Project", label: "Wiki", url: namespace_project_wikis_path(@project.namespace, @project) }, + { category: "Current Project", label: "Wiki", url: namespace_project_wikis_path(@project.namespace, @project) } ] else [] diff --git a/app/helpers/selects_helper.rb b/app/helpers/selects_helper.rb index 8706876ae4a..a7d1fe4aa47 100644 --- a/app/helpers/selects_helper.rb +++ b/app/helpers/selects_helper.rb @@ -67,7 +67,7 @@ module SelectsHelper current_user: opts[:current_user] || false, "push-code-to-protected-branches" => opts[:push_code_to_protected_branches], author_id: opts[:author_id] || '', - skip_users: opts[:skip_users] ? opts[:skip_users].map(&:id) : nil, + skip_users: opts[:skip_users] ? opts[:skip_users].map(&:id) : nil } end end diff --git a/app/helpers/sorting_helper.rb b/app/helpers/sorting_helper.rb index 4882d9b71d2..b408ec0c6a4 100644 --- a/app/helpers/sorting_helper.rb +++ b/app/helpers/sorting_helper.rb @@ -58,7 +58,7 @@ module SortingHelper sort_value_due_date_soon => sort_title_due_date_soon, sort_value_due_date_later => sort_title_due_date_later, sort_value_start_date_soon => sort_title_start_date_soon, - sort_value_start_date_later => sort_title_start_date_later, + sort_value_start_date_later => sort_title_start_date_later } end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index f19e2f9db9c..0ff2d5ce4cd 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -63,7 +63,7 @@ module TodosHelper project_id: params[:project_id], author_id: params[:author_id], type: params[:type], - action_id: params[:action_id], + action_id: params[:action_id] } end diff --git a/app/models/blob.rb b/app/models/blob.rb index eaf0b713122..8452a96e909 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -33,7 +33,7 @@ class Blob < SimpleDelegator BlobViewer::PDF, BlobViewer::BinarySTL, - BlobViewer::TextSTL, + BlobViewer::TextSTL ].freeze BINARY_VIEWERS = RICH_VIEWERS.select(&:binary?).freeze diff --git a/app/models/commit.rb b/app/models/commit.rb index dea18bfedef..3a143a5a1f6 100644 --- a/app/models/commit.rb +++ b/app/models/commit.rb @@ -49,7 +49,7 @@ class Commit def max_diff_options { max_files: DIFF_HARD_LIMIT_FILES, - max_lines: DIFF_HARD_LIMIT_LINES, + max_lines: DIFF_HARD_LIMIT_LINES } end diff --git a/app/models/environment.rb b/app/models/environment.rb index bf33010fd21..61efc1b2d17 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -62,7 +62,7 @@ class Environment < ActiveRecord::Base def predefined_variables [ { key: 'CI_ENVIRONMENT_NAME', value: name, public: true }, - { key: 'CI_ENVIRONMENT_SLUG', value: slug, public: true }, + { key: 'CI_ENVIRONMENT_SLUG', value: slug, public: true } ] end diff --git a/app/models/hooks/web_hook.rb b/app/models/hooks/web_hook.rb index 595602e80fe..22a177ed367 100644 --- a/app/models/hooks/web_hook.rb +++ b/app/models/hooks/web_hook.rb @@ -31,7 +31,7 @@ class WebHook < ActiveRecord::Base post_url = url.gsub("#{parsed_url.userinfo}@", '') auth = { username: CGI.unescape(parsed_url.user), - password: CGI.unescape(parsed_url.password), + password: CGI.unescape(parsed_url.password) } response = WebHook.post(post_url, body: data.to_json, diff --git a/app/models/project.rb b/app/models/project.rb index 1f550cc02e2..be4960aef8a 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -967,7 +967,7 @@ class Project < ActiveRecord::Base namespace: namespace.name, visibility_level: visibility_level, path_with_namespace: path_with_namespace, - default_branch: default_branch, + default_branch: default_branch } # Backward compatibility diff --git a/app/models/project_services/bamboo_service.rb b/app/models/project_services/bamboo_service.rb index 400020ee04a..3f5b3eb159b 100644 --- a/app/models/project_services/bamboo_service.rb +++ b/app/models/project_services/bamboo_service.rb @@ -52,7 +52,7 @@ class BambooService < CiService placeholder: 'Bamboo build plan key like KEY' }, { type: 'text', name: 'username', placeholder: 'A user with API access, if applicable' }, - { type: 'password', name: 'password' }, + { type: 'password', name: 'password' } ] end diff --git a/app/models/project_services/chat_notification_service.rb b/app/models/project_services/chat_notification_service.rb index 6464bf3f4a4..779ef54cfcb 100644 --- a/app/models/project_services/chat_notification_service.rb +++ b/app/models/project_services/chat_notification_service.rb @@ -39,7 +39,7 @@ class ChatNotificationService < Service { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" }, { type: 'text', name: 'username', placeholder: 'e.g. GitLab' }, { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - { type: 'checkbox', name: 'notify_only_default_branch' }, + { type: 'checkbox', name: 'notify_only_default_branch' } ] end diff --git a/app/models/project_services/emails_on_push_service.rb b/app/models/project_services/emails_on_push_service.rb index f4f913ee0b6..1a236e232f9 100644 --- a/app/models/project_services/emails_on_push_service.rb +++ b/app/models/project_services/emails_on_push_service.rb @@ -47,7 +47,7 @@ class EmailsOnPushService < Service help: "Send notifications from the committer's email address if the domain is part of the domain GitLab is running on (e.g. #{domains})." }, { type: 'checkbox', name: 'disable_diffs', title: "Disable code diffs", help: "Don't include possibly sensitive code diffs in notification body." }, - { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' }, + { type: 'textarea', name: 'recipients', placeholder: 'Emails separated by whitespace' } ] end end diff --git a/app/models/project_services/external_wiki_service.rb b/app/models/project_services/external_wiki_service.rb index bdf6fa6a586..b4d7c977ce4 100644 --- a/app/models/project_services/external_wiki_service.rb +++ b/app/models/project_services/external_wiki_service.rb @@ -19,7 +19,7 @@ class ExternalWikiService < Service def fields [ - { type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' }, + { type: 'text', name: 'external_wiki_url', placeholder: 'The URL of the external Wiki' } ] end diff --git a/app/models/project_services/hipchat_service.rb b/app/models/project_services/hipchat_service.rb index 8b181221bb0..c19fed339ba 100644 --- a/app/models/project_services/hipchat_service.rb +++ b/app/models/project_services/hipchat_service.rb @@ -41,7 +41,7 @@ class HipchatService < Service placeholder: 'Leave blank for default (v2)' }, { type: 'text', name: 'server', placeholder: 'Leave blank for default. https://hipchat.example.com' }, - { type: 'checkbox', name: 'notify_only_broken_pipelines' }, + { type: 'checkbox', name: 'notify_only_broken_pipelines' } ] end diff --git a/app/models/project_services/irker_service.rb b/app/models/project_services/irker_service.rb index c62bb4fa120..a51d43adcb9 100644 --- a/app/models/project_services/irker_service.rb +++ b/app/models/project_services/irker_service.rb @@ -58,7 +58,7 @@ class IrkerService < Service ' want to use a password, you have to omit the "#" on the channel). If you ' \ ' specify a default IRC URI to prepend before each recipient, you can just ' \ ' give a channel name.' }, - { type: 'checkbox', name: 'colorize_messages' }, + { type: 'checkbox', name: 'colorize_messages' } ] end diff --git a/app/models/project_services/jira_service.rb b/app/models/project_services/jira_service.rb index 97e997d3899..f388773efee 100644 --- a/app/models/project_services/jira_service.rb +++ b/app/models/project_services/jira_service.rb @@ -149,7 +149,7 @@ class JiraService < IssueTrackerService data = { user: { name: author.name, - url: resource_url(user_path(author)), + url: resource_url(user_path(author)) }, project: { name: self.project.path_with_namespace, diff --git a/app/models/project_services/kubernetes_service.rb b/app/models/project_services/kubernetes_service.rb index 9c56518c991..b2494a0be6e 100644 --- a/app/models/project_services/kubernetes_service.rb +++ b/app/models/project_services/kubernetes_service.rb @@ -73,7 +73,7 @@ class KubernetesService < DeploymentService { type: 'textarea', name: 'ca_pem', title: 'Custom CA bundle', - placeholder: 'Certificate Authority bundle (PEM format)' }, + placeholder: 'Certificate Authority bundle (PEM format)' } ] end diff --git a/app/models/project_services/microsoft_teams_service.rb b/app/models/project_services/microsoft_teams_service.rb index 9b218fd81b4..2facff53e26 100644 --- a/app/models/project_services/microsoft_teams_service.rb +++ b/app/models/project_services/microsoft_teams_service.rb @@ -35,7 +35,7 @@ class MicrosoftTeamsService < ChatNotificationService [ { type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}" }, { type: 'checkbox', name: 'notify_only_broken_pipelines' }, - { type: 'checkbox', name: 'notify_only_default_branch' }, + { type: 'checkbox', name: 'notify_only_default_branch' } ] end diff --git a/app/models/project_services/mock_ci_service.rb b/app/models/project_services/mock_ci_service.rb index a8d581a1f67..546b6e0a498 100644 --- a/app/models/project_services/mock_ci_service.rb +++ b/app/models/project_services/mock_ci_service.rb @@ -21,7 +21,7 @@ class MockCiService < CiService [ { type: 'text', name: 'mock_service_url', - placeholder: 'http://localhost:4004' }, + placeholder: 'http://localhost:4004' } ] end diff --git a/app/models/project_services/pipelines_email_service.rb b/app/models/project_services/pipelines_email_service.rb index ac617f409d9..f824171ad09 100644 --- a/app/models/project_services/pipelines_email_service.rb +++ b/app/models/project_services/pipelines_email_service.rb @@ -55,7 +55,7 @@ class PipelinesEmailService < Service name: 'recipients', placeholder: 'Emails separated by comma' }, { type: 'checkbox', - name: 'notify_only_broken_pipelines' }, + name: 'notify_only_broken_pipelines' } ] end diff --git a/app/models/project_services/pushover_service.rb b/app/models/project_services/pushover_service.rb index 3e618a8dbf1..fc29a5277bb 100644 --- a/app/models/project_services/pushover_service.rb +++ b/app/models/project_services/pushover_service.rb @@ -55,7 +55,7 @@ class PushoverService < Service ['Pushover Echo (long)', 'echo'], ['Up Down (long)', 'updown'], ['None (silent)', 'none'] - ] }, + ] } ] end diff --git a/app/models/project_services/teamcity_service.rb b/app/models/project_services/teamcity_service.rb index cbaffb8ce48..b16beb406b9 100644 --- a/app/models/project_services/teamcity_service.rb +++ b/app/models/project_services/teamcity_service.rb @@ -55,7 +55,7 @@ class TeamcityService < CiService placeholder: 'Build configuration ID' }, { type: 'text', name: 'username', placeholder: 'A user with permissions to trigger a manual build' }, - { type: 'password', name: 'password' }, + { type: 'password', name: 'password' } ] end @@ -78,7 +78,7 @@ class TeamcityService < CiService auth = { username: username, - password: password, + password: password } branch = Gitlab::Git.ref_name(data[:ref]) diff --git a/app/services/akismet_service.rb b/app/services/akismet_service.rb index 76b9f1feda7..8e11a2a36a7 100644 --- a/app/services/akismet_service.rb +++ b/app/services/akismet_service.rb @@ -16,7 +16,7 @@ class AkismetService created_at: DateTime.now, author: owner.name, author_email: owner.email, - referrer: options[:referrer], + referrer: options[:referrer] } begin diff --git a/app/services/audit_event_service.rb b/app/services/audit_event_service.rb index 8a000585e89..5ad9a50687c 100644 --- a/app/services/audit_event_service.rb +++ b/app/services/audit_event_service.rb @@ -8,7 +8,7 @@ class AuditEventService with: @details[:with], target_id: @author.id, target_type: 'User', - target_details: @author.name, + target_details: @author.name } self diff --git a/app/services/projects/update_pages_configuration_service.rb b/app/services/projects/update_pages_configuration_service.rb index eb4809afa85..cacb74b1205 100644 --- a/app/services/projects/update_pages_configuration_service.rb +++ b/app/services/projects/update_pages_configuration_service.rb @@ -27,7 +27,7 @@ module Projects { domain: domain.domain, certificate: domain.certificate, - key: domain.key, + key: domain.key } end end diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index af0ddbe5934..628d6d7b4f6 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -113,7 +113,7 @@ class SystemHooksService user_name: model.user.name, user_email: model.user.email, user_id: model.user.id, - group_access: model.human_access, + group_access: model.human_access } end end diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb index 74aba6c5d06..cc4f6a1d0fb 100644 --- a/config/initializers/static_files.rb +++ b/config/initializers/static_files.rb @@ -23,7 +23,7 @@ if app.config.serve_static_files host: dev_server.host, port: dev_server.port, manifest_host: dev_server.host, - manifest_port: dev_server.port, + manifest_port: dev_server.port } if Rails.env.development? diff --git a/db/migrate/20160810142633_remove_redundant_indexes.rb b/db/migrate/20160810142633_remove_redundant_indexes.rb index d7ab022d7bc..ea7d1f9a436 100644 --- a/db/migrate/20160810142633_remove_redundant_indexes.rb +++ b/db/migrate/20160810142633_remove_redundant_indexes.rb @@ -69,7 +69,7 @@ class RemoveRedundantIndexes < ActiveRecord::Migration [:namespaces, 'index_namespaces_on_created_at_and_id'], [:notes, 'index_notes_on_created_at_and_id'], [:projects, 'index_projects_on_created_at_and_id'], - [:users, 'index_users_on_created_at_and_id'], + [:users, 'index_users_on_created_at_and_id'] ] transaction do diff --git a/db/migrate/20160829114652_add_markdown_cache_columns.rb b/db/migrate/20160829114652_add_markdown_cache_columns.rb index 9cb44dfa9f9..6ad7237f4cd 100644 --- a/db/migrate/20160829114652_add_markdown_cache_columns.rb +++ b/db/migrate/20160829114652_add_markdown_cache_columns.rb @@ -25,7 +25,7 @@ class AddMarkdownCacheColumns < ActiveRecord::Migration notes: [:note], projects: [:description], releases: [:description], - snippets: [:title, :content], + snippets: [:title, :content] }.freeze def change diff --git a/lib/api/internal.rb b/lib/api/internal.rb index 2a11790b215..96aaaf868ea 100644 --- a/lib/api/internal.rb +++ b/lib/api/internal.rb @@ -90,7 +90,7 @@ module API { api_version: API.version, gitlab_version: Gitlab::VERSION, - gitlab_rev: Gitlab::REVISION, + gitlab_rev: Gitlab::REVISION } end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 9a6cb43abf7..687efe7da65 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -226,7 +226,7 @@ module API :shared_runners_enabled, :snippets_enabled, :visibility, - :wiki_enabled, + :wiki_enabled ] optional :name, type: String, desc: 'The name of the project' optional :default_branch, type: String, desc: 'The default branch of the project' diff --git a/lib/api/services.rb b/lib/api/services.rb index 23ef62c2258..cb07df9e249 100644 --- a/lib/api/services.rb +++ b/lib/api/services.rb @@ -356,7 +356,7 @@ module API name: :ca_pem, type: String, desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)' - }, + } ], 'mattermost-slash-commands' => [ { @@ -559,7 +559,7 @@ module API SlackService, MattermostService, MicrosoftTeamsService, - TeamcityService, + TeamcityService ] if Rails.env.development? @@ -577,7 +577,7 @@ module API service_classes += [ MockCiService, MockDeploymentService, - MockMonitoringService, + MockMonitoringService ] end diff --git a/lib/api/subscriptions.rb b/lib/api/subscriptions.rb index dbe54d3cd31..91567909998 100644 --- a/lib/api/subscriptions.rb +++ b/lib/api/subscriptions.rb @@ -5,7 +5,7 @@ module API subscribable_types = { 'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'issues' => proc { |id| find_project_issue(id) }, - 'labels' => proc { |id| find_project_label(id) }, + 'labels' => proc { |id| find_project_label(id) } } params do diff --git a/lib/api/v3/services.rb b/lib/api/v3/services.rb index 61629a04174..118c6df6549 100644 --- a/lib/api/v3/services.rb +++ b/lib/api/v3/services.rb @@ -377,7 +377,7 @@ module API name: :ca_pem, type: String, desc: 'A custom certificate authority bundle to verify the Kubernetes cluster with (PEM format)' - }, + } ], 'mattermost-slash-commands' => [ { diff --git a/lib/api/v3/subscriptions.rb b/lib/api/v3/subscriptions.rb index 068750ec077..690768db82f 100644 --- a/lib/api/v3/subscriptions.rb +++ b/lib/api/v3/subscriptions.rb @@ -7,7 +7,7 @@ module API 'merge_request' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'merge_requests' => proc { |id| find_merge_request_with_access(id, :update_merge_request) }, 'issues' => proc { |id| find_project_issue(id) }, - 'labels' => proc { |id| find_project_label(id) }, + 'labels' => proc { |id| find_project_label(id) } } params do diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index b439b0ee29b..55402101e43 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -20,7 +20,7 @@ module Ci italic: 0x02, underline: 0x04, conceal: 0x08, - cross: 0x10, + cross: 0x10 }.freeze def self.convert(ansi, state = nil) diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb index 15a461a16dd..b06474cda7f 100644 --- a/lib/ci/gitlab_ci_yaml_processor.rb +++ b/lib/ci/gitlab_ci_yaml_processor.rb @@ -70,7 +70,7 @@ module Ci cache: job[:cache], dependencies: job[:dependencies], after_script: job[:after_script], - environment: job[:environment], + environment: job[:environment] }.compact } end diff --git a/lib/gitlab/access.rb b/lib/gitlab/access.rb index 8c28009b9c6..4714ab18cc1 100644 --- a/lib/gitlab/access.rb +++ b/lib/gitlab/access.rb @@ -32,7 +32,7 @@ module Gitlab "Guest" => GUEST, "Reporter" => REPORTER, "Developer" => DEVELOPER, - "Master" => MASTER, + "Master" => MASTER } end @@ -47,7 +47,7 @@ module Gitlab guest: GUEST, reporter: REPORTER, developer: DEVELOPER, - master: MASTER, + master: MASTER } end @@ -60,7 +60,7 @@ module Gitlab "Not protected: Both developers and masters can push new commits, force push, or delete the branch." => PROTECTION_NONE, "Protected against pushes: Developers cannot push new commits, but are allowed to accept merge requests to the branch." => PROTECTION_DEV_CAN_MERGE, "Partially protected: Developers can push new commits, but cannot force push or delete the branch. Masters can do all of those." => PROTECTION_DEV_CAN_PUSH, - "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL, + "Fully protected: Developers cannot push new commits, force push, or delete the branch. Only masters can do any of those." => PROTECTION_FULL } end diff --git a/lib/gitlab/chat_commands/command.rb b/lib/gitlab/chat_commands/command.rb index f34ed0f4cf2..3e0c30c33b7 100644 --- a/lib/gitlab/chat_commands/command.rb +++ b/lib/gitlab/chat_commands/command.rb @@ -5,7 +5,7 @@ module Gitlab Gitlab::ChatCommands::IssueShow, Gitlab::ChatCommands::IssueNew, Gitlab::ChatCommands::IssueSearch, - Gitlab::ChatCommands::Deploy, + Gitlab::ChatCommands::Deploy ].freeze def execute diff --git a/lib/gitlab/cycle_analytics/permissions.rb b/lib/gitlab/cycle_analytics/permissions.rb index bef3b95ff1b..1e11e84a9cb 100644 --- a/lib/gitlab/cycle_analytics/permissions.rb +++ b/lib/gitlab/cycle_analytics/permissions.rb @@ -7,7 +7,7 @@ module Gitlab test: :read_build, review: :read_merge_request, staging: :read_build, - production: :read_issue, + production: :read_issue }.freeze def self.get(*args) diff --git a/lib/gitlab/data_builder/build.rb b/lib/gitlab/data_builder/build.rb index f78106f5b10..8e74e18a311 100644 --- a/lib/gitlab/data_builder/build.rb +++ b/lib/gitlab/data_builder/build.rb @@ -36,7 +36,7 @@ module Gitlab user: { id: user.try(:id), name: user.try(:name), - email: user.try(:email), + email: user.try(:email) }, commit: { @@ -49,7 +49,7 @@ module Gitlab status: commit.status, duration: commit.duration, started_at: commit.started_at, - finished_at: commit.finished_at, + finished_at: commit.finished_at }, repository: { @@ -60,7 +60,7 @@ module Gitlab git_http_url: project.http_url_to_repo, git_ssh_url: project.ssh_url_to_repo, visibility_level: project.visibility_level - }, + } } data diff --git a/lib/gitlab/etag_caching/router.rb b/lib/gitlab/etag_caching/router.rb index 692c909d838..31a5b9d108b 100644 --- a/lib/gitlab/etag_caching/router.rb +++ b/lib/gitlab/etag_caching/router.rb @@ -40,7 +40,7 @@ module Gitlab Gitlab::EtagCaching::Router::Route.new( %r(^(?!.*(#{RESERVED_WORDS})).*/pipelines/\d+\.json\z), 'project_pipeline' - ), + ) ].freeze def self.match(env) diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb index 9ed12ead023..256318cb833 100644 --- a/lib/gitlab/git/repository.rb +++ b/lib/gitlab/git/repository.rb @@ -258,7 +258,7 @@ module Gitlab 'RepoPath' => path, 'ArchivePrefix' => prefix, 'ArchivePath' => archive_file_path(prefix, storage_path, format), - 'CommitId' => commit.id, + 'CommitId' => commit.id } end diff --git a/lib/gitlab/kubernetes.rb b/lib/gitlab/kubernetes.rb index 3a7af363548..4a6091488c8 100644 --- a/lib/gitlab/kubernetes.rb +++ b/lib/gitlab/kubernetes.rb @@ -38,7 +38,7 @@ module Gitlab url: container_exec_url(api_url, namespace, pod_name, container["name"]), subprotocols: ['channel.k8s.io'], headers: Hash.new { |h, k| h[k] = [] }, - created_at: created_at, + created_at: created_at } end end @@ -64,7 +64,7 @@ module Gitlab tty: true, stdin: true, stdout: true, - stderr: true, + stderr: true }.to_query + '&' + EXEC_COMMAND case url.scheme diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index 8c5ad01e8c2..f3b3dea5318 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -22,7 +22,7 @@ module Gitlab params = { GL_ID: Gitlab::GlId.gl_id(user), GL_REPOSITORY: Gitlab::GlRepository.gl_repository(project, is_wiki), - RepoPath: repo_path, + RepoPath: repo_path } if Gitlab.config.gitaly.enabled @@ -51,7 +51,7 @@ module Gitlab { StoreLFSPath: "#{Gitlab.config.lfs.storage_path}/tmp/upload", LfsOid: oid, - LfsSize: size, + LfsSize: size } end @@ -62,7 +62,7 @@ module Gitlab def send_git_blob(repository, blob) params = { 'RepoPath' => repository.path_to_repo, - 'BlobId' => blob.id, + 'BlobId' => blob.id } [ @@ -127,7 +127,7 @@ module Gitlab 'Subprotocols' => terminal[:subprotocols], 'Url' => terminal[:url], 'Header' => terminal[:headers], - 'MaxSessionTime' => terminal[:max_session_time], + 'MaxSessionTime' => terminal[:max_session_time] } } details['Terminal']['CAPem'] = terminal[:ca_pem] if terminal.has_key?(:ca_pem) diff --git a/lib/tasks/gemojione.rake b/lib/tasks/gemojione.rake index b5572a39d30..87ca39b079b 100644 --- a/lib/tasks/gemojione.rake +++ b/lib/tasks/gemojione.rake @@ -21,7 +21,7 @@ namespace :gemojione do moji: emoji_hash['moji'], description: emoji_hash['description'], unicodeVersion: Gitlab::Emoji.emoji_unicode_version(name), - digest: hash_digest, + digest: hash_digest } resultant_emoji_map[name] = entry diff --git a/lib/tasks/gitlab/update_templates.rake b/lib/tasks/gitlab/update_templates.rake index 1b04e1350ed..59c32bbe7a4 100644 --- a/lib/tasks/gitlab/update_templates.rake +++ b/lib/tasks/gitlab/update_templates.rake @@ -49,7 +49,7 @@ namespace :gitlab do Template.new( "https://gitlab.com/gitlab-org/Dockerfile.git", /(\.{1,2}|LICENSE|CONTRIBUTING.md|\.Dockerfile)\z/ - ), + ) ].freeze def vendor_directory diff --git a/lib/tasks/spec.rake b/lib/tasks/spec.rake index 602c60be828..2eddcb3c777 100644 --- a/lib/tasks/spec.rake +++ b/lib/tasks/spec.rake @@ -60,7 +60,7 @@ desc "GitLab | Run specs" task :spec do cmds = [ %w(rake gitlab:setup), - %w(rspec spec), + %w(rspec spec) ] run_commands(cmds) end diff --git a/scripts/trigger-build b/scripts/trigger-build index 741e6361f01..565bc314ef1 100755 --- a/scripts/trigger-build +++ b/scripts/trigger-build @@ -8,7 +8,7 @@ params = { "ref" => ENV["OMNIBUS_BRANCH"] || "master", "token" => ENV["BUILD_TRIGGER_TOKEN"], "variables[GITLAB_VERSION]" => ENV["CI_COMMIT_SHA"], - "variables[ALTERNATIVE_SOURCES]" => true, + "variables[ALTERNATIVE_SOURCES]" => true } Dir.glob("*_VERSION").each do |version_file| diff --git a/spec/factories/services.rb b/spec/factories/services.rb index 62aa71ae8d8..28ddd0da753 100644 --- a/spec/factories/services.rb +++ b/spec/factories/services.rb @@ -22,7 +22,7 @@ FactoryGirl.define do properties({ namespace: 'somepath', api_url: 'https://kubernetes.example.com', - token: 'a' * 40, + token: 'a' * 40 }) end diff --git a/spec/features/auto_deploy_spec.rb b/spec/features/auto_deploy_spec.rb index 67b0f006854..eba1bca83a8 100644 --- a/spec/features/auto_deploy_spec.rb +++ b/spec/features/auto_deploy_spec.rb @@ -10,7 +10,7 @@ describe 'Auto deploy' do properties: { namespace: project.path, api_url: 'https://kubernetes.example.com', - token: 'a' * 40, + token: 'a' * 40 } ) project.team << [user, :master] diff --git a/spec/features/merge_requests/conflicts_spec.rb b/spec/features/merge_requests/conflicts_spec.rb index 43977ad2fc5..04b7593ce68 100644 --- a/spec/features/merge_requests/conflicts_spec.rb +++ b/spec/features/merge_requests/conflicts_spec.rb @@ -151,7 +151,7 @@ feature 'Merge request conflict resolution', js: true, feature: true do 'conflict-too-large' => 'when the conflicts contain a large file', 'conflict-binary-file' => 'when the conflicts contain a binary file', 'conflict-missing-side' => 'when the conflicts contain a file edited in one branch and deleted in another', - 'conflict-non-utf8' => 'when the conflicts contain a non-UTF-8 file', + 'conflict-non-utf8' => 'when the conflicts contain a non-UTF-8 file' }.freeze UNRESOLVABLE_CONFLICTS.each do |source_branch, description| diff --git a/spec/features/projects/features_visibility_spec.rb b/spec/features/projects/features_visibility_spec.rb index e1781cf320a..4533a6fb144 100644 --- a/spec/features/projects/features_visibility_spec.rb +++ b/spec/features/projects/features_visibility_spec.rb @@ -74,7 +74,7 @@ describe 'Edit Project Settings', feature: true do issues: namespace_project_issues_path(project.namespace, project), wiki: namespace_project_wiki_path(project.namespace, project, :home), snippets: namespace_project_snippets_path(project.namespace, project), - merge_requests: namespace_project_merge_requests_path(project.namespace, project), + merge_requests: namespace_project_merge_requests_path(project.namespace, project) } end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index 53abc056602..d1d2dcc4998 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -225,7 +225,7 @@ module Ci before_script: ["pwd"], rspec: { script: "rspec", type: "test", only: %w(master deploy) }, staging: { script: "deploy", type: "deploy", only: %w(master deploy) }, - production: { script: "deploy", type: "deploy", only: ["master@path", "deploy"] }, + production: { script: "deploy", type: "deploy", only: ["master@path", "deploy"] } }) config_processor = GitlabCiYamlProcessor.new(config, 'fork') @@ -381,7 +381,7 @@ module Ci before_script: ["pwd"], rspec: { script: "rspec", type: "test", except: ["master", "deploy", "test@fork"] }, staging: { script: "deploy", type: "deploy", except: ["master"] }, - production: { script: "deploy", type: "deploy", except: ["master@fork"] }, + production: { script: "deploy", type: "deploy", except: ["master@fork"] } }) config_processor = GitlabCiYamlProcessor.new(config, 'fork') @@ -743,7 +743,7 @@ module Ci cache: { paths: ["logs/", "binaries/"], untracked: true, key: 'global' }, rspec: { script: "rspec", - cache: { paths: ["test/"], untracked: false, key: 'local' }, + cache: { paths: ["test/"], untracked: false, key: 'local' } } }) diff --git a/spec/lib/expand_variables_spec.rb b/spec/lib/expand_variables_spec.rb index 90628917943..7faa0f31b68 100644 --- a/spec/lib/expand_variables_spec.rb +++ b/spec/lib/expand_variables_spec.rb @@ -25,7 +25,7 @@ describe ExpandVariables do result: 'keyvalueresult', variables: [ { key: 'variable', value: 'value' }, - { key: 'variable2', value: 'result' }, + { key: 'variable2', value: 'result' } ] }, { value: 'key${variable}${variable2}', result: 'keyvalueresult', @@ -37,7 +37,7 @@ describe ExpandVariables do result: 'keyresultvalue', variables: [ { key: 'variable', value: 'value' }, - { key: 'variable2', value: 'result' }, + { key: 'variable2', value: 'result' } ] }, { value: 'key${variable2}${variable}', result: 'keyresultvalue', @@ -49,7 +49,7 @@ describe ExpandVariables do result: 'review/feature/add-review-apps', variables: [ { key: 'CI_COMMIT_REF_NAME', value: 'feature/add-review-apps' } - ] }, + ] } ] tests.each do |test| diff --git a/spec/lib/gitlab/backup/manager_spec.rb b/spec/lib/gitlab/backup/manager_spec.rb index f84782ab440..c59ff7fb290 100644 --- a/spec/lib/gitlab/backup/manager_spec.rb +++ b/spec/lib/gitlab/backup/manager_spec.rb @@ -151,7 +151,7 @@ describe Backup::Manager, lib: true do allow(Dir).to receive(:glob).and_return( [ '1451606400_2016_01_01_gitlab_backup.tar', - '1451520000_2015_12_31_gitlab_backup.tar', + '1451520000_2015_12_31_gitlab_backup.tar' ] ) end diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index a10a251dc4a..4d202a76e1b 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -1372,7 +1372,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do nil, { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, { old_path: file_name, old_line: 6 }, - { new_path: file_name, new_line: 7 }, + { new_path: file_name, new_line: 7 } ] expect_positions(old_position_attrs, new_position_attrs) @@ -1444,7 +1444,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do nil, { old_path: file_name, new_path: file_name, old_line: 5, new_line: 5 }, { old_path: file_name, old_line: 6 }, - { new_path: file_name, new_line: 7 }, + { new_path: file_name, new_line: 7 } ] expect_positions(old_position_attrs, new_position_attrs) @@ -1498,7 +1498,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do { old_path: file_name, new_path: file_name, old_line: 5, new_line: 4 }, { old_path: file_name, new_path: file_name, old_line: 6, new_line: 5 }, nil, - { new_path: file_name, new_line: 6 }, + { new_path: file_name, new_line: 6 } ] expect_positions(old_position_attrs, new_position_attrs) @@ -1746,7 +1746,7 @@ describe Gitlab::Diff::PositionTracer, lib: true do { old_path: file_name, new_path: file_name, old_line: 4, new_line: 5 }, { old_path: file_name, old_line: 5 }, { new_path: file_name, new_line: 6 }, - { new_path: file_name, new_line: 7 }, + { new_path: file_name, new_line: 7 } ] expect_positions(old_position_attrs, new_position_attrs) diff --git a/spec/lib/gitlab/git/encoding_helper_spec.rb b/spec/lib/gitlab/git/encoding_helper_spec.rb index f6ac7b23d1d..1a3bf802a07 100644 --- a/spec/lib/gitlab/git/encoding_helper_spec.rb +++ b/spec/lib/gitlab/git/encoding_helper_spec.rb @@ -19,8 +19,8 @@ describe Gitlab::Git::EncodingHelper do [ 'removes invalid bytes from ASCII-8bit encoded multibyte string. This can occur when a git diff match line truncates in the middle of a multibyte character. This occurs after the second word in this example. The test string is as short as we can get while still triggering the error condition when not looking at `detect[:confidence]`.', "mu ns\xC3\n Lorem ipsum dolor sit amet, consectetur adipisicing ut\xC3\xA0y\xC3\xB9abcd\xC3\xB9efg kia elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non p\n {: .normal_pn}\n \n-Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n# *Lorem ipsum\xC3\xB9l\xC3\xB9l\xC3\xA0 dolor\xC3\xB9k\xC3\xB9 sit\xC3\xA8b\xC3\xA8 N\xC3\xA8 amet b\xC3\xA0d\xC3\xAC*\n+# *consectetur\xC3\xB9l\xC3\xB9l\xC3\xA0 adipisicing\xC3\xB9k\xC3\xB9 elit\xC3\xA8b\xC3\xA8 N\xC3\xA8 sed do\xC3\xA0d\xC3\xAC*{: .italic .smcaps}\n \n \xEF\x9B\xA1 eiusmod tempor incididunt, ut\xC3\xAAn\xC3\xB9 labore et dolore. Tw\xC4\x83nj\xC3\xAC magna aliqua. Ut enim ad minim veniam\n {: .normal}\n@@ -9,5 +9,5 @@ quis nostrud\xC3\xAAt\xC3\xB9 exercitiation ullamco laboris m\xC3\xB9s\xC3\xB9k\xC3\xB9abc\xC3\xB9 nisi ".force_encoding('ASCII-8BIT'), - "mu ns\n Lorem ipsum dolor sit amet, consectetur adipisicing ut\xC3\xA0y\xC3\xB9abcd\xC3\xB9efg kia elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non p\n {: .normal_pn}\n \n-Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n# *Lorem ipsum\xC3\xB9l\xC3\xB9l\xC3\xA0 dolor\xC3\xB9k\xC3\xB9 sit\xC3\xA8b\xC3\xA8 N\xC3\xA8 amet b\xC3\xA0d\xC3\xAC*\n+# *consectetur\xC3\xB9l\xC3\xB9l\xC3\xA0 adipisicing\xC3\xB9k\xC3\xB9 elit\xC3\xA8b\xC3\xA8 N\xC3\xA8 sed do\xC3\xA0d\xC3\xAC*{: .italic .smcaps}\n \n \xEF\x9B\xA1 eiusmod tempor incididunt, ut\xC3\xAAn\xC3\xB9 labore et dolore. Tw\xC4\x83nj\xC3\xAC magna aliqua. Ut enim ad minim veniam\n {: .normal}\n@@ -9,5 +9,5 @@ quis nostrud\xC3\xAAt\xC3\xB9 exercitiation ullamco laboris m\xC3\xB9s\xC3\xB9k\xC3\xB9abc\xC3\xB9 nisi ", - ], + "mu ns\n Lorem ipsum dolor sit amet, consectetur adipisicing ut\xC3\xA0y\xC3\xB9abcd\xC3\xB9efg kia elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non p\n {: .normal_pn}\n \n-Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in\n# *Lorem ipsum\xC3\xB9l\xC3\xB9l\xC3\xA0 dolor\xC3\xB9k\xC3\xB9 sit\xC3\xA8b\xC3\xA8 N\xC3\xA8 amet b\xC3\xA0d\xC3\xAC*\n+# *consectetur\xC3\xB9l\xC3\xB9l\xC3\xA0 adipisicing\xC3\xB9k\xC3\xB9 elit\xC3\xA8b\xC3\xA8 N\xC3\xA8 sed do\xC3\xA0d\xC3\xAC*{: .italic .smcaps}\n \n \xEF\x9B\xA1 eiusmod tempor incididunt, ut\xC3\xAAn\xC3\xB9 labore et dolore. Tw\xC4\x83nj\xC3\xAC magna aliqua. Ut enim ad minim veniam\n {: .normal}\n@@ -9,5 +9,5 @@ quis nostrud\xC3\xAAt\xC3\xB9 exercitiation ullamco laboris m\xC3\xB9s\xC3\xB9k\xC3\xB9abc\xC3\xB9 nisi " + ] ].each do |description, test_string, xpect| it description do expect(ext_class.encode!(test_string)).to eq(xpect) @@ -37,18 +37,18 @@ describe Gitlab::Git::EncodingHelper do [ "encodes valid utf8 encoded string to utf8", "λ, λ, λ".encode("UTF-8"), - "λ, λ, λ".encode("UTF-8"), + "λ, λ, λ".encode("UTF-8") ], [ "encodes valid ASCII-8BIT encoded string to utf8", "ascii only".encode("ASCII-8BIT"), - "ascii only".encode("UTF-8"), + "ascii only".encode("UTF-8") ], [ "encodes valid ISO-8859-1 encoded string to utf8", "Rüby ist eine Programmiersprache. Wir verlängern den text damit ICU die Sprache erkennen kann.".encode("ISO-8859-1", "UTF-8"), - "Rüby ist eine Programmiersprache. Wir verlängern den text damit ICU die Sprache erkennen kann.".encode("UTF-8"), - ], + "Rüby ist eine Programmiersprache. Wir verlängern den text damit ICU die Sprache erkennen kann.".encode("UTF-8") + ] ].each do |description, test_string, xpect| it description do r = ext_class.encode_utf8(test_string.force_encoding('UTF-8')) @@ -77,8 +77,8 @@ describe Gitlab::Git::EncodingHelper do [ 'removes invalid bytes from ASCII-8bit encoded multibyte string.', "Lorem ipsum\xC3\n dolor sit amet, xy\xC3\xA0y\xC3\xB9abcd\xC3\xB9efg".force_encoding('ASCII-8BIT'), - "Lorem ipsum\n dolor sit amet, xyàyùabcdùefg", - ], + "Lorem ipsum\n dolor sit amet, xyàyùabcdùefg" + ] ].each do |description, test_string, xpect| it description do expect(ext_class.encode!(test_string)).to eq(xpect) diff --git a/spec/lib/gitlab/git/util_spec.rb b/spec/lib/gitlab/git/util_spec.rb index 69d3ca55397..88c871855df 100644 --- a/spec/lib/gitlab/git/util_spec.rb +++ b/spec/lib/gitlab/git/util_spec.rb @@ -6,7 +6,7 @@ describe Gitlab::Git::Util do ["", 0], ["foo", 1], ["foo\n", 1], - ["foo\n\n", 2], + ["foo\n\n", 2] ].each do |string, line_count| it "counts #{line_count} lines in #{string.inspect}" do expect(described_class.count_lines(string)).to eq(line_count) diff --git a/spec/lib/gitlab/import_export/relation_factory_spec.rb b/spec/lib/gitlab/import_export/relation_factory_spec.rb index 06cd8ab87ed..744fed44925 100644 --- a/spec/lib/gitlab/import_export/relation_factory_spec.rb +++ b/spec/lib/gitlab/import_export/relation_factory_spec.rb @@ -95,7 +95,7 @@ describe Gitlab::ImportExport::RelationFactory, lib: true do 'random_id' => 99, 'milestone_id' => 99, 'project_id' => 99, - 'user_id' => 99, + 'user_id' => 99 } end diff --git a/spec/lib/gitlab/repo_path_spec.rb b/spec/lib/gitlab/repo_path_spec.rb index f94c9c2e315..f9025397107 100644 --- a/spec/lib/gitlab/repo_path_spec.rb +++ b/spec/lib/gitlab/repo_path_spec.rb @@ -29,7 +29,7 @@ describe ::Gitlab::RepoPath do before do allow(Gitlab.config.repositories).to receive(:storages).and_return({ 'storage1' => { 'path' => '/foo' }, - 'storage2' => { 'path' => '/bar' }, + 'storage2' => { 'path' => '/bar' } }) end diff --git a/spec/lib/gitlab/workhorse_spec.rb b/spec/lib/gitlab/workhorse_spec.rb index beb1791a429..67b759f7dcd 100644 --- a/spec/lib/gitlab/workhorse_spec.rb +++ b/spec/lib/gitlab/workhorse_spec.rb @@ -202,7 +202,7 @@ describe Gitlab::Workhorse, lib: true do context 'when Gitaly is enabled' do let(:gitaly_params) do { - GitalyAddress: Gitlab::GitalyClient.get_address('default'), + GitalyAddress: Gitlab::GitalyClient.get_address('default') } end @@ -214,7 +214,7 @@ describe Gitlab::Workhorse, lib: true do repo_param = { Repository: { path: repo_path, storage_name: 'default', - relative_path: project.full_path + '.git', + relative_path: project.full_path + '.git' } } expect(subject).to include(repo_param) diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index c2c19c62048..3c3ae3832de 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -89,7 +89,7 @@ describe ApplicationSetting, models: true do storages = { 'custom1' => 'tmp/tests/custom_repositories_1', 'custom2' => 'tmp/tests/custom_repositories_2', - 'custom3' => 'tmp/tests/custom_repositories_3', + 'custom3' => 'tmp/tests/custom_repositories_3' } allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 5231ce28c9d..e971b4bc3f9 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -972,7 +972,7 @@ describe Ci::Build, :models do 'fix-1-foo' => 'fix-1-foo', 'a' * 63 => 'a' * 63, 'a' * 64 => 'a' * 63, - 'FOO' => 'foo', + 'FOO' => 'foo' }.each do |ref, slug| it "transforms #{ref} to #{slug}" do build.ref = ref @@ -1144,7 +1144,7 @@ describe Ci::Build, :models do { key: 'CI_PIPELINE_ID', value: pipeline.id.to_s, public: true }, { key: 'CI_REGISTRY_USER', value: 'gitlab-ci-token', public: true }, { key: 'CI_REGISTRY_PASSWORD', value: build.token, public: false }, - { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false }, + { key: 'CI_REPOSITORY_URL', value: build.repo_url, public: false } ] end diff --git a/spec/models/environment_spec.rb b/spec/models/environment_spec.rb index 28e5c3f80f4..edc1c204014 100644 --- a/spec/models/environment_spec.rb +++ b/spec/models/environment_spec.rb @@ -438,7 +438,7 @@ describe Environment, models: true do "foo**bar" => "foo-bar" + SUFFIX, "*-foo" => "env-foo" + SUFFIX, "staging-12345678-" => "staging-12345678" + SUFFIX, - "staging-12345678-01234567" => "staging-12345678" + SUFFIX, + "staging-12345678-01234567" => "staging-12345678" + SUFFIX }.each do |name, matcher| it "returns a slug matching #{matcher}, given #{name}" do slug = described_class.new(name: name).generate_slug diff --git a/spec/models/global_milestone_spec.rb b/spec/models/global_milestone_spec.rb index 55b87d1c48a..a14efda3eda 100644 --- a/spec/models/global_milestone_spec.rb +++ b/spec/models/global_milestone_spec.rb @@ -137,7 +137,7 @@ describe GlobalMilestone, models: true do [ milestone1_project1, milestone1_project2, - milestone1_project3, + milestone1_project3 ] milestones_relation = Milestone.where(id: milestones.map(&:id)) diff --git a/spec/models/project_authorization_spec.rb b/spec/models/project_authorization_spec.rb index 33ef67f97a7..cd0a4a94809 100644 --- a/spec/models/project_authorization_spec.rb +++ b/spec/models/project_authorization_spec.rb @@ -16,7 +16,7 @@ describe ProjectAuthorization do it 'inserts rows in batches' do described_class.insert_authorizations([ [user.id, project1.id, Gitlab::Access::MASTER], - [user.id, project2.id, Gitlab::Access::MASTER], + [user.id, project2.id, Gitlab::Access::MASTER] ], 1) expect(user.project_authorizations.count).to eq(2) diff --git a/spec/models/project_services/asana_service_spec.rb b/spec/models/project_services/asana_service_spec.rb index 48aef3a93f2..95c35162d96 100644 --- a/spec/models/project_services/asana_service_spec.rb +++ b/spec/models/project_services/asana_service_spec.rb @@ -28,7 +28,7 @@ describe AsanaService, models: true do commits: messages.map do |m| { message: m, - url: 'https://gitlab.com/', + url: 'https://gitlab.com/' } end } diff --git a/spec/models/project_services/chat_message/issue_message_spec.rb b/spec/models/project_services/chat_message/issue_message_spec.rb index 34e2d94b1ed..c159ab00ab1 100644 --- a/spec/models/project_services/chat_message/issue_message_spec.rb +++ b/spec/models/project_services/chat_message/issue_message_spec.rb @@ -48,7 +48,7 @@ describe ChatMessage::IssueMessage, models: true do title: "#100 Issue title", title_link: "http://url.com", text: "issue description", - color: color, + color: color } ]) end diff --git a/spec/models/project_services/chat_message/merge_message_spec.rb b/spec/models/project_services/chat_message/merge_message_spec.rb index fa0a1f4a5b7..61f17031172 100644 --- a/spec/models/project_services/chat_message/merge_message_spec.rb +++ b/spec/models/project_services/chat_message/merge_message_spec.rb @@ -22,7 +22,7 @@ describe ChatMessage::MergeMessage, models: true do state: 'opened', description: 'merge request description', source_branch: 'source_branch', - target_branch: 'target_branch', + target_branch: 'target_branch' } } end diff --git a/spec/models/project_services/chat_message/note_message_spec.rb b/spec/models/project_services/chat_message/note_message_spec.rb index 7cd9c61ee2b..7996536218a 100644 --- a/spec/models/project_services/chat_message/note_message_spec.rb +++ b/spec/models/project_services/chat_message/note_message_spec.rb @@ -15,7 +15,7 @@ describe ChatMessage::NoteMessage, models: true do project_url: 'http://somewhere.com', repository: { name: 'project_name', - url: 'http://somewhere.com', + url: 'http://somewhere.com' }, object_attributes: { id: 10, diff --git a/spec/models/project_services/chat_message/push_message_spec.rb b/spec/models/project_services/chat_message/push_message_spec.rb index 63eb078c44e..c794f659c41 100644 --- a/spec/models/project_services/chat_message/push_message_spec.rb +++ b/spec/models/project_services/chat_message/push_message_spec.rb @@ -21,7 +21,7 @@ describe ChatMessage::PushMessage, models: true do before do args[:commits] = [ { message: 'message1', url: 'http://url1.com', id: 'abcdefghijkl', author: { name: 'author1' } }, - { message: 'message2', url: 'http://url2.com', id: '123456789012', author: { name: 'author2' } }, + { message: 'message2', url: 'http://url2.com', id: '123456789012', author: { name: 'author2' } } ] end @@ -33,7 +33,7 @@ describe ChatMessage::PushMessage, models: true do expect(subject.attachments).to eq([{ text: ": message1 - author1\n\n"\ ": message2 - author2", - color: color, + color: color }]) end end diff --git a/spec/models/project_services/chat_message/wiki_page_message_spec.rb b/spec/models/project_services/chat_message/wiki_page_message_spec.rb index 0df7db2abc2..4ca1b8aa7b7 100644 --- a/spec/models/project_services/chat_message/wiki_page_message_spec.rb +++ b/spec/models/project_services/chat_message/wiki_page_message_spec.rb @@ -53,7 +53,7 @@ describe ChatMessage::WikiPageMessage, models: true do expect(subject.attachments).to eq([ { text: "Wiki page description", - color: color, + color: color } ]) end @@ -66,7 +66,7 @@ describe ChatMessage::WikiPageMessage, models: true do expect(subject.attachments).to eq([ { text: "Wiki page description", - color: color, + color: color } ]) end diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index e69eb0098dd..80966b99292 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -54,7 +54,7 @@ describe KubernetesService, models: true, caching: true do 'a' * 63 => true, 'a' * 64 => false, 'a.b' => false, - 'a*b' => false, + 'a*b' => false }.each do |namespace, validity| it "validates #{namespace} as #{validity ? 'valid' : 'invalid'}" do subject.namespace = namespace diff --git a/spec/models/project_services/pivotaltracker_service_spec.rb b/spec/models/project_services/pivotaltracker_service_spec.rb index 45b2f1068bf..a76e909d04d 100644 --- a/spec/models/project_services/pivotaltracker_service_spec.rb +++ b/spec/models/project_services/pivotaltracker_service_spec.rb @@ -40,7 +40,7 @@ describe PivotaltrackerService, models: true do name: 'Some User' }, url: 'https://example.com/commit', - message: 'commit message', + message: 'commit message' } ] } diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 28aa44d8458..f2b4e9070b4 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -973,7 +973,7 @@ describe Project, models: true do before do storages = { 'default' => { 'path' => 'tmp/tests/repositories' }, - 'picked' => { 'path' => 'tmp/tests/repositories' }, + 'picked' => { 'path' => 'tmp/tests/repositories' } } allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index b845e85b295..f2c059010f4 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -676,7 +676,7 @@ describe User, models: true do protocol_and_expectation = { 'http' => false, 'ssh' => true, - '' => true, + '' => true } protocol_and_expectation.each do |protocol, expected| diff --git a/spec/requests/api/files_spec.rb b/spec/requests/api/files_spec.rb index fa28047d49c..deb2cac6869 100644 --- a/spec/requests/api/files_spec.rb +++ b/spec/requests/api/files_spec.rb @@ -329,7 +329,7 @@ describe API::Files do end let(:get_params) do { - ref: 'master', + ref: 'master' } end diff --git a/spec/requests/api/groups_spec.rb b/spec/requests/api/groups_spec.rb index ed93a8815d3..90b36374ded 100644 --- a/spec/requests/api/groups_spec.rb +++ b/spec/requests/api/groups_spec.rb @@ -73,7 +73,7 @@ describe API::Groups do storage_size: 702, repository_size: 123, lfs_objects_size: 234, - build_artifacts_size: 345, + build_artifacts_size: 345 }.stringify_keys exposed_attributes = attributes.dup exposed_attributes['job_artifacts_size'] = exposed_attributes.delete('build_artifacts_size') diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb index ab70ce5cd2f..d5c3b5b34ad 100644 --- a/spec/requests/api/projects_spec.rb +++ b/spec/requests/api/projects_spec.rb @@ -661,7 +661,7 @@ describe API::Projects do 'name' => user.namespace.name, 'path' => user.namespace.path, 'kind' => user.namespace.kind, - 'full_path' => user.namespace.full_path, + 'full_path' => user.namespace.full_path }) end diff --git a/spec/requests/api/v3/files_spec.rb b/spec/requests/api/v3/files_spec.rb index 5bcbb441979..378ca1720ff 100644 --- a/spec/requests/api/v3/files_spec.rb +++ b/spec/requests/api/v3/files_spec.rb @@ -53,7 +53,7 @@ describe API::V3::Files do let(:params) do { file_path: 'app/models/application.rb', - ref: 'master', + ref: 'master' } end @@ -263,7 +263,7 @@ describe API::V3::Files do let(:get_params) do { file_path: file_path, - ref: 'master', + ref: 'master' } end diff --git a/spec/requests/api/v3/groups_spec.rb b/spec/requests/api/v3/groups_spec.rb index 065cb7ecfe4..bc261b5e07c 100644 --- a/spec/requests/api/v3/groups_spec.rb +++ b/spec/requests/api/v3/groups_spec.rb @@ -69,7 +69,7 @@ describe API::V3::Groups do storage_size: 702, repository_size: 123, lfs_objects_size: 234, - build_artifacts_size: 345, + build_artifacts_size: 345 }.stringify_keys project1.statistics.update!(attributes) diff --git a/spec/requests/api/v3/projects_spec.rb b/spec/requests/api/v3/projects_spec.rb index e15b90d7a9e..dc7c3d125b1 100644 --- a/spec/requests/api/v3/projects_spec.rb +++ b/spec/requests/api/v3/projects_spec.rb @@ -227,7 +227,7 @@ describe API::V3::Projects do storage_size: 702, repository_size: 123, lfs_objects_size: 234, - build_artifacts_size: 345, + build_artifacts_size: 345 } project4.statistics.update!(attributes) @@ -706,7 +706,7 @@ describe API::V3::Projects do 'name' => user.namespace.name, 'path' => user.namespace.path, 'kind' => user.namespace.kind, - 'full_path' => user.namespace.full_path, + 'full_path' => user.namespace.full_path }) end diff --git a/spec/requests/lfs_http_spec.rb b/spec/requests/lfs_http_spec.rb index 5d495bc9e7d..0c9b4121adf 100644 --- a/spec/requests/lfs_http_spec.rb +++ b/spec/requests/lfs_http_spec.rb @@ -425,7 +425,7 @@ describe 'Git LFS API and storage' do 'size' => sample_size, 'error' => { 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", + 'message' => "Object does not exist on the server or you don't have permissions to access it" } } ] @@ -456,7 +456,7 @@ describe 'Git LFS API and storage' do 'size' => 1575078, 'error' => { 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", + 'message' => "Object does not exist on the server or you don't have permissions to access it" } } ] @@ -493,7 +493,7 @@ describe 'Git LFS API and storage' do 'size' => 1575078, 'error' => { 'code' => 404, - 'message' => "Object does not exist on the server or you don't have permissions to access it", + 'message' => "Object does not exist on the server or you don't have permissions to access it" } }, { diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb index fbb69bc0920..1a5d388382d 100644 --- a/spec/requests/openid_connect_spec.rb +++ b/spec/requests/openid_connect_spec.rb @@ -79,7 +79,7 @@ describe 'OpenID Connect requests' do 'email_verified' => true, 'website' => 'https://example.com', 'profile' => 'http://localhost/alice', - 'picture' => "http://localhost/uploads/user/avatar/#{user.id}/dk.png", + 'picture' => "http://localhost/uploads/user/avatar/#{user.id}/dk.png" }) end end diff --git a/spec/serializers/analytics_issue_entity_spec.rb b/spec/serializers/analytics_issue_entity_spec.rb index 68086216ba9..75d606d5eb3 100644 --- a/spec/serializers/analytics_issue_entity_spec.rb +++ b/spec/serializers/analytics_issue_entity_spec.rb @@ -9,7 +9,7 @@ describe AnalyticsIssueEntity do iid: "1", id: "1", created_at: "2016-11-12 15:04:02.948604", - author: user, + author: user } end diff --git a/spec/serializers/analytics_issue_serializer_spec.rb b/spec/serializers/analytics_issue_serializer_spec.rb index ba24cf8e481..7c14c198a74 100644 --- a/spec/serializers/analytics_issue_serializer_spec.rb +++ b/spec/serializers/analytics_issue_serializer_spec.rb @@ -16,7 +16,7 @@ describe AnalyticsIssueSerializer do iid: "1", id: "1", created_at: "2016-11-12 15:04:02.948604", - author: user, + author: user } end diff --git a/spec/services/cohorts_service_spec.rb b/spec/services/cohorts_service_spec.rb index 1e99442fdcb..77595d7ba2d 100644 --- a/spec/services/cohorts_service_spec.rb +++ b/spec/services/cohorts_service_spec.rb @@ -89,7 +89,7 @@ describe CohortsService do activity_months: [{ total: 2, percentage: 100 }], total: 2, inactive: 1 - }, + } ] expect(described_class.new.execute).to eq(months_included: 12, diff --git a/spec/services/create_deployment_service_spec.rb b/spec/services/create_deployment_service_spec.rb index a883705bd45..f35d7a33548 100644 --- a/spec/services/create_deployment_service_spec.rb +++ b/spec/services/create_deployment_service_spec.rb @@ -255,7 +255,7 @@ describe CreateDeploymentService, services: true do environment: 'production', ref: 'master', tag: false, - sha: '97de212e80737a608d939f648d959671fb0a0142b', + sha: '97de212e80737a608d939f648d959671fb0a0142b' } end diff --git a/spec/services/issuable/bulk_update_service_spec.rb b/spec/services/issuable/bulk_update_service_spec.rb index 5b1639ca0d6..3ddd0badd39 100644 --- a/spec/services/issuable/bulk_update_service_spec.rb +++ b/spec/services/issuable/bulk_update_service_spec.rb @@ -163,7 +163,7 @@ describe Issuable::BulkUpdateService, services: true do { label_ids: labels.map(&:id), add_label_ids: add_labels.map(&:id), - remove_label_ids: remove_labels.map(&:id), + remove_label_ids: remove_labels.map(&:id) } end diff --git a/spec/services/merge_requests/refresh_service_spec.rb b/spec/services/merge_requests/refresh_service_spec.rb index 03215a4624a..1f109eab268 100644 --- a/spec/services/merge_requests/refresh_service_spec.rb +++ b/spec/services/merge_requests/refresh_service_spec.rb @@ -348,7 +348,7 @@ describe MergeRequests::RefreshService, services: true do title: 'fixup! Fix issue', work_in_progress?: true, to_reference: 'ccccccc' - ), + ) ]) refresh_service.execute(@oldrev, @newrev, 'refs/heads/wip') reload_mrs diff --git a/spec/services/notification_service_spec.rb b/spec/services/notification_service_spec.rb index 74f96b97909..de3bbc6b6a1 100644 --- a/spec/services/notification_service_spec.rb +++ b/spec/services/notification_service_spec.rb @@ -350,7 +350,7 @@ describe NotificationService, services: true do create(:note_on_personal_snippet, noteable: snippet, note: 'note', author: @u_participant), create(:note_on_personal_snippet, noteable: snippet, note: 'note', author: @u_mentioned), create(:note_on_personal_snippet, noteable: snippet, note: 'note', author: @u_disabled), - create(:note_on_personal_snippet, noteable: snippet, note: 'note', author: @u_note_author), + create(:note_on_personal_snippet, noteable: snippet, note: 'note', author: @u_note_author) ] end diff --git a/spec/support/kubernetes_helpers.rb b/spec/support/kubernetes_helpers.rb index b5ed71ba3be..d2a1ded57ff 100644 --- a/spec/support/kubernetes_helpers.rb +++ b/spec/support/kubernetes_helpers.rb @@ -5,7 +5,7 @@ module KubernetesHelpers { "kind" => "APIResourceList", "resources" => [ - { "name" => "pods", "namespaced" => true, "kind" => "Pod" }, + { "name" => "pods", "namespaced" => true, "kind" => "Pod" } ] } end @@ -22,13 +22,13 @@ module KubernetesHelpers "metadata" => { "name" => "kube-pod", "creationTimestamp" => "2016-11-25T19:55:19Z", - "labels" => { "app" => app }, + "labels" => { "app" => app } }, "spec" => { "containers" => [ { "name" => "container-0" }, - { "name" => "container-1" }, - ], + { "name" => "container-1" } + ] }, "status" => { "phase" => "Running" } } diff --git a/spec/support/repo_helpers.rb b/spec/support/repo_helpers.rb index e9d5c7b12ae..3c6956cf5e0 100644 --- a/spec/support/repo_helpers.rb +++ b/spec/support/repo_helpers.rb @@ -92,11 +92,11 @@ eos changes = [ { line_code: 'a5cc2925ca8258af241be7e5b0381edf30266302_20_20', - file_path: '.gitignore', + file_path: '.gitignore' }, { line_code: '7445606fbf8f3683cd42bdc54b05d7a0bc2dfc44_4_6', - file_path: '.gitmodules', + file_path: '.gitmodules' } ] diff --git a/spec/support/workhorse_helpers.rb b/spec/support/workhorse_helpers.rb index 47673cd4c3a..ef1f9f68671 100644 --- a/spec/support/workhorse_helpers.rb +++ b/spec/support/workhorse_helpers.rb @@ -9,7 +9,7 @@ module WorkhorseHelpers header = split_header.join(':') [ type, - JSON.parse(Base64.urlsafe_decode64(header)), + JSON.parse(Base64.urlsafe_decode64(header)) ] end end diff --git a/spec/tasks/gitlab/gitaly_rake_spec.rb b/spec/tasks/gitlab/gitaly_rake_spec.rb index aaf998a546f..f035504320b 100644 --- a/spec/tasks/gitlab/gitaly_rake_spec.rb +++ b/spec/tasks/gitlab/gitaly_rake_spec.rb @@ -80,7 +80,7 @@ describe 'gitlab:gitaly namespace rake task' do it 'prints storage configuration in a TOML format' do config = { 'default' => { 'path' => '/path/to/default' }, - 'nfs_01' => { 'path' => '/path/to/nfs_01' }, + 'nfs_01' => { 'path' => '/path/to/nfs_01' } } allow(Gitlab.config.repositories).to receive(:storages).and_return(config) -- cgit v1.2.1 From 3db37e05622aa3daa2be41bb9edc486cd2e54bcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Coutable?= Date: Wed, 3 May 2017 13:27:17 +0200 Subject: Enable the Style/TrailingCommaInArguments cop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the EnforcedStyleForMultiline: no_comma option. Signed-off-by: Rémy Coutable --- .rubocop.yml | 5 +++++ .rubocop_todo.yml | 7 ------- app/controllers/profiles/preferences_controller.rb | 2 +- app/controllers/projects/issues_controller.rb | 2 +- app/models/diff_discussion.rb | 2 +- app/models/key.rb | 2 +- app/models/namespace.rb | 2 +- app/models/project_services/flowdock_service.rb | 2 +- app/models/repository.rb | 2 +- app/models/sent_notification.rb | 2 +- app/services/boards/issues/move_service.rb | 2 +- app/services/notification_service.rb | 2 +- app/services/system_hooks_service.rb | 2 +- app/workers/repository_check/clear_worker.rb | 2 +- app/workers/repository_check/single_repository_worker.rb | 2 +- config/initializers/ar_monkey_patch.rb | 2 +- config/initializers/hamlit.rb | 4 ++-- config/initializers/static_files.rb | 4 ++-- features/steps/explore/projects.rb | 2 +- lib/api/groups.rb | 2 +- lib/api/helpers.rb | 2 +- lib/api/projects.rb | 2 +- lib/api/v3/groups.rb | 2 +- lib/api/v3/projects.rb | 2 +- lib/gitlab/git/blob.rb | 2 +- lib/gitlab/git/tree.rb | 2 +- lib/gitlab/gitaly_client/commit.rb | 2 +- lib/gitlab/gitaly_client/util.rb | 2 +- lib/gitlab/ldap/config.rb | 2 +- lib/gitlab/sentry.rb | 2 +- lib/gitlab/workhorse.rb | 2 +- spec/controllers/groups_controller_spec.rb | 2 +- spec/features/admin/admin_uses_repository_checks_spec.rb | 2 +- spec/features/copy_as_gfm_spec.rb | 2 +- spec/features/projects/pipelines/pipelines_spec.rb | 2 +- spec/lib/ci/gitlab_ci_yaml_processor_spec.rb | 6 +++--- spec/lib/gitlab/auth_spec.rb | 4 ++-- spec/lib/gitlab/ci/config/entry/global_spec.rb | 2 +- spec/lib/gitlab/contributions_calendar_spec.rb | 2 +- spec/lib/gitlab/git/diff_spec.rb | 2 +- spec/lib/gitlab/gitaly_client/commit_spec.rb | 4 ++-- spec/models/project_services/kubernetes_service_spec.rb | 4 ++-- spec/models/project_statistics_spec.rb | 4 ++-- spec/requests/ci/api/builds_spec.rb | 2 +- spec/requests/openid_connect_spec.rb | 2 +- spec/services/issues/build_service_spec.rb | 2 +- spec/services/issues/resolve_discussions_spec.rb | 2 +- spec/workers/git_garbage_collect_worker_spec.rb | 2 +- spec/workers/repository_check/clear_worker_spec.rb | 2 +- 49 files changed, 60 insertions(+), 62 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 7438763984d..4e1d456d8d1 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -497,6 +497,11 @@ Style/TrailingCommaInLiteral: Enabled: true EnforcedStyleForMultiline: no_comma +# This cop checks for trailing comma in argument lists. +Style/TrailingCommaInArguments: + Enabled: true + EnforcedStyleForMultiline: no_comma + # Checks for %W when interpolation is not needed. Style/UnneededCapitalW: Enabled: true diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 38b22afdf82..7582f761bcb 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -369,13 +369,6 @@ Style/SymbolProc: Style/TernaryParentheses: Enabled: false -# Offense count: 53 -# Cop supports --auto-correct. -# Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline. -# SupportedStylesForMultiline: comma, consistent_comma, no_comma -Style/TrailingCommaInArguments: - Enabled: false - # Offense count: 18 # Cop supports --auto-correct. # Configuration parameters: AllowNamedUnderscoreVariables. diff --git a/app/controllers/profiles/preferences_controller.rb b/app/controllers/profiles/preferences_controller.rb index 0d891ef4004..5414142e2df 100644 --- a/app/controllers/profiles/preferences_controller.rb +++ b/app/controllers/profiles/preferences_controller.rb @@ -33,7 +33,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController :color_scheme_id, :layout, :dashboard, - :project_view, + :project_view ) end end diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index c376bc8a785..7c0459648ef 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -269,7 +269,7 @@ class Projects::IssuesController < Projects::ApplicationController def issue_params params.require(:issue).permit( :title, :assignee_id, :position, :description, :confidential, - :milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [], assignee_ids: [], + :milestone_id, :due_date, :state_event, :task_num, :lock_version, label_ids: [], assignee_ids: [] ) end diff --git a/app/models/diff_discussion.rb b/app/models/diff_discussion.rb index d627fbe327f..14ddd2fcc88 100644 --- a/app/models/diff_discussion.rb +++ b/app/models/diff_discussion.rb @@ -39,7 +39,7 @@ class DiffDiscussion < Discussion def reply_attributes super.merge( original_position: original_position.to_json, - position: position.to_json, + position: position.to_json ) end end diff --git a/app/models/key.rb b/app/models/key.rb index 9c74ca84753..b7956052c3f 100644 --- a/app/models/key.rb +++ b/app/models/key.rb @@ -74,7 +74,7 @@ class Key < ActiveRecord::Base GitlabShellWorker.perform_async( :remove_key, shell_id, - key, + key ) end diff --git a/app/models/namespace.rb b/app/models/namespace.rb index 397dc7a25ab..a7ede5e3b9e 100644 --- a/app/models/namespace.rb +++ b/app/models/namespace.rb @@ -56,7 +56,7 @@ class Namespace < ActiveRecord::Base 'COALESCE(SUM(ps.storage_size), 0) AS storage_size', 'COALESCE(SUM(ps.repository_size), 0) AS repository_size', 'COALESCE(SUM(ps.lfs_objects_size), 0) AS lfs_objects_size', - 'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size', + 'COALESCE(SUM(ps.build_artifacts_size), 0) AS build_artifacts_size' ) end diff --git a/app/models/project_services/flowdock_service.rb b/app/models/project_services/flowdock_service.rb index 10a13c3fbdc..2a05d757eb4 100644 --- a/app/models/project_services/flowdock_service.rb +++ b/app/models/project_services/flowdock_service.rb @@ -37,7 +37,7 @@ class FlowdockService < Service repo: project.repository.path_to_repo, repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}", commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s", - diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s", + diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s" ) end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 0c797dd5814..0f645c9f1da 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -833,7 +833,7 @@ class Repository actual_options = options.merge( parents: [our_commit, their_commit], - tree: merge_index.write_tree(rugged), + tree: merge_index.write_tree(rugged) ) commit_id = create_commit(actual_options) diff --git a/app/models/sent_notification.rb b/app/models/sent_notification.rb index bfaf0eb2fae..0ae5864615a 100644 --- a/app/models/sent_notification.rb +++ b/app/models/sent_notification.rb @@ -39,7 +39,7 @@ class SentNotification < ActiveRecord::Base noteable_type: noteable.class.name, noteable_id: noteable_id, - commit_id: commit_id, + commit_id: commit_id ) create(attrs) diff --git a/app/services/boards/issues/move_service.rb b/app/services/boards/issues/move_service.rb index e73b1a4361a..ecabb2a48e4 100644 --- a/app/services/boards/issues/move_service.rb +++ b/app/services/boards/issues/move_service.rb @@ -38,7 +38,7 @@ module Boards attrs.merge!( add_label_ids: add_label_ids, remove_label_ids: remove_label_ids, - state_event: issue_state, + state_event: issue_state ) end diff --git a/app/services/notification_service.rb b/app/services/notification_service.rb index c65c66d7150..646ccbdb2bf 100644 --- a/app/services/notification_service.rb +++ b/app/services/notification_service.rb @@ -298,7 +298,7 @@ class NotificationService recipients ||= NotificationRecipientService.new(pipeline.project).build_pipeline_recipients( pipeline, pipeline.user, - action: pipeline.status, + action: pipeline.status ).map(&:notification_email) if recipients.any? diff --git a/app/services/system_hooks_service.rb b/app/services/system_hooks_service.rb index 628d6d7b4f6..ed476fc9d0c 100644 --- a/app/services/system_hooks_service.rb +++ b/app/services/system_hooks_service.rb @@ -51,7 +51,7 @@ class SystemHooksService path: model.path, group_id: model.id, owner_name: owner.respond_to?(:name) ? owner.name : nil, - owner_email: owner.respond_to?(:email) ? owner.email : nil, + owner_email: owner.respond_to?(:email) ? owner.email : nil ) when GroupMember data.merge!(group_member_data(model)) diff --git a/app/workers/repository_check/clear_worker.rb b/app/workers/repository_check/clear_worker.rb index 1f1b38540ee..85bc9103538 100644 --- a/app/workers/repository_check/clear_worker.rb +++ b/app/workers/repository_check/clear_worker.rb @@ -8,7 +8,7 @@ module RepositoryCheck Project.select(:id).find_in_batches(batch_size: 100) do |batch| Project.where(id: batch.map(&:id)).update_all( last_repository_check_failed: nil, - last_repository_check_at: nil, + last_repository_check_at: nil ) end end diff --git a/app/workers/repository_check/single_repository_worker.rb b/app/workers/repository_check/single_repository_worker.rb index 3d8bfc6fc6c..164586cf0b7 100644 --- a/app/workers/repository_check/single_repository_worker.rb +++ b/app/workers/repository_check/single_repository_worker.rb @@ -7,7 +7,7 @@ module RepositoryCheck project = Project.find(project_id) project.update_columns( last_repository_check_failed: !check(project), - last_repository_check_at: Time.now, + last_repository_check_at: Time.now ) end diff --git a/config/initializers/ar_monkey_patch.rb b/config/initializers/ar_monkey_patch.rb index 6979f4641b0..9266ff0f615 100644 --- a/config/initializers/ar_monkey_patch.rb +++ b/config/initializers/ar_monkey_patch.rb @@ -33,7 +33,7 @@ module ActiveRecord affected_rows = relation.where( self.class.primary_key => id, - lock_col => previous_lock_value, + lock_col => previous_lock_value ).update_all( attributes_for_update(attribute_names).map do |name| [name, _read_attribute(name)] diff --git a/config/initializers/hamlit.rb b/config/initializers/hamlit.rb index 7b545d8c06c..51dbffeda05 100644 --- a/config/initializers/hamlit.rb +++ b/config/initializers/hamlit.rb @@ -3,7 +3,7 @@ module Hamlit def call(template) Engine.new( generator: Temple::Generators::RailsOutputBuffer, - attr_quote: '"', + attr_quote: '"' ).call(template.source) end end @@ -11,7 +11,7 @@ end ActionView::Template.register_template_handler( :haml, - Hamlit::TemplateHandler.new, + Hamlit::TemplateHandler.new ) Hamlit::Filters.remove_filter('coffee') diff --git a/config/initializers/static_files.rb b/config/initializers/static_files.rb index cc4f6a1d0fb..9ed96ddb0b4 100644 --- a/config/initializers/static_files.rb +++ b/config/initializers/static_files.rb @@ -30,14 +30,14 @@ if app.config.serve_static_files settings.merge!( host: Gitlab.config.gitlab.host, port: Gitlab.config.gitlab.port, - https: Gitlab.config.gitlab.https, + https: Gitlab.config.gitlab.https ) app.config.middleware.insert_before( Gitlab::Middleware::Static, Gitlab::Middleware::WebpackProxy, proxy_path: app.config.webpack.public_path, proxy_host: dev_server.host, - proxy_port: dev_server.port, + proxy_port: dev_server.port ) end diff --git a/features/steps/explore/projects.rb b/features/steps/explore/projects.rb index 7dc33ab5683..b2194275751 100644 --- a/features/steps/explore/projects.rb +++ b/features/steps/explore/projects.rb @@ -101,7 +101,7 @@ class Spinach::Features::ExploreProjects < Spinach::FeatureSteps create(:merge_request, title: "Bug fix for public project", source_project: public_project, - target_project: public_project, + target_project: public_project ) end diff --git a/lib/api/groups.rb b/lib/api/groups.rb index 09d105f6b4c..450b2f8d9a9 100644 --- a/lib/api/groups.rb +++ b/lib/api/groups.rb @@ -24,7 +24,7 @@ module API def present_groups(groups, options = {}) options = options.reverse_merge( with: Entities::Group, - current_user: current_user, + current_user: current_user ) groups = groups.with_statistics if options[:statistics] diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 86bf567fe69..4caa210b9f2 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -301,7 +301,7 @@ module API UploadedFile.new( file_path, params["#{field}.name"], - params["#{field}.type"] || 'application/octet-stream', + params["#{field}.type"] || 'application/octet-stream' ) end diff --git a/lib/api/projects.rb b/lib/api/projects.rb index 687efe7da65..ed5004e8d1a 100644 --- a/lib/api/projects.rb +++ b/lib/api/projects.rb @@ -69,7 +69,7 @@ module API options = options.reverse_merge( with: Entities::Project, current_user: current_user, - simple: params[:simple], + simple: params[:simple] ) projects = filter_projects(projects) diff --git a/lib/api/v3/groups.rb b/lib/api/v3/groups.rb index 63d464b926b..0a63cfd3df1 100644 --- a/lib/api/v3/groups.rb +++ b/lib/api/v3/groups.rb @@ -20,7 +20,7 @@ module API def present_groups(groups, options = {}) options = options.reverse_merge( with: Entities::Group, - current_user: current_user, + current_user: current_user ) groups = groups.with_statistics if options[:statistics] diff --git a/lib/api/v3/projects.rb b/lib/api/v3/projects.rb index 06cc704afc6..164612cb8dd 100644 --- a/lib/api/v3/projects.rb +++ b/lib/api/v3/projects.rb @@ -88,7 +88,7 @@ module API options = options.reverse_merge( with: ::API::V3::Entities::Project, current_user: current_user, - simple: params[:simple], + simple: params[:simple] ) projects = filter_projects(projects) diff --git a/lib/gitlab/git/blob.rb b/lib/gitlab/git/blob.rb index 12458f9f410..c1b31618e0d 100644 --- a/lib/gitlab/git/blob.rb +++ b/lib/gitlab/git/blob.rb @@ -90,7 +90,7 @@ module Gitlab name: blob_entry[:name], data: '', path: path, - commit_id: sha, + commit_id: sha ) end end diff --git a/lib/gitlab/git/tree.rb b/lib/gitlab/git/tree.rb index b722d8a9f56..d41256d9a84 100644 --- a/lib/gitlab/git/tree.rb +++ b/lib/gitlab/git/tree.rb @@ -35,7 +35,7 @@ module Gitlab type: entry[:type], mode: entry[:filemode].to_s(8), path: path ? File.join(path, entry[:name]) : entry[:name], - commit_id: sha, + commit_id: sha ) end end diff --git a/lib/gitlab/gitaly_client/commit.rb b/lib/gitlab/gitaly_client/commit.rb index 0b001a9903d..8e9323b05e1 100644 --- a/lib/gitlab/gitaly_client/commit.rb +++ b/lib/gitlab/gitaly_client/commit.rb @@ -34,7 +34,7 @@ module Gitlab left_commit_id: parent_id, right_commit_id: commit.id, ignore_whitespace_change: options.fetch(:ignore_whitespace_change, false), - paths: options.fetch(:paths, []), + paths: options.fetch(:paths, []) ) Gitlab::Git::DiffCollection.new(stub.commit_diff(request), options) diff --git a/lib/gitlab/gitaly_client/util.rb b/lib/gitlab/gitaly_client/util.rb index 4acd297f5cb..86d055d3533 100644 --- a/lib/gitlab/gitaly_client/util.rb +++ b/lib/gitlab/gitaly_client/util.rb @@ -6,7 +6,7 @@ module Gitlab Gitaly::Repository.new( path: File.join(Gitlab.config.repositories.storages[repository_storage]['path'], relative_path), storage_name: repository_storage, - relative_path: relative_path, + relative_path: relative_path ) end end diff --git a/lib/gitlab/ldap/config.rb b/lib/gitlab/ldap/config.rb index 46deea3cc9f..6fdf68641e2 100644 --- a/lib/gitlab/ldap/config.rb +++ b/lib/gitlab/ldap/config.rb @@ -39,7 +39,7 @@ module Gitlab def adapter_options opts = base_options.merge( - encryption: encryption, + encryption: encryption ) opts.merge!(auth_options) if has_auth? diff --git a/lib/gitlab/sentry.rb b/lib/gitlab/sentry.rb index 117fc508135..2442c2ded3b 100644 --- a/lib/gitlab/sentry.rb +++ b/lib/gitlab/sentry.rb @@ -11,7 +11,7 @@ module Gitlab Raven.user_context( id: current_user.id, email: current_user.email, - username: current_user.username, + username: current_user.username ) end end diff --git a/lib/gitlab/workhorse.rb b/lib/gitlab/workhorse.rb index f3b3dea5318..351e2b10595 100644 --- a/lib/gitlab/workhorse.rb +++ b/lib/gitlab/workhorse.rb @@ -165,7 +165,7 @@ module Gitlab encoded_message, secret, true, - { iss: 'gitlab-workhorse', verify_iss: true, algorithm: 'HS256' }, + { iss: 'gitlab-workhorse', verify_iss: true, algorithm: 'HS256' } ) end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 073b87a1cb4..765d2bdbf7a 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -33,7 +33,7 @@ describe GroupsController do before do create_list(:award_emoji, 3, awardable: issue_2) create_list(:award_emoji, 2, awardable: issue_1) - create_list(:award_emoji, 2, :downvote, awardable: issue_2,) + create_list(:award_emoji, 2, :downvote, awardable: issue_2) sign_in(user) end diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb index 855247de2ea..ab5c42365fe 100644 --- a/spec/features/admin/admin_uses_repository_checks_spec.rb +++ b/spec/features/admin/admin_uses_repository_checks_spec.rb @@ -23,7 +23,7 @@ feature 'Admin uses repository checks', feature: true do project = create(:empty_project) project.update_columns( last_repository_check_failed: true, - last_repository_check_at: Time.now, + last_repository_check_at: Time.now ) visit_admin_project_page(project) diff --git a/spec/features/copy_as_gfm_spec.rb b/spec/features/copy_as_gfm_spec.rb index f197fb44608..be615519a09 100644 --- a/spec/features/copy_as_gfm_spec.rb +++ b/spec/features/copy_as_gfm_spec.rb @@ -96,7 +96,7 @@ describe 'Copy as GFM', feature: true, js: true do # issue link "[Issue](#{namespace_project_issue_url(@project.namespace, @project, @feat.issue)})", # issue link with note anchor - "[Issue](#{namespace_project_issue_url(@project.namespace, @project, @feat.issue, anchor: 'note_123')})", + "[Issue](#{namespace_project_issue_url(@project.namespace, @project, @feat.issue, anchor: 'note_123')})" ) verify( diff --git a/spec/features/projects/pipelines/pipelines_spec.rb b/spec/features/projects/pipelines/pipelines_spec.rb index 8cc96c7b00f..5f82cf2f5e5 100644 --- a/spec/features/projects/pipelines/pipelines_spec.rb +++ b/spec/features/projects/pipelines/pipelines_spec.rb @@ -22,7 +22,7 @@ describe 'Pipelines', :feature, :js do project: project, ref: 'master', status: 'running', - sha: project.commit.id, + sha: project.commit.id ) end diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb index d1d2dcc4998..fe2c00bb2ca 100644 --- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb +++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb @@ -716,7 +716,7 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["logs/", "binaries/"], untracked: true, - key: 'key', + key: 'key' ) end @@ -734,7 +734,7 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["logs/", "binaries/"], untracked: true, - key: 'key', + key: 'key' ) end @@ -753,7 +753,7 @@ module Ci expect(config_processor.builds_for_stage_and_ref("test", "master").first[:options][:cache]).to eq( paths: ["test/"], untracked: false, - key: 'local', + key: 'local' ) end end diff --git a/spec/lib/gitlab/auth_spec.rb b/spec/lib/gitlab/auth_spec.rb index d4a43192d03..50bc3ef1b7c 100644 --- a/spec/lib/gitlab/auth_spec.rb +++ b/spec/lib/gitlab/auth_spec.rb @@ -175,7 +175,7 @@ describe Gitlab::Auth, lib: true do user = create( :user, username: 'normal_user', - password: 'my-secret', + password: 'my-secret' ) expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) @@ -186,7 +186,7 @@ describe Gitlab::Auth, lib: true do user = create( :user, username: 'oauth2', - password: 'my-secret', + password: 'my-secret' ) expect(gl_auth.find_for_git_client(user.username, user.password, project: nil, ip: 'ip')) diff --git a/spec/lib/gitlab/ci/config/entry/global_spec.rb b/spec/lib/gitlab/ci/config/entry/global_spec.rb index 684d01e9056..cf03acbfd3a 100644 --- a/spec/lib/gitlab/ci/config/entry/global_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/global_spec.rb @@ -167,7 +167,7 @@ describe Gitlab::Ci::Config::Entry::Global do cache: { key: 'k', untracked: true, paths: ['public/'] }, variables: {}, ignore: false, - after_script: ['make clean'] }, + after_script: ['make clean'] } ) end end diff --git a/spec/lib/gitlab/contributions_calendar_spec.rb b/spec/lib/gitlab/contributions_calendar_spec.rb index e18a219ef36..79632e2b6a3 100644 --- a/spec/lib/gitlab/contributions_calendar_spec.rb +++ b/spec/lib/gitlab/contributions_calendar_spec.rb @@ -47,7 +47,7 @@ describe Gitlab::ContributionsCalendar do action: Event::CREATED, target: @targets[project], author: contributor, - created_at: day, + created_at: day ) end diff --git a/spec/lib/gitlab/git/diff_spec.rb b/spec/lib/gitlab/git/diff_spec.rb index 7253a2edeff..4189aaef643 100644 --- a/spec/lib/gitlab/git/diff_spec.rb +++ b/spec/lib/gitlab/git/diff_spec.rb @@ -120,7 +120,7 @@ EOT new_mode: 0100644, from_id: '357406f3075a57708d0163752905cc1576fceacc', to_id: '8e5177d718c561d36efde08bad36b43687ee6bf0', - raw_chunks: raw_chunks, + raw_chunks: raw_chunks ) ) end diff --git a/spec/lib/gitlab/gitaly_client/commit_spec.rb b/spec/lib/gitlab/gitaly_client/commit_spec.rb index abe08ccdfa1..08c072caf8c 100644 --- a/spec/lib/gitlab/gitaly_client/commit_spec.rb +++ b/spec/lib/gitlab/gitaly_client/commit_spec.rb @@ -12,7 +12,7 @@ describe Gitlab::GitalyClient::Commit do request = Gitaly::CommitDiffRequest.new( repository: repository_message, left_commit_id: 'cfe32cf61b73a0d5e9f13e774abde7ff789b1660', - right_commit_id: commit.id, + right_commit_id: commit.id ) expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request) @@ -27,7 +27,7 @@ describe Gitlab::GitalyClient::Commit do request = Gitaly::CommitDiffRequest.new( repository: repository_message, left_commit_id: '4b825dc642cb6eb9a060e54bf8d69288fbee4904', - right_commit_id: initial_commit.id, + right_commit_id: initial_commit.id ) expect_any_instance_of(Gitaly::Diff::Stub).to receive(:commit_diff).with(request) diff --git a/spec/models/project_services/kubernetes_service_spec.rb b/spec/models/project_services/kubernetes_service_spec.rb index 80966b99292..c1c2f2a7219 100644 --- a/spec/models/project_services/kubernetes_service_spec.rb +++ b/spec/models/project_services/kubernetes_service_spec.rb @@ -168,7 +168,7 @@ describe KubernetesService, models: true, caching: true do { key: 'KUBE_TOKEN', value: 'token', public: false }, { key: 'KUBE_NAMESPACE', value: 'my-project', public: true }, { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true }, - { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }, + { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true } ) end end @@ -179,7 +179,7 @@ describe KubernetesService, models: true, caching: true do { key: 'KUBE_URL', value: 'https://kube.domain.com', public: true }, { key: 'KUBE_TOKEN', value: 'token', public: false }, { key: 'KUBE_CA_PEM', value: 'CA PEM DATA', public: true }, - { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true }, + { key: 'KUBE_CA_PEM_FILE', value: 'CA PEM DATA', public: true, file: true } ) end diff --git a/spec/models/project_statistics_spec.rb b/spec/models/project_statistics_spec.rb index ff29f6f66ba..c5ffbda9821 100644 --- a/spec/models/project_statistics_spec.rb +++ b/spec/models/project_statistics_spec.rb @@ -35,7 +35,7 @@ describe ProjectStatistics, models: true do commit_count: 8.exabytes - 1, repository_size: 2.exabytes, lfs_objects_size: 2.exabytes, - build_artifacts_size: 4.exabytes - 1, + build_artifacts_size: 4.exabytes - 1 ) statistics.reload @@ -149,7 +149,7 @@ describe ProjectStatistics, models: true do it "sums all storage counters" do statistics.update!( repository_size: 2, - lfs_objects_size: 3, + lfs_objects_size: 3 ) statistics.reload diff --git a/spec/requests/ci/api/builds_spec.rb b/spec/requests/ci/api/builds_spec.rb index 108f73bb965..286de277ae7 100644 --- a/spec/requests/ci/api/builds_spec.rb +++ b/spec/requests/ci/api/builds_spec.rb @@ -185,7 +185,7 @@ describe Ci::API::Builds do { "key" => "CI_PIPELINE_TRIGGERED", "value" => "true", "public" => true }, { "key" => "DB_NAME", "value" => "postgres", "public" => true }, { "key" => "SECRET_KEY", "value" => "secret_value", "public" => false }, - { "key" => "TRIGGER_KEY_1", "value" => "TRIGGER_VALUE_1", "public" => false }, + { "key" => "TRIGGER_KEY_1", "value" => "TRIGGER_VALUE_1", "public" => false } ) end end diff --git a/spec/requests/openid_connect_spec.rb b/spec/requests/openid_connect_spec.rb index 1a5d388382d..05176c3beaa 100644 --- a/spec/requests/openid_connect_spec.rb +++ b/spec/requests/openid_connect_spec.rb @@ -61,7 +61,7 @@ describe 'OpenID Connect requests' do email: private_email.email, public_email: public_email.email, website_url: 'https://example.com', - avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png"), + avatar: fixture_file_upload(Rails.root + "spec/fixtures/dk.png") ) end diff --git a/spec/services/issues/build_service_spec.rb b/spec/services/issues/build_service_spec.rb index 55d635235b0..bed25fe7ccf 100644 --- a/spec/services/issues/build_service_spec.rb +++ b/spec/services/issues/build_service_spec.rb @@ -136,7 +136,7 @@ describe Issues::BuildService, services: true do user, title: 'Issue #1', description: 'Issue description', - milestone_id: milestone.id, + milestone_id: milestone.id ).execute expect(issue.title).to eq('Issue #1') diff --git a/spec/services/issues/resolve_discussions_spec.rb b/spec/services/issues/resolve_discussions_spec.rb index c3b4c2176ee..86f218dec12 100644 --- a/spec/services/issues/resolve_discussions_spec.rb +++ b/spec/services/issues/resolve_discussions_spec.rb @@ -77,7 +77,7 @@ describe Issues::ResolveDiscussions, services: true do _second_discussion = Discussion.new([create(:diff_note_on_merge_request, :resolved, noteable: merge_request, project: merge_request.target_project, - line_number: 15, + line_number: 15 )]) service = DummyService.new( project, diff --git a/spec/workers/git_garbage_collect_worker_spec.rb b/spec/workers/git_garbage_collect_worker_spec.rb index 7a590f64e3c..8c5303b61cc 100644 --- a/spec/workers/git_garbage_collect_worker_spec.rb +++ b/spec/workers/git_garbage_collect_worker_spec.rb @@ -105,7 +105,7 @@ describe GitGarbageCollectWorker do author: Gitlab::Git.committer_hash(email: 'foo@bar', name: 'baz'), committer: Gitlab::Git.committer_hash(email: 'foo@bar', name: 'baz'), tree: old_commit.tree, - parents: [old_commit], + parents: [old_commit] ) GitOperationService.new(nil, project.repository).send( :update_ref, diff --git a/spec/workers/repository_check/clear_worker_spec.rb b/spec/workers/repository_check/clear_worker_spec.rb index a3b70c74787..3b1a64c5057 100644 --- a/spec/workers/repository_check/clear_worker_spec.rb +++ b/spec/workers/repository_check/clear_worker_spec.rb @@ -5,7 +5,7 @@ describe RepositoryCheck::ClearWorker do project = create(:empty_project) project.update_columns( last_repository_check_failed: true, - last_repository_check_at: Time.now, + last_repository_check_at: Time.now ) described_class.new.perform -- cgit v1.2.1 From 9d08dddfdb0ef66de9ec3b7c7cbfd96e2f949678 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Wed, 10 May 2017 13:30:54 -0300 Subject: Ensure all Serializers receive `current_user` instead `user` --- app/controllers/projects/deployments_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb index b33c0b00ad9..dcdb2a8fa3e 100644 --- a/app/controllers/projects/deployments_controller.rb +++ b/app/controllers/projects/deployments_controller.rb @@ -6,7 +6,7 @@ class Projects::DeploymentsController < Projects::ApplicationController deployments = environment.deployments.reorder(created_at: :desc) deployments = deployments.where('created_at > ?', params[:after].to_time) if params[:after]&.to_time - render json: { deployments: DeploymentSerializer.new(user: @current_user, project: project) + render json: { deployments: DeploymentSerializer.new(current_user: @current_user, project: project) .represent_concise(deployments) } end -- cgit v1.2.1 From f4b6865aef48b6c328fd297b499b53f5d37260d9 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 10 May 2017 13:36:15 -0400 Subject: Fix aria labels on custom notifications modal --- app/views/shared/notifications/_custom_notifications.html.haml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/shared/notifications/_custom_notifications.html.haml b/app/views/shared/notifications/_custom_notifications.html.haml index 708adbc38f1..183ed34fba1 100644 --- a/app/views/shared/notifications/_custom_notifications.html.haml +++ b/app/views/shared/notifications/_custom_notifications.html.haml @@ -1,9 +1,9 @@ -.modal.fade{ tabindex: "-1", role: "dialog", id: notifications_menu_identifier("modal", notification_setting), aria: { labelledby: "custom-notifications-title" } } +.modal.fade{ tabindex: "-1", role: "dialog", id: notifications_menu_identifier("modal", notification_setting), "aria-labelledby": "custom-notifications-title" } .modal-dialog .modal-content .modal-header - %button.close{ type: "button", data: { dismiss: "modal" }, aria: { label: "close" } } - %span{ aria: { hidden: "true" } } × + %button.close{ type: "button", "aria-label": "close", data: { dismiss: "modal" } } + %span{ "aria-hidden": "true" } } × %h4#custom-notifications-title.modal-title Custom notification events -- cgit v1.2.1 From 368bf99eb758a738d225134e3baa6763869e7541 Mon Sep 17 00:00:00 2001 From: Oswaldo Ferreira Date: Wed, 10 May 2017 15:21:31 -0300 Subject: Remove unnecessary user hash being passed to DeploymentSerializer --- app/controllers/projects/deployments_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/projects/deployments_controller.rb b/app/controllers/projects/deployments_controller.rb index dcdb2a8fa3e..f06a4d943f3 100644 --- a/app/controllers/projects/deployments_controller.rb +++ b/app/controllers/projects/deployments_controller.rb @@ -6,7 +6,7 @@ class Projects::DeploymentsController < Projects::ApplicationController deployments = environment.deployments.reorder(created_at: :desc) deployments = deployments.where('created_at > ?', params[:after].to_time) if params[:after]&.to_time - render json: { deployments: DeploymentSerializer.new(current_user: @current_user, project: project) + render json: { deployments: DeploymentSerializer.new(project: project) .represent_concise(deployments) } end -- cgit v1.2.1 From d5eb66663e757706e734ebff7f61918fed898075 Mon Sep 17 00:00:00 2001 From: Marcia Ramos Date: Wed, 10 May 2017 15:48:07 -0300 Subject: update API doc with +API (h1 heading) --- doc/api/access_requests.md | 2 +- doc/api/enviroments.md | 2 +- doc/api/groups.md | 2 +- doc/api/issues.md | 2 +- doc/api/keys.md | 2 +- doc/api/labels.md | 2 +- doc/api/members.md | 2 +- doc/api/merge_requests.md | 2 +- doc/api/notification_settings.md | 2 +- doc/api/projects.md | 2 +- doc/api/settings.md | 2 +- doc/api/snippets.md | 2 +- doc/api/todos.md | 2 +- doc/api/users.md | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/doc/api/access_requests.md b/doc/api/access_requests.md index 21de7d18632..603fa4a8194 100644 --- a/doc/api/access_requests.md +++ b/doc/api/access_requests.md @@ -1,4 +1,4 @@ -# Group and project access requests +# Group and project access requests API >**Note:** This feature was introduced in GitLab 8.11 diff --git a/doc/api/enviroments.md b/doc/api/enviroments.md index 49930f01945..5ca766bf87d 100644 --- a/doc/api/enviroments.md +++ b/doc/api/enviroments.md @@ -1,4 +1,4 @@ -# Environments +# Environments API ## List environments diff --git a/doc/api/groups.md b/doc/api/groups.md index bc61bfec9b9..2b3d8e125c8 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1,4 +1,4 @@ -# Groups +# Groups API ## List groups diff --git a/doc/api/issues.md b/doc/api/issues.md index 1d43b1298b9..75794cc8d04 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -1,4 +1,4 @@ -# Issues +# Issues API Every API call to issues must be authenticated. diff --git a/doc/api/keys.md b/doc/api/keys.md index 3ace1040f38..376ac27df3a 100644 --- a/doc/api/keys.md +++ b/doc/api/keys.md @@ -1,4 +1,4 @@ -# Keys +# Keys API ## Get SSH key with user by ID of an SSH key diff --git a/doc/api/labels.md b/doc/api/labels.md index 778348ea371..ec93cf50e7a 100644 --- a/doc/api/labels.md +++ b/doc/api/labels.md @@ -1,4 +1,4 @@ -# Labels +# Labels API ## List labels diff --git a/doc/api/members.md b/doc/api/members.md index 3c661284f11..3234f833eae 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -1,4 +1,4 @@ -# Group and project members +# Group and project members API **Valid access levels** diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index dde855b2bd4..cb22b67f556 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -1,4 +1,4 @@ -# Merge requests +# Merge requests API ## List merge requests diff --git a/doc/api/notification_settings.md b/doc/api/notification_settings.md index 43047917f77..3a2c398e355 100644 --- a/doc/api/notification_settings.md +++ b/doc/api/notification_settings.md @@ -1,4 +1,4 @@ -# Notification settings +# Notification settings API >**Note:** This feature was [introduced][ce-5632] in GitLab 8.12. diff --git a/doc/api/projects.md b/doc/api/projects.md index 188fbe7447d..673cf02705d 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -1,4 +1,4 @@ -# Projects +# Projects API ### Project visibility level diff --git a/doc/api/settings.md b/doc/api/settings.md index d99695ca986..eefbdda42ce 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -1,4 +1,4 @@ -# Application settings +# Application settings API These API calls allow you to read and modify GitLab instance application settings as appear in `/admin/application_settings`. You have to be an diff --git a/doc/api/snippets.md b/doc/api/snippets.md index e09d930698e..fb8cf97896c 100644 --- a/doc/api/snippets.md +++ b/doc/api/snippets.md @@ -1,4 +1,4 @@ -# Snippets +# Snippets API > [Introduced][ce-6373] in GitLab 8.15. diff --git a/doc/api/todos.md b/doc/api/todos.md index 77667a57195..dd4c737b729 100644 --- a/doc/api/todos.md +++ b/doc/api/todos.md @@ -1,4 +1,4 @@ -# Todos +# Todos API > [Introduced][ce-3188] in GitLab 8.10. diff --git a/doc/api/users.md b/doc/api/users.md index 86027bcc05c..331f9a9b80b 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -1,4 +1,4 @@ -# Users +# Users API ## List users -- cgit v1.2.1 From 76ac0e46d80d6b48fecc632e49f6036b70fb4d43 Mon Sep 17 00:00:00 2001 From: Clement Ho Date: Wed, 10 May 2017 14:32:40 -0500 Subject: Remove sidebar bundle spec --- spec/javascripts/sidebar/sidebar_bundle_spec.js | 42 ------------------------- 1 file changed, 42 deletions(-) delete mode 100644 spec/javascripts/sidebar/sidebar_bundle_spec.js diff --git a/spec/javascripts/sidebar/sidebar_bundle_spec.js b/spec/javascripts/sidebar/sidebar_bundle_spec.js deleted file mode 100644 index 7760b34e071..00000000000 --- a/spec/javascripts/sidebar/sidebar_bundle_spec.js +++ /dev/null @@ -1,42 +0,0 @@ -import Vue from 'vue'; -import SidebarBundleDomContentLoaded from '~/sidebar/sidebar_bundle'; -import SidebarTimeTracking from '~/sidebar/components/time_tracking/sidebar_time_tracking'; -import SidebarMediator from '~/sidebar/sidebar_mediator'; -import SidebarService from '~/sidebar/services/sidebar_service'; -import SidebarStore from '~/sidebar/stores/sidebar_store'; -import Mock from './mock_data'; - -describe('sidebar bundle', () => { - gl.sidebarOptions = Mock.mediator; - - beforeEach(() => { - spyOn(SidebarTimeTracking.methods, 'listenForSlashCommands').and.callFake(() => { }); - preloadFixtures('issues/open-issue.html.raw'); - Vue.http.interceptors.push(Mock.sidebarMockInterceptor); - loadFixtures('issues/open-issue.html.raw'); - spyOn(Vue.prototype, '$mount'); - SidebarBundleDomContentLoaded(); - this.mediator = new SidebarMediator(); - }); - - afterEach(() => { - SidebarService.singleton = null; - SidebarStore.singleton = null; - SidebarMediator.singleton = null; - }); - - it('the mediator should be already defined with some data', () => { - SidebarBundleDomContentLoaded(); - - expect(this.mediator.store).toBeDefined(); - expect(this.mediator.service).toBeDefined(); - expect(this.mediator.store.currentUser).toEqual(Mock.mediator.currentUser); - expect(this.mediator.store.rootPath).toEqual(Mock.mediator.rootPath); - expect(this.mediator.store.endPoint).toEqual(Mock.mediator.endPoint); - expect(this.mediator.store.editable).toEqual(Mock.mediator.editable); - }); - - it('the sidebar time tracking and assignees components to have been mounted', () => { - expect(Vue.prototype.$mount).toHaveBeenCalledTimes(2); - }); -}); -- cgit v1.2.1 From c8bbe191b64986824aa7af9a182d17e776bd5cf1 Mon Sep 17 00:00:00 2001 From: Valery Sizov Date: Thu, 11 May 2017 00:00:02 +0300 Subject: Issue API change: assignee_id parameter and assignee object in a response --- changelogs/unreleased/issue_api_change.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/issue_api_change.yml diff --git a/changelogs/unreleased/issue_api_change.yml b/changelogs/unreleased/issue_api_change.yml new file mode 100644 index 00000000000..3ad2d57317c --- /dev/null +++ b/changelogs/unreleased/issue_api_change.yml @@ -0,0 +1,5 @@ +--- +title: 'Issue API change: assignee_id parameter and assignee object in a response + have been deprecated' +merge_request: +author: -- cgit v1.2.1 From 3af84b4216c26b25f4fbe40996bbd41409552519 Mon Sep 17 00:00:00 2001 From: Mike Greiling Date: Wed, 10 May 2017 16:11:23 -0500 Subject: ensure filtered_search utilizes common_vue bundle --- app/views/projects/boards/_show.html.haml | 6 +++--- app/views/projects/issues/index.html.haml | 3 ++- app/views/projects/merge_requests/index.html.haml | 3 ++- config/webpack.config.js | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/views/projects/boards/_show.html.haml b/app/views/projects/boards/_show.html.haml index 7ca0ec8ed2b..efec69662f3 100644 --- a/app/views/projects/boards/_show.html.haml +++ b/app/views/projects/boards/_show.html.haml @@ -3,9 +3,9 @@ - page_title "Boards" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('common_vue') - = page_specific_javascript_bundle_tag('filtered_search') - = page_specific_javascript_bundle_tag('boards') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'filtered_search' + = webpack_bundle_tag 'boards' %script#js-board-template{ type: "text/x-template" }= render "projects/boards/components/board" %script#js-board-modal-filter{ type: "text/x-template" }= render "shared/issuable/search_bar", type: :boards_modal diff --git a/app/views/projects/issues/index.html.haml b/app/views/projects/issues/index.html.haml index 4ac0bc1d028..60900e9d660 100644 --- a/app/views/projects/issues/index.html.haml +++ b/app/views/projects/issues/index.html.haml @@ -7,7 +7,8 @@ = render "projects/issues/head" - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('filtered_search') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'filtered_search' = content_for :meta_tags do = auto_discovery_link_tag(:atom, params.merge(rss_url_options), title: "#{@project.name} issues") diff --git a/app/views/projects/merge_requests/index.html.haml b/app/views/projects/merge_requests/index.html.haml index 6bf0035e051..502220232a1 100644 --- a/app/views/projects/merge_requests/index.html.haml +++ b/app/views/projects/merge_requests/index.html.haml @@ -8,7 +8,8 @@ = render 'projects/last_push' - content_for :page_specific_javascripts do - = page_specific_javascript_bundle_tag('filtered_search') + = webpack_bundle_tag 'common_vue' + = webpack_bundle_tag 'filtered_search' - if @project.merge_requests.exists? %div{ class: container_class } diff --git a/config/webpack.config.js b/config/webpack.config.js index 7e413c8493e..cb0ccdab74a 100644 --- a/config/webpack.config.js +++ b/config/webpack.config.js @@ -141,6 +141,7 @@ var config = { 'diff_notes', 'environments', 'environments_folder', + 'filtered_search', 'sidebar', 'issue_show', 'merge_conflicts', -- cgit v1.2.1 From 2434d135d6d7953726d1a521fd9faf6ee4590b8a Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Sun, 7 May 2017 22:20:37 -0400 Subject: Keep input data after creating existing tag --- app/controllers/projects/tags_controller.rb | 2 ++ app/views/projects/_zen.html.haml | 3 ++- app/views/projects/tags/new.html.haml | 4 ++-- ...loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml | 4 ++++ 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml diff --git a/app/controllers/projects/tags_controller.rb b/app/controllers/projects/tags_controller.rb index 750c3ec486a..afbea3e2b40 100644 --- a/app/controllers/projects/tags_controller.rb +++ b/app/controllers/projects/tags_controller.rb @@ -38,6 +38,8 @@ class Projects::TagsController < Projects::ApplicationController redirect_to namespace_project_tag_path(@project.namespace, @project, @tag.name) else @error = result[:message] + @message = params[:message] + @release_description = params[:release_description] render action: 'new' end end diff --git a/app/views/projects/_zen.html.haml b/app/views/projects/_zen.html.haml index 0c8241053e7..3b3d08ddd3c 100644 --- a/app/views/projects/_zen.html.haml +++ b/app/views/projects/_zen.html.haml @@ -1,10 +1,11 @@ - @gfm_form = true +- current_text ||= nil - supports_slash_commands = local_assigns.fetch(:supports_slash_commands, false) .zen-backdrop - classes << ' js-gfm-input js-autosize markdown-area' - if defined?(f) && f = f.text_area attr, class: classes, placeholder: placeholder, data: { supports_slash_commands: supports_slash_commands } - else - = text_area_tag attr, nil, class: classes, placeholder: placeholder + = text_area_tag attr, current_text, class: classes, placeholder: placeholder %a.zen-control.zen-control-leave.js-zen-leave{ href: "#" } = icon('compress') diff --git a/app/views/projects/tags/new.html.haml b/app/views/projects/tags/new.html.haml index 7c607d2956b..cbf841762b7 100644 --- a/app/views/projects/tags/new.html.haml +++ b/app/views/projects/tags/new.html.haml @@ -22,14 +22,14 @@ .form-group = label_tag :message, nil, class: 'control-label' .col-sm-10 - = text_area_tag :message, nil, required: false, tabindex: 3, class: 'form-control', rows: 5 + = text_area_tag :message, @message, required: false, tabindex: 3, class: 'form-control', rows: 5 .help-block Optionally, add a message to the tag. %hr .form-group = label_tag :release_description, 'Release notes', class: 'control-label' .col-sm-10 = render layout: 'projects/md_preview', locals: { url: preview_markdown_path(@project), referenced_users: true } do - = render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here..." + = render 'projects/zen', attr: :release_description, classes: 'note-textarea', placeholder: "Write your release notes or drag files here...", current_text: @release_description = render 'shared/notes/hints' .help-block Optionally, add release notes to the tag. They will be stored in the GitLab database and displayed on the tags page. .form-actions diff --git a/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml b/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml new file mode 100644 index 00000000000..aae760b0ef5 --- /dev/null +++ b/changelogs/unreleased/31625-tag-editor-loses-all-inputs-when-you-try-to-add-a-tag-that-already-exists.yml @@ -0,0 +1,4 @@ +--- +title: Keep input data after creating a tag that already exists +merge_request: 11155 +author: -- cgit v1.2.1 From b304d41232ce591bcea9a2b86df9b924950126ef Mon Sep 17 00:00:00 2001 From: Winnie Hellmann Date: Wed, 10 May 2017 22:01:00 +0000 Subject: Track pending requests in AjaxCache --- app/assets/javascripts/lib/utils/ajax_cache.js | 70 +++++++++++++++++--------- spec/javascripts/lib/utils/ajax_cache_spec.js | 57 +++++++++++++++------ 2 files changed, 89 insertions(+), 38 deletions(-) diff --git a/app/assets/javascripts/lib/utils/ajax_cache.js b/app/assets/javascripts/lib/utils/ajax_cache.js index d99eefb5089..cf030d613df 100644 --- a/app/assets/javascripts/lib/utils/ajax_cache.js +++ b/app/assets/javascripts/lib/utils/ajax_cache.js @@ -1,32 +1,54 @@ -const AjaxCache = { - internalStorage: { }, +class AjaxCache { + constructor() { + this.internalStorage = { }; + this.pendingRequests = { }; + } + get(endpoint) { return this.internalStorage[endpoint]; - }, + } + hasData(endpoint) { return Object.prototype.hasOwnProperty.call(this.internalStorage, endpoint); - }, - purge(endpoint) { + } + + remove(endpoint) { delete this.internalStorage[endpoint]; - }, + } + retrieve(endpoint) { - if (AjaxCache.hasData(endpoint)) { - return Promise.resolve(AjaxCache.get(endpoint)); + if (this.hasData(endpoint)) { + return Promise.resolve(this.get(endpoint)); } - return new Promise((resolve, reject) => { - $.ajax(endpoint) // eslint-disable-line promise/catch-or-return - .then(data => resolve(data), - (jqXHR, textStatus, errorThrown) => { - const error = new Error(`${endpoint}: ${errorThrown}`); - error.textStatus = textStatus; - reject(error); - }, - ); - }) - .then((data) => { this.internalStorage[endpoint] = data; }) - .then(() => AjaxCache.get(endpoint)); - }, -}; - -export default AjaxCache; + let pendingRequest = this.pendingRequests[endpoint]; + + if (!pendingRequest) { + pendingRequest = new Promise((resolve, reject) => { + // jQuery 2 is not Promises/A+ compatible (missing catch) + $.ajax(endpoint) // eslint-disable-line promise/catch-or-return + .then(data => resolve(data), + (jqXHR, textStatus, errorThrown) => { + const error = new Error(`${endpoint}: ${errorThrown}`); + error.textStatus = textStatus; + reject(error); + }, + ); + }) + .then((data) => { + this.internalStorage[endpoint] = data; + delete this.pendingRequests[endpoint]; + }) + .catch((error) => { + delete this.pendingRequests[endpoint]; + throw error; + }); + + this.pendingRequests[endpoint] = pendingRequest; + } + + return pendingRequest.then(() => this.get(endpoint)); + } +} + +export default new AjaxCache(); diff --git a/spec/javascripts/lib/utils/ajax_cache_spec.js b/spec/javascripts/lib/utils/ajax_cache_spec.js index 7b466a11b92..e1747a82329 100644 --- a/spec/javascripts/lib/utils/ajax_cache_spec.js +++ b/spec/javascripts/lib/utils/ajax_cache_spec.js @@ -5,19 +5,13 @@ describe('AjaxCache', () => { const dummyResponse = { important: 'dummy data', }; - let ajaxSpy = (url) => { - expect(url).toBe(dummyEndpoint); - const deferred = $.Deferred(); - deferred.resolve(dummyResponse); - return deferred.promise(); - }; beforeEach(() => { AjaxCache.internalStorage = { }; - spyOn(jQuery, 'ajax').and.callFake(url => ajaxSpy(url)); + AjaxCache.pendingRequests = { }; }); - describe('#get', () => { + describe('get', () => { it('returns undefined if cache is empty', () => { const data = AjaxCache.get(dummyEndpoint); @@ -41,7 +35,7 @@ describe('AjaxCache', () => { }); }); - describe('#hasData', () => { + describe('hasData', () => { it('returns false if cache is empty', () => { expect(AjaxCache.hasData(dummyEndpoint)).toBe(false); }); @@ -59,9 +53,9 @@ describe('AjaxCache', () => { }); }); - describe('#purge', () => { + describe('remove', () => { it('does nothing if cache is empty', () => { - AjaxCache.purge(dummyEndpoint); + AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage).toEqual({ }); }); @@ -69,7 +63,7 @@ describe('AjaxCache', () => { it('does nothing if cache contains no matching data', () => { AjaxCache.internalStorage['not matching'] = dummyResponse; - AjaxCache.purge(dummyEndpoint); + AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage['not matching']).toBe(dummyResponse); }); @@ -77,14 +71,27 @@ describe('AjaxCache', () => { it('removes matching data', () => { AjaxCache.internalStorage[dummyEndpoint] = dummyResponse; - AjaxCache.purge(dummyEndpoint); + AjaxCache.remove(dummyEndpoint); expect(AjaxCache.internalStorage).toEqual({ }); }); }); - describe('#retrieve', () => { + describe('retrieve', () => { + let ajaxSpy; + + beforeEach(() => { + spyOn(jQuery, 'ajax').and.callFake(url => ajaxSpy(url)); + }); + it('stores and returns data from Ajax call if cache is empty', (done) => { + ajaxSpy = (url) => { + expect(url).toBe(dummyEndpoint); + const deferred = $.Deferred(); + deferred.resolve(dummyResponse); + return deferred.promise(); + }; + AjaxCache.retrieve(dummyEndpoint) .then((data) => { expect(data).toBe(dummyResponse); @@ -94,6 +101,28 @@ describe('AjaxCache', () => { .catch(fail); }); + it('makes no Ajax call if request is pending', () => { + const responseDeferred = $.Deferred(); + + ajaxSpy = (url) => { + expect(url).toBe(dummyEndpoint); + // neither reject nor resolve to keep request pending + return responseDeferred.promise(); + }; + + const unexpectedResponse = data => fail(`Did not expect response: ${data}`); + + AjaxCache.retrieve(dummyEndpoint) + .then(unexpectedResponse) + .catch(fail); + + AjaxCache.retrieve(dummyEndpoint) + .then(unexpectedResponse) + .catch(fail); + + expect($.ajax.calls.count()).toBe(1); + }); + it('returns undefined if Ajax call fails and cache is empty', (done) => { const dummyStatusText = 'exploded'; const dummyErrorMessage = 'server exploded'; -- cgit v1.2.1 From 08706f683725dcfbda1708ddf079347d989fbef1 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Mon, 8 May 2017 18:50:23 -0500 Subject: Implement auxiliary blob viewers --- app/assets/javascripts/blob/viewer/index.js | 99 ++++++++++++++-------- app/controllers/concerns/renders_blob.rb | 5 +- app/helpers/projects_helper.rb | 7 +- app/models/blob.rb | 34 +++++--- app/models/blob_viewer/auxiliary.rb | 12 +++ app/models/blob_viewer/base.rb | 30 +++++-- app/models/blob_viewer/gitlab_ci_yml.rb | 23 +++++ app/models/blob_viewer/license.rb | 23 +++++ app/models/blob_viewer/route_map.rb | 30 +++++++ app/models/blob_viewer/server_side.rb | 6 ++ app/models/repository.rb | 11 ++- app/views/projects/blob/_blob.html.haml | 5 ++ app/views/projects/blob/_viewer.html.haml | 3 +- .../projects/blob/viewers/_gitlab_ci_yml.html.haml | 9 ++ .../blob/viewers/_gitlab_ci_yml_loading.html.haml | 4 + app/views/projects/blob/viewers/_license.html.haml | 8 ++ app/views/projects/blob/viewers/_loading.html.haml | 2 + .../blob/viewers/_loading_auxiliary.html.haml | 2 + .../projects/blob/viewers/_route_map.html.haml | 9 ++ .../blob/viewers/_route_map_loading.html.haml | 4 + doc/ci/environments.md | 3 +- lib/gitlab/file_detector.rb | 3 +- spec/features/projects/blobs/blob_show_spec.rb | 98 ++++++++++++++++----- spec/models/blob_spec.rb | 46 ++++++++++ spec/models/blob_viewer/base_spec.rb | 72 ++++++++-------- spec/models/blob_viewer/gitlab_ci_yml_spec.rb | 32 +++++++ spec/models/blob_viewer/license_spec.rb | 34 ++++++++ spec/models/blob_viewer/route_map_spec.rb | 38 +++++++++ spec/models/blob_viewer/server_side_spec.rb | 25 ++++++ spec/models/repository_spec.rb | 51 +++++++++-- spec/views/projects/blob/_viewer.html.haml_spec.rb | 4 +- 31 files changed, 598 insertions(+), 134 deletions(-) create mode 100644 app/models/blob_viewer/auxiliary.rb create mode 100644 app/models/blob_viewer/gitlab_ci_yml.rb create mode 100644 app/models/blob_viewer/license.rb create mode 100644 app/models/blob_viewer/route_map.rb create mode 100644 app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml create mode 100644 app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml create mode 100644 app/views/projects/blob/viewers/_license.html.haml create mode 100644 app/views/projects/blob/viewers/_loading.html.haml create mode 100644 app/views/projects/blob/viewers/_loading_auxiliary.html.haml create mode 100644 app/views/projects/blob/viewers/_route_map.html.haml create mode 100644 app/views/projects/blob/viewers/_route_map_loading.html.haml create mode 100644 spec/models/blob_viewer/gitlab_ci_yml_spec.rb create mode 100644 spec/models/blob_viewer/license_spec.rb create mode 100644 spec/models/blob_viewer/route_map_spec.rb create mode 100644 spec/models/blob_viewer/server_side_spec.rb diff --git a/app/assets/javascripts/blob/viewer/index.js b/app/assets/javascripts/blob/viewer/index.js index 69ff2f95799..849da633c89 100644 --- a/app/assets/javascripts/blob/viewer/index.js +++ b/app/assets/javascripts/blob/viewer/index.js @@ -1,20 +1,38 @@ /* global Flash */ export default class BlobViewer { constructor() { + BlobViewer.initAuxiliaryViewer(); + + this.initMainViewers(); + } + + static initAuxiliaryViewer() { + const auxiliaryViewer = document.querySelector('.blob-viewer[data-type="auxiliary"]'); + if (!auxiliaryViewer) return; + + BlobViewer.loadViewer(auxiliaryViewer); + } + + initMainViewers() { + this.$fileHolder = $('.file-holder'); + if (!this.$fileHolder.length) return; + this.switcher = document.querySelector('.js-blob-viewer-switcher'); this.switcherBtns = document.querySelectorAll('.js-blob-viewer-switch-btn'); this.copySourceBtn = document.querySelector('.js-copy-blob-source-btn'); - this.simpleViewer = document.querySelector('.blob-viewer[data-type="simple"]'); - this.richViewer = document.querySelector('.blob-viewer[data-type="rich"]'); - this.$fileHolder = $('.file-holder'); - const initialViewer = document.querySelector('.blob-viewer:not(.hidden)'); - if (!initialViewer) return; - - let initialViewerName = initialViewer.getAttribute('data-type'); + this.simpleViewer = this.$fileHolder[0].querySelector('.blob-viewer[data-type="simple"]'); + this.richViewer = this.$fileHolder[0].querySelector('.blob-viewer[data-type="rich"]'); this.initBindings(); + this.switchToInitialViewer(); + } + + switchToInitialViewer() { + const initialViewer = this.$fileHolder[0].querySelector('.blob-viewer:not(.hidden)'); + let initialViewerName = initialViewer.getAttribute('data-type'); + if (this.switcher && location.hash.indexOf('#L') === 0) { initialViewerName = 'simple'; } @@ -64,40 +82,13 @@ export default class BlobViewer { $(this.copySourceBtn).tooltip('fixTitle'); } - loadViewer(viewerParam) { - const viewer = viewerParam; - const url = viewer.getAttribute('data-url'); - - if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) { - return; - } - - viewer.setAttribute('data-loading', 'true'); - - $.ajax({ - url, - dataType: 'JSON', - }) - .fail(() => new Flash('Error loading source view')) - .done((data) => { - viewer.innerHTML = data.html; - $(viewer).syntaxHighlight(); - - viewer.setAttribute('data-loaded', 'true'); - - this.$fileHolder.trigger('highlight:line'); - - this.toggleCopyButtonState(); - }); - } - switchToViewer(name) { - const newViewer = document.querySelector(`.blob-viewer[data-type='${name}']`); + const newViewer = this.$fileHolder[0].querySelector(`.blob-viewer[data-type='${name}']`); if (this.activeViewer === newViewer) return; const oldButton = document.querySelector('.js-blob-viewer-switch-btn.active'); const newButton = document.querySelector(`.js-blob-viewer-switch-btn[data-viewer='${name}']`); - const oldViewer = document.querySelector(`.blob-viewer:not([data-type='${name}'])`); + const oldViewer = this.$fileHolder[0].querySelector(`.blob-viewer:not([data-type='${name}'])`); if (oldButton) { oldButton.classList.remove('active'); @@ -118,6 +109,40 @@ export default class BlobViewer { this.toggleCopyButtonState(); - this.loadViewer(newViewer); + BlobViewer.loadViewer(newViewer) + .then((viewer) => { + $(viewer).syntaxHighlight(); + + this.$fileHolder.trigger('highlight:line'); + + this.toggleCopyButtonState(); + }) + .catch(() => new Flash('Error loading viewer')); + } + + static loadViewer(viewerParam) { + const viewer = viewerParam; + const url = viewer.getAttribute('data-url'); + + return new Promise((resolve, reject) => { + if (!url || viewer.getAttribute('data-loaded') || viewer.getAttribute('data-loading')) { + resolve(viewer); + return; + } + + viewer.setAttribute('data-loading', 'true'); + + $.ajax({ + url, + dataType: 'JSON', + }) + .fail(reject) + .done((data) => { + viewer.innerHTML = data.html; + viewer.setAttribute('data-loaded', 'true'); + + resolve(viewer); + }); + }); } } diff --git a/app/controllers/concerns/renders_blob.rb b/app/controllers/concerns/renders_blob.rb index 9faf68e6d97..4a6630dfd90 100644 --- a/app/controllers/concerns/renders_blob.rb +++ b/app/controllers/concerns/renders_blob.rb @@ -3,8 +3,11 @@ module RendersBlob def render_blob_json(blob) viewer = - if params[:viewer] == 'rich' + case params[:viewer] + when 'rich' blob.rich_viewer + when 'auxiliary' + blob.auxiliary_viewer else blob.simple_viewer end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 8c26348a975..78b54dc20e5 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -110,11 +110,8 @@ module ProjectsHelper end def license_short_name(project) - return 'LICENSE' if project.repository.license_key.nil? - - license = Licensee::License.new(project.repository.license_key) - - license.nickname || license.name + license = project.repository.license + license&.nickname || license&.name || 'LICENSE' end def last_push_event diff --git a/app/models/blob.rb b/app/models/blob.rb index 8452a96e909..63a81c0e3bd 100644 --- a/app/models/blob.rb +++ b/app/models/blob.rb @@ -34,10 +34,13 @@ class Blob < SimpleDelegator BlobViewer::BinarySTL, BlobViewer::TextSTL - ].freeze + ].sort_by { |v| v.binary? ? 0 : 1 }.freeze - BINARY_VIEWERS = RICH_VIEWERS.select(&:binary?).freeze - TEXT_VIEWERS = RICH_VIEWERS.select(&:text?).freeze + AUXILIARY_VIEWERS = [ + BlobViewer::GitlabCiYml, + BlobViewer::RouteMap, + BlobViewer::License + ].freeze attr_reader :project @@ -154,6 +157,12 @@ class Blob < SimpleDelegator @rich_viewer = rich_viewer_class&.new(self) end + def auxiliary_viewer + return @auxiliary_viewer if defined?(@auxiliary_viewer) + + @auxiliary_viewer = auxiliary_viewer_class&.new(self) + end + def rendered_as_text?(ignore_errors: true) simple_viewer.text? && (ignore_errors || simple_viewer.render_error.nil?) end @@ -180,17 +189,18 @@ class Blob < SimpleDelegator end def rich_viewer_class + viewer_class_from(RICH_VIEWERS) + end + + def auxiliary_viewer_class + viewer_class_from(AUXILIARY_VIEWERS) + end + + def viewer_class_from(classes) return if empty? || external_storage_error? - classes = - if stored_externally? - BINARY_VIEWERS + TEXT_VIEWERS - elsif binary? - BINARY_VIEWERS - else # text - TEXT_VIEWERS - end + verify_binary = !stored_externally? - classes.find { |viewer_class| viewer_class.can_render?(self) } + classes.find { |viewer_class| viewer_class.can_render?(self, verify_binary: verify_binary) } end end diff --git a/app/models/blob_viewer/auxiliary.rb b/app/models/blob_viewer/auxiliary.rb new file mode 100644 index 00000000000..db124397b27 --- /dev/null +++ b/app/models/blob_viewer/auxiliary.rb @@ -0,0 +1,12 @@ +module BlobViewer + module Auxiliary + extend ActiveSupport::Concern + + included do + self.loading_partial_name = 'loading_auxiliary' + self.type = :auxiliary + self.max_size = 100.kilobytes + self.absolute_max_size = 100.kilobytes + end + end +end diff --git a/app/models/blob_viewer/base.rb b/app/models/blob_viewer/base.rb index a8b91d8d6bc..4f38c31714b 100644 --- a/app/models/blob_viewer/base.rb +++ b/app/models/blob_viewer/base.rb @@ -1,8 +1,12 @@ module BlobViewer class Base - class_attribute :partial_name, :type, :extensions, :client_side, :binary, :switcher_icon, :switcher_title, :max_size, :absolute_max_size + PARTIAL_PATH_PREFIX = 'projects/blob/viewers'.freeze - delegate :partial_path, :rich?, :simple?, :client_side?, :server_side?, :text?, :binary?, to: :class + class_attribute :partial_name, :loading_partial_name, :type, :extensions, :file_type, :client_side, :binary, :switcher_icon, :switcher_title, :max_size, :absolute_max_size + + self.loading_partial_name = 'loading' + + delegate :partial_path, :loading_partial_path, :rich?, :simple?, :client_side?, :server_side?, :text?, :binary?, to: :class attr_reader :blob attr_accessor :override_max_size @@ -12,7 +16,11 @@ module BlobViewer end def self.partial_path - "projects/blob/viewers/#{partial_name}" + File.join(PARTIAL_PATH_PREFIX, partial_name) + end + + def self.loading_partial_path + File.join(PARTIAL_PATH_PREFIX, loading_partial_name) end def self.rich? @@ -23,6 +31,10 @@ module BlobViewer type == :simple end + def self.auxiliary? + type == :auxiliary + end + def self.client_side? client_side end @@ -39,8 +51,12 @@ module BlobViewer !binary? end - def self.can_render?(blob) - !extensions || extensions.include?(blob.extension) + def self.can_render?(blob, verify_binary: true) + return false if verify_binary && binary? != blob.binary? + return true if extensions&.include?(blob.extension) + return true if file_type && Gitlab::FileDetector.type_of(blob.path) == file_type + + false end def too_large? @@ -83,9 +99,7 @@ module BlobViewer end def prepare! - if server_side? && blob.project - blob.load_all_data!(blob.project.repository) - end + # To be overridden by subclasses end private diff --git a/app/models/blob_viewer/gitlab_ci_yml.rb b/app/models/blob_viewer/gitlab_ci_yml.rb new file mode 100644 index 00000000000..81afab2f49b --- /dev/null +++ b/app/models/blob_viewer/gitlab_ci_yml.rb @@ -0,0 +1,23 @@ +module BlobViewer + class GitlabCiYml < Base + include ServerSide + include Auxiliary + + self.partial_name = 'gitlab_ci_yml' + self.loading_partial_name = 'gitlab_ci_yml_loading' + self.file_type = :gitlab_ci + self.binary = false + + def validation_message + return @validation_message if defined?(@validation_message) + + prepare! + + @validation_message = Ci::GitlabCiYamlProcessor.validation_message(blob.data) + end + + def valid? + validation_message.blank? + end + end +end diff --git a/app/models/blob_viewer/license.rb b/app/models/blob_viewer/license.rb new file mode 100644 index 00000000000..3ad49570c88 --- /dev/null +++ b/app/models/blob_viewer/license.rb @@ -0,0 +1,23 @@ +module BlobViewer + class License < Base + # We treat the License viewer as if it renders the content client-side, + # so that it doesn't attempt to load the entire blob contents and is + # rendered synchronously instead of loaded asynchronously. + include ClientSide + include Auxiliary + + self.partial_name = 'license' + self.file_type = :license + self.binary = false + + def license + blob.project.repository.license + end + + def render_error + return if license + + :unknown_license + end + end +end diff --git a/app/models/blob_viewer/route_map.rb b/app/models/blob_viewer/route_map.rb new file mode 100644 index 00000000000..1ca730c1ea0 --- /dev/null +++ b/app/models/blob_viewer/route_map.rb @@ -0,0 +1,30 @@ +module BlobViewer + class RouteMap < Base + include ServerSide + include Auxiliary + + self.partial_name = 'route_map' + self.loading_partial_name = 'route_map_loading' + self.file_type = :route_map + self.binary = false + + def validation_message + return @validation_message if defined?(@validation_message) + + prepare! + + @validation_message = + begin + Gitlab::RouteMap.new(blob.data) + + nil + rescue Gitlab::RouteMap::FormatError => e + e.message + end + end + + def valid? + validation_message.blank? + end + end +end diff --git a/app/models/blob_viewer/server_side.rb b/app/models/blob_viewer/server_side.rb index 899107d02ea..e8c5c17b824 100644 --- a/app/models/blob_viewer/server_side.rb +++ b/app/models/blob_viewer/server_side.rb @@ -7,5 +7,11 @@ module BlobViewer self.max_size = 2.megabytes self.absolute_max_size = 5.megabytes end + + def prepare! + if blob.project + blob.load_all_data!(blob.project.repository) + end + end end end diff --git a/app/models/repository.rb b/app/models/repository.rb index 9d9d94c4486..2aec7237640 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -549,6 +549,13 @@ class Repository end cache_method :license_key + def license + return @license if defined?(@license) + return unless license_key + + @license = Licensee::License.new(license_key) + end + def gitignore file_on_head(:gitignore) end @@ -1083,8 +1090,8 @@ class Repository def file_on_head(type) if head = tree(:head) - head.blobs.find do |file| - Gitlab::FileDetector.type_of(file.name) == type + head.blobs.find do |blob| + Gitlab::FileDetector.type_of(blob.path) == type end end end diff --git a/app/views/projects/blob/_blob.html.haml b/app/views/projects/blob/_blob.html.haml index f4307421ed0..8af945ddb2c 100644 --- a/app/views/projects/blob/_blob.html.haml +++ b/app/views/projects/blob/_blob.html.haml @@ -6,6 +6,11 @@ - blob_commit = @repository.last_commit_for_path(@commit.id, blob.path) = render blob_commit, project: @project, ref: @ref + - auxiliary_viewer = blob.auxiliary_viewer + - if auxiliary_viewer && !auxiliary_viewer.render_error + .well-segment.blob-auxiliary-viewer + = render 'projects/blob/viewer', viewer: auxiliary_viewer + #blob-content-holder.blob-content-holder %article.file-holder = render "projects/blob/header", blob: blob diff --git a/app/views/projects/blob/_viewer.html.haml b/app/views/projects/blob/_viewer.html.haml index 41187d5ce66..3d9c3a59980 100644 --- a/app/views/projects/blob/_viewer.html.haml +++ b/app/views/projects/blob/_viewer.html.haml @@ -5,8 +5,7 @@ - viewer_url = local_assigns.fetch(:viewer_url) { url_for(params.merge(viewer: viewer.type, format: :json)) } if load_asynchronously .blob-viewer{ data: { type: viewer.type, url: viewer_url }, class: ('hidden' if hidden) } - if load_asynchronously - .text-center.prepend-top-default.append-bottom-default - = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content') + = render viewer.loading_partial_path, viewer: viewer - elsif render_error = render 'projects/blob/render_error', viewer: viewer - else diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml new file mode 100644 index 00000000000..28c5be6ebf3 --- /dev/null +++ b/app/views/projects/blob/viewers/_gitlab_ci_yml.html.haml @@ -0,0 +1,9 @@ +- if viewer.valid? + = icon('check fw') + This GitLab CI configuration is valid. +- else + = icon('warning fw') + This GitLab CI configuration is invalid: + = viewer.validation_message + += link_to 'Learn more', help_page_path('ci/yaml/README') diff --git a/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml new file mode 100644 index 00000000000..10cbf6a2f7a --- /dev/null +++ b/app/views/projects/blob/viewers/_gitlab_ci_yml_loading.html.haml @@ -0,0 +1,4 @@ += icon('spinner spin fw') +Validating GitLab CI configuration… + += link_to 'Learn more', help_page_path('ci/yaml/README') diff --git a/app/views/projects/blob/viewers/_license.html.haml b/app/views/projects/blob/viewers/_license.html.haml new file mode 100644 index 00000000000..9a79d164692 --- /dev/null +++ b/app/views/projects/blob/viewers/_license.html.haml @@ -0,0 +1,8 @@ +- license = viewer.license + += icon('balance-scale fw') +This project is licensed under the += succeed '.' do + %strong= license.name + += link_to 'Learn more about this license', license.url, target: '_blank', rel: 'noopener noreferrer' diff --git a/app/views/projects/blob/viewers/_loading.html.haml b/app/views/projects/blob/viewers/_loading.html.haml new file mode 100644 index 00000000000..120c0540335 --- /dev/null +++ b/app/views/projects/blob/viewers/_loading.html.haml @@ -0,0 +1,2 @@ +.text-center.prepend-top-default.append-bottom-default + = icon('spinner spin 2x', 'aria-hidden' => 'true', 'aria-label' => 'Loading content…') diff --git a/app/views/projects/blob/viewers/_loading_auxiliary.html.haml b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml new file mode 100644 index 00000000000..058c74bce0d --- /dev/null +++ b/app/views/projects/blob/viewers/_loading_auxiliary.html.haml @@ -0,0 +1,2 @@ += icon('spinner spin fw') +Loading… diff --git a/app/views/projects/blob/viewers/_route_map.html.haml b/app/views/projects/blob/viewers/_route_map.html.haml new file mode 100644 index 00000000000..d0fcd55f6c1 --- /dev/null +++ b/app/views/projects/blob/viewers/_route_map.html.haml @@ -0,0 +1,9 @@ +- if viewer.valid? + = icon('check fw') + This Route Map is valid. +- else + = icon('warning fw') + This Route Map is invalid: + = viewer.validation_message + += link_to 'Learn more', help_page_path('ci/environments', anchor: 'route-map') diff --git a/app/views/projects/blob/viewers/_route_map_loading.html.haml b/app/views/projects/blob/viewers/_route_map_loading.html.haml new file mode 100644 index 00000000000..2318cf82f58 --- /dev/null +++ b/app/views/projects/blob/viewers/_route_map_loading.html.haml @@ -0,0 +1,4 @@ += icon('spinner spin fw') +Validating Route Map… + += link_to 'Learn more', help_page_path('ci/environments', anchor: 'route-map') diff --git a/doc/ci/environments.md b/doc/ci/environments.md index b28f3e13eae..bab765d1e12 100644 --- a/doc/ci/environments.md +++ b/doc/ci/environments.md @@ -442,7 +442,8 @@ and/or `production`) you can see this information in the merge request itself. ![Environment URLs in merge request](img/environments_link_url_mr.png) -### Go directly from source files to public pages on the environment +### Go directly from source files to public pages on the environment + > Introduced in GitLab 8.17. diff --git a/lib/gitlab/file_detector.rb b/lib/gitlab/file_detector.rb index c9ca4cadd1c..f8b3d0b4965 100644 --- a/lib/gitlab/file_detector.rb +++ b/lib/gitlab/file_detector.rb @@ -13,7 +13,8 @@ module Gitlab gitignore: '.gitignore', koding: '.koding.yml', gitlab_ci: '.gitlab-ci.yml', - avatar: /\Alogo\.(png|jpg|gif)\z/ + avatar: /\Alogo\.(png|jpg|gif)\z/, + route_map: 'route-map.yml' }.freeze # Returns an Array of file types based on the given paths. diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb index 5955623f565..9888624a509 100644 --- a/spec/features/projects/blobs/blob_show_spec.rb +++ b/spec/features/projects/blobs/blob_show_spec.rb @@ -5,13 +5,13 @@ feature 'File blob', :js, feature: true do def visit_blob(path, fragment = nil) visit namespace_project_blob_path(project.namespace, project, File.join('master', path), anchor: fragment) + + wait_for_ajax end context 'Ruby file' do before do visit_blob('files/ruby/popen.rb') - - wait_for_ajax end it 'displays the blob' do @@ -35,8 +35,6 @@ feature 'File blob', :js, feature: true do context 'visiting directly' do before do visit_blob('files/markdown/ruby-style-guide.md') - - wait_for_ajax end it 'displays the blob using the rich viewer' do @@ -104,8 +102,6 @@ feature 'File blob', :js, feature: true do context 'visiting with a line number anchor' do before do visit_blob('files/markdown/ruby-style-guide.md', 'L1') - - wait_for_ajax end it 'displays the blob using the simple viewer' do @@ -148,8 +144,6 @@ feature 'File blob', :js, feature: true do project.update_attribute(:lfs_enabled, true) visit_blob('files/lfs/file.md') - - wait_for_ajax end it 'displays an error' do @@ -198,8 +192,6 @@ feature 'File blob', :js, feature: true do context 'when LFS is disabled on the project' do before do visit_blob('files/lfs/file.md') - - wait_for_ajax end it 'displays the blob' do @@ -235,8 +227,6 @@ feature 'File blob', :js, feature: true do ).execute visit_blob('files/test.pdf') - - wait_for_ajax end it 'displays the blob' do @@ -263,8 +253,6 @@ feature 'File blob', :js, feature: true do project.update_attribute(:lfs_enabled, true) visit_blob('files/lfs/lfs_object.iso') - - wait_for_ajax end it 'displays the blob' do @@ -287,8 +275,6 @@ feature 'File blob', :js, feature: true do context 'when LFS is disabled on the project' do before do visit_blob('files/lfs/lfs_object.iso') - - wait_for_ajax end it 'displays the blob' do @@ -312,8 +298,6 @@ feature 'File blob', :js, feature: true do context 'ZIP file' do before do visit_blob('Gemfile.zip') - - wait_for_ajax end it 'displays the blob' do @@ -348,8 +332,6 @@ feature 'File blob', :js, feature: true do ).execute visit_blob('files/empty.md') - - wait_for_ajax end it 'displays an error' do @@ -369,4 +351,80 @@ feature 'File blob', :js, feature: true do end end end + + context '.gitlab-ci.yml' do + before do + project.add_master(project.creator) + + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add .gitlab-ci.yml", + file_path: '.gitlab-ci.yml', + file_content: File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) + ).execute + + visit_blob('.gitlab-ci.yml') + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that configuration is valid + expect(page).to have_content('This GitLab CI configuration is valid.') + + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end + + context '.gitlab/route-map.yml' do + before do + project.add_master(project.creator) + + Files::CreateService.new( + project, + project.creator, + start_branch: 'master', + branch_name: 'master', + commit_message: "Add .gitlab/route-map.yml", + file_path: '.gitlab/route-map.yml', + file_content: <<-MAP.strip_heredoc + # Team data + - source: 'data/team.yml' + public: 'team/' + MAP + ).execute + + visit_blob('.gitlab/route-map.yml') + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows that map is valid + expect(page).to have_content('This Route Map is valid.') + + # shows a learn more link + expect(page).to have_link('Learn more') + end + end + end + + context 'LICENSE' do + before do + visit_blob('LICENSE') + end + + it 'displays an auxiliary viewer' do + aggregate_failures do + # shows license + expect(page).to have_content('This project is licensed under the MIT License.') + + # shows a learn more link + expect(page).to have_link('Learn more about this license', 'http://choosealicense.com/licenses/mit/') + end + end + end end diff --git a/spec/models/blob_spec.rb b/spec/models/blob_spec.rb index f84c6b48173..f19e1af65a6 100644 --- a/spec/models/blob_spec.rb +++ b/spec/models/blob_spec.rb @@ -271,6 +271,52 @@ describe Blob do end end + describe '#auxiliary_viewer' do + context 'when the blob has an external storage error' do + before do + project.lfs_enabled = false + end + + it 'returns nil' do + blob = fake_blob(path: 'LICENSE', lfs: true) + + expect(blob.auxiliary_viewer).to be_nil + end + end + + context 'when the blob is empty' do + it 'returns nil' do + blob = fake_blob(data: '') + + expect(blob.auxiliary_viewer).to be_nil + end + end + + context 'when the blob is stored externally' do + it 'returns a matching viewer' do + blob = fake_blob(path: 'LICENSE', lfs: true) + + expect(blob.auxiliary_viewer).to be_a(BlobViewer::License) + end + end + + context 'when the blob is binary' do + it 'returns nil' do + blob = fake_blob(path: 'LICENSE', binary: true) + + expect(blob.auxiliary_viewer).to be_nil + end + end + + context 'when the blob is text-based' do + it 'returns a matching text-based viewer' do + blob = fake_blob(path: 'LICENSE') + + expect(blob.auxiliary_viewer).to be_a(BlobViewer::License) + end + end + end + describe '#rendered_as_text?' do context 'when ignoring errors' do context 'when the simple viewer is text-based' do diff --git a/spec/models/blob_viewer/base_spec.rb b/spec/models/blob_viewer/base_spec.rb index 740ad9d275e..a6641970e1b 100644 --- a/spec/models/blob_viewer/base_spec.rb +++ b/spec/models/blob_viewer/base_spec.rb @@ -8,6 +8,7 @@ describe BlobViewer::Base, model: true do let(:viewer_class) do Class.new(described_class) do self.extensions = %w(pdf) + self.binary = true self.max_size = 1.megabyte self.absolute_max_size = 5.megabytes self.client_side = false @@ -18,14 +19,47 @@ describe BlobViewer::Base, model: true do describe '.can_render?' do context 'when the extension is supported' do - let(:blob) { fake_blob(path: 'file.pdf') } + context 'when the binaryness matches' do + let(:blob) { fake_blob(path: 'file.pdf', binary: true) } - it 'returns true' do - expect(viewer_class.can_render?(blob)).to be_truthy + it 'returns true' do + expect(viewer_class.can_render?(blob)).to be_truthy + end + end + + context 'when the binaryness does not match' do + let(:blob) { fake_blob(path: 'file.pdf', binary: false) } + + it 'returns false' do + expect(viewer_class.can_render?(blob)).to be_falsey + end + end + end + + context 'when the file type is supported' do + before do + viewer_class.file_type = :license + viewer_class.binary = false + end + + context 'when the binaryness matches' do + let(:blob) { fake_blob(path: 'LICENSE', binary: false) } + + it 'returns true' do + expect(viewer_class.can_render?(blob)).to be_truthy + end + end + + context 'when the binaryness does not match' do + let(:blob) { fake_blob(path: 'LICENSE', binary: true) } + + it 'returns false' do + expect(viewer_class.can_render?(blob)).to be_falsey + end end end - context 'when the extension is not supported' do + context 'when the extension and file type are not supported' do let(:blob) { fake_blob(path: 'file.txt') } it 'returns false' do @@ -153,34 +187,4 @@ describe BlobViewer::Base, model: true do end end end - - describe '#prepare!' do - context 'when the viewer is server side' do - let(:blob) { fake_blob(path: 'file.md') } - - before do - viewer_class.client_side = false - end - - it 'loads all blob data' do - expect(blob).to receive(:load_all_data!) - - viewer.prepare! - end - end - - context 'when the viewer is client side' do - let(:blob) { fake_blob(path: 'file.md') } - - before do - viewer_class.client_side = true - end - - it "doesn't load all blob data" do - expect(blob).not_to receive(:load_all_data!) - - viewer.prepare! - end - end - end end diff --git a/spec/models/blob_viewer/gitlab_ci_yml_spec.rb b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb new file mode 100644 index 00000000000..0c6c24ece21 --- /dev/null +++ b/spec/models/blob_viewer/gitlab_ci_yml_spec.rb @@ -0,0 +1,32 @@ +require 'spec_helper' + +describe BlobViewer::GitlabCiYml, model: true do + include FakeBlobHelpers + + let(:project) { build(:project) } + let(:data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) } + let(:blob) { fake_blob(path: '.gitlab-ci.yml', data: data) } + subject { described_class.new(blob) } + + describe '#validation_message' do + it 'calls prepare! on the viewer' do + expect(subject).to receive(:prepare!) + + subject.validation_message + end + + context 'when the configuration is valid' do + it 'returns nil' do + expect(subject.validation_message).to be_nil + end + end + + context 'when the configuration is invalid' do + let(:data) { 'oof' } + + it 'returns the error message' do + expect(subject.validation_message).to eq('Invalid configuration format') + end + end + end +end diff --git a/spec/models/blob_viewer/license_spec.rb b/spec/models/blob_viewer/license_spec.rb new file mode 100644 index 00000000000..944ddd32b92 --- /dev/null +++ b/spec/models/blob_viewer/license_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +describe BlobViewer::License, model: true do + include FakeBlobHelpers + + let(:project) { create(:project, :repository) } + let(:blob) { fake_blob(path: 'LICENSE') } + subject { described_class.new(blob) } + + describe '#license' do + it 'returns the blob project repository license' do + expect(subject.license).not_to be_nil + expect(subject.license).to eq(project.repository.license) + end + end + + describe '#render_error' do + context 'when there is no license' do + before do + allow(project.repository).to receive(:license).and_return(nil) + end + + it 'returns :unknown_license' do + expect(subject.render_error).to eq(:unknown_license) + end + end + + context 'when there is a license' do + it 'returns nil' do + expect(subject.render_error).to be_nil + end + end + end +end diff --git a/spec/models/blob_viewer/route_map_spec.rb b/spec/models/blob_viewer/route_map_spec.rb new file mode 100644 index 00000000000..4854e0262d9 --- /dev/null +++ b/spec/models/blob_viewer/route_map_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe BlobViewer::RouteMap, model: true do + include FakeBlobHelpers + + let(:project) { build(:project) } + let(:data) do + <<-MAP.strip_heredoc + # Team data + - source: 'data/team.yml' + public: 'team/' + MAP + end + let(:blob) { fake_blob(path: '.gitlab/route-map.yml', data: data) } + subject { described_class.new(blob) } + + describe '#validation_message' do + it 'calls prepare! on the viewer' do + expect(subject).to receive(:prepare!) + + subject.validation_message + end + + context 'when the configuration is valid' do + it 'returns nil' do + expect(subject.validation_message).to be_nil + end + end + + context 'when the configuration is invalid' do + let(:data) { 'oof' } + + it 'returns the error message' do + expect(subject.validation_message).to eq('Route map is not an array') + end + end + end +end diff --git a/spec/models/blob_viewer/server_side_spec.rb b/spec/models/blob_viewer/server_side_spec.rb new file mode 100644 index 00000000000..ddca9b79390 --- /dev/null +++ b/spec/models/blob_viewer/server_side_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe BlobViewer::ServerSide, model: true do + include FakeBlobHelpers + + let(:project) { build(:empty_project) } + + let(:viewer_class) do + Class.new(BlobViewer::Base) do + include BlobViewer::ServerSide + end + end + + subject { viewer_class.new(blob) } + + describe '#prepare!' do + let(:blob) { fake_blob(path: 'file.txt') } + + it 'loads all blob data' do + expect(blob).to receive(:load_all_data!) + + subject.prepare! + end + end +end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index cea8db7a926..6ebc9965924 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Repository, models: true do include RepoHelpers - TestBlob = Struct.new(:name) + TestBlob = Struct.new(:path) let(:project) { create(:project, :repository) } let(:repository) { project.repository } @@ -565,31 +565,31 @@ describe Repository, models: true do it 'accepts changelog' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('changelog')]) - expect(repository.changelog.name).to eq('changelog') + expect(repository.changelog.path).to eq('changelog') end it 'accepts news instead of changelog' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('news')]) - expect(repository.changelog.name).to eq('news') + expect(repository.changelog.path).to eq('news') end it 'accepts history instead of changelog' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('history')]) - expect(repository.changelog.name).to eq('history') + expect(repository.changelog.path).to eq('history') end it 'accepts changes instead of changelog' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('changes')]) - expect(repository.changelog.name).to eq('changes') + expect(repository.changelog.path).to eq('changes') end it 'is case-insensitive' do expect(repository.tree).to receive(:blobs).and_return([TestBlob.new('CHANGELOG')]) - expect(repository.changelog.name).to eq('CHANGELOG') + expect(repository.changelog.path).to eq('CHANGELOG') end end @@ -624,7 +624,7 @@ describe Repository, models: true do repository.create_file(user, 'LICENSE', 'Copyright!', message: 'Add LICENSE', branch_name: 'master') - expect(repository.license_blob.name).to eq('LICENSE') + expect(repository.license_blob.path).to eq('LICENSE') end %w[LICENSE LICENCE LiCensE LICENSE.md LICENSE.foo COPYING COPYING.md].each do |filename| @@ -654,7 +654,7 @@ describe Repository, models: true do expect(repository.license_key).to be_nil end - it 'detects license file with no recognizable open-source license content' do + it 'returns nil when the content is not recognizable' do repository.create_file(user, 'LICENSE', 'Copyright!', message: 'Add LICENSE', branch_name: 'master') @@ -670,12 +670,45 @@ describe Repository, models: true do end end + describe '#license' do + before do + repository.delete_file(user, 'LICENSE', + message: 'Remove LICENSE', branch_name: 'master') + end + + it 'returns nil when no license is detected' do + expect(repository.license).to be_nil + end + + it 'returns nil when the repository does not exist' do + expect(repository).to receive(:exists?).and_return(false) + + expect(repository.license).to be_nil + end + + it 'returns nil when the content is not recognizable' do + repository.create_file(user, 'LICENSE', 'Copyright!', + message: 'Add LICENSE', branch_name: 'master') + + expect(repository.license).to be_nil + end + + it 'returns the license' do + license = Licensee::License.new('mit') + repository.create_file(user, 'LICENSE', + license.content, + message: 'Add LICENSE', branch_name: 'master') + + expect(repository.license).to eq(license) + end + end + describe "#gitlab_ci_yml", caching: true do it 'returns valid file' do files = [TestBlob.new('file'), TestBlob.new('.gitlab-ci.yml'), TestBlob.new('copying')] expect(repository.tree).to receive(:blobs).and_return(files) - expect(repository.gitlab_ci_yml.name).to eq('.gitlab-ci.yml') + expect(repository.gitlab_ci_yml.path).to eq('.gitlab-ci.yml') end it 'returns nil if not exists' do diff --git a/spec/views/projects/blob/_viewer.html.haml_spec.rb b/spec/views/projects/blob/_viewer.html.haml_spec.rb index 501f90c5f9a..08018767624 100644 --- a/spec/views/projects/blob/_viewer.html.haml_spec.rb +++ b/spec/views/projects/blob/_viewer.html.haml_spec.rb @@ -47,10 +47,10 @@ describe 'projects/blob/_viewer.html.haml', :view do expect(rendered).to have_css('.blob-viewer[data-url]') end - it 'displays a spinner' do + it 'renders the loading indicator' do render_view - expect(rendered).to have_css('i[aria-label="Loading content"]') + expect(view).to render_template('projects/blob/viewers/_loading') end end -- cgit v1.2.1 From 77798c6506aa5253e10325d78ee1b73901d80b06 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 10 May 2017 09:02:28 -0500 Subject: Reset Repository#license memo when license file is changed --- app/models/repository.rb | 20 +++++++++++++------- spec/models/repository_spec.rb | 3 ++- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/app/models/repository.rb b/app/models/repository.rb index 2aec7237640..11163ec77e9 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -30,7 +30,7 @@ class Repository METHOD_CACHES_FOR_FILE_TYPES = { readme: :rendered_readme, changelog: :changelog, - license: %i(license_blob license_key), + license: %i(license_blob license_key license), contributing: :contribution_guide, gitignore: :gitignore, koding: :koding_yml, @@ -42,13 +42,13 @@ class Repository # variable. # # This only works for methods that do not take any arguments. - def self.cache_method(name, fallback: nil) + def self.cache_method(name, fallback: nil, memoize_only: false) original = :"_uncached_#{name}" alias_method(original, name) define_method(name) do - cache_method_output(name, fallback: fallback) { __send__(original) } + cache_method_output(name, fallback: fallback, memoize_only: memoize_only) { __send__(original) } end end @@ -550,11 +550,11 @@ class Repository cache_method :license_key def license - return @license if defined?(@license) return unless license_key - @license = Licensee::License.new(license_key) + Licensee::License.new(license_key) end + cache_method :license, memoize_only: true def gitignore file_on_head(:gitignore) @@ -1068,14 +1068,20 @@ class Repository # # key - The name of the key to cache the data in. # fallback - A value to fall back to in the event of a Git error. - def cache_method_output(key, fallback: nil, &block) + def cache_method_output(key, fallback: nil, memoize_only: false, &block) ivar = cache_instance_variable_name(key) if instance_variable_defined?(ivar) instance_variable_get(ivar) else begin - instance_variable_set(ivar, cache.fetch(key, &block)) + value = + if memoize_only + yield + else + cache.fetch(key, &block) + end + instance_variable_set(ivar, value) rescue Rugged::ReferenceError, Gitlab::Git::Repository::NoRepository # if e.g. HEAD or the entire repository doesn't exist we want to # gracefully handle this and not cache anything. diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index 6ebc9965924..00a9f2abeb9 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -1858,11 +1858,12 @@ describe Repository, models: true do describe '#refresh_method_caches' do it 'refreshes the caches of the given types' do expect(repository).to receive(:expire_method_caches). - with(%i(rendered_readme license_blob license_key)) + with(%i(rendered_readme license_blob license_key license)) expect(repository).to receive(:rendered_readme) expect(repository).to receive(:license_blob) expect(repository).to receive(:license_key) + expect(repository).to receive(:license) repository.refresh_method_caches(%i(readme license)) end -- cgit v1.2.1 From 909975051369f57278000acb7cddc7b0dafc9906 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 10 May 2017 10:32:04 -0500 Subject: Add changelog --- changelogs/unreleased/dm-auxiliary-viewers.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelogs/unreleased/dm-auxiliary-viewers.yml diff --git a/changelogs/unreleased/dm-auxiliary-viewers.yml b/changelogs/unreleased/dm-auxiliary-viewers.yml new file mode 100644 index 00000000000..ba73a499115 --- /dev/null +++ b/changelogs/unreleased/dm-auxiliary-viewers.yml @@ -0,0 +1,5 @@ +--- +title: Display extra info about files on .gitlab-ci.yml, .gitlab/route-map.yml and + LICENSE blob pages +merge_request: +author: -- cgit v1.2.1 From 965b41769f878ba526f88761b06182e6a2e0f538 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Wed, 10 May 2017 20:33:51 -0500 Subject: Fix MySQL build failure --- .../20170502101023_cleanup_namespaceless_pending_delete_projects.rb | 2 +- spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb b/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb index 2d242da9ef8..ce52de91cdd 100644 --- a/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb +++ b/db/post_migrate/20170502101023_cleanup_namespaceless_pending_delete_projects.rb @@ -30,7 +30,7 @@ class CleanupNamespacelessPendingDeleteProjects < ActiveRecord::Migration private def pending_delete_batch - connection.exec_query(find_batch).map{ |row| row['id'] } + connection.exec_query(find_batch).map{ |row| row['id'].to_i } end BATCH_SIZE = 5000 diff --git a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb index 0b8af5010ba..49e750a3f4d 100644 --- a/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb +++ b/spec/migrations/cleanup_namespaceless_pending_delete_projects_spec.rb @@ -15,7 +15,7 @@ describe CleanupNamespacelessPendingDeleteProjects do project = build(:empty_project, pending_delete: true, namespace_id: nil) project.save(validate: false) - expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id.to_s]]) + expect(NamespacelessProjectDestroyWorker).to receive(:bulk_perform_async).with([[project.id]]) described_class.new.up end -- cgit v1.2.1 From 08edfb67b141b4f1b51fe624264c79dab3d2028e Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Wed, 10 May 2017 22:15:03 -0500 Subject: Fix flickering of system notes Fix https://gitlab.com/gitlab-org/gitlab-ce/issues/32087 Easy reproduction: 1. Edit an issue title 1. Notice the system note added 1. Switch to another tab and back (to fire the polling immediately) 1. Notice the flicker (without this fix) --- app/views/shared/notes/_note.html.haml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/views/shared/notes/_note.html.haml b/app/views/shared/notes/_note.html.haml index 5c1156b06fb..87aae793966 100644 --- a/app/views/shared/notes/_note.html.haml +++ b/app/views/shared/notes/_note.html.haml @@ -29,6 +29,8 @@ - if note.system %span.system-note-message = note.redacted_note_html + .original-note-content.hidden + = note.note %a{ href: "##{dom_id(note)}" } = time_ago_with_tooltip(note.created_at, placement: 'bottom', html_class: 'note-created-ago') - unless note.system? -- cgit v1.2.1 From a41a0c7642aacdf5d360cf6862e203d5db4a45d5 Mon Sep 17 00:00:00 2001 From: Mark Fletcher Date: Thu, 11 May 2017 11:09:07 +0800 Subject: Add summary lines for collapsed details in the bug report template [skip ci] --- .gitlab/issue_templates/Bug.md | 2 ++ changelogs/unreleased/issue-templates-summary-lines.yml | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 changelogs/unreleased/issue-templates-summary-lines.yml diff --git a/.gitlab/issue_templates/Bug.md b/.gitlab/issue_templates/Bug.md index 66e1e0e20b3..58af062e75e 100644 --- a/.gitlab/issue_templates/Bug.md +++ b/.gitlab/issue_templates/Bug.md @@ -40,6 +40,7 @@ logs, and code as it's very hard to read otherwise.) #### Results of GitLab environment info
+Expand for output related to GitLab environment info
 
 (For installations with omnibus-gitlab package run and paste the output of:
@@ -54,6 +55,7 @@ logs, and code as it's very hard to read otherwise.)
 #### Results of GitLab application Check
 
 
+Expand for output related to the GitLab application check
 
 (For installations with omnibus-gitlab package run and paste the output of:
diff --git a/changelogs/unreleased/issue-templates-summary-lines.yml b/changelogs/unreleased/issue-templates-summary-lines.yml
new file mode 100644
index 00000000000..0c8c3d884ce
--- /dev/null
+++ b/changelogs/unreleased/issue-templates-summary-lines.yml
@@ -0,0 +1,4 @@
+---
+title: Add summary lines for collapsed details in the bug report template
+merge_request:
+author:
-- 
cgit v1.2.1


From b1645ab91e9f1476172ec386c3486ea64365a930 Mon Sep 17 00:00:00 2001
From: winh 
Date: Thu, 4 May 2017 21:25:04 +0200
Subject: Add failing test for #29368

---
 .../components/pipelines_table_row_spec.js         | 90 +++++++++++++++++++---
 1 file changed, 79 insertions(+), 11 deletions(-)

diff --git a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js
index 3036a98d0b9..0a2c66e72d7 100644
--- a/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js
+++ b/spec/javascripts/vue_shared/components/pipelines_table_row_spec.js
@@ -3,31 +3,45 @@ import tableRowComp from '~/vue_shared/components/pipelines_table_row';
 
 describe('Pipelines Table Row', () => {
   const jsonFixtureName = 'pipelines/pipelines.json';
+  const buildComponent = (pipeline) => {
+    const PipelinesTableRowComponent = Vue.extend(tableRowComp);
+    return new PipelinesTableRowComponent({
+      el: document.querySelector('.test-dom-element'),
+      propsData: {
+        pipeline,
+        service: {},
+      },
+    }).$mount();
+  };
 
   let component;
   let pipeline;
+  let pipelineWithoutAuthor;
+  let pipelineWithoutCommit;
 
   preloadFixtures(jsonFixtureName);
 
   beforeEach(() => {
     const pipelines = getJSONFixture(jsonFixtureName).pipelines;
     pipeline = pipelines.find(p => p.id === 1);
-    const PipelinesTableRowComponent = Vue.extend(tableRowComp);
+    pipelineWithoutAuthor = pipelines.find(p => p.id === 2);
+    pipelineWithoutCommit = pipelines.find(p => p.id === 3);
+  });
 
-    component = new PipelinesTableRowComponent({
-      el: document.querySelector('.test-dom-element'),
-      propsData: {
-        pipeline,
-        service: {},
-      },
-    }).$mount();
+  afterEach(() => {
+    component.$destroy();
   });
 
   it('should render a table row', () => {
+    component = buildComponent(pipeline);
     expect(component.$el).toEqual('TR');
   });
 
   describe('status column', () => {
+    beforeEach(() => {
+      component = buildComponent(pipeline);
+    });
+
     it('should render a pipeline link', () => {
       expect(
         component.$el.querySelector('td.commit-link a').getAttribute('href'),
@@ -42,6 +56,10 @@ describe('Pipelines Table Row', () => {
   });
 
   describe('information column', () => {
+    beforeEach(() => {
+      component = buildComponent(pipeline);
+    });
+
     it('should render a pipeline link', () => {
       expect(
         component.$el.querySelector('td:nth-child(2) a').getAttribute('href'),
@@ -69,13 +87,59 @@ describe('Pipelines Table Row', () => {
 
   describe('commit column', () => {
     it('should render link to commit', () => {
-      expect(
-        component.$el.querySelector('td:nth-child(3) .commit-id').getAttribute('href'),
-      ).toEqual(pipeline.commit.commit_path);
+      component = buildComponent(pipeline);
+
+      const commitLink = component.$el.querySelector('.branch-commit .commit-id');
+      expect(commitLink.getAttribute('href')).toEqual(pipeline.commit.commit_path);
+    });
+
+    const findElements = () => {
+      const commitTitleElement = component.$el.querySelector('.branch-commit .commit-title');
+      const commitAuthorElement = commitTitleElement.querySelector('a.avatar-image-container');
+
+      if (!commitAuthorElement) {
+        return { commitAuthorElement };
+      }
+
+      const commitAuthorLink = commitAuthorElement.getAttribute('href');
+      const commitAuthorName = commitAuthorElement.querySelector('img.avatar').getAttribute('title');
+
+      return { commitAuthorElement, commitAuthorLink, commitAuthorName };
+    };
+
+    it('renders nothing without commit', () => {
+      expect(pipelineWithoutCommit.commit).toBe(null);
+      component = buildComponent(pipelineWithoutCommit);
+
+      const { commitAuthorElement } = findElements();
+
+      expect(commitAuthorElement).toBe(null);
+    });
+
+    it('renders commit author', () => {
+      component = buildComponent(pipeline);
+      const { commitAuthorLink, commitAuthorName } = findElements();
+
+      expect(commitAuthorLink).toEqual(pipeline.commit.author.web_url);
+      expect(commitAuthorName).toEqual(pipeline.commit.author.username);
+    });
+
+    it('renders commit with unregistered author', () => {
+      expect(pipelineWithoutAuthor.commit.author).toBe(null);
+      component = buildComponent(pipelineWithoutAuthor);
+
+      const { commitAuthorLink, commitAuthorName } = findElements();
+
+      expect(commitAuthorLink).toEqual(`mailto:${pipelineWithoutAuthor.commit.author_email}`);
+      expect(commitAuthorName).toEqual(pipelineWithoutAuthor.commit.author_name);
     });
   });
 
   describe('stages column', () => {
+    beforeEach(() => {
+      component = buildComponent(pipeline);
+    });
+
     it('should render an icon for each stage', () => {
       expect(
         component.$el.querySelectorAll('td:nth-child(4) .js-builds-dropdown-button').length,
@@ -84,6 +148,10 @@ describe('Pipelines Table Row', () => {
   });
 
   describe('actions column', () => {
+    beforeEach(() => {
+      component = buildComponent(pipeline);
+    });
+
     it('should render the provided actions', () => {
       expect(
         component.$el.querySelectorAll('td:nth-child(6) ul li').length,
-- 
cgit v1.2.1


From 50181499bf21d8cc691896fe446e7435ad627be2 Mon Sep 17 00:00:00 2001
From: winh 
Date: Tue, 9 May 2017 12:33:24 +0200
Subject: Link to commit author user page from pipelines (!11100)

---
 .../vue_shared/components/pipelines_table_row.js          | 15 +++++++--------
 changelogs/unreleased/winh-pipeline-author-link.yml       |  4 ++++
 2 files changed, 11 insertions(+), 8 deletions(-)
 create mode 100644 changelogs/unreleased/winh-pipeline-author-link.yml

diff --git a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js
index fbae85c85f6..7ac7ceaa4e5 100644
--- a/app/assets/javascripts/vue_shared/components/pipelines_table_row.js
+++ b/app/assets/javascripts/vue_shared/components/pipelines_table_row.js
@@ -62,10 +62,12 @@ export default {
     commitAuthor() {
       let commitAuthorInformation;
 
+      if (!this.pipeline || !this.pipeline.commit) {
+        return null;
+      }
+
       // 1. person who is an author of a commit might be a GitLab user
-      if (this.pipeline &&
-        this.pipeline.commit &&
-        this.pipeline.commit.author) {
+      if (this.pipeline.commit.author) {
         // 2. if person who is an author of a commit is a GitLab user
         // he/she can have a GitLab avatar
         if (this.pipeline.commit.author.avatar_url) {
@@ -77,11 +79,8 @@ export default {
             avatar_url: this.pipeline.commit.author_gravatar_url,
           });
         }
-      }
-
-      // 4. If committer is not a GitLab User he/she can have a Gravatar
-      if (this.pipeline &&
-        this.pipeline.commit) {
+        // 4. If committer is not a GitLab User he/she can have a Gravatar
+      } else {
         commitAuthorInformation = {
           avatar_url: this.pipeline.commit.author_gravatar_url,
           web_url: `mailto:${this.pipeline.commit.author_email}`,
diff --git a/changelogs/unreleased/winh-pipeline-author-link.yml b/changelogs/unreleased/winh-pipeline-author-link.yml
new file mode 100644
index 00000000000..1b903d1e357
--- /dev/null
+++ b/changelogs/unreleased/winh-pipeline-author-link.yml
@@ -0,0 +1,4 @@
+---
+title: Link to commit author user page from pipelines
+merge_request: 11100
+author:
-- 
cgit v1.2.1


From 5c25629a1427fd9a2e571bcde070f9aead2efd91 Mon Sep 17 00:00:00 2001
From: Kushal Pandya 
Date: Thu, 11 May 2017 09:05:07 +0000
Subject: Fix slash commands detection in comments

---
 app/assets/javascripts/notes.js |  2 +-
 spec/javascripts/notes_spec.js  | 25 +++++++++++++++++++------
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index f6fe6d9f0fd..7ba44835741 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -24,7 +24,7 @@ const normalizeNewlines = function(str) {
 (function() {
   this.Notes = (function() {
     const MAX_VISIBLE_COMMIT_LIST_COUNT = 3;
-    const REGEX_SLASH_COMMANDS = /\/\w+/g;
+    const REGEX_SLASH_COMMANDS = /^\/\w+/gm;
 
     Notes.interval = null;
 
diff --git a/spec/javascripts/notes_spec.js b/spec/javascripts/notes_spec.js
index cfd599f793e..be4605a5b89 100644
--- a/spec/javascripts/notes_spec.js
+++ b/spec/javascripts/notes_spec.js
@@ -376,13 +376,20 @@ import '~/notes';
         this.notes = new Notes('', []);
       });
 
-      it('should return true when comment has slash commands', () => {
-        const sampleComment = '/wip /milestone %1.0 /merge /unassign Merging this';
+      it('should return true when comment begins with a slash command', () => {
+        const sampleComment = '/wip \n/milestone %1.0 \n/merge \n/unassign Merging this';
         const hasSlashCommands = this.notes.hasSlashCommands(sampleComment);
 
         expect(hasSlashCommands).toBeTruthy();
       });
 
+      it('should return false when comment does NOT begin with a slash command', () => {
+        const sampleComment = 'Hey, /unassign Merging this';
+        const hasSlashCommands = this.notes.hasSlashCommands(sampleComment);
+
+        expect(hasSlashCommands).toBeFalsy();
+      });
+
       it('should return false when comment does NOT have any slash commands', () => {
         const sampleComment = 'Looking good, Awesome!';
         const hasSlashCommands = this.notes.hasSlashCommands(sampleComment);
@@ -392,14 +399,20 @@ import '~/notes';
     });
 
     describe('stripSlashCommands', () => {
-      const REGEX_SLASH_COMMANDS = /\/\w+/g;
+      it('should strip slash commands from the comment which begins with a slash command', () => {
+        this.notes = new Notes();
+        const sampleComment = '/wip \n/milestone %1.0 \n/merge \n/unassign Merging this';
+        const stripedComment = this.notes.stripSlashCommands(sampleComment);
+
+        expect(stripedComment).not.toBe(sampleComment);
+      });
 
-      it('should strip slash commands from the comment', () => {
+      it('should NOT strip string that has slashes within', () => {
         this.notes = new Notes();
-        const sampleComment = '/wip /milestone %1.0 /merge /unassign Merging this';
+        const sampleComment = 'http://127.0.0.1:3000/root/gitlab-shell/issues/1';
         const stripedComment = this.notes.stripSlashCommands(sampleComment);
 
-        expect(REGEX_SLASH_COMMANDS.test(stripedComment)).toBeFalsy();
+        expect(stripedComment).toBe(sampleComment);
       });
     });
 
-- 
cgit v1.2.1


From 5d74fc8a5496423b31eb4dc0daf02b39d0fb51de Mon Sep 17 00:00:00 2001
From: Phil Hughes 
Date: Thu, 11 May 2017 11:37:40 +0100
Subject: Use position sticky on merge request tabs

Removes the need for Bootstraps affix on browser that support sticky positions. On these browsers, there should be a slight performance improvement as there will be no scrolling events, it will all be handled by the browser
---
 app/assets/javascripts/merge_request_tabs.js     | 7 +++++++
 app/assets/stylesheets/pages/merge_requests.scss | 9 +++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/app/assets/javascripts/merge_request_tabs.js b/app/assets/javascripts/merge_request_tabs.js
index 93c30c54a8e..a3dff25c93b 100644
--- a/app/assets/javascripts/merge_request_tabs.js
+++ b/app/assets/javascripts/merge_request_tabs.js
@@ -358,6 +358,13 @@ import BlobForkSuggestion from './blob/blob_fork_suggestion';
       // So we dont affix the tabs on these
       if (Breakpoints.get().getBreakpointSize() === 'xs' || !$tabs.length) return;
 
+      /**
+        If the browser does not support position sticky, it returns the position as static.
+        If the browser does support sticky, then we allow the browser to handle it, if not
+        then we default back to Bootstraps affix
+      **/
+      if ($tabs.css('position') !== 'static') return;
+
       const $diffTabs = $('#diff-notes-app');
 
       $tabs.off('affix.bs.affix affix-top.bs.affix')
diff --git a/app/assets/stylesheets/pages/merge_requests.scss b/app/assets/stylesheets/pages/merge_requests.scss
index 75c57e369e7..87592926930 100644
--- a/app/assets/stylesheets/pages/merge_requests.scss
+++ b/app/assets/stylesheets/pages/merge_requests.scss
@@ -693,12 +693,17 @@
 }
 
 .merge-request-tabs-holder {
+  top: 0;
+  z-index: 10;
   background-color: $white-light;
 
+  @media(min-width: $screen-sm-min) {
+    position: sticky;
+    position: -webkit-sticky;
+  }
+
   &.affix {
-    top: 0;
     left: 0;
-    z-index: 10;
     transition: right .15s;
 
     @media (max-width: $screen-xs-max) {
-- 
cgit v1.2.1


From 75e613459df3ef8630800af29e11ea3767d92d7f Mon Sep 17 00:00:00 2001
From: winh 
Date: Tue, 9 May 2017 14:34:08 +0200
Subject: Add missing tear down of sidebarMockInterceptor (!11204)

---
 spec/javascripts/sidebar/sidebar_assignees_spec.js | 1 +
 spec/javascripts/sidebar/sidebar_mediator_spec.js  | 1 +
 spec/javascripts/sidebar/sidebar_service_spec.js   | 1 +
 3 files changed, 3 insertions(+)

diff --git a/spec/javascripts/sidebar/sidebar_assignees_spec.js b/spec/javascripts/sidebar/sidebar_assignees_spec.js
index e0df0a3228f..865951b2ad7 100644
--- a/spec/javascripts/sidebar/sidebar_assignees_spec.js
+++ b/spec/javascripts/sidebar/sidebar_assignees_spec.js
@@ -24,6 +24,7 @@ describe('sidebar assignees', () => {
     SidebarService.singleton = null;
     SidebarStore.singleton = null;
     SidebarMediator.singleton = null;
+    Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor);
   });
 
   it('calls the mediator when saves the assignees', () => {
diff --git a/spec/javascripts/sidebar/sidebar_mediator_spec.js b/spec/javascripts/sidebar/sidebar_mediator_spec.js
index 2b00fa17334..e246f41ee82 100644
--- a/spec/javascripts/sidebar/sidebar_mediator_spec.js
+++ b/spec/javascripts/sidebar/sidebar_mediator_spec.js
@@ -14,6 +14,7 @@ describe('Sidebar mediator', () => {
     SidebarService.singleton = null;
     SidebarStore.singleton = null;
     SidebarMediator.singleton = null;
+    Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor);
   });
 
   it('assigns yourself ', () => {
diff --git a/spec/javascripts/sidebar/sidebar_service_spec.js b/spec/javascripts/sidebar/sidebar_service_spec.js
index d41162096a6..91a4dd669a7 100644
--- a/spec/javascripts/sidebar/sidebar_service_spec.js
+++ b/spec/javascripts/sidebar/sidebar_service_spec.js
@@ -10,6 +10,7 @@ describe('Sidebar service', () => {
 
   afterEach(() => {
     SidebarService.singleton = null;
+    Vue.http.interceptors = _.without(Vue.http.interceptors, Mock.sidebarMockInterceptor);
   });
 
   it('gets the data', (done) => {
-- 
cgit v1.2.1


From 9e8ed540b75d24484f19f36cf6e95a199135b935 Mon Sep 17 00:00:00 2001
From: Marcia Ramos 
Date: Thu, 11 May 2017 10:51:39 +0000
Subject: Complement tech articles guidelines

---
 doc/articles/how_to_configure_ldap_gitlab_ce/index.md | 2 +-
 doc/development/doc_styleguide.md                     | 9 ++++++++-
 doc/development/writing_documentation.md              | 6 ++++--
 doc/user/project/pages/getting_started_part_four.md   | 5 +++--
 doc/user/project/pages/getting_started_part_one.md    | 5 +++--
 doc/user/project/pages/getting_started_part_three.md  | 5 +++--
 doc/user/project/pages/getting_started_part_two.md    | 5 +++--
 7 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/doc/articles/how_to_configure_ldap_gitlab_ce/index.md b/doc/articles/how_to_configure_ldap_gitlab_ce/index.md
index 1702c2184f2..6892905dd94 100644
--- a/doc/articles/how_to_configure_ldap_gitlab_ce/index.md
+++ b/doc/articles/how_to_configure_ldap_gitlab_ce/index.md
@@ -1,6 +1,6 @@
 # How to configure LDAP with GitLab CE
 
-> **Type:** admin guide ||
+> **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** admin guide ||
 > **Level:** intermediary ||
 > **Author:** [Chris Wilson](https://gitlab.com/MrChrisW) ||
 > **Publication date:** 2017/05/03
diff --git a/doc/development/doc_styleguide.md b/doc/development/doc_styleguide.md
index 1e81905c081..5b09f79f143 100644
--- a/doc/development/doc_styleguide.md
+++ b/doc/development/doc_styleguide.md
@@ -198,10 +198,17 @@ You can combine one or more of the following:
   the `.md` document that you're working on is located. Always prepend their
   names with the name of the document that they will be included in. For
   example, if there is a document called `twitter.md`, then a valid image name
-  could be `twitter_login_screen.png`.
+  could be `twitter_login_screen.png`. [**Exception**: images for
+  [articles](writing_documentation.md#technical-articles) should be
+  put in a directory called `img` underneath `/articles/article_title/img/`, therefore,
+  there's no need to prepend the document name to their filenames.]
 - Images should have a specific, non-generic name that will differentiate them.
 - Keep all file names in lower case.
 - Consider using PNG images instead of JPEG.
+- Compress all images with  or similar tool.
+- Compress gifs with  or similar toll.
+- Images should be used (only when necessary) to _illustrate_ the description
+of a process, not to _replace_ it.
 
 Inside the document:
 
diff --git a/doc/development/writing_documentation.md b/doc/development/writing_documentation.md
index 2814c18e0b6..657a826d7ee 100644
--- a/doc/development/writing_documentation.md
+++ b/doc/development/writing_documentation.md
@@ -52,11 +52,13 @@ Every **Technical Article** contains, in the very beginning, a blockquote with t
 - A reference to the **type of article** (user guide, admin guide, tech overview, tutorial)
 - A reference to the **knowledge level** expected from the reader to be able to follow through (beginner, intermediate, advanced)
 - A reference to the **author's name** and **GitLab.com handle**
+- A reference of the **publication date**
 
 ```md
-> **Type:** tutorial ||
+> **Article [Type](../../development/writing_documentation.html#types-of-technical-articles):** tutorial ||
 > **Level:** intermediary ||
-> **Author:** [Name Surname](https://gitlab.com/username)
+> **Author:** [Name Surname](https://gitlab.com/username) ||
+> **Publication date:** AAAA/MM/DD
 ```
 
 #### Technical Articles - Writing Method
diff --git a/doc/user/project/pages/getting_started_part_four.md b/doc/user/project/pages/getting_started_part_four.md
index 50767095aa0..bd0cb437924 100644
--- a/doc/user/project/pages/getting_started_part_four.md
+++ b/doc/user/project/pages/getting_started_part_four.md
@@ -1,8 +1,9 @@
 # GitLab Pages from A to Z: Part 4
 
-> **Type**: user guide || 
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide || 
 > **Level**: intermediate || 
-> **Author**: [Marcia Ramos](https://gitlab.com/marcia)
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
 
 - [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
 - [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md
index 8a8a73a156c..2f104c7becc 100644
--- a/doc/user/project/pages/getting_started_part_one.md
+++ b/doc/user/project/pages/getting_started_part_one.md
@@ -1,8 +1,9 @@
 # GitLab Pages from A to Z: Part 1
 
-> **Type**: user guide || 
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide || 
 > **Level**: beginner || 
-> **Author**: [Marcia Ramos](https://gitlab.com/marcia)
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
 
 - **Part 1: Static sites and GitLab Pages domains**
 - [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
diff --git a/doc/user/project/pages/getting_started_part_three.md b/doc/user/project/pages/getting_started_part_three.md
index 80f16e43e20..53fd1786cfa 100644
--- a/doc/user/project/pages/getting_started_part_three.md
+++ b/doc/user/project/pages/getting_started_part_three.md
@@ -1,8 +1,9 @@
 # GitLab Pages from A to Z: Part 3
 
-> **Type**: user guide || 
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide || 
 > **Level**: beginner || 
-> **Author**: [Marcia Ramos](https://gitlab.com/marcia)
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
 
 - [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
 - [Part 2: Quick start guide - Setting up GitLab Pages](getting_started_part_two.md)
diff --git a/doc/user/project/pages/getting_started_part_two.md b/doc/user/project/pages/getting_started_part_two.md
index 578ad13f5df..c91e2d8c261 100644
--- a/doc/user/project/pages/getting_started_part_two.md
+++ b/doc/user/project/pages/getting_started_part_two.md
@@ -1,8 +1,9 @@
 # GitLab Pages from A to Z: Part 2
 
-> **Type**: user guide || 
+> **Article [Type](../../../development/writing_documentation.html#types-of-technical-articles)**: user guide || 
 > **Level**: beginner || 
-> **Author**: [Marcia Ramos](https://gitlab.com/marcia)
+> **Author**: [Marcia Ramos](https://gitlab.com/marcia) ||
+> **Publication date:** 2017/02/22
 
 - [Part 1: Static sites and GitLab Pages domains](getting_started_part_one.md)
 - **Part 2: Quick start guide - Setting up GitLab Pages**
-- 
cgit v1.2.1


From 383883382bac97477eb8448bef3ffac15d7ceacf Mon Sep 17 00:00:00 2001
From: "Z.J. van de Weg" 
Date: Mon, 8 May 2017 19:15:43 +0200
Subject: Prevent NULL values on ci_variables columns

To be more specific; key, and project_id. If either of these is
NULL its wrong, because:

1. storing a key value pair without key is just plain wrong
2. all variables should belong to a project

Non of these cases existed on the staging database.
---
 ...20170508153950_add_not_null_contraints_to_ci_variables.rb | 12 ++++++++++++
 1 file changed, 12 insertions(+)
 create mode 100644 db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb

diff --git a/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb b/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
new file mode 100644
index 00000000000..41c687a4f6e
--- /dev/null
+++ b/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
@@ -0,0 +1,12 @@
+class AddNotNullContraintsToCiVariables < ActiveRecord::Migration
+  DOWNTIME = false
+
+  def up
+    change_column(:ci_variables, :key, :string, null: false)
+    change_column(:ci_variables, :project_id, :integer, null: false)
+  end
+
+  def down
+    # no op
+  end
+end
-- 
cgit v1.2.1


From 2ee35a34edb9e617cc5bf8e5ceaceeeae12a61f0 Mon Sep 17 00:00:00 2001
From: Yorick Peterse 
Date: Thu, 11 May 2017 13:56:39 +0200
Subject: Update DB requirements in the documentation

This makes it more obvious that we greatly prefer PostgreSQL over
MySQL/MariaDB and that all users are recommended to use PostgreSQL
instead. This also removes the paragraph mentioning the size per user
row, as this is completely inaccurate and doesn't really help users with
anticipating the database size. Instead we now simply recommend users to
have at least 5-10 GB of storage at minimum.

[ci skip]
---
 doc/install/requirements.md | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 35586091f74..148796b73d4 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -122,15 +122,22 @@ To change the Unicorn workers when you have the Omnibus package please see [the
 
 We currently support the following databases:
 
-- PostgreSQL (recommended)
+- PostgreSQL
 - MySQL/MariaDB
 
-If you want to run the database separately, expect a size of about 1 MB per user.
+We _highly_ recommend the use of PostgreSQL instead of MySQL/MariaDB as not all
+features of GitLab may work with MySQL/MariaDB. Existing users using GitLab with
+MySQL/MariaDB are advised to migrate to PostgreSQL instead.
+
+The server running the database should have _at least_ 5-10 GB of storage
+available, though the exact requirements depend on the size of the GitLab
+installation (e.g. the number of users, projects, etc).
 
 ### PostgreSQL Requirements
 
-As of GitLab 9.0, PostgreSQL 9.6 is recommended. Lower versions of PostgreSQL
-may work but primary testing and developement takes place using PostgreSQL 9.6.
+As of GitLab 9.0, PostgreSQL 9.2 or newer is required, and earlier versions are
+not supported. We highly recommend users to use at least PostgreSQL 9.6 as this
+is the PostgreSQL version used for development and testing.
 
 Users using PostgreSQL must ensure the `pg_trgm` extension is loaded into every
 GitLab database. This extension can be enabled (using a PostgreSQL super user)
@@ -165,4 +172,4 @@ about it, check the [Prometheus documentation](../administration/monitoring/prom
 
 We support the current and the previous major release of Firefox, Chrome/Chromium, Safari and Microsoft browsers (Microsoft Edge and Internet Explorer 11).
 
-Each time a new browser version is released, we begin supporting that version and stop supporting the third most recent version.
\ No newline at end of file
+Each time a new browser version is released, we begin supporting that version and stop supporting the third most recent version.
-- 
cgit v1.2.1


From 9139e25df2794ff7eb1d48103391e271f7b0edfa Mon Sep 17 00:00:00 2001
From: Oche Ejembi 
Date: Thu, 11 May 2017 12:06:06 +0000
Subject: fixed small typo - piplnie should be pipeline

---
 doc/user/project/new_ci_build_permissions_model.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md
index f846736028f..051a28efea6 100644
--- a/doc/user/project/new_ci_build_permissions_model.md
+++ b/doc/user/project/new_ci_build_permissions_model.md
@@ -89,7 +89,7 @@ to steal the tokens of other jobs.
 
 ## Pipeline triggers
 
-Since 9.0 [pipelnie triggers][triggers] do support the new permission model.
+Since 9.0 [pipeline triggers][triggers] do support the new permission model.
 The new triggers do impersonate their associated user including their access
 to projects and their project permissions. To migrate trigger to use new permisison
 model use **Take ownership**.
-- 
cgit v1.2.1


From 3eb8435fec3cd7311544a256a3205f31d1dc3a0c Mon Sep 17 00:00:00 2001
From: "Z.J. van de Weg" 
Date: Mon, 8 May 2017 21:52:27 +0200
Subject: Add a foreign key to ci_variables to projects

Variables shouldn't exist without a project, so a foreign key was added
with CASCADE'ing effects.
---
 ...3950_add_not_null_contraints_to_ci_variables.rb | 12 +++++++++++
 ...170508190732_add_foreign_key_to_ci_variables.rb | 25 ++++++++++++++++++++++
 ...3950_add_not_null_contraints_to_ci_variables.rb | 12 -----------
 db/schema.rb                                       |  7 +++---
 4 files changed, 41 insertions(+), 15 deletions(-)
 create mode 100644 db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
 create mode 100644 db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
 delete mode 100644 db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb

diff --git a/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb b/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
new file mode 100644
index 00000000000..41c687a4f6e
--- /dev/null
+++ b/db/migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
@@ -0,0 +1,12 @@
+class AddNotNullContraintsToCiVariables < ActiveRecord::Migration
+  DOWNTIME = false
+
+  def up
+    change_column(:ci_variables, :key, :string, null: false)
+    change_column(:ci_variables, :project_id, :integer, null: false)
+  end
+
+  def down
+    # no op
+  end
+end
diff --git a/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
new file mode 100644
index 00000000000..13837324787
--- /dev/null
+++ b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
@@ -0,0 +1,25 @@
+class AddForeignKeyToCiVariables < ActiveRecord::Migration
+  include Gitlab::Database::MigrationHelpers
+
+  DOWNTIME = false
+
+  disable_ddl_transaction!
+
+  def up
+    execute <<~SQL
+      DELETE FROM ci_variables
+      WHERE NOT EXISTS (
+        SELECT true
+        FROM projects
+        WHERE projects.id = ci_variables.project_id
+      )
+      OR ci_variables.project_id IS NULL
+    SQL
+
+    add_concurrent_foreign_key(:ci_variables, :projects, column: :project_id)
+  end
+
+  def down
+    remove_foreign_key(:ci_variables, column: :project_id)
+  end
+end
diff --git a/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb b/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
deleted file mode 100644
index 41c687a4f6e..00000000000
--- a/db/post_migrate/20170508153950_add_not_null_contraints_to_ci_variables.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-class AddNotNullContraintsToCiVariables < ActiveRecord::Migration
-  DOWNTIME = false
-
-  def up
-    change_column(:ci_variables, :key, :string, null: false)
-    change_column(:ci_variables, :project_id, :integer, null: false)
-  end
-
-  def down
-    # no op
-  end
-end
diff --git a/db/schema.rb b/db/schema.rb
index 6eaab4832e9..60077ffd812 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema.define(version: 20170508170547) do
+ActiveRecord::Schema.define(version: 20170508190732) do
 
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
@@ -347,12 +347,12 @@ ActiveRecord::Schema.define(version: 20170508170547) do
   add_index "ci_triggers", ["project_id"], name: "index_ci_triggers_on_project_id", using: :btree
 
   create_table "ci_variables", force: :cascade do |t|
-    t.string "key"
+    t.string "key", null: false
     t.text "value"
     t.text "encrypted_value"
     t.string "encrypted_value_salt"
     t.string "encrypted_value_iv"
-    t.integer "project_id"
+    t.integer "project_id", null: false
   end
 
   add_index "ci_variables", ["project_id"], name: "index_ci_variables_on_project_id", using: :btree
@@ -1417,6 +1417,7 @@ ActiveRecord::Schema.define(version: 20170508170547) do
   add_foreign_key "ci_pipelines", "ci_pipelines", column: "auto_canceled_by_id", name: "fk_262d4c2d19", on_delete: :nullify
   add_foreign_key "ci_trigger_requests", "ci_triggers", column: "trigger_id", name: "fk_b8ec8b7245", on_delete: :cascade
   add_foreign_key "ci_triggers", "users", column: "owner_id", name: "fk_e8e10d1964", on_delete: :cascade
+  add_foreign_key "ci_variables", "projects", name: "fk_ada5eb64b3", on_delete: :cascade
   add_foreign_key "container_repositories", "projects"
   add_foreign_key "issue_assignees", "issues", on_delete: :cascade
   add_foreign_key "issue_assignees", "users", on_delete: :cascade
-- 
cgit v1.2.1


From d922f54548ee64ff8cffb7234f574333d4edd2b7 Mon Sep 17 00:00:00 2001
From: "Z.J. van de Weg" 
Date: Mon, 8 May 2017 21:56:37 +0200
Subject: Remove rails dependent: :destroy statement

Enforced by the database, and no callbacks need to be called.

Combined with 7b9b2c6099 and 294a8b8a6d this resolves
gitlab-org/gitlab-ce#31799
---
 app/models/project.rb                                        | 2 +-
 changelogs/unreleased/zj-clean-up-ci-variables-table.yml     | 4 ++++
 db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb | 1 -
 spec/factories/ci/variables.rb                               | 2 ++
 spec/models/ci/variable_spec.rb                              | 2 +-
 5 files changed, 8 insertions(+), 3 deletions(-)
 create mode 100644 changelogs/unreleased/zj-clean-up-ci-variables-table.yml

diff --git a/app/models/project.rb b/app/models/project.rb
index be4960aef8a..65745fd6d37 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -175,7 +175,7 @@ class Project < ActiveRecord::Base
   has_many :builds, class_name: 'Ci::Build' # the builds are created from the commit_statuses
   has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject'
   has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner'
-  has_many :variables, dependent: :destroy, class_name: 'Ci::Variable'
+  has_many :variables, class_name: 'Ci::Variable'
   has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger'
   has_many :environments, dependent: :destroy
   has_many :deployments, dependent: :destroy
diff --git a/changelogs/unreleased/zj-clean-up-ci-variables-table.yml b/changelogs/unreleased/zj-clean-up-ci-variables-table.yml
new file mode 100644
index 00000000000..ea2db40d590
--- /dev/null
+++ b/changelogs/unreleased/zj-clean-up-ci-variables-table.yml
@@ -0,0 +1,4 @@
+---
+title: Cleanup ci_variables schema and table
+merge_request:
+author:
diff --git a/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
index 13837324787..20ecaa2c36c 100644
--- a/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
+++ b/db/migrate/20170508190732_add_foreign_key_to_ci_variables.rb
@@ -13,7 +13,6 @@ class AddForeignKeyToCiVariables < ActiveRecord::Migration
         FROM projects
         WHERE projects.id = ci_variables.project_id
       )
-      OR ci_variables.project_id IS NULL
     SQL
 
     add_concurrent_foreign_key(:ci_variables, :projects, column: :project_id)
diff --git a/spec/factories/ci/variables.rb b/spec/factories/ci/variables.rb
index 6653f0bb5c3..c5fba597c1c 100644
--- a/spec/factories/ci/variables.rb
+++ b/spec/factories/ci/variables.rb
@@ -2,5 +2,7 @@ FactoryGirl.define do
   factory :ci_variable, class: Ci::Variable do
     sequence(:key) { |n| "VARIABLE_#{n}" }
     value 'VARIABLE_VALUE'
+
+    project factory: :empty_project
   end
 end
diff --git a/spec/models/ci/variable_spec.rb b/spec/models/ci/variable_spec.rb
index 048d25869bc..fe8c52d5353 100644
--- a/spec/models/ci/variable_spec.rb
+++ b/spec/models/ci/variable_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe Ci::Variable, models: true do
-  subject { Ci::Variable.new }
+  subject { build(:ci_variable) }
 
   let(:secret_value) { 'secret' }
 
-- 
cgit v1.2.1


From 6bcf316ed701620fa5ba654f2184a261650fd7b9 Mon Sep 17 00:00:00 2001
From: Bryce Johnson 
Date: Tue, 9 May 2017 11:35:22 -0400
Subject: Pass docsUrl to pipeline schedules callout component.

---
 .../components/pipeline_schedules_callout.js              | 12 ++++++++----
 .../pipeline_schedules/pipeline_schedules_index_bundle.js | 15 +++++++++------
 app/views/projects/pipeline_schedules/index.html.haml     |  2 +-
 .../unreleased/pipeline-schedules-callout-docs-url.yml    |  4 ++++
 .../pipeline_schedules/pipeline_schedule_callout_spec.js  | 15 +++++++++++++++
 5 files changed, 37 insertions(+), 11 deletions(-)
 create mode 100644 changelogs/unreleased/pipeline-schedules-callout-docs-url.yml

diff --git a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
index 27ffe6ea304..5109b110b31 100644
--- a/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
+++ b/app/assets/javascripts/pipeline_schedules/components/pipeline_schedules_callout.js
@@ -4,8 +4,10 @@ import illustrationSvg from '../icons/intro_illustration.svg';
 const cookieKey = 'pipeline_schedules_callout_dismissed';
 
 export default {
+  name: 'PipelineSchedulesCallout',
   data() {
     return {
+      docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
       illustrationSvg,
       calloutDismissed: Cookies.get(cookieKey) === 'true',
     };
@@ -28,13 +30,15 @@ export default {
         

Scheduling Pipelines

-

- The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. +

+ The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user.

Learn more in the - - pipeline schedules documentation. + pipeline schedules documentation.

diff --git a/app/assets/javascripts/pipeline_schedules/pipeline_schedules_index_bundle.js b/app/assets/javascripts/pipeline_schedules/pipeline_schedules_index_bundle.js index e36dc5db2ab..6584549ad06 100644 --- a/app/assets/javascripts/pipeline_schedules/pipeline_schedules_index_bundle.js +++ b/app/assets/javascripts/pipeline_schedules/pipeline_schedules_index_bundle.js @@ -1,9 +1,12 @@ import Vue from 'vue'; import PipelineSchedulesCallout from './components/pipeline_schedules_callout'; -const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout); - -document.addEventListener('DOMContentLoaded', () => { - new PipelineSchedulesCalloutComponent() - .$mount('#scheduling-pipelines-callout'); -}); +document.addEventListener('DOMContentLoaded', () => new Vue({ + el: '#pipeline-schedules-callout', + components: { + 'pipeline-schedules-callout': PipelineSchedulesCallout, + }, + render(createElement) { + return createElement('pipeline-schedules-callout'); + }, +})); diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml index dd35c3055f2..a597d745e33 100644 --- a/app/views/projects/pipeline_schedules/index.html.haml +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -6,7 +6,7 @@ = render "projects/pipelines/head" %div{ class: container_class } - #scheduling-pipelines-callout + #pipeline-schedules-callout{ data: { docs_url: help_page_path('ci/pipeline_schedules') } } .top-area - schedule_path_proc = ->(scope) { pipeline_schedules_path(@project, scope: scope) } = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope diff --git a/changelogs/unreleased/pipeline-schedules-callout-docs-url.yml b/changelogs/unreleased/pipeline-schedules-callout-docs-url.yml new file mode 100644 index 00000000000..b21bb162380 --- /dev/null +++ b/changelogs/unreleased/pipeline-schedules-callout-docs-url.yml @@ -0,0 +1,4 @@ +--- +title: Pass docsUrl to pipeline schedules callout component. +merge_request: !1126 +author: diff --git a/spec/javascripts/pipeline_schedules/pipeline_schedule_callout_spec.js b/spec/javascripts/pipeline_schedules/pipeline_schedule_callout_spec.js index 1d05f37cb36..6120d224ac0 100644 --- a/spec/javascripts/pipeline_schedules/pipeline_schedule_callout_spec.js +++ b/spec/javascripts/pipeline_schedules/pipeline_schedule_callout_spec.js @@ -4,8 +4,15 @@ import PipelineSchedulesCallout from '~/pipeline_schedules/components/pipeline_s const PipelineSchedulesCalloutComponent = Vue.extend(PipelineSchedulesCallout); const cookieKey = 'pipeline_schedules_callout_dismissed'; +const docsUrl = 'help/ci/scheduled_pipelines'; describe('Pipeline Schedule Callout', () => { + beforeEach(() => { + setFixtures(` +
+ `); + }); + describe('independent of cookies', () => { beforeEach(() => { this.calloutComponent = new PipelineSchedulesCalloutComponent().$mount(); @@ -18,6 +25,10 @@ describe('Pipeline Schedule Callout', () => { it('correctly sets illustrationSvg', () => { expect(this.calloutComponent.illustrationSvg).toContain(' { + expect(this.calloutComponent.docsUrl).toContain(docsUrl); + }); }); describe(`when ${cookieKey} cookie is set`, () => { @@ -61,6 +72,10 @@ describe('Pipeline Schedule Callout', () => { expect(this.calloutComponent.$el.outerHTML).toContain('runs pipelines in the future'); }); + it('renders the documentation url', () => { + expect(this.calloutComponent.$el.outerHTML).toContain(docsUrl); + }); + it('updates calloutDismissed when close button is clicked', (done) => { this.calloutComponent.$el.querySelector('#dismiss-callout-btn').click(); -- cgit v1.2.1 From 49fb31db416cb73899cf5211de8f5817c00adc0b Mon Sep 17 00:00:00 2001 From: Bob Van Landuyt Date: Thu, 11 May 2017 16:25:15 +0200 Subject: Add a new column before creating rename triggers MySQL doesn't allow us to create a trigger for a column that doesn't exist yet. Failing with this error: ``` Mysql2::Error: Unknown column 'build_events' in 'NEW': CREATE TRIGGER trigger_6a80c097c862_insert BEFORE INSERT ON `services` FOR EACH ROW SET NEW.`build_events` = NEW.`job_events` ``` Creating the new column before creating the trigger avoids this. --- lib/gitlab/database/migration_helpers.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/gitlab/database/migration_helpers.rb b/lib/gitlab/database/migration_helpers.rb index 298b1a1f4e6..f04a907004c 100644 --- a/lib/gitlab/database/migration_helpers.rb +++ b/lib/gitlab/database/migration_helpers.rb @@ -278,6 +278,16 @@ module Gitlab raise 'rename_column_concurrently can not be run inside a transaction' end + old_col = column_for(table, old) + new_type = type || old_col.type + + add_column(table, new, new_type, + limit: old_col.limit, + default: old_col.default, + null: old_col.null, + precision: old_col.precision, + scale: old_col.scale) + trigger_name = rename_trigger_name(table, old, new) quoted_table = quote_table_name(table) quoted_old = quote_column_name(old) @@ -291,16 +301,6 @@ module Gitlab quoted_old, quoted_new) end - old_col = column_for(table, old) - new_type = type || old_col.type - - add_column(table, new, new_type, - limit: old_col.limit, - default: old_col.default, - null: old_col.null, - precision: old_col.precision, - scale: old_col.scale) - update_column_in_batches(table, new, Arel::Table.new(table)[old]) copy_indexes(table, old, new) -- cgit v1.2.1 From 2f75bfad481496d1ceb4732a289cbcfe6fb76a36 Mon Sep 17 00:00:00 2001 From: Annabel Dunstone Gray Date: Thu, 11 May 2017 11:16:42 -0500 Subject: Fix overlapping lines in SVG --- app/views/shared/empty_states/icons/_pipelines_empty.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/empty_states/icons/_pipelines_empty.svg b/app/views/shared/empty_states/icons/_pipelines_empty.svg index 8119d5bebe0..7c672538097 100644 --- a/app/views/shared/empty_states/icons/_pipelines_empty.svg +++ b/app/views/shared/empty_states/icons/_pipelines_empty.svg @@ -1 +1 @@ - \ No newline at end of file + -- cgit v1.2.1 From ecbb6e940c71e29d4a7043a42d1baa991cac0958 Mon Sep 17 00:00:00 2001 From: Alfredo Sumaran Date: Thu, 11 May 2017 12:32:47 -0500 Subject: Update copy on Create merge request dropdown --- app/views/projects/issues/_new_branch.html.haml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/projects/issues/_new_branch.html.haml b/app/views/projects/issues/_new_branch.html.haml index 6bc6bf76e18..dba092c8844 100644 --- a/app/views/projects/issues/_new_branch.html.haml +++ b/app/views/projects/issues/_new_branch.html.haml @@ -17,7 +17,7 @@ .description %strong Create a merge request %span - Creates a branch named after this issue and a merge request. The source branch is '#{@project.default_branch}' by default. + Creates a merge request named after this issue, with source branch created from '#{@project.default_branch}'. %li.divider.droplab-item-ignore %li{ role: 'button', data: { value: 'create-branch', 'text' => 'Create a branch' } } .menu-item @@ -26,4 +26,4 @@ .description %strong Create a branch %span - Creates a branch named after this issue. The source branch is '#{@project.default_branch}' by default. + Creates a branch named after this issue, from '#{@project.default_branch}'. -- cgit v1.2.1