Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cleanup_tags_base_service.rb « container_repository « projects « services « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 8ea4ae4830ac471501c7d1e1703452098b5f0087 (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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# frozen_string_literal: true

module Projects
  module ContainerRepository
    class CleanupTagsBaseService < BaseContainerRepositoryService
      private

      def filter_out_latest!(tags)
        tags.reject!(&:latest?)
      end

      def filter_by_name!(tags)
        regex_delete = ::Gitlab::UntrustedRegexp.new("\\A#{name_regex_delete || name_regex}\\z")
        regex_retain = ::Gitlab::UntrustedRegexp.new("\\A#{name_regex_keep}\\z")

        tags.select! do |tag|
          # regex_retain will override any overlapping matches by regex_delete
          regex_delete.match?(tag.name) && !regex_retain.match?(tag.name)
        end
      end

      # Should return [tags_to_delete, tags_to_keep]
      def partition_by_keep_n(tags)
        return [tags, []] unless keep_n

        tags = order_by_date_desc(tags)

        tags.partition.with_index { |_, index| index >= keep_n_as_integer }
      end

      # Should return [tags_to_delete, tags_to_keep]
      def partition_by_older_than(tags)
        return [tags, []] unless older_than

        older_than_timestamp = older_than_in_seconds.ago

        tags.partition do |tag|
          timestamp = pushed_at(tag)

          timestamp && timestamp < older_than_timestamp
        end
      end

      def order_by_date_desc(tags)
        now = DateTime.current
        tags.sort_by! { |tag| pushed_at(tag) || now }
            .reverse!
      end

      def delete_tags(tags)
        return success(deleted: []) unless tags.any?

        service = Projects::ContainerRepository::DeleteTagsService.new(
          project,
          current_user,
          tags: tags.map(&:name),
          container_expiration_policy: container_expiration_policy
        )

        service.execute(container_repository)
      end

      def can_destroy?
        return true if container_expiration_policy

        can?(current_user, :destroy_container_image, project)
      end

      def valid_regex?
        %w[name_regex_delete name_regex name_regex_keep].each do |param_name|
          regex = params[param_name]
          ::Gitlab::UntrustedRegexp.new(regex) unless regex.blank?
        end
        true
      rescue RegexpError => e
        ::Gitlab::ErrorTracking.log_exception(e, project_id: project.id)
        false
      end

      def older_than
        params['older_than']
      end

      def name_regex_delete
        params['name_regex_delete']
      end

      def name_regex
        params['name_regex']
      end

      def name_regex_keep
        params['name_regex_keep']
      end

      def container_expiration_policy
        params['container_expiration_policy']
      end

      def keep_n
        params['keep_n']
      end

      def project
        container_repository.project
      end

      def keep_n_as_integer
        keep_n.to_i
      end

      def older_than_in_seconds
        strong_memoize(:older_than_in_seconds) do
          ChronicDuration.parse(older_than).seconds
        end
      end
    end
  end
end