summaryrefslogtreecommitdiff
path: root/qa/qa/resource/repository/commit.rb
blob: 1fe35f7a77dbcfeccf29b6d5d822b30f89524ec8 (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
120
121
122
123
124
125
126
127
128
129
130
# frozen_string_literal: true

module QA
  module Resource
    module Repository
      class Commit < Base
        attr_accessor :author_email,
                      :author_name,
                      :branch,
                      :commit_message,
                      :file_path,
                      :sha,
                      :start_branch

        attribute :short_id

        attribute :project do
          Project.fabricate! do |resource|
            resource.name = 'project-with-commit'
          end
        end

        def initialize
          @commit_message = 'QA Test - Commit message'
          @actions = []
        end

        # If `actions` are specified, it performs the actions to create,
        # update, or delete commits. If no actions are specified it
        # gets existing commits.
        def fabricate_via_api!
          return api_get if actions.empty?

          super
        rescue ResourceNotFoundError
          result = super

          project.wait_for_push(commit_message)

          result
        end

        def api_get_path
          "/projects/#{CGI.escape(project.path_with_namespace)}/repository/commits"
        end

        def api_post_path
          api_get_path
        end

        def api_post_body
          {
            branch: branch || project.default_branch,
            author_email: author_email || api_client.user&.email || Runtime::User.default_email,
            author_name: author_name || api_client.user&.name || Runtime::User.username,
            commit_message: commit_message,
            actions: actions
          }.merge(new_branch)
        end

        # Add files
        # Pass in array of new files like, example:
        # [{ "file_path": "foo/bar", "content": "some content" }]
        #
        # @param [Array<Hash>] files
        # @return [void]
        def add_files(files)
          validate_files!(files)

          actions.push(*files.map { |file| file.merge({ action: "create" }) })
        end

        # Update files
        # Pass in array of files and it's contents, example:
        # [{ "file_path": "foo/bar", "content": "some content" }]
        #
        # @param [Array<Hash>] files
        # @return [void]
        def update_files(files)
          validate_files!(files)

          actions.push(*files.map { |file| file.merge({ action: "update" }) })
        end

        # Add all files from directory
        #
        # @param [Pathname] dir
        # @return [void]
        def add_directory(dir)
          raise "Must set directory as a Pathname" unless dir.is_a?(Pathname)

          files_to_add = []

          dir.each_child do |child|
            case child.ftype
            when "directory"
              add_directory(child)
            when "file"
              files_to_add.push({ file_path: child.basename, content: child.read })
            else
              continue
            end
          end

          add_files(files_to_add)
        end

        private

        attr_reader :actions

        def validate_files!(files)
          if !files.is_a?(Array) ||
              files.empty? ||
              files.any? { |file| !file.has_key?(:file_path) || !file.has_key?(:content) }
            raise ArgumentError, "Please provide an array of hashes e.g.: [{file_path: 'file1', content: 'foo'}]"
          end
        end

        def new_branch
          return {} unless start_branch

          {
            start_branch: start_branch
          }
        end
      end
    end
  end
end