Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
05f1d5d981
commit
b4028d4500
|
|
@ -28,6 +28,11 @@ export default {
|
|||
required: false,
|
||||
default: 7,
|
||||
},
|
||||
showParticipantLabel: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -80,6 +85,7 @@ export default {
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="showParticipantLabel"
|
||||
v-tooltip
|
||||
:title="participantLabel"
|
||||
class="sidebar-collapsed-icon"
|
||||
|
|
@ -92,7 +98,7 @@ export default {
|
|||
<gl-loading-icon v-if="loading" class="js-participants-collapsed-loading-icon" />
|
||||
<span v-else class="js-participants-collapsed-count"> {{ participantCount }} </span>
|
||||
</div>
|
||||
<div class="title hide-collapsed">
|
||||
<div v-if="showParticipantLabel" class="title hide-collapsed">
|
||||
<gl-loading-icon
|
||||
v-if="loading"
|
||||
:inline="true"
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ class Projects::TreeController < Projects::ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
lfs_blob_ids
|
||||
lfs_blob_ids if Feature.disabled?(:vue_file_list, @project)
|
||||
|
||||
@last_commit = @repository.last_commit_for_path(@commit.id, @tree.path) || @commit
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,8 +21,7 @@ class ProjectsController < Projects::ApplicationController
|
|||
before_action :assign_ref_vars, if: -> { action_name == 'show' && repo_exists? }
|
||||
before_action :tree,
|
||||
if: -> { action_name == 'show' && repo_exists? && project_view_files? }
|
||||
before_action :lfs_blob_ids,
|
||||
if: -> { action_name == 'show' && repo_exists? && project_view_files? }
|
||||
before_action :lfs_blob_ids, if: :show_blob_ids?, only: :show
|
||||
before_action :project_export_enabled, only: [:export, :download_export, :remove_export, :generate_new_export]
|
||||
before_action :present_project, only: [:edit]
|
||||
before_action :authorize_download_code!, only: [:refs]
|
||||
|
|
@ -296,6 +295,10 @@ class ProjectsController < Projects::ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def show_blob_ids?
|
||||
repo_exists? && project_view_files? && Feature.disabled?(:vue_file_list, @project)
|
||||
end
|
||||
|
||||
# Render project landing depending of which features are available
|
||||
# So if page is not available in the list it renders the next page
|
||||
#
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module HasStatus
|
|||
BLOCKED_STATUS = %w[manual scheduled].freeze
|
||||
AVAILABLE_STATUSES = %w[created waiting_for_resource preparing pending running success failed canceled skipped manual scheduled].freeze
|
||||
STARTED_STATUSES = %w[running success failed skipped manual scheduled].freeze
|
||||
ACTIVE_STATUSES = %w[preparing pending running].freeze
|
||||
ACTIVE_STATUSES = %w[waiting_for_resource preparing pending running].freeze
|
||||
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
|
||||
ORDERED_STATUSES = %w[failed preparing pending running waiting_for_resource manual scheduled canceled success skipped created].freeze
|
||||
PASSED_WITH_WARNINGS_STATUSES = %w[failed canceled].to_set.freeze
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Extend Design view sidebar with issue link and a list of participants
|
||||
merge_request: 22103
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: New API endpoint GET /projects/:id/services
|
||||
merge_request: 21330
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: add background migration for sha256 fingerprints of ssh keys
|
||||
merge_request: 21579
|
||||
author: Roger Meier
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Add migrations for version control snippets
|
||||
merge_request: 22275
|
||||
author:
|
||||
type: added
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Execute Gitaly LFS call once when Vue file enabled
|
||||
merge_request: 22168
|
||||
author:
|
||||
type: performance
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Make jobs with resource group cancellable
|
||||
merge_request: 22356
|
||||
author:
|
||||
type: fixed
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRepositoryStorageToSnippets < ActiveRecord::Migration[5.2]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
DOWNTIME = false
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
|
||||
:snippets,
|
||||
:repository_storage,
|
||||
:string,
|
||||
default: 'default',
|
||||
limit: 255,
|
||||
allow_null: false
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column(:snippets, :repository_storage)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddStorageVersionToSnippets < ActiveRecord::Migration[5.2]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
# Set this constant to true if this migration requires downtime.
|
||||
DOWNTIME = false
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_column_with_default( # rubocop:disable Migration/AddColumnWithDefault
|
||||
:snippets,
|
||||
:storage_version,
|
||||
:integer,
|
||||
default: 2,
|
||||
allow_null: false
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column(:snippets, :storage_version)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UpdateFingerprintSha256WithinKeys < ActiveRecord::Migration[5.0]
|
||||
include Gitlab::Database::MigrationHelpers
|
||||
|
||||
class Key < ActiveRecord::Base
|
||||
include EachBatch
|
||||
|
||||
self.table_name = 'keys'
|
||||
self.inheritance_column = :_type_disabled
|
||||
end
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
queue_background_migration_jobs_by_range_at_intervals(Key, 'MigrateFingerprintSha256WithinKeys', 5.minutes)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2020_01_02_170221) do
|
||||
ActiveRecord::Schema.define(version: 2020_01_06_071113) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pg_trgm"
|
||||
|
|
@ -3803,6 +3803,8 @@ ActiveRecord::Schema.define(version: 2020_01_02_170221) do
|
|||
t.string "encrypted_secret_token", limit: 255
|
||||
t.string "encrypted_secret_token_iv", limit: 255
|
||||
t.boolean "secret", default: false, null: false
|
||||
t.string "repository_storage", limit: 255, default: "default", null: false
|
||||
t.integer "storage_version", default: 2, null: false
|
||||
t.index ["author_id"], name: "index_snippets_on_author_id"
|
||||
t.index ["content"], name: "index_snippets_on_content_trigram", opclass: :gin_trgm_ops, using: :gin
|
||||
t.index ["created_at"], name: "index_snippets_on_created_at"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,59 @@
|
|||
|
||||
>**Note:** This API requires an access token with Maintainer or Owner permissions
|
||||
|
||||
## List all active services
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/merge_requests/21330) in GitLab 12.7.
|
||||
|
||||
Get a list of all active project services.
|
||||
|
||||
```
|
||||
GET /projects/:id/services
|
||||
```
|
||||
|
||||
Example response:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 75,
|
||||
"title": "Jenkins CI",
|
||||
"created_at": "2019-11-20T11:20:25.297Z",
|
||||
"updated_at": "2019-11-20T12:24:37.498Z",
|
||||
"active": true,
|
||||
"commit_events": true,
|
||||
"push_events": true,
|
||||
"issues_events": true,
|
||||
"confidential_issues_events": true,
|
||||
"merge_requests_events": true,
|
||||
"tag_push_events": false,
|
||||
"note_events": true,
|
||||
"confidential_note_events": true,
|
||||
"pipeline_events": true,
|
||||
"wiki_page_events": true,
|
||||
"job_events": true
|
||||
}
|
||||
{
|
||||
"id": 76,
|
||||
"title": "Alerts endpoint",
|
||||
"created_at": "2019-11-20T11:20:25.297Z",
|
||||
"updated_at": "2019-11-20T12:24:37.498Z",
|
||||
"active": true,
|
||||
"commit_events": true,
|
||||
"push_events": true,
|
||||
"issues_events": true,
|
||||
"confidential_issues_events": true,
|
||||
"merge_requests_events": true,
|
||||
"tag_push_events": true,
|
||||
"note_events": true,
|
||||
"confidential_note_events": true,
|
||||
"pipeline_events": true,
|
||||
"wiki_page_events": true,
|
||||
"job_events": true
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Asana
|
||||
|
||||
Asana - Teamwork without email
|
||||
|
|
|
|||
|
|
@ -1109,12 +1109,15 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
class ProjectService < Grape::Entity
|
||||
class ProjectServiceBasic < Grape::Entity
|
||||
expose :id, :title, :created_at, :updated_at, :active
|
||||
expose :commit_events, :push_events, :issues_events, :confidential_issues_events
|
||||
expose :merge_requests_events, :tag_push_events, :note_events
|
||||
expose :confidential_note_events, :pipeline_events, :wiki_page_events
|
||||
expose :job_events
|
||||
end
|
||||
|
||||
class ProjectService < ProjectServiceBasic
|
||||
# Expose serialized properties
|
||||
expose :properties do |service, options|
|
||||
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
|
||||
|
|
|
|||
|
|
@ -66,6 +66,15 @@ module API
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Get all active project services' do
|
||||
success Entities::ProjectServiceBasic
|
||||
end
|
||||
get ":id/services" do
|
||||
services = user_project.services.active
|
||||
|
||||
present services, with: Entities::ProjectServiceBasic
|
||||
end
|
||||
|
||||
SERVICES.each do |service_slug, settings|
|
||||
desc "Set #{service_slug} service for project"
|
||||
params do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# This class is responsible to update all sha256 fingerprints within the keys table
|
||||
class MigrateFingerprintSha256WithinKeys
|
||||
# Temporary AR table for keys
|
||||
class Key < ActiveRecord::Base
|
||||
include EachBatch
|
||||
|
||||
self.table_name = 'keys'
|
||||
self.inheritance_column = :_type_disabled
|
||||
end
|
||||
|
||||
TEMP_TABLE = 'tmp_fingerprint_sha256_migration'
|
||||
|
||||
def perform(start_id, stop_id)
|
||||
ActiveRecord::Base.transaction do
|
||||
execute(<<~SQL)
|
||||
CREATE TEMPORARY TABLE #{TEMP_TABLE}
|
||||
(id bigint primary key, fingerprint_sha256 bytea not null)
|
||||
ON COMMIT DROP
|
||||
SQL
|
||||
|
||||
fingerprints = []
|
||||
Key.where(id: start_id..stop_id, fingerprint_sha256: nil).find_each do |regular_key|
|
||||
fingerprint = Base64.decode64(generate_ssh_public_key(regular_key.key))
|
||||
|
||||
fingerprints << {
|
||||
id: regular_key.id,
|
||||
fingerprint_sha256: ActiveRecord::Base.connection.escape_bytea(fingerprint)
|
||||
}
|
||||
end
|
||||
|
||||
Gitlab::Database.bulk_insert(TEMP_TABLE, fingerprints)
|
||||
|
||||
execute("ANALYZE #{TEMP_TABLE}")
|
||||
|
||||
execute(<<~SQL)
|
||||
UPDATE keys
|
||||
SET fingerprint_sha256 = t.fingerprint_sha256
|
||||
FROM #{TEMP_TABLE} t
|
||||
WHERE keys.id = t.id
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def generate_ssh_public_key(regular_key)
|
||||
Gitlab::SSHPublicKey.new(regular_key).fingerprint("SHA256").gsub("SHA256:", "")
|
||||
end
|
||||
|
||||
def execute(query)
|
||||
ActiveRecord::Base.connection.execute(query)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -172,6 +172,8 @@ excluded_attributes:
|
|||
- :secret
|
||||
- :encrypted_secret_token
|
||||
- :encrypted_secret_token_iv
|
||||
- :repository_storage
|
||||
- :storage_version
|
||||
merge_request_diff:
|
||||
- :external_diff
|
||||
- :stored_externally
|
||||
|
|
|
|||
|
|
@ -15,13 +15,9 @@ module QA
|
|||
issue.visit!
|
||||
|
||||
Page::Project::Issue::Show.perform do |show|
|
||||
my_first_discussion = 'My first discussion'
|
||||
|
||||
show.select_all_activities_filter
|
||||
show.start_discussion(my_first_discussion)
|
||||
page.assert_text(my_first_discussion)
|
||||
show.start_discussion('My first discussion')
|
||||
show.reply_to_discussion(my_first_reply)
|
||||
page.assert_text(my_first_reply)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -89,6 +89,34 @@ describe Projects::TreeController do
|
|||
end
|
||||
end
|
||||
|
||||
describe "GET show" do
|
||||
context 'lfs_blob_ids instance variable' do
|
||||
let(:id) { 'master' }
|
||||
|
||||
context 'with vue tree view enabled' do
|
||||
before do
|
||||
get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
|
||||
end
|
||||
|
||||
it 'is not set' do
|
||||
expect(assigns[:lfs_blob_ids]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'with vue tree view disabled' do
|
||||
before do
|
||||
stub_feature_flags(vue_file_list: false)
|
||||
|
||||
get(:show, params: { namespace_id: project.namespace.to_param, project_id: project, id: id })
|
||||
end
|
||||
|
||||
it 'is set' do
|
||||
expect(assigns[:lfs_blob_ids]).not_to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET show with whitespace in ref' do
|
||||
render_views
|
||||
|
||||
|
|
|
|||
|
|
@ -289,6 +289,36 @@ describe ProjectsController do
|
|||
.not_to exceed_query_limit(2).for_query(expected_query)
|
||||
end
|
||||
end
|
||||
|
||||
context 'lfs_blob_ids instance variable' do
|
||||
let(:project) { create(:project, :public, :repository) }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
context 'with vue tree view enabled' do
|
||||
before do
|
||||
get :show, params: { namespace_id: project.namespace, id: project }
|
||||
end
|
||||
|
||||
it 'is not set' do
|
||||
expect(assigns[:lfs_blob_ids]).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'with vue tree view disabled' do
|
||||
before do
|
||||
stub_feature_flags(vue_file_list: false)
|
||||
|
||||
get :show, params: { namespace_id: project.namespace, id: project }
|
||||
end
|
||||
|
||||
it 'is set' do
|
||||
expect(assigns[:lfs_blob_ids]).not_to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET edit' do
|
||||
|
|
|
|||
|
|
@ -306,6 +306,21 @@ describe 'Jobs', :clean_gitlab_redis_shared_state do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when job is waiting for resource', :js do
|
||||
let(:job) { create(:ci_build, :waiting_for_resource, pipeline: pipeline, resource_group: resource_group) }
|
||||
let(:resource_group) { create(:ci_resource_group, project: project) }
|
||||
|
||||
before do
|
||||
visit project_job_path(project, job)
|
||||
wait_for_requests
|
||||
end
|
||||
|
||||
it 'shows correct UI components' do
|
||||
expect(page).to have_content("This job is waiting for resource: #{resource_group.key}")
|
||||
expect(page).to have_link("Cancel this job")
|
||||
end
|
||||
end
|
||||
|
||||
context "Job from other project" do
|
||||
before do
|
||||
visit project_job_path(project, job2)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": { "type": "integer" },
|
||||
"title": { "type": "string" },
|
||||
"created_at": { "type": "date-time" },
|
||||
"updated_at": { "type": "date-time" },
|
||||
"active": { "type": "boolean" },
|
||||
"commit_events": { "type": "boolean" },
|
||||
"push_events": { "type": "boolean" },
|
||||
"issues_events": { "type": "boolean" },
|
||||
"confidential_issues_events": { "type": "boolean" },
|
||||
"merge_requests_events": { "type": "boolean" },
|
||||
"tag_push_events": { "type": "boolean" },
|
||||
"note_events": { "type": "boolean" },
|
||||
"confidential_note_events": { "type": "boolean" },
|
||||
"pipeline_events": { "type": "boolean" },
|
||||
"wiki_page_events": { "type": "boolean" },
|
||||
"job_events": { "type": "boolean" }
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"type": "array",
|
||||
"items": { "$ref": "service.json" }
|
||||
}
|
||||
|
|
@ -182,4 +182,21 @@ describe('Participants', function() {
|
|||
expect(vm.$emit).toHaveBeenCalledWith('toggleSidebar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when not showing participants label', () => {
|
||||
beforeEach(() => {
|
||||
vm = mountComponent(Participants, {
|
||||
participants: PARTICIPANT_LIST,
|
||||
showParticipantLabel: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('does not show sidebar collapsed icon', () => {
|
||||
expect(vm.$el.querySelector('.sidebar-collapsed-icon')).not.toBeTruthy();
|
||||
});
|
||||
|
||||
it('does not show participants label title', () => {
|
||||
expect(vm.$el.querySelector('.title')).not.toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::BackgroundMigration::MigrateFingerprintSha256WithinKeys, :migration, schema: 20200106071113 do
|
||||
subject(:fingerprint_migrator) { described_class.new }
|
||||
|
||||
let(:key_table) { table(:keys) }
|
||||
|
||||
before do
|
||||
generate_fingerprints!
|
||||
end
|
||||
|
||||
it 'correctly creates a sha256 fingerprint for a key' do
|
||||
key_1 = Key.find(1017)
|
||||
key_2 = Key.find(1027)
|
||||
|
||||
expect(key_1.fingerprint_md5).to eq('ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1')
|
||||
expect(key_1.fingerprint_sha256).to eq(nil)
|
||||
|
||||
expect(key_2.fingerprint_md5).to eq('39:e3:64:a6:24:ea:45:a2:8c:55:2a:e9:4d:4f:1f:b4')
|
||||
expect(key_2.fingerprint_sha256).to eq(nil)
|
||||
|
||||
query_count = ActiveRecord::QueryRecorder.new do
|
||||
fingerprint_migrator.perform(1, 10000)
|
||||
end.count
|
||||
|
||||
expect(query_count).to eq(8)
|
||||
|
||||
key_1.reload
|
||||
key_2.reload
|
||||
|
||||
expect(key_1.fingerprint_md5).to eq('ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1')
|
||||
expect(key_1.fingerprint_sha256).to eq('nUhzNyftwADy8AH3wFY31tAKs7HufskYTte2aXo/lCg')
|
||||
|
||||
expect(key_2.fingerprint_md5).to eq('39:e3:64:a6:24:ea:45:a2:8c:55:2a:e9:4d:4f:1f:b4')
|
||||
expect(key_2.fingerprint_sha256).to eq('zMNbLekgdjtcgDv8VSC0z5lpdACMG3Q4PUoIz5+H2jM')
|
||||
end
|
||||
|
||||
it 'migrates all keys' do
|
||||
expect(Key.where(fingerprint_sha256: nil).count).to eq(Key.all.count)
|
||||
|
||||
fingerprint_migrator.perform(1, 10000)
|
||||
|
||||
expect(Key.where(fingerprint_sha256: nil).count).to eq(0)
|
||||
end
|
||||
|
||||
def generate_fingerprints!
|
||||
values = ""
|
||||
(1000..2000).to_a.each do |record|
|
||||
key = base_key_for(record)
|
||||
fingerprint = fingerprint_for(key)
|
||||
|
||||
values += "(#{record}, #{record}, 'test-#{record}', '#{key}', '#{fingerprint}'),"
|
||||
end
|
||||
|
||||
update_query = <<~SQL
|
||||
INSERT INTO keys ( id, user_id, title, key, fingerprint )
|
||||
VALUES
|
||||
#{values.chomp(",")};
|
||||
SQL
|
||||
|
||||
ActiveRecord::Base.connection.execute(update_query)
|
||||
end
|
||||
|
||||
def base_key_for(record)
|
||||
'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt0000k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0='
|
||||
.gsub("0000", "%04d" % (record - 1)) # generate arbitrary keys with placeholder 0000 within the key above
|
||||
end
|
||||
|
||||
def fingerprint_for(key)
|
||||
Gitlab::SSHPublicKey.new(key).fingerprint("md5")
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
require Rails.root.join('db', 'post_migrate', '20200106071113_update_fingerprint_sha256_within_keys.rb')
|
||||
|
||||
describe UpdateFingerprintSha256WithinKeys, :sidekiq, :migration do
|
||||
let(:key_table) { table(:keys) }
|
||||
|
||||
describe '#up' do
|
||||
it 'the BackgroundMigrationWorker will be triggered and fingerprint_sha256 populated' do
|
||||
key_table.create!(
|
||||
id: 1,
|
||||
user_id: 1,
|
||||
title: 'test',
|
||||
key: 'ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt1016k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=',
|
||||
fingerprint: 'ba:81:59:68:d7:6c:cd:02:02:bf:6a:9b:55:4e:af:d1',
|
||||
fingerprint_sha256: nil
|
||||
)
|
||||
|
||||
expect(Key.first.fingerprint_sha256).to eq(nil)
|
||||
|
||||
described_class.new.up
|
||||
|
||||
expect(BackgroundMigrationWorker.jobs.size).to eq(1)
|
||||
expect(BackgroundMigrationWorker.jobs.first["args"][0]).to eq("MigrateFingerprintSha256WithinKeys")
|
||||
expect(BackgroundMigrationWorker.jobs.first["args"][1]).to eq([1, 1])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1610,6 +1610,12 @@ describe Ci::Build do
|
|||
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
|
||||
context 'when build is waiting for resource' do
|
||||
let(:build) { create(:ci_build, :waiting_for_resource) }
|
||||
|
||||
it { is_expected.to be_cancelable }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when build is not cancelable' do
|
||||
|
|
|
|||
|
|
@ -10,6 +10,37 @@ describe API::Services do
|
|||
create(:project, creator_id: user.id, namespace: user.namespace)
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/services" do
|
||||
it 'returns authentication error when unauthenticated' do
|
||||
get api("/projects/#{project.id}/services")
|
||||
|
||||
expect(response).to have_gitlab_http_status(401)
|
||||
end
|
||||
|
||||
it "returns error when authenticated but user is not a project owner" do
|
||||
project.add_developer(user2)
|
||||
get api("/projects/#{project.id}/services", user2)
|
||||
|
||||
expect(response).to have_gitlab_http_status(403)
|
||||
end
|
||||
|
||||
context 'project with services' do
|
||||
let!(:active_service) { create(:emails_on_push_service, project: project, active: true) }
|
||||
let!(:service) { create(:custom_issue_tracker_service, project: project, active: false) }
|
||||
|
||||
it "returns a list of all active services" do
|
||||
get api("/projects/#{project.id}/services", user)
|
||||
|
||||
aggregate_failures 'expect successful response with all active services' do
|
||||
expect(response).to have_gitlab_http_status(200)
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.count).to eq(1)
|
||||
expect(response).to match_response_schema('public_api/v4/services')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Service.available_services_names.each do |service|
|
||||
describe "PUT /projects/:id/services/#{service.dasherize}" do
|
||||
include_context service
|
||||
|
|
|
|||
Loading…
Reference in New Issue