summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilipa Lacerda <filipa@gitlab.com>2018-05-11 16:29:01 +0000
committerFilipa Lacerda <filipa@gitlab.com>2018-05-11 16:29:01 +0000
commit0f953ac4f20f0add09cf5b247954b2f094a2bcde (patch)
tree4f489699c4e9c923b505d709c757c326705601e2
parentd66ae2d5ab336137e5c87b178f5398a83c028d37 (diff)
parentabd24d1c145fce609f9caed27c39ba758571ebd9 (diff)
downloadgitlab-ce-0f953ac4f20f0add09cf5b247954b2f094a2bcde.tar.gz
Merge branch '10-8-stable-prepare-rc8' into '10-8-stable'
Prepare 10.8 RC8 release See merge request gitlab-org/gitlab-ce!18883
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/ide/components/ide.vue4
-rw-r--r--app/assets/javascripts/ide/components/repo_editor.vue2
-rw-r--r--app/assets/javascripts/ide/stores/utils.js1
-rw-r--r--app/assets/stylesheets/framework/terms.scss9
-rw-r--r--app/controllers/users/terms_controller.rb4
-rw-r--r--app/models/ci/runner.rb8
-rw-r--r--app/models/concerns/sha_attribute.rb3
-rw-r--r--app/views/layouts/terms.html.haml4
-rw-r--r--app/workers/object_storage/migrate_uploads_worker.rb79
-rw-r--r--changelogs/unreleased/46210-terms-acceptance-dropdown-menu.yml5
-rw-r--r--changelogs/unreleased/fix-project-mirror-data-schema.yml6
-rw-r--r--changelogs/unreleased/fix-wiki-find-page-invalid-encoding.yml5
-rw-r--r--changelogs/unreleased/jr-46209-web-ide-copy.yml5
-rw-r--r--config/initializers/gollum.rb14
-rw-r--r--db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb21
-rw-r--r--db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb31
-rw-r--r--db/schema.rb6
-rw-r--r--spec/features/users/login_spec.rb102
-rw-r--r--spec/javascripts/ide/components/repo_editor_spec.js26
-rw-r--r--spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb18
-rw-r--r--spec/models/ci/runner_spec.rb28
-rw-r--r--spec/models/concerns/sha_attribute_spec.rb10
-rw-r--r--spec/models/project_wiki_spec.rb11
-rw-r--r--spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb165
-rw-r--r--vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml54
26 files changed, 413 insertions, 210 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 01781720cd4..897e21587ed 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-0.99.0
+0.100.0
diff --git a/app/assets/javascripts/ide/components/ide.vue b/app/assets/javascripts/ide/components/ide.vue
index d479b705e35..6c373a92776 100644
--- a/app/assets/javascripts/ide/components/ide.vue
+++ b/app/assets/javascripts/ide/components/ide.vue
@@ -110,8 +110,8 @@ export default {
Welcome to the GitLab IDE
</h4>
<p>
- You can select a file in the left sidebar to begin
- editing and use the right sidebar to commit your changes.
+ Select a file from the left sidebar to begin editing.
+ Afterwards, you'll be able to commit your changes.
</p>
</div>
</div>
diff --git a/app/assets/javascripts/ide/components/repo_editor.vue b/app/assets/javascripts/ide/components/repo_editor.vue
index ff7e546fb9c..f8678b602ac 100644
--- a/app/assets/javascripts/ide/components/repo_editor.vue
+++ b/app/assets/javascripts/ide/components/repo_editor.vue
@@ -140,7 +140,7 @@ export default {
this.file.staged && this.file.key.indexOf('unstaged-') === 0 ? head : null,
);
- if (this.viewer === viewerTypes.mr) {
+ if (this.viewer === viewerTypes.mr && this.file.mrChange) {
this.editor.attachMergeRequestModel(this.model);
} else {
this.editor.attachModel(this.model);
diff --git a/app/assets/javascripts/ide/stores/utils.js b/app/assets/javascripts/ide/stores/utils.js
index bc79ff4a542..e0b9766fbee 100644
--- a/app/assets/javascripts/ide/stores/utils.js
+++ b/app/assets/javascripts/ide/stores/utils.js
@@ -44,6 +44,7 @@ export const dataStructure = () => ({
size: 0,
parentPath: null,
lastOpenedAt: 0,
+ mrChange: null,
});
export const decorateData = entity => {
diff --git a/app/assets/stylesheets/framework/terms.scss b/app/assets/stylesheets/framework/terms.scss
index 16293d32dfa..744fd0ff796 100644
--- a/app/assets/stylesheets/framework/terms.scss
+++ b/app/assets/stylesheets/framework/terms.scss
@@ -17,6 +17,7 @@
display: flex;
align-items: center;
justify-content: space-between;
+ line-height: $line-height-base;
.title {
display: flex;
@@ -33,10 +34,14 @@
.navbar-collapse {
padding-right: 0;
+
+ .navbar-nav {
+ margin: 0;
+ }
}
- .nav li a {
- color: $theme-gray-700;
+ .nav li {
+ float: none;
}
}
diff --git a/app/controllers/users/terms_controller.rb b/app/controllers/users/terms_controller.rb
index 95c5c3432d5..ab685b9106e 100644
--- a/app/controllers/users/terms_controller.rb
+++ b/app/controllers/users/terms_controller.rb
@@ -3,6 +3,10 @@ module Users
include InternalRedirect
skip_before_action :enforce_terms!
+ skip_before_action :check_password_expiration
+ skip_before_action :check_two_factor_requirement
+ skip_before_action :require_email
+
before_action :terms
layout 'terms'
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb
index 23078f1c3ed..9b76817b4c8 100644
--- a/app/models/ci/runner.rb
+++ b/app/models/ci/runner.rb
@@ -107,7 +107,13 @@ module Ci
end
def assign_to(project, current_user = nil)
- self.is_shared = false if shared?
+ if shared?
+ self.is_shared = false if shared?
+ self.runner_type = :project_type
+ elsif group_type?
+ raise ArgumentError, 'Transitioning a group runner to a project runner is not supported'
+ end
+
self.save
project.runner_projects.create(runner_id: self.id)
end
diff --git a/app/models/concerns/sha_attribute.rb b/app/models/concerns/sha_attribute.rb
index 3340dc96e9f..3796737427a 100644
--- a/app/models/concerns/sha_attribute.rb
+++ b/app/models/concerns/sha_attribute.rb
@@ -22,7 +22,8 @@ module ShaAttribute
column = columns.find { |c| c.name == name.to_s }
unless column
- raise ArgumentError.new("sha_attribute #{name.inspect} is invalid since the column doesn't exist")
+ warn "WARNING: sha_attribute #{name.inspect} is invalid since the column doesn't exist - you may need to run database migrations"
+ return
end
unless column.type == :binary
diff --git a/app/views/layouts/terms.html.haml b/app/views/layouts/terms.html.haml
index a30d6e2688c..87f4151f241 100644
--- a/app/views/layouts/terms.html.haml
+++ b/app/views/layouts/terms.html.haml
@@ -20,10 +20,10 @@
= brand_header_logo
- logo_text = brand_header_logo_type
- if logo_text.present?
- %span.logo-text.hidden-xs.prepend-left-8
+ %span.logo-text.prepend-left-8
= logo_text
- if header_link?(:user_dropdown)
- .navbar-collapse.collapse
+ .navbar-collapse
%ul.nav.navbar-nav
%li.header-user.dropdown
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown" } do
diff --git a/app/workers/object_storage/migrate_uploads_worker.rb b/app/workers/object_storage/migrate_uploads_worker.rb
index a6b2c251254..a3ecfa8e711 100644
--- a/app/workers/object_storage/migrate_uploads_worker.rb
+++ b/app/workers/object_storage/migrate_uploads_worker.rb
@@ -9,85 +9,6 @@ module ObjectStorage
SanityCheckError = Class.new(StandardError)
- class Upload < ActiveRecord::Base
- # Upper limit for foreground checksum processing
- CHECKSUM_THRESHOLD = 100.megabytes
-
- belongs_to :model, polymorphic: true # rubocop:disable Cop/PolymorphicAssociations
-
- validates :size, presence: true
- validates :path, presence: true
- validates :model, presence: true
- validates :uploader, presence: true
-
- before_save :calculate_checksum!, if: :foreground_checksummable?
- after_commit :schedule_checksum, if: :checksummable?
-
- scope :stored_locally, -> { where(store: [nil, ObjectStorage::Store::LOCAL]) }
- scope :stored_remotely, -> { where(store: ObjectStorage::Store::REMOTE) }
-
- def self.hexdigest(path)
- Digest::SHA256.file(path).hexdigest
- end
-
- def absolute_path
- raise ObjectStorage::RemoteStoreError, "Remote object has no absolute path." unless local?
- return path unless relative_path?
-
- uploader_class.absolute_path(self)
- end
-
- def calculate_checksum!
- self.checksum = nil
- return unless checksummable?
-
- self.checksum = self.class.hexdigest(absolute_path)
- end
-
- def build_uploader(mounted_as = nil)
- uploader_class.new(model, mounted_as).tap do |uploader|
- uploader.upload = self
- uploader.retrieve_from_store!(identifier)
- end
- end
-
- def exist?
- File.exist?(absolute_path)
- end
-
- def local?
- return true if store.nil?
-
- store == ObjectStorage::Store::LOCAL
- end
-
- private
-
- def checksummable?
- checksum.nil? && local? && exist?
- end
-
- def foreground_checksummable?
- checksummable? && size <= CHECKSUM_THRESHOLD
- end
-
- def schedule_checksum
- UploadChecksumWorker.perform_async(id)
- end
-
- def relative_path?
- !path.start_with?('/')
- end
-
- def identifier
- File.basename(path)
- end
-
- def uploader_class
- Object.const_get(uploader)
- end
- end
-
class MigrationResult
attr_reader :upload
attr_accessor :error
diff --git a/changelogs/unreleased/46210-terms-acceptance-dropdown-menu.yml b/changelogs/unreleased/46210-terms-acceptance-dropdown-menu.yml
new file mode 100644
index 00000000000..8a7c549e356
--- /dev/null
+++ b/changelogs/unreleased/46210-terms-acceptance-dropdown-menu.yml
@@ -0,0 +1,5 @@
+---
+title: 46210 Display logo and user dropdown on mobile for terms page and fix styling
+merge_request:
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-project-mirror-data-schema.yml b/changelogs/unreleased/fix-project-mirror-data-schema.yml
new file mode 100644
index 00000000000..107f1fe3b9c
--- /dev/null
+++ b/changelogs/unreleased/fix-project-mirror-data-schema.yml
@@ -0,0 +1,6 @@
+---
+title: Fixes database inconsistencies between Community and Enterprise Edition on
+ import state
+merge_request: 18811
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-wiki-find-page-invalid-encoding.yml b/changelogs/unreleased/fix-wiki-find-page-invalid-encoding.yml
new file mode 100644
index 00000000000..f003bef8671
--- /dev/null
+++ b/changelogs/unreleased/fix-wiki-find-page-invalid-encoding.yml
@@ -0,0 +1,5 @@
+---
+title: Fix finding wiki pages when they have invalidly-encoded content
+merge_request: 18856
+author:
+type: fixed
diff --git a/changelogs/unreleased/jr-46209-web-ide-copy.yml b/changelogs/unreleased/jr-46209-web-ide-copy.yml
new file mode 100644
index 00000000000..87ccae6ced0
--- /dev/null
+++ b/changelogs/unreleased/jr-46209-web-ide-copy.yml
@@ -0,0 +1,5 @@
+---
+title: Fix outdated Web IDE welcome copy
+merge_request: 18861
+author:
+type: fixed
diff --git a/config/initializers/gollum.rb b/config/initializers/gollum.rb
index 81e0577a7c9..ea9cc151a57 100644
--- a/config/initializers/gollum.rb
+++ b/config/initializers/gollum.rb
@@ -7,6 +7,20 @@ module Gollum
end
require "gollum-lib"
+module Gollum
+ class Page
+ def text_data(encoding = nil)
+ data = if raw_data.respond_to?(:encoding)
+ raw_data.force_encoding(encoding || Encoding::UTF_8)
+ else
+ raw_data
+ end
+
+ Gitlab::EncodingHelper.encode!(data)
+ end
+ end
+end
+
Rails.application.configure do
config.after_initialize do
Gollum::Page.per_page = Kaminari.config.default_per_page
diff --git a/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb b/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb
new file mode 100644
index 00000000000..82087d15ccb
--- /dev/null
+++ b/db/migrate/20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb
@@ -0,0 +1,21 @@
+class AddNotNullConstraintToProjectMirrorDataForeignKey < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ class ProjectImportState < ActiveRecord::Base
+ include EachBatch
+
+ self.table_name = 'project_mirror_data'
+ end
+
+ def up
+ ProjectImportState.where(project_id: nil).delete_all
+
+ change_column_null :project_mirror_data, :project_id, false
+ end
+
+ def down
+ change_column_null :project_mirror_data, :project_id, true
+ end
+end
diff --git a/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb b/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb
new file mode 100644
index 00000000000..acb976b52fa
--- /dev/null
+++ b/db/migrate/20180508102840_add_unique_constraint_to_project_mirror_data_project_id_index.rb
@@ -0,0 +1,31 @@
+class AddUniqueConstraintToProjectMirrorDataProjectIdIndex < ActiveRecord::Migration
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ disable_ddl_transaction!
+
+ def up
+ add_concurrent_index(:project_mirror_data,
+ :project_id,
+ unique: true,
+ name: 'index_project_mirror_data_on_project_id_unique')
+
+ remove_concurrent_index_by_name(:project_mirror_data, 'index_project_mirror_data_on_project_id')
+
+ rename_index(:project_mirror_data,
+ 'index_project_mirror_data_on_project_id_unique',
+ 'index_project_mirror_data_on_project_id')
+ end
+
+ def down
+ rename_index(:project_mirror_data,
+ 'index_project_mirror_data_on_project_id',
+ 'index_project_mirror_data_on_project_id_old')
+
+ add_concurrent_index(:project_mirror_data, :project_id)
+
+ remove_concurrent_index_by_name(:project_mirror_data,
+ 'index_project_mirror_data_on_project_id_old')
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 22a851f83a6..168ab198025 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: 20180508055821) do
+ActiveRecord::Schema.define(version: 20180508102840) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -1529,14 +1529,14 @@ ActiveRecord::Schema.define(version: 20180508055821) do
add_index "project_import_data", ["project_id"], name: "index_project_import_data_on_project_id", using: :btree
create_table "project_mirror_data", force: :cascade do |t|
- t.integer "project_id"
+ t.integer "project_id", null: false
t.string "status"
t.string "jid"
t.text "last_error"
end
add_index "project_mirror_data", ["jid"], name: "index_project_mirror_data_on_jid", using: :btree
- add_index "project_mirror_data", ["project_id"], name: "index_project_mirror_data_on_project_id", using: :btree
+ add_index "project_mirror_data", ["project_id"], name: "index_project_mirror_data_on_project_id", unique: true, using: :btree
add_index "project_mirror_data", ["status"], name: "index_project_mirror_data_on_status", using: :btree
create_table "project_statistics", force: :cascade do |t|
diff --git a/spec/features/users/login_spec.rb b/spec/features/users/login_spec.rb
index 94a2b289e64..6f968a2c590 100644
--- a/spec/features/users/login_spec.rb
+++ b/spec/features/users/login_spec.rb
@@ -437,5 +437,107 @@ feature 'Login' do
expect(current_path).to eq(root_path)
end
+
+ context 'when 2FA is required for the user' do
+ before do
+ group = create(:group, require_two_factor_authentication: true)
+ group.add_developer(user)
+ end
+
+ context 'when the user did not enable 2FA' do
+ it 'asks to set 2FA before asking to accept the terms' do
+ visit new_user_session_path
+
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: '12345678'
+
+ click_button 'Sign in'
+
+ expect_to_be_on_terms_page
+ click_button 'Accept terms'
+
+ expect(current_path).to eq(profile_two_factor_auth_path)
+
+ fill_in 'pin_code', with: user.reload.current_otp
+
+ click_button 'Register with two-factor app'
+ click_link 'Proceed'
+
+ expect(current_path).to eq(profile_account_path)
+ end
+ end
+
+ context 'when the user already enabled 2FA' do
+ before do
+ user.update!(otp_required_for_login: true,
+ otp_secret: User.generate_otp_secret(32))
+ end
+
+ it 'asks the user to accept the terms' do
+ visit new_user_session_path
+
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: '12345678'
+ click_button 'Sign in'
+
+ fill_in 'user_otp_attempt', with: user.reload.current_otp
+ click_button 'Verify code'
+
+ expect_to_be_on_terms_page
+ click_button 'Accept terms'
+
+ expect(current_path).to eq(root_path)
+ end
+ end
+ end
+
+ context 'when the users password is expired' do
+ before do
+ user.update!(password_expires_at: Time.parse('2018-05-08 11:29:46 UTC'))
+ end
+
+ it 'asks the user to accept the terms before setting a new password' do
+ visit new_user_session_path
+
+ fill_in 'user_login', with: user.email
+ fill_in 'user_password', with: '12345678'
+ click_button 'Sign in'
+
+ expect_to_be_on_terms_page
+ click_button 'Accept terms'
+
+ expect(current_path).to eq(new_profile_password_path)
+
+ fill_in 'user_current_password', with: '12345678'
+ fill_in 'user_password', with: 'new password'
+ fill_in 'user_password_confirmation', with: 'new password'
+ click_button 'Set new password'
+
+ expect(page).to have_content('Password successfully changed')
+ end
+ end
+
+ context 'when the user does not have an email configured' do
+ let(:user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'saml', email: 'temp-email-for-oauth-user@gitlab.localhost') }
+
+ before do
+ stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config])
+ end
+
+ it 'asks the user to accept the terms before setting an email' do
+ gitlab_sign_in_via('saml', user, 'my-uid')
+
+ expect_to_be_on_terms_page
+ click_button 'Accept terms'
+
+ expect(current_path).to eq(profile_path)
+
+ fill_in 'Email', with: 'hello@world.com'
+
+ click_button 'Update profile settings'
+
+ expect(page).to have_content('Profile was successfully updated')
+ end
+ end
end
end
diff --git a/spec/javascripts/ide/components/repo_editor_spec.js b/spec/javascripts/ide/components/repo_editor_spec.js
index 360b6d4dc15..ff500acd849 100644
--- a/spec/javascripts/ide/components/repo_editor_spec.js
+++ b/spec/javascripts/ide/components/repo_editor_spec.js
@@ -24,7 +24,7 @@ describe('RepoEditor', () => {
f.active = true;
f.tempFile = true;
vm.$store.state.openFiles.push(f);
- vm.$store.state.entries[f.path] = f;
+ Vue.set(vm.$store.state.entries, f.path, f);
vm.monaco = true;
vm.$mount();
@@ -215,6 +215,30 @@ describe('RepoEditor', () => {
expect(vm.editor.attachModel).toHaveBeenCalledWith(vm.model);
});
+ it('attaches model to merge request editor', () => {
+ vm.$store.state.viewer = 'mrdiff';
+ vm.file.mrChange = true;
+ spyOn(vm.editor, 'attachMergeRequestModel');
+
+ Editor.editorInstance.modelManager.dispose();
+
+ vm.setupEditor();
+
+ expect(vm.editor.attachMergeRequestModel).toHaveBeenCalledWith(vm.model);
+ });
+
+ it('does not attach model to merge request editor when not a MR change', () => {
+ vm.$store.state.viewer = 'mrdiff';
+ vm.file.mrChange = false;
+ spyOn(vm.editor, 'attachMergeRequestModel');
+
+ Editor.editorInstance.modelManager.dispose();
+
+ vm.setupEditor();
+
+ expect(vm.editor.attachMergeRequestModel).not.toHaveBeenCalledWith(vm.model);
+ });
+
it('adds callback methods', () => {
spyOn(vm.editor, 'onPositionChange').and.callThrough();
diff --git a/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb b/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb
new file mode 100644
index 00000000000..6fd3cb1f44e
--- /dev/null
+++ b/spec/migrations/add_not_null_constraint_to_project_mirror_data_foreign_key_spec.rb
@@ -0,0 +1,18 @@
+require 'spec_helper'
+require Rails.root.join('db', 'migrate', '20180508100222_add_not_null_constraint_to_project_mirror_data_foreign_key.rb')
+
+describe AddNotNullConstraintToProjectMirrorDataForeignKey, :migration do
+ let(:namespaces) { table(:namespaces) }
+ let(:projects) { table(:projects) }
+ let(:import_state) { table(:project_mirror_data) }
+
+ before do
+ import_state.create!(id: 1, project_id: nil, status: :started)
+ end
+
+ it 'removes every import state without an associated project_id' do
+ expect do
+ subject.up
+ end.to change { import_state.count }.from(1).to(0)
+ end
+end
diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb
index cc4d4e5e4ae..4c1d3c712f4 100644
--- a/spec/models/ci/runner_spec.rb
+++ b/spec/models/ci/runner_spec.rb
@@ -198,16 +198,30 @@ describe Ci::Runner do
end
describe '#assign_to' do
- let!(:project) { FactoryBot.create :project }
- let!(:shared_runner) { FactoryBot.create(:ci_runner, :shared) }
+ let!(:project) { FactoryBot.create(:project) }
- before do
- shared_runner.assign_to(project)
+ subject { runner.assign_to(project) }
+
+ context 'with shared runner' do
+ let!(:runner) { FactoryBot.create(:ci_runner, :shared) }
+
+ it 'transitions shared runner to project runner and assigns project' do
+ subject
+ expect(runner).to be_specific
+ expect(runner).to be_project_type
+ expect(runner.projects).to eq([project])
+ expect(runner.only_for?(project)).to be_truthy
+ end
end
- it { expect(shared_runner).to be_specific }
- it { expect(shared_runner.projects).to eq([project]) }
- it { expect(shared_runner.only_for?(project)).to be_truthy }
+ context 'with group runner' do
+ let!(:runner) { FactoryBot.create(:ci_runner, runner_type: :group_type) }
+
+ it 'raises an error' do
+ expect { subject }
+ .to raise_error(ArgumentError, 'Transitioning a group runner to a project runner is not supported')
+ end
+ end
end
describe '.online' do
diff --git a/spec/models/concerns/sha_attribute_spec.rb b/spec/models/concerns/sha_attribute_spec.rb
index 592feddf1dc..0d3beb6a6e3 100644
--- a/spec/models/concerns/sha_attribute_spec.rb
+++ b/spec/models/concerns/sha_attribute_spec.rb
@@ -36,24 +36,26 @@ describe ShaAttribute do
end
context 'when the table does not exist' do
- it 'allows the attribute to be added' do
+ it 'allows the attribute to be added and issues a warning' do
allow(model).to receive(:table_exists?).and_return(false)
expect(model).not_to receive(:columns)
expect(model).to receive(:attribute)
+ expect(model).to receive(:warn)
model.sha_attribute(:name)
end
end
context 'when the column does not exist' do
- it 'raises ArgumentError' do
+ it 'allows the attribute to be added and issues a warning' do
allow(model).to receive(:table_exists?).and_return(true)
expect(model).to receive(:columns)
- expect(model).not_to receive(:attribute)
+ expect(model).to receive(:attribute)
+ expect(model).to receive(:warn)
- expect { model.sha_attribute(:no_name) }.to raise_error(ArgumentError)
+ model.sha_attribute(:no_name)
end
end
diff --git a/spec/models/project_wiki_spec.rb b/spec/models/project_wiki_spec.rb
index d6c4031329d..f1142832f1a 100644
--- a/spec/models/project_wiki_spec.rb
+++ b/spec/models/project_wiki_spec.rb
@@ -159,6 +159,17 @@ describe ProjectWiki do
expect(page.title).to eq("autre pagé")
end
end
+
+ context 'pages with invalidly-encoded content' do
+ before do
+ create_page("encoding is fun", "f\xFCr".b)
+ end
+
+ it "can find the page" do
+ page = subject.find_page("encoding is fun")
+ expect(page.content).to eq("fr")
+ end
+ end
end
context 'when Gitaly wiki_find_page is enabled' do
diff --git a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
index 7a7dcb71680..aed62f97448 100644
--- a/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
+++ b/spec/uploaders/workers/object_storage/migrate_uploads_worker_spec.rb
@@ -7,113 +7,138 @@ describe ObjectStorage::MigrateUploadsWorker, :sidekiq do
end
end
- let!(:projects) { create_list(:project, 10, :with_avatar) }
- let(:uploads) { Upload.all }
let(:model_class) { Project }
- let(:mounted_as) { :avatar }
+ let(:uploads) { Upload.all }
let(:to_store) { ObjectStorage::Store::REMOTE }
- before do
- stub_uploads_object_storage(AvatarUploader)
- end
-
- describe '.enqueue!' do
- def enqueue!
- described_class.enqueue!(uploads, Project, mounted_as, to_store)
- end
+ shared_examples "uploads migration worker" do
+ describe '.enqueue!' do
+ def enqueue!
+ described_class.enqueue!(uploads, Project, mounted_as, to_store)
+ end
- it 'is guarded by .sanity_check!' do
- expect(described_class).to receive(:perform_async)
- expect(described_class).to receive(:sanity_check!)
+ it 'is guarded by .sanity_check!' do
+ expect(described_class).to receive(:perform_async)
+ expect(described_class).to receive(:sanity_check!)
- enqueue!
- end
+ enqueue!
+ end
- context 'sanity_check! fails' do
- include_context 'sanity_check! fails'
+ context 'sanity_check! fails' do
+ include_context 'sanity_check! fails'
- it 'does not enqueue a job' do
- expect(described_class).not_to receive(:perform_async)
+ it 'does not enqueue a job' do
+ expect(described_class).not_to receive(:perform_async)
- expect { enqueue! }.to raise_error(described_class::SanityCheckError)
+ expect { enqueue! }.to raise_error(described_class::SanityCheckError)
+ end
end
end
- end
- describe '.sanity_check!' do
- shared_examples 'raises a SanityCheckError' do
- let(:mount_point) { nil }
+ describe '.sanity_check!' do
+ shared_examples 'raises a SanityCheckError' do
+ let(:mount_point) { nil }
- it do
- expect { described_class.sanity_check!(uploads, model_class, mount_point) }
- .to raise_error(described_class::SanityCheckError)
+ it do
+ expect { described_class.sanity_check!(uploads, model_class, mount_point) }
+ .to raise_error(described_class::SanityCheckError)
+ end
end
- end
- context 'uploader types mismatch' do
- let!(:outlier) { create(:upload, uploader: 'FileUploader') }
+ before do
+ stub_const("WrongModel", Class.new)
+ end
- include_examples 'raises a SanityCheckError'
- end
+ context 'uploader types mismatch' do
+ let!(:outlier) { create(:upload, uploader: 'GitlabUploader') }
- context 'model types mismatch' do
- let!(:outlier) { create(:upload, model_type: 'Potato') }
+ include_examples 'raises a SanityCheckError'
+ end
- include_examples 'raises a SanityCheckError'
- end
+ context 'model types mismatch' do
+ let!(:outlier) { create(:upload, model_type: 'WrongModel') }
- context 'mount point not found' do
- include_examples 'raises a SanityCheckError' do
- let(:mount_point) { :potato }
+ include_examples 'raises a SanityCheckError'
end
- end
- end
- describe '#perform' do
- def perform
- described_class.new.perform(uploads.ids, model_class.to_s, mounted_as, to_store)
- rescue ObjectStorage::MigrateUploadsWorker::Report::MigrationFailures
- # swallow
+ context 'mount point not found' do
+ include_examples 'raises a SanityCheckError' do
+ let(:mount_point) { :potato }
+ end
+ end
end
- shared_examples 'outputs correctly' do |success: 0, failures: 0|
- total = success + failures
+ describe '#perform' do
+ def perform
+ described_class.new.perform(uploads.ids, model_class.to_s, mounted_as, to_store)
+ rescue ObjectStorage::MigrateUploadsWorker::Report::MigrationFailures
+ # swallow
+ end
+
+ shared_examples 'outputs correctly' do |success: 0, failures: 0|
+ total = success + failures
- if success > 0
- it 'outputs the reports' do
- expect(Rails.logger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
+ if success > 0
+ it 'outputs the reports' do
+ expect(Rails.logger).to receive(:info).with(%r{Migrated #{success}/#{total} files})
- perform
+ perform
+ end
end
- end
- if failures > 0
- it 'outputs upload failures' do
- expect(Rails.logger).to receive(:warn).with(/Error .* I am a teapot/)
+ if failures > 0
+ it 'outputs upload failures' do
+ expect(Rails.logger).to receive(:warn).with(/Error .* I am a teapot/)
- perform
+ perform
+ end
end
end
- end
- it_behaves_like 'outputs correctly', success: 10
+ it_behaves_like 'outputs correctly', success: 10
+
+ it 'migrates files' do
+ perform
- it 'migrates files' do
- perform
+ expect(Upload.where(store: ObjectStorage::Store::LOCAL).count).to eq(0)
+ end
- aggregate_failures do
- projects.each do |project|
- expect(project.reload.avatar.upload.local?).to be_falsey
+ context 'migration is unsuccessful' do
+ before do
+ allow_any_instance_of(ObjectStorage::Concern)
+ .to receive(:migrate!).and_raise(CarrierWave::UploadError, "I am a teapot.")
end
+
+ it_behaves_like 'outputs correctly', failures: 10
end
end
+ end
- context 'migration is unsuccessful' do
- before do
- allow_any_instance_of(ObjectStorage::Concern).to receive(:migrate!).and_raise(CarrierWave::UploadError, "I am a teapot.")
- end
+ context "for AvatarUploader" do
+ let!(:projects) { create_list(:project, 10, :with_avatar) }
+ let(:mounted_as) { :avatar }
- it_behaves_like 'outputs correctly', failures: 10
+ before do
+ stub_uploads_object_storage(AvatarUploader)
+ end
+
+ it_behaves_like "uploads migration worker"
+ end
+
+ context "for FileUploader" do
+ let!(:projects) { create_list(:project, 10) }
+ let(:secret) { SecureRandom.hex }
+ let(:mounted_as) { nil }
+
+ before do
+ stub_uploads_object_storage(FileUploader)
+
+ projects.map do |project|
+ uploader = FileUploader.new(project)
+ uploader.store!(fixture_file_upload('spec/fixtures/doc_sample.txt'))
+ end
end
+
+ it_behaves_like "uploads migration worker"
end
end
diff --git a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
index 020031af3cb..a00c6e89a1d 100644
--- a/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
+++ b/vendor/gitlab-ci-yml/Auto-DevOps.gitlab-ci.yml
@@ -12,8 +12,10 @@
# AUTO_DEVOPS_DOMAIN must also be set as a variable at the group or project
# level, or manually added below.
#
-# If you want to deploy to staging first, or enable canary deploys,
-# uncomment the relevant jobs in the pipeline below.
+# Continuous deployment to production is enabled by default.
+# If you want to deploy to staging first, or enable incremental rollouts,
+# set STAGING_ENABLED or INCREMENTAL_ROLLOUT_ENABLED environment variables.
+# If you want to use canary deployments, uncomment the canary job.
#
# If Auto DevOps fails to detect the proper buildpack, or if you want to
# specify a custom buildpack, set a project variable `BUILDPACK_URL` to the
@@ -88,14 +90,6 @@ codequality:
artifacts:
paths: [codeclimate.json]
-license_management:
- image: registry.gitlab.com/gitlab-org/security-products/license-management:latest
- allow_failure: true
- script:
- - license_management
- artifacts:
- paths: [gl-license-report.json]
-
performance:
stage: performance
image: docker:stable
@@ -223,8 +217,8 @@ stop_review:
# Staging deploys are disabled by default since
# continuous deployment to production is enabled by default
# If you prefer to automatically deploy to staging and
-# only manually promote to production, enable this job by removing the dot (.),
-# and uncomment the `when: manual` line in the `production` job.
+# only manually promote to production, enable this job by setting
+# STAGING_ENABLED.
staging:
stage: staging
@@ -245,13 +239,9 @@ staging:
kubernetes: active
variables:
- $STAGING_ENABLED
- except:
- variables:
- - $INCREMENTAL_ROLLOUT_ENABLED
# Canaries are disabled by default, but if you want them,
-# and know what the downsides are, enable this job by removing the dot (.),
-# and uncomment the `when: manual` line in the `production` job.
+# and know what the downsides are, enable this job by removing the dot (.).
.canary:
stage: canary
@@ -272,11 +262,6 @@ staging:
- master
kubernetes: active
-# This job continuously deploys to production on every push to `master`.
-# To make this a manual process, either because you're enabling `staging`
-# or `canary` deploys, or you simply want more control over when you deploy
-# to production, uncomment the `when: manual` line in the `production` job.
-
.production: &production_template
stage: production
script:
@@ -310,6 +295,7 @@ production:
production_manual:
<<: *production_template
when: manual
+ allow_failure: false
only:
refs:
- master
@@ -345,6 +331,7 @@ rollout 10%:
<<: *rollout_template
variables:
ROLLOUT_PERCENTAGE: 10
+ when: manual
only:
refs:
- master
@@ -379,6 +366,7 @@ rollout 50%:
rollout 100%:
<<: *production_template
when: manual
+ allow_failure: false
only:
refs:
- master
@@ -428,14 +416,6 @@ rollout 100%:
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
}
- function license_management() {
- if echo $GITLAB_FEATURES |grep license_management > /dev/null ; then
- /run.sh .
- else
- echo "License management is not available in your subscription"
- fi
- }
-
function sast() {
case "$CI_SERVER_VERSION" in
*-ee)
@@ -562,12 +542,14 @@ rollout 100%:
replicas=$(get_replicas "$track" "$percentage")
- helm upgrade --reuse-values \
- --wait \
- --set replicaCount="$replicas" \
- --namespace="$KUBE_NAMESPACE" \
- "$name" \
- chart/
+ if [[ -n "$(helm ls -q "^$name$")" ]]; then
+ helm upgrade --reuse-values \
+ --wait \
+ --set replicaCount="$replicas" \
+ --namespace="$KUBE_NAMESPACE" \
+ "$name" \
+ chart/
+ fi
}
function install_dependencies() {