Commit af7bdf18 authored by GitLab Bot's avatar GitLab Bot

Merge remote-tracking branch 'upstream/master' into ce-to-ee-2018-10-23

# Conflicts:
#	app/assets/stylesheets/pages/issues.scss
#	app/models/user.rb
#	db/schema.rb
#	locale/gitlab.pot

[ci skip]
parents 4cdade66 ba3e6500
...@@ -903,7 +903,7 @@ gitlab:assets:compile: ...@@ -903,7 +903,7 @@ gitlab:assets:compile:
- public/assets/ - public/assets/
karma: karma:
<<: *dedicated-no-docs-and-no-qa-pull-cache-job <<: *dedicated-no-docs-pull-cache-job
<<: *use-pg <<: *use-pg
dependencies: dependencies:
- compile-assets - compile-assets
......
...@@ -67,6 +67,11 @@ export const conditions = [ ...@@ -67,6 +67,11 @@ export const conditions = [
tokenKey: 'milestone', tokenKey: 'milestone',
value: 'none', value: 'none',
}, },
{
url: 'milestone_title=Any+Milestone',
tokenKey: 'milestone',
value: 'any',
},
{ {
url: 'milestone_title=%23upcoming', url: 'milestone_title=%23upcoming',
tokenKey: 'milestone', tokenKey: 'milestone',
......
...@@ -330,6 +330,7 @@ ul.related-merge-requests > li { ...@@ -330,6 +330,7 @@ ul.related-merge-requests > li {
text-align: right; text-align: right;
} }
} }
<<<<<<< HEAD
.issue-token { .issue-token {
display: inline-flex; display: inline-flex;
...@@ -436,3 +437,5 @@ ul.related-merge-requests > li { ...@@ -436,3 +437,5 @@ ul.related-merge-requests > li {
font-size: 0.9em; font-size: 0.9em;
} }
} }
=======
>>>>>>> upstream/master
...@@ -388,8 +388,8 @@ module IssuablesHelper ...@@ -388,8 +388,8 @@ module IssuablesHelper
{ {
todo_text: "Add todo", todo_text: "Add todo",
mark_text: "Mark todo as done", mark_text: "Mark todo as done",
todo_icon: (is_collapsed ? icon('plus-square') : nil), todo_icon: (is_collapsed ? sprite_icon('todo-add') : nil),
mark_icon: (is_collapsed ? icon('check-square', class: 'todo-undone') : nil), mark_icon: (is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : nil),
issuable_id: issuable.id, issuable_id: issuable.id,
issuable_type: issuable.class.name.underscore, issuable_type: issuable.class.name.underscore,
url: project_todos_path(@project), url: project_todos_path(@project),
......
...@@ -281,6 +281,12 @@ module Ci ...@@ -281,6 +281,12 @@ module Ci
stage unless stage.statuses_count.zero? stage unless stage.statuses_count.zero?
end end
def ref_exists?
project.repository.ref_exists?(git_ref)
rescue Gitlab::Git::Repository::NoRepository
false
end
## ##
# TODO We do not completely switch to persisted stages because of # TODO We do not completely switch to persisted stages because of
# race conditions with setting statuses gitlab-ce#23257. # race conditions with setting statuses gitlab-ce#23257.
...@@ -687,11 +693,11 @@ module Ci ...@@ -687,11 +693,11 @@ module Ci
def push_details def push_details
strong_memoize(:push_details) do strong_memoize(:push_details) do
Gitlab::Git::Push.new(project, before_sha, sha, push_ref) Gitlab::Git::Push.new(project, before_sha, sha, git_ref)
end end
end end
def push_ref def git_ref
if branch? if branch?
Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s Gitlab::Git::BRANCH_REF_PREFIX + ref.to_s
elsif tag? elsif tag?
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
module Clusters module Clusters
module Applications module Applications
class Runner < ActiveRecord::Base class Runner < ActiveRecord::Base
VERSION = '0.1.34'.freeze VERSION = '0.1.35'.freeze
self.table_name = 'clusters_applications_runners' self.table_name = 'clusters_applications_runners'
......
...@@ -561,6 +561,8 @@ class Project < ActiveRecord::Base ...@@ -561,6 +561,8 @@ class Project < ActiveRecord::Base
self[:lfs_enabled] && Gitlab.config.lfs.enabled self[:lfs_enabled] && Gitlab.config.lfs.enabled
end end
alias_method :lfs_enabled, :lfs_enabled?
def auto_devops_enabled? def auto_devops_enabled?
if auto_devops&.enabled.nil? if auto_devops&.enabled.nil?
has_auto_devops_implicitly_enabled? has_auto_devops_implicitly_enabled?
......
...@@ -229,8 +229,11 @@ class User < ActiveRecord::Base ...@@ -229,8 +229,11 @@ class User < ActiveRecord::Base
delegate :path, to: :namespace, allow_nil: true, prefix: true delegate :path, to: :namespace, allow_nil: true, prefix: true
delegate :notes_filter_for, to: :user_preference delegate :notes_filter_for, to: :user_preference
delegate :set_notes_filter, to: :user_preference delegate :set_notes_filter, to: :user_preference
<<<<<<< HEAD
accepts_nested_attributes_for :namespace accepts_nested_attributes_for :namespace
=======
>>>>>>> upstream/master
state_machine :state, initial: :active do state_machine :state, initial: :active do
event :block do event :block do
......
...@@ -13,7 +13,11 @@ ...@@ -13,7 +13,11 @@
= pluralize @pipeline.total_size, "job" = pluralize @pipeline.total_size, "job"
- if @pipeline.ref - if @pipeline.ref
from from
= link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name" - if @pipeline.ref_exists?
= link_to @pipeline.ref, project_ref_path(@project, @pipeline.ref), class: "ref-name"
- else
%span.ref-name
= @pipeline.ref
- if @pipeline.duration - if @pipeline.duration
in in
= time_interval_in_words(@pipeline.duration) = time_interval_in_words(@pipeline.duration)
......
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
= sprite_icon('search') = sprite_icon('search')
%span %span
Press Enter or click to search = _('Press Enter or click to search')
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item %li.filter-dropdown-item
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
No Assignee = _('No Assignee')
%li.divider.droplab-item-ignore %li.divider.droplab-item-ignore
- if current_user - if current_user
= render 'shared/issuable/user_dropdown_item', = render 'shared/issuable/user_dropdown_item',
...@@ -74,13 +74,16 @@ ...@@ -74,13 +74,16 @@
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
No Milestone = _('None')
%li.filter-dropdown-item{ data: { value: 'any' } }
%button.btn.btn-link{ type: 'button' }
= _('Any')
%li.filter-dropdown-item{ data: { value: 'upcoming' } } %li.filter-dropdown-item{ data: { value: 'upcoming' } }
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
Upcoming = _('Upcoming')
%li.filter-dropdown-item{ 'data-value' => 'started' } %li.filter-dropdown-item{ 'data-value' => 'started' }
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
Started = _('Started')
%li.divider.droplab-item-ignore %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item %li.filter-dropdown-item
...@@ -90,7 +93,7 @@ ...@@ -90,7 +93,7 @@
%ul{ data: { dropdown: true } } %ul{ data: { dropdown: true } }
%li.filter-dropdown-item{ data: { value: 'none' } } %li.filter-dropdown-item{ data: { value: 'none' } }
%button.btn.btn-link{ type: 'button' } %button.btn.btn-link{ type: 'button' }
No Label = _('No Label')
%li.divider.droplab-item-ignore %li.divider.droplab-item-ignore
%ul.filter-dropdown{ data: { dynamic: true, dropdown: true } } %ul.filter-dropdown{ data: { dynamic: true, dropdown: true } }
%li.filter-dropdown-item %li.filter-dropdown-item
......
- is_collapsed = local_assigns.fetch(:is_collapsed, false) - is_collapsed = local_assigns.fetch(:is_collapsed, false)
- mark_content = is_collapsed ? icon('check-square', class: 'todo-undone') : _('Mark todo as done') - mark_content = is_collapsed ? sprite_icon('todo-done', css_class: 'todo-undone') : _('Mark todo as done')
- todo_content = is_collapsed ? icon('plus-square') : _('Add todo') - todo_content = is_collapsed ? sprite_icon('todo-add') : _('Add todo')
%button.issuable-todo-btn.js-issuable-todo{ type: 'button', %button.issuable-todo-btn.js-issuable-todo{ type: 'button',
class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'btn btn-default issuable-header-btn float-right'), class: (is_collapsed ? 'btn-blank sidebar-collapsed-icon dont-change-state has-tooltip' : 'btn btn-default issuable-header-btn float-right'),
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
%td= @runner.active? ? 'Yes' : 'No' %td= @runner.active? ? 'Yes' : 'No'
%tr %tr
%td Protected %td Protected
%td= @runner.active? ? _('Yes') : _('No') %td= @runner.ref_protected? ? 'Yes' : 'No'
%tr %tr
%td Can run untagged jobs %td Can run untagged jobs
%td= @runner.run_untagged? ? 'Yes' : 'No' %td= @runner.run_untagged? ? 'Yes' : 'No'
......
---
title: Update Todo icons in collapsed sidebar for Issues and MRs
merge_request: 22534
author:
type: changed
---
title: Only render link to branch when branch still exists in pipeline page
merge_request:
author:
type: fixed
---
title: Added `Any` option to milestones filter
merge_request: 22351
author: Heinrich Lee Yu
type: added
---
title: Fix rendering of 'Protected' value on Runner details page
merge_request: 22459
author:
type: fixed
---
title: Introduce new kubernetes helpers
merge_request: 22525
author:
type: other
---
title: Allow kubeclient to call RoleBinding methods
merge_request: 22524
author:
type: other
---
title: Resolve LFS not correctly showing enabled
merge_request: 22501
author:
type: fixed
---
title: Fix EOF detection with CI artifacts metadata
merge_request: 22479
author:
type: fixed
---
title: Update used version of Runner Helm Chart to 0.1.35
merge_request: 22541
author:
type: other
...@@ -915,9 +915,6 @@ test: ...@@ -915,9 +915,6 @@ test:
default: default:
path: tmp/tests/repositories/ path: tmp/tests/repositories/
gitaly_address: unix:tmp/tests/gitaly/gitaly.socket gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
broken:
path: tmp/tests/non-existent-repositories
gitaly_address: unix:tmp/tests/gitaly/gitaly.socket
gitaly: gitaly:
client_path: tmp/tests/gitaly client_path: tmp/tests/gitaly
......
...@@ -3384,8 +3384,13 @@ ActiveRecord::Schema.define(version: 20181017131623) do ...@@ -3384,8 +3384,13 @@ ActiveRecord::Schema.define(version: 20181017131623) do
add_foreign_key "u2f_registrations", "users" add_foreign_key "u2f_registrations", "users"
add_foreign_key "user_callouts", "users", on_delete: :cascade add_foreign_key "user_callouts", "users", on_delete: :cascade
add_foreign_key "user_custom_attributes", "users", on_delete: :cascade add_foreign_key "user_custom_attributes", "users", on_delete: :cascade
<<<<<<< HEAD
add_foreign_key "user_interacted_projects", "projects", on_delete: :cascade add_foreign_key "user_interacted_projects", "projects", on_delete: :cascade
add_foreign_key "user_interacted_projects", "users", on_delete: :cascade add_foreign_key "user_interacted_projects", "users", on_delete: :cascade
=======
add_foreign_key "user_interacted_projects", "projects", name: "fk_722ceba4f7", on_delete: :cascade
add_foreign_key "user_interacted_projects", "users", name: "fk_0894651f08", on_delete: :cascade
>>>>>>> upstream/master
add_foreign_key "user_preferences", "users", on_delete: :cascade add_foreign_key "user_preferences", "users", on_delete: :cascade
add_foreign_key "user_statuses", "users", on_delete: :cascade add_foreign_key "user_statuses", "users", on_delete: :cascade
add_foreign_key "user_synced_attributes_metadata", "users", on_delete: :cascade add_foreign_key "user_synced_attributes_metadata", "users", on_delete: :cascade
......
...@@ -411,6 +411,23 @@ args: { ...@@ -411,6 +411,23 @@ args: {
} }
``` ```
### `uid_attribute`
> [Introduced](https://gitlab.com/gitlab-org/gitlab-ce/issues/43806) in GitLab 10.7.
By default, the `uid` is set as the `name_id` in the SAML response. If you'd like to designate a unique attribute for the `uid`, you can set the `uid_attribute`. In the example below, the value of `uid` attribute in the SAML response is set as the `uid_attribute`.
```yaml
args: {
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
idp_sso_target_url: 'https://login.example.com/idp',
issuer: 'https://gitlab.example.com',
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
uid_attribute: 'uid'
}
```
## Troubleshooting ## Troubleshooting
### 500 error after login ### 500 error after login
......
...@@ -74,7 +74,8 @@ From the project issue/merge request list pages and the group issue/merge reques ...@@ -74,7 +74,8 @@ From the project issue/merge request list pages and the group issue/merge reques
When filtering by milestone, in addition to choosing a specific project milestone or group milestone, you can choose a special milestone filter. When filtering by milestone, in addition to choosing a specific project milestone or group milestone, you can choose a special milestone filter.
- **No Milestone**: Show issues or merge requests with no assigned milestone. - **None**: Show issues or merge requests with no assigned milestone.
- **Any**: Show issues or merge requests that have an assigned milestone.
- **Upcoming**: Show issues or merge requests that have been assigned the open milestone that has the next upcoming due date (i.e. nearest due date in the future). - **Upcoming**: Show issues or merge requests that have been assigned the open milestone that has the next upcoming due date (i.e. nearest due date in the future).
- **Started**: Show issues or merge requests that have an assigned milestone with a start date that is before today. - **Started**: Show issues or merge requests that have an assigned milestone with a start date that is before today.
......
...@@ -59,9 +59,12 @@ module Gitlab ...@@ -59,9 +59,12 @@ module Gitlab
until gz.eof? until gz.eof?
begin begin
path = read_string(gz).force_encoding('UTF-8') path = read_string(gz)&.force_encoding('UTF-8')
meta = read_string(gz).force_encoding('UTF-8') meta = read_string(gz)&.force_encoding('UTF-8')
# We might hit an EOF while reading either value, so we should
# abort if we don't get any data.
next unless path && meta
next unless path.valid_encoding? && meta.valid_encoding? next unless path.valid_encoding? && meta.valid_encoding?
next unless path =~ match_pattern next unless path =~ match_pattern
next if path =~ INVALID_PATH_PATTERN next if path =~ INVALID_PATH_PATTERN
......
...@@ -937,7 +937,7 @@ database (#{dbname}) using a super user and running: ...@@ -937,7 +937,7 @@ database (#{dbname}) using a super user and running:
For MySQL you instead need to run: For MySQL you instead need to run:
GRANT ALL PRIVILEGES ON *.* TO #{user}@'%' GRANT ALL PRIVILEGES ON #{dbname}.* TO #{user}@'%'
Both queries will grant the user super user permissions, ensuring you don't run Both queries will grant the user super user permissions, ensuring you don't run
into similar problems in the future (e.g. when new tables are created). into similar problems in the future (e.g. when new tables are created).
......
...@@ -45,6 +45,13 @@ module Gitlab ...@@ -45,6 +45,13 @@ module Gitlab
:update_cluster_role_binding, :update_cluster_role_binding,
to: :rbac_client to: :rbac_client
# RBAC methods delegates to the apis/rbac.authorization.k8s.io api
# group client
delegate :create_role_binding,
:get_role_binding,
:update_role_binding,
to: :rbac_client
# Deployments resource is currently on the apis/extensions api group # Deployments resource is currently on the apis/extensions api group
delegate :get_deployments, delegate :get_deployments,
to: :extensions_client to: :extensions_client
......
# frozen_string_literal: true
module Gitlab
module Kubernetes
class RoleBinding
attr_reader :role_name, :namespace, :service_account_name
def initialize(role_name:, namespace:, service_account_name:)
@role_name = role_name
@namespace = namespace
@service_account_name = service_account_name
end
def generate
::Kubeclient::Resource.new.tap do |resource|
resource.metadata = metadata
resource.roleRef = role_ref
resource.subjects = subjects
end
end
private
def metadata
{ name: "gitlab-#{namespace}", namespace: namespace }
end
def role_ref
{
apiGroup: 'rbac.authorization.k8s.io',
kind: 'Role',
name: role_name
}
end
def subjects
[
{
kind: 'ServiceAccount',
name: service_account_name,
namespace: namespace
}
]
end
end
end
end
...@@ -32,7 +32,10 @@ module Gitlab ...@@ -32,7 +32,10 @@ module Gitlab
end end
if Rails.env.test? if Rails.env.test?
storages << { name: 'test_second_storage', path: Rails.root.join('tmp', 'tests', 'second_storage').to_s } storage_path = Rails.root.join('tmp', 'tests', 'second_storage').to_s
FileUtils.mkdir(storage_path) unless File.exist?(storage_path)
storages << { name: 'test_second_storage', path: storage_path }
end end
config = { socket_path: address.sub(/\Aunix:/, ''), storage: storages } config = { socket_path: address.sub(/\Aunix:/, ''), storage: storages }
......
...@@ -5254,6 +5254,12 @@ msgstr "" ...@@ -5254,6 +5254,12 @@ msgstr ""
msgid "No" msgid "No"
msgstr "" msgstr ""
<<<<<<< HEAD
=======
msgid "No Assignee"
msgstr ""
>>>>>>> upstream/master
msgid "No Label" msgid "No Label"
msgstr "" msgstr ""
...@@ -7233,6 +7239,7 @@ msgstr "" ...@@ -7233,6 +7239,7 @@ msgstr ""
msgid "Something went wrong while closing the %{issuable}. Please try again later" msgid "Something went wrong while closing the %{issuable}. Please try again later"
msgstr "" msgstr ""
<<<<<<< HEAD
msgid "Something went wrong while fetching %{listType} list" msgid "Something went wrong while fetching %{listType} list"
msgstr "" msgstr ""
...@@ -7242,6 +7249,11 @@ msgstr "" ...@@ -7242,6 +7249,11 @@ msgstr ""
msgid "Something went wrong while fetching group member contributions" msgid "Something went wrong while fetching group member contributions"
msgstr "" msgstr ""
=======
msgid "Something went wrong while fetching comments. Please try again."
msgstr ""
>>>>>>> upstream/master
msgid "Something went wrong while fetching the projects." msgid "Something went wrong while fetching the projects."
msgstr "" msgstr ""
...@@ -8376,6 +8388,9 @@ msgstr "" ...@@ -8376,6 +8388,9 @@ msgstr ""
msgid "Up to date" msgid "Up to date"
msgstr "" msgstr ""
msgid "Upcoming"
msgstr ""
msgid "Update" msgid "Update"
msgstr "" msgstr ""
......
...@@ -47,5 +47,15 @@ FactoryBot.define do ...@@ -47,5 +47,15 @@ FactoryBot.define do
trait :ref_protected do trait :ref_protected do
access_level :ref_protected access_level :ref_protected
end end
trait :tagged_only do
run_untagged false
tag_list %w(tag1 tag2)
end
trait :locked do
locked true
end
end end
end end
...@@ -189,13 +189,21 @@ describe 'Dropdown milestone', :js do ...@@ -189,13 +189,21 @@ describe 'Dropdown milestone', :js do
end end
it 'selects `no milestone`' do it 'selects `no milestone`' do
click_static_milestone('No Milestone') click_static_milestone('None')
expect(page).to have_css(js_dropdown_milestone, visible: false) expect(page).to have_css(js_dropdown_milestone, visible: false)
expect_tokens([milestone_token('none', false)]) expect_tokens([milestone_token('none', false)])
expect_filtered_search_input_empty expect_filtered_search_input_empty
end end
it 'selects `any milestone`' do
click_static_milestone('Any')
expect(page).to have_css(js_dropdown_milestone, visible: false)
expect_tokens([milestone_token('any', false)])
expect_filtered_search_input_empty
end
it 'selects `upcoming milestone`' do it 'selects `upcoming milestone`' do
click_static_milestone('Upcoming') click_static_milestone('Upcoming')
......
...@@ -68,6 +68,10 @@ describe 'Pipeline', :js do ...@@ -68,6 +68,10 @@ describe 'Pipeline', :js do
expect(page).to have_css('#js-tab-pipeline.active') expect(page).to have_css('#js-tab-pipeline.active')
end end
it 'shows link to the pipeline ref' do
expect(page).to have_link(pipeline.ref)
end
it_behaves_like 'showing user status' do it_behaves_like 'showing user status' do
let(:user_with_status) { pipeline.user } let(:user_with_status) { pipeline.user }
...@@ -236,6 +240,20 @@ describe 'Pipeline', :js do ...@@ -236,6 +240,20 @@ describe 'Pipeline', :js do
it { expect(page).not_to have_content('Cancel running') } it { expect(page).not_to have_content('Cancel running') }
end end
end end
context 'when pipeline ref does not exist in repository anymore' do
let(:pipeline) do
create(:ci_empty_pipeline, project: project,
ref: 'non-existent',
sha: project.commit.id,
user: user)
end
it 'does not render link to the pipeline ref' do
expect(page).not_to have_link(pipeline.ref)
expect(page).to have_content(pipeline.ref)
end
end
end end
context 'when user does not have access to read jobs' do context 'when user does not have access to read jobs' do
......
...@@ -45,8 +45,10 @@ describe('Issuable right sidebar collapsed todo toggle', () => { ...@@ -45,8 +45,10 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
expect(document.querySelector('.js-issuable-todo.sidebar-collapsed-icon')).not.toBeNull(); expect(document.querySelector('.js-issuable-todo.sidebar-collapsed-icon')).not.toBeNull();
expect( expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .fa-plus-square'), document
).not.toBeNull(); .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg use')
.getAttribute('xlink:href'),
).toContain('todo-add');
expect( expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'), document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .todo-undone'),
...@@ -68,8 +70,10 @@ describe('Issuable right sidebar collapsed todo toggle', () => { ...@@ -68,8 +70,10 @@ describe('Issuable right sidebar collapsed todo toggle', () => {
).not.toBeNull(); ).not.toBeNull();
expect( expect(
document.querySelector('.js-issuable-todo.sidebar-collapsed-icon .fa-check-square'), document
).not.toBeNull(); .querySelector('.js-issuable-todo.sidebar-collapsed-icon svg.todo-undone use')
.getAttribute('xlink:href'),
).toContain('todo-done');
done(); done();
}); });
......
...@@ -26,9 +26,7 @@ describe Gitaly::Server do ...@@ -26,9 +26,7 @@ describe Gitaly::Server do
end end
end end
context 'when the storage is not readable' do context 'when the storage is not readable', :broken_storage do
let(:server) { described_class.new('broken') }
it 'returns false' do it 'returns false' do
expect(server).not_to be_readable expect(server).not_to be_readable
end end
...@@ -42,9 +40,7 @@ describe Gitaly::Server do ...@@ -42,9 +40,7 @@ describe Gitaly::Server do
end end
end end
context 'when the storage is not writeable' do context 'when the storage is not writeable', :broken_storage do
let(:server) { described_class.new('broken') }
it 'returns false' do it 'returns false' do
expect(server).not_to be_writeable expect(server).not_to be_writeable
end end
......
...@@ -112,4 +112,34 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do ...@@ -112,4 +112,34 @@ describe Gitlab::Ci::Build::Artifacts::Metadata do
end end
end end
end end
context 'generated metadata' do
let(:tmpfile) { Tempfile.new('test-metadata') }
let(:generator) { CiArtifactMetadataGenerator.new(tmpfile) }
let(:entry_count) { 5 }
before do
tmpfile.binmode
(1..entry_count).each do |index|
generator.add_entry("public/test-#{index}.txt")
end
generator.write
end
after do
File.unlink(tmpfile.path)
end
describe '#find_entries!' do
it 'reads expected number of entries' do
stream = File.open(tmpfile.path)
metadata = described_class.new(stream, 'public', { recursive: true })
expect(metadata.find_entries!.count).to eq entry_count
end
end
end
end end
...@@ -335,7 +335,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do ...@@ -335,7 +335,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do
restored_project_json restored_project_json
expect(project.lfs_enabled).to be_nil expect(project.lfs_enabled).to be_falsey
end end
end end
......
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::Kubernetes::RoleBinding, '#generate' do
let(:role_name) { 'edit' }
let(:namespace) { 'my-namespace' }
let(:service_account_name) { 'my-service-account' }
let(:subjects) do
[
{
kind: 'ServiceAccount',
name: service_account_name,
namespace: namespace
}
]
end
let(:role_ref) do
{
apiGroup: 'rbac.authorization.k8s.io',
kind: 'Role',
name: role_name
}
end
let(:resource) do
::Kubeclient::Resource.new(
metadata: { name: "gitlab-#{namespace}", namespace: namespace },
roleRef: role_ref,
subjects: subjects
)
end
subject do
described_class.new(
role_name: role_name,
namespace: namespace,
service_account_name: service_account_name
).generate
end
it 'should build a Kubeclient Resource' do
is_expected.to eq(resource)
end
end
...@@ -788,6 +788,41 @@ describe Ci::Pipeline, :mailer do ...@@ -788,6 +788,41 @@ describe Ci::Pipeline, :mailer do
end end
end end
describe 'ref_exists?' do
context 'when repository exists' do
using RSpec::Parameterized::TableSyntax
let(:project) { create(:project, :repository) }
where(:tag, :ref, :result) do
false | 'master' | true
false | 'non-existent-branch' | false
true | 'v1.1.0' | true
true | 'non-existent-tag' | false
end
with_them do
let(:pipeline) do
create(:ci_empty_pipeline, project: project, tag: tag, ref: ref)
end
it "correctly detects ref" do
expect(pipeline.ref_exists?).to be result
end
end
end
context 'when repository does not exist' do
let(:pipeline) do
create(:ci_empty_pipeline, project: project, ref: 'master')
end
it 'always returns false' do
expect(pipeline.ref_exists?).to eq false
end
end
end
context 'with non-empty project' do context 'with non-empty project' do
let(:project) { create(:project, :repository) } let(:project) { create(:project, :repository) }
......
...@@ -17,7 +17,7 @@ describe Clusters::Applications::Runner do ...@@ -17,7 +17,7 @@ describe Clusters::Applications::Runner do
let(:application) { create(:clusters_applications_runner, :scheduled, version: '0.1.30') } let(:application) { create(:clusters_applications_runner, :scheduled, version: '0.1.30') }
it 'updates the application version' do it 'updates the application version' do
expect(application.reload.version).to eq('0.1.34') expect(application.reload.version).to eq('0.1.35')
end end
end end
end end
...@@ -45,7 +45,7 @@ describe Clusters::Applications::Runner do ...@@ -45,7 +45,7 @@ describe Clusters::Applications::Runner do
it 'should be initialized with 4 arguments' do it 'should be initialized with 4 arguments' do
expect(subject.name).to eq('runner') expect(subject.name).to eq('runner')
expect(subject.chart).to eq('runner/gitlab-runner') expect(subject.chart).to eq('runner/gitlab-runner')
expect(subject.version).to eq('0.1.34') expect(subject.version).to eq('0.1.35')
expect(subject).not_to be_rbac expect(subject).not_to be_rbac
expect(subject.repository).to eq('https://charts.gitlab.io') expect(subject.repository).to eq('https://charts.gitlab.io')
expect(subject.files).to eq(gitlab_runner.files) expect(subject.files).to eq(gitlab_runner.files)
...@@ -63,7 +63,7 @@ describe Clusters::Applications::Runner do ...@@ -63,7 +63,7 @@ describe Clusters::Applications::Runner do
let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') } let(:gitlab_runner) { create(:clusters_applications_runner, :errored, runner: ci_runner, version: '0.1.13') }
it 'should be initialized with the locked version' do it 'should be initialized with the locked version' do
expect(subject.version).to eq('0.1.34') expect(subject.version).to eq('0.1.35')
end end
end end
end end
......
# frozen_sting_literal: true
# This generates fake CI metadata .gz for testing
# Based off https://gitlab.com/gitlab-org/gitlab-workhorse/blob/master/internal/zipartifacts/metadata.go
class CiArtifactMetadataGenerator
attr_accessor :entries, :output
ARTIFACT_METADATA = "GitLab Build Artifacts Metadata 0.0.2\n".freeze
def initialize(stream)
@entries = {}
@output = Zlib::GzipWriter.new(stream)
end
def add_entry(filename)
@entries[filename] = { CRC: rand(0xfffffff), Comment: FFaker::Lorem.sentence(10) }
end
def write
write_version
write_errors
write_entries
output.close
end
private
def write_version
write_string(ARTIFACT_METADATA)
end
def write_errors
write_string('{}')
end
def write_entries
entries.each do |filename, metadata|
write_string(filename)
write_string(metadata.to_json + "\n")
end
end
def write_string(data)
bytes = [data.length].pack('L>')
output.write(bytes)
output.write(data)
end
end
...@@ -44,10 +44,11 @@ module KubernetesHelpers ...@@ -44,10 +44,11 @@ module KubernetesHelpers
WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response) WebMock.stub_request(:get, deployments_url).to_return(response || kube_deployments_response)
end end
def stub_kubeclient_get_secret(api_url, namespace: 'default', **options) def stub_kubeclient_get_secret(api_url, **options)
options[:metadata_name] ||= "default-token-1" options[:metadata_name] ||= "default-token-1"
options[:namespace] ||= "default"
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}/secrets/#{options[:metadata_name]}") WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{options[:namespace]}/secrets/#{options[:metadata_name]}")
.to_return(kube_response(kube_v1_secret_body(options))) .to_return(kube_response(kube_v1_secret_body(options)))
end end
...@@ -76,6 +77,21 @@ module KubernetesHelpers ...@@ -76,6 +77,21 @@ module KubernetesHelpers
.to_return(kube_response({})) .to_return(kube_response({}))
end end
def stub_kubeclient_create_role_binding(api_url, namespace: 'default')
WebMock.stub_request(:post, api_url + "/apis/rbac.authorization.k8s.io/v1/namespaces/#{namespace}/rolebindings")
.to_return(kube_response({}))
end
def stub_kubeclient_create_namespace(api_url)
WebMock.stub_request(:post, api_url + "/api/v1/namespaces")
.to_return(kube_response({}))
end
def stub_kubeclient_get_namespace(api_url, namespace: 'default')
WebMock.stub_request(:get, api_url + "/api/v1/namespaces/#{namespace}")
.to_return(kube_response({}))
end
def kube_v1_secret_body(**options) def kube_v1_secret_body(**options)
{ {
"kind" => "SecretList", "kind" => "SecretList",
...@@ -98,7 +114,8 @@ module KubernetesHelpers ...@@ -98,7 +114,8 @@ module KubernetesHelpers
{ "name" => "deployments", "namespaced" => true, "kind" => "Deployment" }, { "name" => "deployments", "namespaced" => true, "kind" => "Deployment" },
{ "name" => "secrets", "namespaced" => true, "kind" => "Secret" }, { "name" => "secrets", "namespaced" => true, "kind" => "Secret" },
{ "name" => "serviceaccounts", "namespaced" => true, "kind" => "ServiceAccount" }, { "name" => "serviceaccounts", "namespaced" => true, "kind" => "ServiceAccount" },
{ "name" => "services", "namespaced" => true, "kind" => "Service" } { "name" => "services", "namespaced" => true, "kind" => "Service" },
{ "name" => "namespaces", "namespaced" => true, "kind" => "Namespace" }
] ]
} }
end end
......
...@@ -70,7 +70,6 @@ module TestEnv ...@@ -70,7 +70,6 @@ module TestEnv
TMP_TEST_PATH = Rails.root.join('tmp', 'tests', '**') TMP_TEST_PATH = Rails.root.join('tmp', 'tests', '**')
REPOS_STORAGE = 'default'.freeze REPOS_STORAGE = 'default'.freeze
BROKEN_STORAGE = 'broken'.freeze
# Test environment # Test environment
# #
...@@ -159,10 +158,6 @@ module TestEnv ...@@ -159,10 +158,6 @@ module TestEnv
version: Gitlab::GitalyClient.expected_server_version, version: Gitlab::GitalyClient.expected_server_version,
task: "gitlab:gitaly:install[#{gitaly_dir},#{repos_path}]") do task: "gitlab:gitaly:install[#{gitaly_dir},#{repos_path}]") do
# Re-create config, to specify the broken storage path
storage_paths = { 'default' => repos_path, 'broken' => broken_path }
Gitlab::SetupHelper.create_gitaly_configuration(gitaly_dir, storage_paths, force: true)
start_gitaly(gitaly_dir) start_gitaly(gitaly_dir)
end end
end end
...@@ -257,10 +252,6 @@ module TestEnv ...@@ -257,10 +252,6 @@ module TestEnv
@repos_path ||= Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path @repos_path ||= Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path
end end
def broken_path
@broken_path ||= Gitlab.config.repositories.storages[BROKEN_STORAGE].legacy_disk_path
end
def backup_path def backup_path
Gitlab.config.backup.path Gitlab.config.backup.path
end end
......
RSpec.configure do |config| RSpec.configure do |config|
config.before(:all, :broken_storage) do
FileUtils.rm_rf Gitlab.config.repositories.storages.broken.legacy_disk_path
end
config.before(:each, :broken_storage) do config.before(:each, :broken_storage) do
allow(Gitlab::GitalyClient).to receive(:call) do allow(Gitlab::GitalyClient).to receive(:call) do
raise GRPC::Unavailable.new('Gitaly broken in this spec') raise GRPC::Unavailable.new('Gitaly broken in this spec')
......
# frozen_string_literal: true
require 'spec_helper'
describe 'shared/runners/show.html.haml' do
include PageLayoutHelper
let(:runner) do
create(:ci_runner, name: 'test runner',
version: '11.4.0',
ip_address: '127.1.2.3',
revision: 'abcd1234',
architecture: 'amd64' )
end
before do
assign(:runner, runner)
end
subject do
render
rendered
end
describe 'Page title' do
before do
expect_any_instance_of(PageLayoutHelper).to receive(:page_title).with("#{runner.description} ##{runner.id}", 'Runners')
end
it 'sets proper page title' do
render
end
end
describe 'Runner id and type' do
context 'when runner is of type instance' do
it { is_expected.to have_content("Runner ##{runner.id} Shared") }
end
context 'when runner is of type group' do
let(:runner) { create(:ci_runner, :group) }
it { is_expected.to have_content("Runner ##{runner.id} Group") }
end
context 'when runner is of type project' do
let(:runner) { create(:ci_runner, :project) }
it { is_expected.to have_content("Runner ##{runner.id} Specific") }
end
end
describe 'Active value' do
context 'when runner is active' do
it { is_expected.to have_content('Active Yes') }
end
context 'when runner is inactive' do
let(:runner) { create(:ci_runner, :inactive) }
it { is_expected.to have_content('Active No') }
end
end
describe 'Protected value' do
context 'when runner is not protected' do
it { is_expected.to have_content('Protected No') }
end
context 'when runner is protected' do
let(:runner) { create(:ci_runner, :ref_protected) }
it { is_expected.to have_content('Protected Yes') }
end
end
describe 'Can run untagged jobs value' do
context 'when runner run untagged job is set' do
it { is_expected.to have_content('Can run untagged jobs Yes') }
end
context 'when runner run untagged job is unset' do
let(:runner) { create(:ci_runner, :tagged_only) }
it { is_expected.to have_content('Can run untagged jobs No') }
end
end
describe 'Locked to this project value' do
context 'when runner locked is not set' do
it { is_expected.to have_content('Locked to this project No') }
context 'when runner is of type group' do
let(:runner) { create(:ci_runner, :group) }
it { is_expected.not_to have_content('Locked to this project') }
end
end
context 'when runner locked is set' do
let(:runner) { create(:ci_runner, :locked) }
it { is_expected.to have_content('Locked to this project Yes') }
context 'when runner is of type group' do
let(:runner) { create(:ci_runner, :group, :locked) }
it { is_expected.not_to have_content('Locked to this project') }
end
end
end
describe 'Tags value' do
context 'when runner does not have tags' do
it { is_expected.to have_content('Tags') }
it { is_expected.not_to have_selector('span.badge.badge-primary')}
end
context 'when runner have tags' do
let(:runner) { create(:ci_runner, tag_list: %w(tag2 tag3 tag1)) }
it { is_expected.to have_content('Tags tag1 tag2 tag3') }
it { is_expected.to have_selector('span.badge.badge-primary')}
end
end
describe 'Metadata values' do
it { is_expected.to have_content("Name #{runner.name}") }
it { is_expected.to have_content("Version #{runner.version}") }
it { is_expected.to have_content("IP Address #{runner.ip_address}") }
it { is_expected.to have_content("Revision #{runner.revision}") }
it { is_expected.to have_content("Platform #{runner.platform}") }
it { is_expected.to have_content("Architecture #{runner.architecture}") }
it { is_expected.to have_content("Description #{runner.description}") }
end
describe 'Maximum job timeout value' do
let(:runner) { create(:ci_runner, maximum_timeout: 5400) }
it { is_expected.to have_content('Maximum job timeout 1h 30m') }
end
describe 'Last contact value' do
context 'when runner have not contacted yet' do
it { is_expected.to have_content('Last contact Never') }
end
context 'when runner have already contacted' do
let(:runner) { create(:ci_runner, contacted_at: DateTime.now - 6.days) }
let(:expected_contacted_at) { I18n.localize(runner.contacted_at, format: "%b %d, %Y") }
it { is_expected.to have_content("Last contact #{expected_contacted_at}") }
end
end
end
...@@ -51,7 +51,7 @@ describe RepositoryCheck::BatchWorker do ...@@ -51,7 +51,7 @@ describe RepositoryCheck::BatchWorker do
it 'does nothing when shard is unhealthy' do it 'does nothing when shard is unhealthy' do
shard_name = 'broken' shard_name = 'broken'
create(:project, created_at: 1.week.ago, repository_storage: shard_name) create(:project, :broken_storage, created_at: 1.week.ago)
expect(subject.perform(shard_name)).to eq(nil) expect(subject.perform(shard_name)).to eq(nil)
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment