Commit 42c08a02 authored by Pavel Shutsin's avatar Pavel Shutsin

Merge branch '339198-fj-ci-owned-runners' into 'master'

Use linear version of User#ci_owned_runners

See merge request gitlab-org/gitlab!68848
parents 6a9c73e7 a3454700
...@@ -1614,8 +1614,14 @@ class User < ApplicationRecord ...@@ -1614,8 +1614,14 @@ class User < ApplicationRecord
.joins(:runner) .joins(:runner)
.select('ci_runners.*') .select('ci_runners.*')
base_and_descendants = if Feature.enabled?(:linear_user_ci_owned_runners, self, default_enabled: :yaml)
owned_groups.self_and_descendant_ids
else
Gitlab::ObjectHierarchy.new(owned_groups).base_and_descendants.select(:id)
end
group_runners = Ci::RunnerNamespace group_runners = Ci::RunnerNamespace
.where(namespace_id: Gitlab::ObjectHierarchy.new(owned_groups).base_and_descendants.select(:id)) .where(namespace_id: base_and_descendants)
.joins(:runner) .joins(:runner)
.select('ci_runners.*') .select('ci_runners.*')
......
---
name: linear_user_ci_owned_runners
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68848
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/339435
milestone: '14.6'
type: development
group: group::access
default_enabled: false
...@@ -3673,309 +3673,321 @@ RSpec.describe User do ...@@ -3673,309 +3673,321 @@ RSpec.describe User do
end end
describe '#ci_owned_runners' do describe '#ci_owned_runners' do
let(:user) { create(:user) } shared_examples 'ci_owned_runners examples' do
let(:user) { create(:user) }
shared_examples :nested_groups_owner do shared_examples :nested_groups_owner do
context 'when the user is the owner of a multi-level group' do context 'when the user is the owner of a multi-level group' do
before do before do
set_permissions_for_users set_permissions_for_users
end end
it 'loads all the runners in the tree of groups' do it 'loads all the runners in the tree of groups' do
expect(user.ci_owned_runners).to contain_exactly(runner, group_runner) expect(user.ci_owned_runners).to contain_exactly(runner, group_runner)
end end
it 'returns true for owns_runner?' do it 'returns true for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(true) expect(user.owns_runner?(runner)).to eq(true)
expect(user.owns_runner?(group_runner)).to eq(true) expect(user.owns_runner?(group_runner)).to eq(true)
end
end end
end end
end
shared_examples :group_owner do shared_examples :group_owner do
context 'when the user is the owner of a one level group' do context 'when the user is the owner of a one level group' do
before do before do
group.add_owner(user) group.add_owner(user)
end end
it 'loads the runners in the group' do it 'loads the runners in the group' do
expect(user.ci_owned_runners).to contain_exactly(group_runner) expect(user.ci_owned_runners).to contain_exactly(group_runner)
end end
it 'returns true for owns_runner?' do it 'returns true for owns_runner?' do
expect(user.owns_runner?(group_runner)).to eq(true) expect(user.owns_runner?(group_runner)).to eq(true)
end
end end
end end
end
shared_examples :project_owner do shared_examples :project_owner do
context 'when the user is the owner of a project' do context 'when the user is the owner of a project' do
it 'loads the runner belonging to the project' do it 'loads the runner belonging to the project' do
expect(user.ci_owned_runners).to contain_exactly(runner) expect(user.ci_owned_runners).to contain_exactly(runner)
end end
it 'returns true for owns_runner?' do it 'returns true for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(true) expect(user.owns_runner?(runner)).to eq(true)
end
end end
end end
end
shared_examples :project_member do shared_examples :project_member do
context 'when the user is a maintainer' do context 'when the user is a maintainer' do
before do before do
add_user(:maintainer) add_user(:maintainer)
end end
it 'loads the runners of the project' do it 'loads the runners of the project' do
expect(user.ci_owned_runners).to contain_exactly(project_runner) expect(user.ci_owned_runners).to contain_exactly(project_runner)
end end
it 'returns true for owns_runner?' do it 'returns true for owns_runner?' do
expect(user.owns_runner?(project_runner)).to eq(true) expect(user.owns_runner?(project_runner)).to eq(true)
end
end end
end
context 'when the user is a developer' do context 'when the user is a developer' do
before do before do
add_user(:developer) add_user(:developer)
end end
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(project_runner)).to eq(false) expect(user.owns_runner?(project_runner)).to eq(false)
end
end end
end
context 'when the user is a reporter' do context 'when the user is a reporter' do
before do before do
add_user(:reporter) add_user(:reporter)
end end
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(project_runner)).to eq(false) expect(user.owns_runner?(project_runner)).to eq(false)
end
end end
end
context 'when the user is a guest' do context 'when the user is a guest' do
before do before do
add_user(:guest) add_user(:guest)
end end
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(project_runner)).to eq(false) expect(user.owns_runner?(project_runner)).to eq(false)
end
end end
end end
end
shared_examples :group_member do shared_examples :group_member do
context 'when the user is a maintainer' do context 'when the user is a maintainer' do
before do before do
add_user(:maintainer) add_user(:maintainer)
end end
it 'does not load the runners of the group' do it 'does not load the runners of the group' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(false) expect(user.owns_runner?(runner)).to eq(false)
end
end end
end
context 'when the user is a developer' do context 'when the user is a developer' do
before do before do
add_user(:developer) add_user(:developer)
end end
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(false) expect(user.owns_runner?(runner)).to eq(false)
end
end end
end
context 'when the user is a reporter' do context 'when the user is a reporter' do
before do before do
add_user(:reporter) add_user(:reporter)
end end
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(false) expect(user.owns_runner?(runner)).to eq(false)
end
end end
end
context 'when the user is a guest' do context 'when the user is a guest' do
before do before do
add_user(:guest) add_user(:guest)
end
it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty
end
it 'returns false for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(false)
end
end end
end
context 'without any projects nor groups' do
it 'does not load any runner' do it 'does not load any runner' do
expect(user.ci_owned_runners).to be_empty expect(user.ci_owned_runners).to be_empty
end end
it 'returns false for owns_runner?' do it 'returns false for owns_runner?' do
expect(user.owns_runner?(runner)).to eq(false) expect(user.owns_runner?(create(:ci_runner))).to eq(false)
end end
end end
end
context 'without any projects nor groups' do context 'with runner in a personal project' do
it 'does not load any runner' do let!(:namespace) { create(:user_namespace, owner: user) }
expect(user.ci_owned_runners).to be_empty let!(:project) { create(:project, namespace: namespace) }
end let!(:runner) { create(:ci_runner, :project, projects: [project]) }
it 'returns false for owns_runner?' do it_behaves_like :project_owner
expect(user.owns_runner?(create(:ci_runner))).to eq(false)
end end
end
context 'with runner in a personal project' do context 'with group runner in a non owned group' do
let!(:namespace) { create(:user_namespace, owner: user) } let!(:group) { create(:group) }
let!(:project) { create(:project, namespace: namespace) } let!(:runner) { create(:ci_runner, :group, groups: [group]) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
it_behaves_like :project_owner def add_user(access)
end group.add_user(user, access)
end
context 'with group runner in a non owned group' do
let!(:group) { create(:group) }
let!(:runner) { create(:ci_runner, :group, groups: [group]) }
def add_user(access) it_behaves_like :group_member
group.add_user(user, access)
end end
it_behaves_like :group_member context 'with group runner in an owned group' do
end let!(:group) { create(:group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
context 'with group runner in an owned group' do it_behaves_like :group_owner
let!(:group) { create(:group) } end
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
it_behaves_like :group_owner context 'with group runner in an owned group and group runner in a different owner subgroup' do
end let!(:group) { create(:group) }
let!(:runner) { create(:ci_runner, :group, groups: [group]) }
let!(:subgroup) { create(:group, parent: group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:another_user) { create(:user) }
context 'with group runner in an owned group and group runner in a different owner subgroup' do def set_permissions_for_users
let!(:group) { create(:group) } group.add_owner(user)
let!(:runner) { create(:ci_runner, :group, groups: [group]) } subgroup.add_owner(another_user)
let!(:subgroup) { create(:group, parent: group) } end
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:another_user) { create(:user) }
def set_permissions_for_users it_behaves_like :nested_groups_owner
group.add_owner(user)
subgroup.add_owner(another_user)
end end
it_behaves_like :nested_groups_owner context 'with personal project runner in an an owned group and a group runner in that same group' do
end let!(:group) { create(:group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
let!(:project) { create(:project, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
context 'with personal project runner in an an owned group and a group runner in that same group' do def set_permissions_for_users
let!(:group) { create(:group) } group.add_owner(user)
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) } end
let!(:project) { create(:project, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
def set_permissions_for_users it_behaves_like :nested_groups_owner
group.add_owner(user)
end end
it_behaves_like :nested_groups_owner context 'with personal project runner in an owned group and a group runner in a subgroup' do
end let!(:group) { create(:group) }
let!(:subgroup) { create(:group, parent: group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:project) { create(:project, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
context 'with personal project runner in an owned group and a group runner in a subgroup' do def set_permissions_for_users
let!(:group) { create(:group) } group.add_owner(user)
let!(:subgroup) { create(:group, parent: group) } end
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:project) { create(:project, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
def set_permissions_for_users it_behaves_like :nested_groups_owner
group.add_owner(user)
end end
it_behaves_like :nested_groups_owner context 'with personal project runner in an owned group in an owned namespace and a group runner in that group' do
end let!(:namespace) { create(:user_namespace, owner: user) }
let!(:group) { create(:group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
let!(:project) { create(:project, namespace: namespace, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
context 'with personal project runner in an owned group in an owned namespace and a group runner in that group' do def set_permissions_for_users
let!(:namespace) { create(:user_namespace, owner: user) } group.add_owner(user)
let!(:group) { create(:group) } end
let!(:group_runner) { create(:ci_runner, :group, groups: [group]) }
let!(:project) { create(:project, namespace: namespace, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
def set_permissions_for_users it_behaves_like :nested_groups_owner
group.add_owner(user)
end end
it_behaves_like :nested_groups_owner context 'with personal project runner in an owned namespace, an owned group, a subgroup and a group runner in that subgroup' do
end let!(:namespace) { create(:user_namespace, owner: user) }
let!(:group) { create(:group) }
let!(:subgroup) { create(:group, parent: group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:project) { create(:project, namespace: namespace, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
context 'with personal project runner in an owned namespace, an owned group, a subgroup and a group runner in that subgroup' do def set_permissions_for_users
let!(:namespace) { create(:user_namespace, owner: user) } group.add_owner(user)
let!(:group) { create(:group) } end
let!(:subgroup) { create(:group, parent: group) }
let!(:group_runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:project) { create(:project, namespace: namespace, group: group) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
def set_permissions_for_users it_behaves_like :nested_groups_owner
group.add_owner(user)
end end
it_behaves_like :nested_groups_owner context 'with a project runner that belong to projects that belong to a not owned group' do
end let!(:group) { create(:group) }
let!(:project) { create(:project, group: group) }
let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
context 'with a project runner that belong to projects that belong to a not owned group' do def add_user(access)
let!(:group) { create(:group) } project.add_user(user, access)
let!(:project) { create(:project, group: group) } end
let!(:project_runner) { create(:ci_runner, :project, projects: [project]) }
def add_user(access) it_behaves_like :project_member
project.add_user(user, access)
end end
it_behaves_like :project_member context 'with project runners that belong to projects that do not belong to any group' do
end let!(:project) { create(:project) }
let!(:runner) { create(:ci_runner, :project, projects: [project]) }
context 'with project runners that belong to projects that do not belong to any group' do it 'does not load any runner' do
let!(:project) { create(:project) } expect(user.ci_owned_runners).to be_empty
let!(:runner) { create(:ci_runner, :project, projects: [project]) } end
end
context 'with a group runner that belongs to a subgroup of a group owned by another user' do
let!(:group) { create(:group) }
let!(:subgroup) { create(:group, parent: group) }
let!(:runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:another_user) { create(:user) }
it 'does not load any runner' do def add_user(access)
expect(user.ci_owned_runners).to be_empty subgroup.add_user(user, access)
group.add_user(another_user, :owner)
end
it_behaves_like :group_member
end end
end end
context 'with a group runner that belongs to a subgroup of a group owned by another user' do it_behaves_like 'ci_owned_runners examples'
let!(:group) { create(:group) }
let!(:subgroup) { create(:group, parent: group) }
let!(:runner) { create(:ci_runner, :group, groups: [subgroup]) }
let!(:another_user) { create(:user) }
def add_user(access) context 'when feature flag :linear_user_ci_owned_runners is disabled' do
subgroup.add_user(user, access) before do
group.add_user(another_user, :owner) stub_feature_flags(linear_user_ci_owned_runners: false)
end end
it_behaves_like :group_member it_behaves_like 'ci_owned_runners examples'
end end
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