diff options
30 files changed, 325 insertions, 80 deletions
diff --git a/.gitlab/issue_templates/Security developer workflow.md b/.gitlab/issue_templates/Security developer workflow.md index 1b6a1f87216..039157bf845 100644 --- a/.gitlab/issue_templates/Security developer workflow.md +++ b/.gitlab/issue_templates/Security developer workflow.md @@ -9,10 +9,11 @@ Set the title to: `Description of the original issue` ## Prior to starting the security release work - [ ] Read the [security process for developers] if you are not familiar with it. -- [ ] Link this issue in the Security Release issue on GitLab.com. You can find this issue in the topic of the `#releases` channel. -- [ ] Add a link to the confidential `gitlab-org/gitlab` issue describing the vulnerability next to **Original issue** in the [links table](#links). -- [ ] Add a link to the confidential `gitlab-org/gitlab` Security release issue next to **Security release issue** in the [links table](#links). +- [ ] Mark this [issue as related] to the Security Release tracking issue. You can find it on the topic of the `#releases` Slack channel. - [ ] Run `scripts/security-harness` in your local repository to prevent accidentally pushing to any remote besides `gitlab.com/gitlab-org/security`. +- Fill out the [Links section](#links): + - [ ] Next to **Issue on GitLab**, add a link to the `gitlab-org/gitlab` issue that describes the security vulnerability. + - [ ] Next to **Security Release tracking issue**, add a link to the security release issue that will include this security issue. ## Development @@ -29,7 +30,8 @@ After your merge request has being approved according to our [approval guideline * You can use the script `bin/secpick` instead of the following steps, to help you cherry-picking. See the [secpick documentation] - [ ] Create each MR targeting the stable branch `X-Y-stable`, using the [Security Release merge request template]. * Every merge request will have its own set of TODOs, so make sure to complete those. -- [ ] Make sure all MRs are linked in the [Links section](#links) +- [ ] On the "Related merge requests" section, ensure all MRs are linked to this issue. + * This section should only list the merge requests created for this issue: One targeting `master` and the 3 backports. ## Documentation and final details @@ -46,8 +48,8 @@ After your merge request has being approved according to our [approval guideline | Description | Link | | -------- | -------- | -| Original issue | #TODO | -| Security release issue | #TODO | +| Issue on [GitLab](https://gitlab.com/gitlab-org/gitlab/issues) | #TODO | +| Security Release tracking issue | #TODO | | `master` MR | !TODO | | `Backport X.Y` MR | !TODO | | `Backport X.Y` MR | !TODO | @@ -68,5 +70,6 @@ After your merge request has being approved according to our [approval guideline [security Release merge request template]: https://gitlab.com/gitlab-org/security/gitlab/blob/master/.gitlab/merge_request_templates/Security%20Release.md [code review process]: https://docs.gitlab.com/ee/development/code_review.html [approval guidelines]: https://docs.gitlab.com/ee/development/code_review.html#approval-guidelines +[issue as related]: https://docs.gitlab.com/ee/user/project/issues/related_issues.html#adding-a-related-issue /label ~security @@ -2,7 +2,7 @@ source 'https://rubygems.org' gem 'rails', '6.0.2' -gem 'bootsnap', '~> 1.4' +gem 'bootsnap', '~> 1.4.6' # Improves copy-on-write performance for MRI gem 'nakayoshi_fork', '~> 0.0.4' diff --git a/Gemfile.lock b/Gemfile.lock index bbf1148281b..5fe50053428 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -123,7 +123,7 @@ GEM binding_ninja (0.2.3) binding_of_caller (0.8.0) debug_inspector (>= 0.0.1) - bootsnap (1.4.5) + bootsnap (1.4.6) msgpack (~> 1.0) bootstrap_form (4.2.0) actionpack (>= 5.0) @@ -1171,7 +1171,7 @@ DEPENDENCIES benchmark-memory (~> 0.1) better_errors (~> 2.5.0) binding_of_caller (~> 0.8.0) - bootsnap (~> 1.4) + bootsnap (~> 1.4.6) bootstrap_form (~> 4.2.0) brakeman (~> 4.2) browser (~> 2.5) diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue index 574b63cf8a6..69fb2bb4524 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_title.vue @@ -1,5 +1,10 @@ <script> +import { GlLoadingIcon } from '@gitlab/ui'; + export default { + components: { + GlLoadingIcon, + }, props: { canEdit: { type: Boolean, @@ -13,7 +18,7 @@ export default { <div class="title hide-collapsed append-bottom-10"> {{ __('Labels') }} <template v-if="canEdit"> - <i aria-hidden="true" class="fa fa-spinner fa-spin block-loading" data-hidden="true"> </i> + <gl-loading-icon inline class="align-text-top block-loading" /> <button type="button" class="edit-link btn btn-blank float-right js-sidebar-dropdown-toggle" diff --git a/app/models/releases/link.rb b/app/models/releases/link.rb index 58c2b98e524..65be2a22958 100644 --- a/app/models/releases/link.rb +++ b/app/models/releases/link.rb @@ -6,8 +6,11 @@ module Releases belongs_to :release + FILEPATH_REGEX = /\A\/([\-\.\w]+\/?)*[\da-zA-Z]+\z/.freeze + validates :url, presence: true, addressable_url: { schemes: %w(http https ftp) }, uniqueness: { scope: :release } validates :name, presence: true, uniqueness: { scope: :release } + validates :filepath, uniqueness: { scope: :release }, format: { with: FILEPATH_REGEX }, allow_blank: true, length: { maximum: 128 } scope :sorted, -> { order(created_at: :desc) } diff --git a/app/policies/project_snippet_policy.rb b/app/policies/project_snippet_policy.rb index a38d9154102..869f4716298 100644 --- a/app/policies/project_snippet_policy.rb +++ b/app/policies/project_snippet_policy.rb @@ -31,7 +31,7 @@ class ProjectSnippetPolicy < BasePolicy ~can?(:read_all_resources)) end.prevent :read_snippet - rule { internal_snippet & ~is_author & ~admin }.policy do + rule { internal_snippet & ~is_author & ~admin & ~project.maintainer }.policy do prevent :update_snippet prevent :admin_snippet end @@ -42,7 +42,7 @@ class ProjectSnippetPolicy < BasePolicy prevent :admin_snippet end - rule { is_author | admin }.policy do + rule { is_author | admin | project.maintainer }.policy do enable :read_snippet enable :update_snippet enable :admin_snippet diff --git a/app/views/projects/runners/_runner.html.haml b/app/views/projects/runners/_runner.html.haml index 548977d6a80..55c702b967f 100644 --- a/app/views/projects/runners/_runner.html.haml +++ b/app/views/projects/runners/_runner.html.haml @@ -3,7 +3,7 @@ = runner_status_icon(runner) - if @project_runners.include?(runner) - = link_to runner.short_sha, project_runner_path(@project, runner), class: 'commit-sha' + = link_to runner.short_sha.concat("..."), project_runner_path(@project, runner), class: 'commit-sha has-tooltip', title: _("Partial token for reference only") - if runner.locked? = icon('lock', class: 'has-tooltip', title: _('Locked to current projects')) diff --git a/changelogs/unreleased/27300-enable-a-direct-link-to-a-release-and-release-assets-2.yml b/changelogs/unreleased/27300-enable-a-direct-link-to-a-release-and-release-assets-2.yml new file mode 100644 index 00000000000..3ea5419e3f7 --- /dev/null +++ b/changelogs/unreleased/27300-enable-a-direct-link-to-a-release-and-release-assets-2.yml @@ -0,0 +1,5 @@ +--- +title: Add filepath to ReleaseLink +merge_request: 25512 +author: +type: added diff --git a/changelogs/unreleased/40585-token-disclaimer.yml b/changelogs/unreleased/40585-token-disclaimer.yml new file mode 100644 index 00000000000..ab0a5b4e148 --- /dev/null +++ b/changelogs/unreleased/40585-token-disclaimer.yml @@ -0,0 +1,5 @@ +--- +title: Improvement in token reference +merge_request: +author: +type: other diff --git a/changelogs/unreleased/fix-deployments-pagination.yml b/changelogs/unreleased/fix-deployments-pagination.yml new file mode 100644 index 00000000000..5fe5e95f077 --- /dev/null +++ b/changelogs/unreleased/fix-deployments-pagination.yml @@ -0,0 +1,5 @@ +--- +title: Add API pagination for deployed merge requests +merge_request: 25733 +author: +type: performance diff --git a/changelogs/unreleased/fj-207803-fix-project-snippet-policy-bug.yml b/changelogs/unreleased/fj-207803-fix-project-snippet-policy-bug.yml new file mode 100644 index 00000000000..97659b6019a --- /dev/null +++ b/changelogs/unreleased/fj-207803-fix-project-snippet-policy-bug.yml @@ -0,0 +1,5 @@ +--- +title: Fix bug deleting internal project snippets by project maintainer +merge_request: 25792 +author: +type: fixed diff --git a/changelogs/unreleased/rk4bir-master-patch-97031.yml b/changelogs/unreleased/rk4bir-master-patch-97031.yml new file mode 100644 index 00000000000..7271f9ab92b --- /dev/null +++ b/changelogs/unreleased/rk4bir-master-patch-97031.yml @@ -0,0 +1,5 @@ +--- +title: Migrated the sidebar label select dropdown title component spinner to utilize GlLoadingIcon +merge_request: 24914 +author: Raihan Kabir +type: changed diff --git a/changelogs/unreleased/sh-cleaup-prom-background-migrations.yml b/changelogs/unreleased/sh-cleaup-prom-background-migrations.yml new file mode 100644 index 00000000000..f74d6560eb0 --- /dev/null +++ b/changelogs/unreleased/sh-cleaup-prom-background-migrations.yml @@ -0,0 +1,5 @@ +--- +title: Clean stale background migration jobs +merge_request: 25707 +author: +type: fixed diff --git a/changelogs/unreleased/sh-upgrade-bootsnap-1-4-6.yml b/changelogs/unreleased/sh-upgrade-bootsnap-1-4-6.yml new file mode 100644 index 00000000000..a33c056106f --- /dev/null +++ b/changelogs/unreleased/sh-upgrade-bootsnap-1-4-6.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade to Bootsnap 1.4.6 +merge_request: 25844 +author: +type: performance diff --git a/changelogs/unreleased/sy-alert-embeds.yml b/changelogs/unreleased/sy-alert-embeds.yml new file mode 100644 index 00000000000..f18b93212dd --- /dev/null +++ b/changelogs/unreleased/sy-alert-embeds.yml @@ -0,0 +1,5 @@ +--- +title: Add support for alert-based metric embeds in GFM +merge_request: 25075 +author: +type: added diff --git a/db/migrate/20200219105209_add_filepath_to_release_links.rb b/db/migrate/20200219105209_add_filepath_to_release_links.rb new file mode 100644 index 00000000000..bcc204c22e8 --- /dev/null +++ b/db/migrate/20200219105209_add_filepath_to_release_links.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true +class AddFilepathToReleaseLinks < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :release_links, :filepath, :string, limit: 128 + end +end diff --git a/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb b/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb new file mode 100644 index 00000000000..13b041d8f95 --- /dev/null +++ b/db/migrate/20200221144534_drop_activate_prometheus_services_background_jobs.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +class DropActivatePrometheusServicesBackgroundJobs < ActiveRecord::Migration[6.0] + DOWNTIME = false + DROPPED_JOB_CLASS = 'ActivatePrometheusServicesForSharedClusterApplications'.freeze + QUEUE = 'background_migration'.freeze + + def up + sidekiq_queues.each do |queue| + queue.each do |job| + klass, project_id, *should_be_empty = job.args + next unless klass == DROPPED_JOB_CLASS && project_id.is_a?(Integer) && should_be_empty.empty? + + job.delete + end + end + end + + def down + # no-op + end + + def sidekiq_queues + [Sidekiq::ScheduledSet.new, Sidekiq::RetrySet.new, Sidekiq::Queue.new(QUEUE)] + end +end diff --git a/db/schema.rb b/db/schema.rb index 792e5e7b8b5..c3b1172c6dc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2020_02_21_105436) do +ActiveRecord::Schema.define(version: 2020_02_21_144534) do # These are extensions that must be enabled in order to support this database enable_extension "pg_trgm" @@ -3648,6 +3648,7 @@ ActiveRecord::Schema.define(version: 2020_02_21_105436) do t.string "name", null: false t.datetime_with_timezone "created_at", null: false t.datetime_with_timezone "updated_at", null: false + t.string "filepath", limit: 128 t.index ["release_id", "name"], name: "index_release_links_on_release_id_and_name", unique: true t.index ["release_id", "url"], name: "index_release_links_on_release_id_and_url", unique: true end diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb index 487d4e37a56..cb1dca11e87 100644 --- a/lib/api/deployments.rb +++ b/lib/api/deployments.rb @@ -143,6 +143,7 @@ module API success Entities::MergeRequestBasic end params do + use :pagination requires :deployment_id, type: Integer, desc: 'The deployment ID' use :merge_requests_base_params end @@ -153,7 +154,7 @@ module API mr_params = declared_params.merge(deployment_id: params[:deployment_id]) merge_requests = MergeRequestsFinder.new(current_user, mr_params).execute - present merge_requests, { with: Entities::MergeRequestBasic, current_user: current_user } + present paginate(merge_requests), { with: Entities::MergeRequestBasic, current_user: current_user } end end end diff --git a/lib/banzai/filter/inline_metrics_redactor_filter.rb b/lib/banzai/filter/inline_metrics_redactor_filter.rb index 664a897970a..75bd3325bd4 100644 --- a/lib/banzai/filter/inline_metrics_redactor_filter.rb +++ b/lib/banzai/filter/inline_metrics_redactor_filter.rb @@ -143,3 +143,5 @@ module Banzai end end end + +Banzai::Filter::InlineMetricsRedactorFilter.prepend_if_ee('EE::Banzai::Filter::InlineMetricsRedactorFilter') diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 0ed1aea1dce..402c4c5c17c 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -13655,6 +13655,9 @@ msgstr "" msgid "Part of merge request changes" msgstr "" +msgid "Partial token for reference only" +msgstr "" + msgid "Participants" msgstr "" diff --git a/spec/factories/releases/link.rb b/spec/factories/releases/link.rb index 82446dbdb69..001deeb71a0 100644 --- a/spec/factories/releases/link.rb +++ b/spec/factories/releases/link.rb @@ -5,5 +5,6 @@ FactoryBot.define do release sequence(:name) { |n| "release-18.#{n}.dmg" } sequence(:url) { |n| "https://example.com/scrambled-url/app-#{n}.zip" } + sequence(:filepath) { |n| "/binaries/awesome-app-#{n}" } end end diff --git a/spec/features/markdown/metrics_spec.rb b/spec/features/markdown/metrics_spec.rb index 69e93268b57..81c6b6195c6 100644 --- a/spec/features/markdown/metrics_spec.rb +++ b/spec/features/markdown/metrics_spec.rb @@ -2,25 +2,32 @@ require 'spec_helper' -describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidekiq_might_not_need_inline do +describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidekiq_inline do include PrometheusHelpers include GrafanaApiHelpers + include MetricsDashboardUrlHelpers + + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:prometheus_project) } + let_it_be(:environment) { create(:environment, project: project) } - let(:user) { create(:user) } - let(:project) { create(:prometheus_project) } - let(:environment) { create(:environment, project: project) } let(:issue) { create(:issue, project: project, description: description) } let(:description) { "See [metrics dashboard](#{metrics_url}) for info." } - let(:metrics_url) { metrics_project_environment_url(project, environment) } + let(:metrics_url) { urls.metrics_project_environment_url(project, environment) } before do - configure_host + clear_host_from_memoized_variables + + allow(::Gitlab.config.gitlab) + .to receive(:url) + .and_return(urls.root_url.chomp('/')) + project.add_developer(user) sign_in(user) end after do - restore_host + clear_host_from_memoized_variables end context 'internal metrics embeds' do @@ -38,7 +45,7 @@ describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidek end context 'when dashboard params are in included the url' do - let(:metrics_url) { metrics_project_environment_url(project, environment, **chart_params) } + let(:metrics_url) { urls.metrics_project_environment_url(project, environment, **chart_params) } let(:chart_params) do { @@ -81,32 +88,4 @@ describe 'Metrics rendering', :js, :use_clean_rails_memory_store_caching, :sidek def import_common_metrics ::Gitlab::DatabaseImporters::CommonMetrics::Importer.new.execute end - - def configure_host - @original_default_host = default_url_options[:host] - @original_gitlab_url = Gitlab.config.gitlab[:url] - - # Ensure we create a metrics url with the right host. - # Configure host for route helpers in specs (also updates root_url): - default_url_options[:host] = Capybara.server_host - - # Ensure we identify urls with the appropriate host. - # Configure host to include port in app: - Gitlab.config.gitlab[:url] = root_url.chomp('/') - - clear_host_from_memoized_variables - end - - def restore_host - default_url_options[:host] = @original_default_host - Gitlab.config.gitlab[:url] = @original_gitlab_url - - clear_host_from_memoized_variables - end - - def clear_host_from_memoized_variables - [:metrics_regex, :grafana_regex].each do |method_name| - Gitlab::Metrics::Dashboard::Url.clear_memoization(method_name) - end - end end diff --git a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js index 2fffb31acf5..5cbbb99eaef 100644 --- a/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js +++ b/spec/frontend/vue_shared/components/sidebar/labels_select/dropdown_title_spec.js @@ -1,39 +1,38 @@ -import Vue from 'vue'; - -import mountComponent from 'helpers/vue_mount_component_helper'; +import { shallowMount } from '@vue/test-utils'; +import { GlLoadingIcon } from '@gitlab/ui'; import dropdownTitleComponent from '~/vue_shared/components/sidebar/labels_select/dropdown_title.vue'; -const createComponent = (canEdit = true) => { - const Component = Vue.extend(dropdownTitleComponent); - - return mountComponent(Component, { - canEdit, +const createComponent = (canEdit = true) => + shallowMount(dropdownTitleComponent, { + propsData: { + canEdit, + }, }); -}; describe('DropdownTitleComponent', () => { - let vm; + let wrapper; beforeEach(() => { - vm = createComponent(); + wrapper = createComponent(); }); afterEach(() => { - vm.$destroy(); + wrapper.destroy(); + wrapper = null; }); describe('template', () => { it('renders title text', () => { - expect(vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true); - expect(vm.$el.innerText.trim()).toContain('Labels'); + expect(wrapper.vm.$el.classList.contains('title', 'hide-collapsed')).toBe(true); + expect(wrapper.vm.$el.innerText.trim()).toContain('Labels'); }); it('renders spinner icon element', () => { - expect(vm.$el.querySelector('.fa-spinner.fa-spin.block-loading')).not.toBeNull(); + expect(wrapper.find(GlLoadingIcon)).not.toBeNull(); }); it('renders `Edit` button element', () => { - const editBtnEl = vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle'); + const editBtnEl = wrapper.vm.$el.querySelector('button.edit-link.js-sidebar-dropdown-toggle'); expect(editBtnEl).not.toBeNull(); expect(editBtnEl.innerText.trim()).toBe('Edit'); diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 365b23e04e9..1d652f703b8 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -133,6 +133,7 @@ Releases::Link: - id - url - name +- filepath - created_at - updated_at ProjectMember: diff --git a/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb b/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb new file mode 100644 index 00000000000..0e9a3418e29 --- /dev/null +++ b/spec/migrations/drop_activate_prometheus_services_background_jobs_spec.rb @@ -0,0 +1,89 @@ +# frozen_string_literal: true + +require 'spec_helper' +require Rails.root.join('db', 'migrate', '20200221144534_drop_activate_prometheus_services_background_jobs.rb') + +describe DropActivatePrometheusServicesBackgroundJobs, :sidekiq, :redis, :migration, schema: 2020_02_21_144534 do + subject(:migration) { described_class.new } + + describe '#up' do + let(:retry_set) { Sidekiq::RetrySet.new } + let(:scheduled_set) { Sidekiq::ScheduledSet.new } + + context 'there are only affected jobs on the queue' do + let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } } + let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) } + + it 'removes enqueued ActivatePrometheusServicesForSharedClusterApplications background jobs' do + Sidekiq::Testing.disable! do # https://github.com/mperham/sidekiq/wiki/testing#api Sidekiq's API does not have a testing mode + retry_set.schedule(1.hour.from_now, payload) + scheduled_set.schedule(1.hour.from_now, payload) + Sidekiq::Client.push(queue_payload) + + expect { migration.up }.to change { Sidekiq::Queue.new(described_class::QUEUE).size }.from(1).to(0) + expect(retry_set.size).to eq(0) + expect(scheduled_set.size).to eq(0) + end + end + end + + context "there aren't any affected jobs on the queue" do + let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1] } } + let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) } + + it 'skips other enqueued jobs' do + Sidekiq::Testing.disable! do + retry_set.schedule(1.hour.from_now, payload) + scheduled_set.schedule(1.hour.from_now, payload) + Sidekiq::Client.push(queue_payload) + + expect { migration.up }.not_to change { Sidekiq::Queue.new(described_class::QUEUE).size } + expect(retry_set.size).to eq(1) + expect(scheduled_set.size).to eq(1) + end + end + end + + context "there are multiple types of jobs on the queue" do + let(:payload) { { 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1] } } + let(:queue_payload) { payload.merge('queue' => described_class::QUEUE) } + + it 'skips other enqueued jobs' do + Sidekiq::Testing.disable! do + queue = Sidekiq::Queue.new(described_class::QUEUE) + # these jobs will be deleted + retry_set.schedule(1.hour.from_now, payload) + scheduled_set.schedule(1.hour.from_now, payload) + Sidekiq::Client.push(queue_payload) + # this jobs will be skipped + skipped_jobs_args = [['SomeOtherClass', 1], [described_class::DROPPED_JOB_CLASS, 'wrong id type'], [described_class::DROPPED_JOB_CLASS, 1, 'some wired argument']] + skipped_jobs_args.each do |args| + retry_set.schedule(1.hour.from_now, { 'class' => ::BackgroundMigrationWorker, 'args' => args }) + scheduled_set.schedule(1.hour.from_now, { 'class' => ::BackgroundMigrationWorker, 'args' => args }) + Sidekiq::Client.push('queue' => described_class::QUEUE, 'class' => ::BackgroundMigrationWorker, 'args' => args) + end + + migration.up + + expect(retry_set.size).to be 3 + expect(scheduled_set.size).to be 3 + expect(queue.size).to be 3 + expect(queue.map(&:args)).to match_array skipped_jobs_args + expect(retry_set.map(&:args)).to match_array skipped_jobs_args + expect(scheduled_set.map(&:args)).to match_array skipped_jobs_args + end + end + end + + context "other queues" do + it 'does not modify them' do + Sidekiq::Testing.disable! do + Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => ['SomeOtherClass', 1]) + Sidekiq::Client.push('queue' => 'other', 'class' => ::BackgroundMigrationWorker, 'args' => [described_class::DROPPED_JOB_CLASS, 1]) + + expect { migration.up }.not_to change { Sidekiq::Queue.new('other').size } + end + end + end + end +end diff --git a/spec/models/releases/link_spec.rb b/spec/models/releases/link_spec.rb index 4dd26c976cc..7533d1e6e5c 100644 --- a/spec/models/releases/link_spec.rb +++ b/spec/models/releases/link_spec.rb @@ -13,6 +13,7 @@ describe Releases::Link do describe 'validation' do it { is_expected.to validate_presence_of(:url) } it { is_expected.to validate_presence_of(:name) } + it { is_expected.to validate_length_of(:filepath).is_at_most(128) } context 'when url is invalid' do let(:link) { build(:release_link, url: 'hoge') } @@ -43,6 +44,16 @@ describe Releases::Link do end end + context 'when duplicate filepath is added to a release' do + let!(:link) { create(:release_link, filepath: '/binaries/gitlab-runner-linux-amd64', release: release) } + + it 'raises an error' do + expect do + create(:release_link, filepath: '/binaries/gitlab-runner-linux-amd64', release: release) + end.to raise_error(ActiveRecord::RecordInvalid) + end + end + describe '.sorted' do subject { described_class.sorted } @@ -101,4 +112,38 @@ describe Releases::Link do end end end + + describe 'FILEPATH_REGEX with table' do + using RSpec::Parameterized::TableSyntax + + let(:link) { build(:release_link)} + + where(:reason, :filepath, :result) do + 'cannot contain `//`' | '/https//www.example.com' | be_invalid + 'cannot start with `//`' | '//www.example.com' | be_invalid + 'cannot contain a `?`' | '/example.com/?stuff=true' | be_invalid + 'cannot contain a `:`' | '/example:5000' | be_invalid + 'cannot end in a `-`' | '/binaries/awesome-app.dmg-' | be_invalid + 'cannot end in a `.`' | '/binaries/awesome-app.dmg.' | be_invalid + 'cannot end in a `_`' | '/binaries/awesome-app.dmg_' | be_invalid + 'cannot start with a `.`' | '.binaries/awesome-app.dmg' | be_invalid + 'cannot start with a `-`' | '-binaries/awesome-app.dmg' | be_invalid + 'cannot start with a `_`' | '_binaries/awesome-app.dmg' | be_invalid + 'cannot start with a number' | '3binaries/awesome-app.dmg' | be_invalid + 'cannot start with a letter' | 'binaries/awesome-app.dmg' | be_invalid + 'cannot contain accents' | '/binarïes/âwésome-app.dmg' | be_invalid + 'can end in a character' | '/binaries/awesome-app.dmg' | be_valid + 'can end in a number' | '/binaries/awesome-app-1' | be_valid + 'can contain one or more dots, dashes or underscores' | '/sub_tr__ee.ex..ample-2--1/v99.com' | be_valid + 'can contain multiple non-sequential slashes' | '/example.com/path/to/file.exe' | be_valid + 'can be nil' | nil | be_valid + end + + with_them do + specify do + link.filepath = filepath + expect(link).to result + end + end + end end diff --git a/spec/policies/project_snippet_policy_spec.rb b/spec/policies/project_snippet_policy_spec.rb index b55d565a57c..c5077e119bc 100644 --- a/spec/policies/project_snippet_policy_spec.rb +++ b/spec/policies/project_snippet_policy_spec.rb @@ -20,28 +20,39 @@ describe ProjectSnippetPolicy do subject { described_class.new(current_user, snippet) } shared_examples 'regular user access rights' do - context 'project team member (non guest)' do - before do - project.add_developer(current_user) - end + context 'not snippet author' do + context 'project team member (non guest)' do + before do + project.add_developer(current_user) + end - it do - expect_allowed(:read_snippet, :create_note) - expect_disallowed(*author_permissions) + it do + expect_allowed(:read_snippet, :create_note) + expect_disallowed(*author_permissions) + end end - end - context 'project team member (guest)' do - before do - project.add_guest(current_user) - end + context 'project team member (guest)' do + before do + project.add_guest(current_user) + end - context 'not snippet author' do it do expect_allowed(:read_snippet, :create_note) expect_disallowed(:admin_snippet) end end + + context 'project team member (maintainer)' do + before do + project.add_maintainer(current_user) + end + + it do + expect_allowed(:read_snippet, :create_note) + expect_allowed(*author_permissions) + end + end end context 'snippet author' do @@ -69,6 +80,17 @@ describe ProjectSnippetPolicy do end end + context 'project team member (maintainer)' do + before do + project.add_maintainer(current_user) + end + + it do + expect_allowed(:read_snippet, :create_note) + expect_allowed(*author_permissions) + end + end + context 'not a project member' do it do expect_allowed(:read_snippet, :create_note) diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb index 663478942ae..b820b227fff 100644 --- a/spec/requests/api/deployments_spec.rb +++ b/spec/requests/api/deployments_spec.rb @@ -444,6 +444,7 @@ describe API::Deployments do subject expect(response).to have_gitlab_http_status(:ok) + expect(response).to include_pagination_headers expect(json_response.map { |d| d['id'] }).to contain_exactly(merge_request1.id, merge_request2.id) end diff --git a/spec/support/helpers/metrics_dashboard_url_helpers.rb b/spec/support/helpers/metrics_dashboard_url_helpers.rb new file mode 100644 index 00000000000..5809f152e3e --- /dev/null +++ b/spec/support/helpers/metrics_dashboard_url_helpers.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module MetricsDashboardUrlHelpers + # Using the url_helpers available in the test suite uses + # the sample host, but the urls generated may need to + # point to the configured host in the :js trait + def urls + ::Gitlab::Routing.url_helpers + end + + def clear_host_from_memoized_variables + [:metrics_regex, :grafana_regex, :cluster_metrics, :alerts_regex].each do |method_name| + Gitlab::Metrics::Dashboard::Url.clear_memoization(method_name) + end + end +end |