class Match::Storage::GitStorage

Store the code signing identities in a git repo

Attributes

branch[RW]
clone_branch_directly[RW]
git_basic_authorization[RW]
git_bearer_authorization[RW]
git_full_name[RW]
git_private_key[RW]
git_url[RW]

User provided values

git_user_email[RW]
platform[RW]
shallow_clone[RW]
skip_docs[RW]
type[RW]

Public Class Methods

configure(params) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 24
def self.configure(params)
  return self.new(
    type: params[:type].to_s,
    platform: params[:platform].to_s,
    git_url: params[:git_url],
    shallow_clone: params[:shallow_clone],
    skip_docs: params[:skip_docs],
    branch: params[:git_branch],
    git_full_name: params[:git_full_name],
    git_user_email: params[:git_user_email],
    clone_branch_directly: params[:clone_branch_directly],
    git_basic_authorization: params[:git_basic_authorization],
    git_bearer_authorization: params[:git_bearer_authorization],
    git_private_key: params[:git_private_key]
  )
end
new(type: nil, platform: nil, git_url: nil, shallow_clone: nil, skip_docs: false, branch: "master", git_full_name: nil, git_user_email: nil, clone_branch_directly: false, git_basic_authorization: nil, git_bearer_authorization: nil, git_private_key: nil) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 41
def initialize(type: nil,
               platform: nil,
               git_url: nil,
               shallow_clone: nil,
               skip_docs: false,
               branch: "master",
               git_full_name: nil,
               git_user_email: nil,
               clone_branch_directly: false,
               git_basic_authorization: nil,
               git_bearer_authorization: nil,
               git_private_key: nil)
  self.git_url = git_url
  self.shallow_clone = shallow_clone
  self.skip_docs = skip_docs
  self.branch = branch
  self.git_full_name = git_full_name
  self.git_user_email = git_user_email
  self.clone_branch_directly = clone_branch_directly
  self.git_basic_authorization = git_basic_authorization
  self.git_bearer_authorization = git_bearer_authorization
  self.git_private_key = git_private_key

  self.type = type if type
  self.platform = platform if platform
end

Public Instance Methods

command_from_private_key(command) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 165
def command_from_private_key(command)
  if File.file?(self.git_private_key)
    ssh_add = File.expand_path(self.git_private_key).shellescape.to_s
  else
    UI.message("Private key file does not exist, will continue by using it as a raw key.")
    ssh_add = "- <<< \"#{self.git_private_key}\""
  end
  return "ssh-agent bash -c 'ssh-add #{ssh_add}; #{command}'"
end
delete_files(files_to_delete: [], custom_message: nil) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 129
def delete_files(files_to_delete: [], custom_message: nil)
  # No specific list given, e.g. this happens on `fastlane match nuke`
  # We just want to run `git add -A` to commit everything
  git_push(commands: ["git add -A"], commit_message: custom_message)
end
download() click to toggle source
# File match/lib/match/storage/git_storage.rb, line 72
def download
  # Check if we already have a functional working_directory
  return if @working_directory

  # No existing working directory, creating a new one now
  self.working_directory = Dir.mktmpdir

  command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
  # HTTP headers are supposed to be be case insensitive but
  # Bitbucket requires `Authorization: Basic` and `Authorization Bearer` to work
  # https://github.com/fastlane/fastlane/pull/15928
  command << " -c http.extraheader='Authorization: Basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
  command << " -c http.extraheader='Authorization: Bearer #{self.git_bearer_authorization}'" unless self.git_bearer_authorization.nil?

  if self.shallow_clone
    command << " --depth 1 --no-single-branch"
  elsif self.clone_branch_directly
    command += " -b #{self.branch.shellescape} --single-branch"
  end

  command = command_from_private_key(command) unless self.git_private_key.nil?

  UI.message("Cloning remote git repo...")
  if self.branch && !self.clone_branch_directly
    UI.message("If cloning the repo takes too long, you can use the `clone_branch_directly` option in match.")
  end

  begin
    # GIT_TERMINAL_PROMPT will fail the `git clone` command if user credentials are missing
    Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
      FastlaneCore::CommandExecutor.execute(command: command,
                                          print_all: FastlaneCore::Globals.verbose?,
                                      print_command: FastlaneCore::Globals.verbose?)
    end
  rescue
    UI.error("Error cloning certificates repo, please make sure you have read access to the repository you want to use")
    if self.branch && self.clone_branch_directly
      UI.error("You passed '#{self.branch}' as branch in combination with the `clone_branch_directly` flag. Please remove `clone_branch_directly` flag on the first run for _match_ to create the branch.")
    end
    UI.error("Run the following command manually to make sure you're properly authenticated:")
    UI.command(command)
    UI.user_error!("Error cloning certificates git repo, please make sure you have access to the repository - see instructions above")
  end

  add_user_config(self.git_full_name, self.git_user_email)

  unless File.directory?(self.working_directory)
    UI.user_error!("Error cloning repo, make sure you have access to it '#{self.git_url}'")
  end

  checkout_branch
end
generate_commit_message() click to toggle source

Generate the commit message based on the user's parameters

# File match/lib/match/storage/git_storage.rb, line 144
def generate_commit_message
  [
    "[fastlane]",
    "Updated",
    self.type,
    "and platform",
    self.platform
  ].join(" ")
end
generate_matchfile_content() click to toggle source
# File match/lib/match/storage/git_storage.rb, line 154
def generate_matchfile_content
  UI.important("Please create a new, private git repository to store the certificates and profiles there")
  url = UI.input("URL of the Git Repo: ")

  return "git_url(\"#{url}\")"
end
human_readable_description() click to toggle source
# File match/lib/match/storage/git_storage.rb, line 125
def human_readable_description
  "Git Repo [#{self.git_url}]"
end
list_files(file_name: "", file_ext: "") click to toggle source
# File match/lib/match/storage/git_storage.rb, line 161
def list_files(file_name: "", file_ext: "")
  Dir[File.join(working_directory, "**", file_name, "*.#{file_ext}")]
end
prefixed_working_directory() click to toggle source
# File match/lib/match/storage/git_storage.rb, line 68
def prefixed_working_directory
  return working_directory
end
upload_files(files_to_upload: [], custom_message: nil) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 135
def upload_files(files_to_upload: [], custom_message: nil)
  commands = files_to_upload.map do |current_file|
    "git add #{current_file.shellescape}"
  end

  git_push(commands: commands, commit_message: custom_message)
end

Private Instance Methods

add_user_config(user_name, user_email) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 215
def add_user_config(user_name, user_email)
  # Add git config if needed
  commands = []
  commands << "git config user.name \"#{user_name}\"" unless user_name.nil?
  commands << "git config user.email \"#{user_email}\"" unless user_email.nil?

  return if commands.empty?

  UI.message("Add git user config to local git repo...")
  Dir.chdir(self.working_directory) do
    commands.each do |command|
      FastlaneCore::CommandExecutor.execute(command: command,
                                            print_all: FastlaneCore::Globals.verbose?,
                                            print_command: FastlaneCore::Globals.verbose?)
    end
  end
end
branch_exists?(branch) click to toggle source

Checks if a specific branch exists in the git repo

# File match/lib/match/storage/git_storage.rb, line 204
def branch_exists?(branch)
  return unless self.working_directory

  result = Dir.chdir(self.working_directory) do
    FastlaneCore::CommandExecutor.execute(command: "git --no-pager branch --list origin/#{branch.shellescape} --no-color -r",
                                          print_all: FastlaneCore::Globals.verbose?,
                                          print_command: FastlaneCore::Globals.verbose?)
  end
  return !result.empty?
end
checkout_branch() click to toggle source

Create and checkout an specific branch in the git repo

# File match/lib/match/storage/git_storage.rb, line 178
def checkout_branch
  return unless self.working_directory

  commands = []
  if branch_exists?(self.branch)
    # Checkout the branch if it already exists
    commands << "git checkout #{self.branch.shellescape}"
  else
    # If a new branch is being created, we create it as an 'orphan' to not inherit changes from the master branch.
    commands << "git checkout --orphan #{self.branch.shellescape}"
    # We also need to reset the working directory to not transfer any uncommitted changes to the new branch.
    commands << "git reset --hard"
  end

  UI.message("Checking out branch #{self.branch}...")

  Dir.chdir(self.working_directory) do
    commands.each do |command|
      FastlaneCore::CommandExecutor.execute(command: command,
                                            print_all: FastlaneCore::Globals.verbose?,
                                            print_command: FastlaneCore::Globals.verbose?)
    end
  end
end
git_push(commands: [], commit_message: nil) click to toggle source
# File match/lib/match/storage/git_storage.rb, line 233
def git_push(commands: [], commit_message: nil)
  commit_message ||= generate_commit_message
  commands << "git commit -m #{commit_message.shellescape}"
  git_push_command = "git push origin #{self.branch.shellescape}"
  git_push_command = command_from_private_key(git_push_command) unless self.git_private_key.nil?
  commands << git_push_command

  UI.message("Pushing changes to remote git repo...")
  Helper.with_env_values('GIT_TERMINAL_PROMPT' => '0') do
    commands.each do |command|
      FastlaneCore::CommandExecutor.execute(command: command,
                                          print_all: FastlaneCore::Globals.verbose?,
                                      print_command: FastlaneCore::Globals.verbose?)
    end
  end
rescue => ex
  UI.error("Couldn't commit or push changes back to git...")
  UI.error(ex)
end