summaryrefslogtreecommitdiff
path: root/app/finders/environments/environments_by_deployments_finder.rb
blob: e0ecc98b1c0b739203da6c5387cdb1ed425c45a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# frozen_string_literal: true

module Environments
  class EnvironmentsByDeploymentsFinder
    attr_reader :project, :current_user, :params

    def initialize(project, current_user, params = {})
      @project = project
      @current_user = current_user
      @params = params
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def execute
      deployments = project.deployments
      deployments =
        if ref
          deployments_query = params[:with_tags] ? 'ref = :ref OR tag IS TRUE' : 'ref = :ref'
          deployments.where(deployments_query, ref: ref.to_s)
        elsif commit
          deployments.where(sha: commit.sha)
        else
          deployments.none
        end

      environment_ids = deployments
        .group(:environment_id)
        .select(:environment_id)

      environments = project.environments.available
        .where(id: environment_ids)

      if params[:find_latest]
        find_one(environments.order_by_last_deployed_at_desc)
      else
        find_all(environments.order_by_last_deployed_at.to_a)
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    private

    def find_one(environments)
      [environments.find { |environment| valid_environment?(environment) }].compact
    end

    def find_all(environments)
      environments.select { |environment| valid_environment?(environment) }
    end

    def valid_environment?(environment)
      # Go in order of cost: SQL calls are cheaper than Gitaly calls
      return false unless Ability.allowed?(current_user, :read_environment, environment)

      return false if ref && params[:recently_updated] && !environment.recently_updated_on_branch?(ref)
      return false if ref && commit && !environment.includes_commit?(commit)

      true
    end

    def ref
      params[:ref].try(:to_s)
    end

    def commit
      params[:commit]
    end
  end
end