diff options
| -rw-r--r-- | app/models/ci/runner.rb | 31 | ||||
| -rw-r--r-- | spec/models/ci/runner_spec.rb | 50 |
2 files changed, 75 insertions, 6 deletions
diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 5a4c56ec0dc..8f8dfbda412 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -14,6 +14,8 @@ module Ci has_many :builds has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent has_many :projects, through: :runner_projects + has_many :runner_groups + has_many :groups, through: :runner_groups has_one :last_build, ->() { order('id DESC') }, class_name: 'Ci::Build' @@ -27,8 +29,33 @@ module Ci scope :ordered, ->() { order(id: :desc) } scope :owned_or_shared, ->(project_id) do - joins('LEFT JOIN ci_runner_projects ON ci_runner_projects.runner_id = ci_runners.id') - .where("ci_runner_projects.project_id = :project_id OR ci_runners.is_shared = true", project_id: project_id) + joins( + %{ + -- project runners + LEFT JOIN ci_runner_projects ON ci_runner_projects.runner_id = ci_runners.id + + -- group runners + LEFT JOIN ci_runner_groups ON ci_runner_groups.runner_id = ci_runners.id + LEFT JOIN namespaces ON namespaces.id = ci_runner_groups.group_id + LEFT JOIN projects group_projects ON group_projects.namespace_id = namespaces.id + } + ).where( + %{ + -- project runners + ci_runner_projects.project_id = :project_id + + OR + + -- group runners + group_projects.id = :project_id + + OR + + -- shared runners + ci_runners.is_shared = true + }, + project_id: project_id + ) end scope :assignable_for, ->(project) do diff --git a/spec/models/ci/runner_spec.rb b/spec/models/ci/runner_spec.rb index 529f200b43a..477540fb3b0 100644 --- a/spec/models/ci/runner_spec.rb +++ b/spec/models/ci/runner_spec.rb @@ -52,19 +52,61 @@ describe Ci::Runner do describe 'scopes' do describe 'owned_or_shared' do it 'returns the specific project runner' do + # own specific_project = create :project - other_project = create :project specific_runner = create :ci_runner, :specific, projects: [specific_project] - other_runner = create :ci_runner, :specific, projects: [other_project] + + # other + other_project = create :project + create :ci_runner, :specific, projects: [other_project] expect(described_class.owned_or_shared(specific_project.id)).to eq [specific_runner] end - it 'returns the shared projects' do - runner = create :ci_runner, :shared + it 'returns the shared project runner' do + project = create :project + runner = create :ci_runner, :shared, projects: [project] expect(described_class.owned_or_shared(0)).to eq [runner] end + + it 'returns the specific group runner' do + # own + specific_group = create :group + specific_project = create :project, group: specific_group + specific_runner = create :ci_runner, :specific, groups: [specific_group] + + # other + other_group = create :group + create :project, group: other_group + create :ci_runner, :specific, groups: [other_group] + + expect(described_class.owned_or_shared(specific_project.id)).to eq [specific_runner] + end + + it 'returns the shared group runner' do + group = create :group + runner = create :ci_runner, :shared, groups: [group] + + expect(described_class.owned_or_shared(0)).to eq [runner] + end + + it 'returns a globally shared, a project specific and a group specific runner' do + # group specific + group = create :group + project = create :project, group: group + group_runner = create :ci_runner, :specific, groups: [group] + + # project specific + project_runner = create :ci_runner, :specific, projects: [project] + + # globally shared + shared_runner = create :ci_runner, :shared + + expect(described_class.owned_or_shared(project.id)).to match_array [ + group_runner, project_runner, shared_runner + ] + end end end |
