Class: Jackal::CodeFetcher::GitHub

Inherits:
Callback
  • Object
show all
Defined in:
lib/jackal-code-fetcher/git_hub.rb

Overview

GitHub code fetcher

Instance Method Summary collapse

Instance Method Details

#delete_repository(payload) ⇒ TrueClass, FalseClass

Delete local repository path

Parameters:

  • payload (Smash)

Returns:

  • (TrueClass, FalseClass)


87
88
89
90
91
92
93
94
95
96
# File 'lib/jackal-code-fetcher/git_hub.rb', line 87

def delete_repository(payload)
  path = repository_path(payload)
  if(File.exists?(path))
    warn "Deleting repository directory: #{path}"
    FileUtils.rm_rf(path)
    true
  else
    false
  end
end

#execute(message) ⇒ Object

Fetch code and push to asset store

Parameters:

  • message (Carnivore::Message)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/jackal-code-fetcher/git_hub.rb', line 37

def execute(message)
  failure_wrap(message) do |payload|
    retried = false
    locked = lock_repo(payload)
    begin
      store_reference(payload)
    rescue Git::GitExecuteError => e
      unless(retried)
        retried = true
        delete_repository(payload)
        error "Reference extraction from repository failed. Repository deleted and retrying. (Error: #{e.class} - #{e})"
        retry
      else
        raise
      end
    ensure
      unlock_repo(locked)
    end
    job_completed(:code_fetcher, payload, message)
  end
end

#fetch_repository(payload) ⇒ String

Fetch repository from GitHub

Parameters:

  • payload (Smash)

Returns:

  • (String)

    path to repository directory



140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/jackal-code-fetcher/git_hub.rb', line 140

def fetch_repository(payload)
  repo_path = repository_path(payload)
  if(File.directory?(repo_path))
    debug "Pulling changes to: #{repo_path}"
    repo = Git.open(repo_path)
    repo.checkout('master')
    repo.pull
    repo.fetch
  else
    debug "Initiating repository clone to: #{repo_path}"
    Git.clone(github_url(payload), repo_path)
  end
  repo_path
end

#github_url(payload) ⇒ String

Build github URL for fetching

Parameters:

  • payload (Smash)

Returns:

  • (String)


112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/jackal-code-fetcher/git_hub.rb', line 112

def github_url(payload)
  if(payload.get(:data, :code_fetcher, :info, :private))
    uri = URI.parse(payload.get(:data, :code_fetcher, :info, :url))
    uri.scheme = 'https'
    uri.user = config.fetch(:github, :access_token,
      app_config.get(:github, :access_token)
    )
    uri.to_s
  else
    payload.get(:data, :code_fetcher, :info, :url)
  end
end

#lock_repo(payload) ⇒ File

Lock repository via lock file

Parameters:

  • payload (Smash)

Returns:

  • (File)


63
64
65
66
67
68
69
70
71
72
# File 'lib/jackal-code-fetcher/git_hub.rb', line 63

def lock_repo(payload)
  lock_path = File.join(
    working_directory,
    "#{payload.get(:data, :code_fetcher, :info, :owner)}-" <<
    "#{payload.get(:data, :code_fetcher, :info, :name)}.lock"
  )
  lock_file = File.open(lock_path, 'w')
  lock_file.flock(File::LOCK_EX)
  lock_file
end

#pack_and_store(path, payload) ⇒ TrueClass

Store reference in asset store

Parameters:

  • path (String)

    local path to repository

  • payload (Smash)

Returns:

  • (TrueClass)


160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/jackal-code-fetcher/git_hub.rb', line 160

def pack_and_store(path, payload)
  repo = Git.open(path)
  repo.checkout(
    payload.get(:data, :code_fetcher, :info, :commit_sha)
  )
  asset_key = [
    payload.get(:data, :code_fetcher, :info, :owner),
    payload.get(:data, :code_fetcher, :info, :name),
    payload.get(:data, :code_fetcher, :info, :commit_sha)
  ].join('-') + '.zip'
  _path = File.join(working_directory, Carnivore.uuid)
  begin
    tmp_path = File.join(_path, asset_key)
    FileUtils.mkdir_p(tmp_path)
    origin_path = repository_path(payload)
    files_to_copy = Dir.glob(
      File.join(
        origin_path,
        '{.[^.]*,**}',
        '**',
        '{*,*.*,.*}'
      )
    )
    files_to_copy = files_to_copy.map do |file_path|
      next unless File.file?(file_path)
      relative_path = file_path.sub("#{origin_path}/", '')
      relative_path unless File.fnmatch('.git*', relative_path)
    end.compact
    files_to_copy.each do |relative_path|
      new_path = File.join(tmp_path, relative_path)
      FileUtils.mkdir_p(File.dirname(new_path))
      FileUtils.cp(File.join(origin_path, relative_path), new_path)
    end
    tarball = asset_store.pack(tmp_path)
    asset_store.put(asset_key, tarball)
  ensure
    FileUtils.rm_rf(_path)
  end
  payload.set(:data, :code_fetcher, :asset, asset_key)
  true
end

#repository_path(payload) ⇒ String

Generate local path

Returns:

  • (String)

    path



128
129
130
131
132
133
134
# File 'lib/jackal-code-fetcher/git_hub.rb', line 128

def repository_path(payload)
  File.join(
    working_directory,
    payload.get(:data, :code_fetcher, :info, :owner),
    payload.get(:data, :code_fetcher, :info, :name)
  )
end

#setup(*_) ⇒ Object

Setup callback



9
10
11
12
13
# File 'lib/jackal-code-fetcher/git_hub.rb', line 9

def setup(*_)
  require 'uri'
  require 'git'
  require 'fileutils'
end

#store_reference(payload) ⇒ TrueClass

Fetch reference from GitHub repository and store compressed copy in the asset store

Parameters:

  • payload (Smash)

Returns:

  • (TrueClass)


103
104
105
106
# File 'lib/jackal-code-fetcher/git_hub.rb', line 103

def store_reference(payload)
  repo_dir = fetch_repository(payload)
  pack_and_store(repo_dir, payload)
end

#unlock_repo(lock_file) ⇒ File

Unlock the repository via lock file

Parameters:

  • lock_file (File)

Returns:

  • (File)


78
79
80
81
# File 'lib/jackal-code-fetcher/git_hub.rb', line 78

def unlock_repo(lock_file)
  lock_file.close
  lock_file
end

#valid?(message) ⇒ Truthy, Falsey

Determine validity of message

Parameters:

  • message (Carnivore::Message)

Returns:

  • (Truthy, Falsey)


27
28
29
30
31
32
# File 'lib/jackal-code-fetcher/git_hub.rb', line 27

def valid?(message)
  super do |payload|
    payload.get(:data, :code_fetcher, :info, :commit_sha) &&
      !payload.get(:data, :code_fetcher, :asset)
  end
end

#working_directoryString

Returns working directory.

Returns:

  • (String)

    working directory



16
17
18
19
20
21
# File 'lib/jackal-code-fetcher/git_hub.rb', line 16

def working_directory
  memoize(:working_directory, :direct) do
    FileUtils.mkdir_p(path = config.fetch(:working_directory, '/tmp/jackal-code-fetcher'))
    path
  end
end