class Fastlane::Actions::GithubActionAction
Public Class Methods
available_options()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 294 def self.available_options [ FastlaneCore::ConfigItem.new(key: :server_url, env_name: "FL_GITHUB_API_SERVER_URL", description: "The server url. e.g. 'https://your.internal.github.host/api/v3' (Default: 'https://api.github.com')", default_value: "https://api.github.com", optional: true, verify_block: proc do |value| UI.user_error!("Please include the protocol in the server url, e.g. https://your.github.server/api/v3") unless value.include?("//") end), FastlaneCore::ConfigItem.new(key: :api_token, env_name: "FL_GITHUB_API_TOKEN", description: "Personal API Token for GitHub - generate one at https://github.com/settings/tokens", sensitive: true, code_gen_sensitive: true, is_string: true, default_value: ENV["GITHUB_API_TOKEN"], default_value_dynamic: true, optional: false), FastlaneCore::ConfigItem.new(key: :org, env_name: "FL_GITHUB_ACTIONS_ORG", description: "Name of organization of the repository for GitHub Actions"), FastlaneCore::ConfigItem.new(key: :repo, env_name: "FL_GITHUB_ACTIONS_REPO", description: "Name of repository for GitHub Actions"), FastlaneCore::ConfigItem.new(key: :match_org, env_name: "FL_GITHUB_ACTIONS_MATCH_ORG", description: "Name of organization of the match repository", optional: true), FastlaneCore::ConfigItem.new(key: :match_repo, env_name: "FL_GITHUB_ACTIONS_MATCH_REPO", description: "Name of match repository", optional: true), FastlaneCore::ConfigItem.new(key: :dotenv_paths, env_name: "FL_GITHUB_ACTINOS_DOTENV_PATHS", description: "Paths of .env files to parse", optional: true, type: Array, verify_block: proc do |values| values.each do |value| UI.user_error!("Path #{value} doesn't exist") unless File.exist?(value) end end), ] end
check_for_setup_ci_in_fastfile()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 25 def self.check_for_setup_ci_in_fastfile fastfiles = Dir.glob("./*/Fastfile").map do |path| File.absolute_path(path) end fastfiles.each do |path| content = File.read(path) if !content.include?("setup_ci") UI.confirm("`setup_ci` is not detected for '#{path}'. Do you still want to continue on?") end end end
deploy_key_title()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 21 def self.deploy_key_title "Match Deploy Key (created by fastalne-plugin-github_actions)" end
description()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 282 def self.description "Helper to setup GitHub actions for fastlane and match" end
details()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 290 def self.details "Helper to setup GitHub actions for fastlane and match" end
encrypt_secret(key64, secret)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 269 def self.encrypt_secret(key64, secret) require "rbnacl" require "base64" key = Base64.decode64(key64) public_key = RbNaCl::PublicKey.new(key) box = RbNaCl::Boxes::Sealed.from_public_key(public_key) encrypted_secret = box.encrypt(secret) return Base64.strict_encode64(encrypted_secret) end
generate_deploy_key(params)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 125 def self.generate_deploy_key(params) if params[:match_org].to_s == "" && params[:match_repo].to_s == "" UI.message("Skipping Deploy Key generation...") return {} elsif params[:match_org].to_s == "" UI.user_error!("`match_org` also needs to be specified") elsif params[:match_repo].to_s == "" UI.user_error!("`match_repo` also needs to be specified") end get_deploy_keys_resp = self.match_repo_get(params, "/keys") sleep(1) deploy_keys = get_deploy_keys_resp[:json] || [] deploy_keys.each do |deploy_key| if deploy_key["title"] == deploy_key_title if UI.confirm("Deploy Key for the match repo already exists... Delete it?") self.match_repo_delete(params, "/keys/#{deploy_key["id"]}") UI.message("Deleted existing Deploy Key") sleep(1) else return {} end end end require 'sshkey' k = SSHKey.generate() body = { title: deploy_key_title, key: k.ssh_public_key, read_only: true } post_deploy_key_resp = self.match_repo_post(params, "/keys", body) UI.message("Created Deploy Key") sleep(3) secrets = {} secrets[match_deploy_key] = k.private_key return secrets end
generate_workflow_template(params, secret_names)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 40 def self.generate_workflow_template(params, secret_names) workflows_dir = File.absolute_path(".github/workflows") workflow_path = File.join(workflows_dir, 'fastlane.yml') if File.exist?(workflow_path) if UI.confirm("File already exists at #{workflow_path}. Do you want to overwrite?") UI.message("Overwriting #{workflow_path}") else UI.message("Cancelled workflow template generation...") return end end require 'fastlane/erb_template_helper' include ERB::Util spaces = " " * 10 use_match = secret_names.include?(match_deploy_key) # # Clone test secrets and commands # if use_match clone_test_secrets = [ 'GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"', "#{match_deploy_key}: ${{ secrets.#{match_deploy_key} }}" ].map do |secret| "#{spaces}#{secret}" end.join("\n") clone_test_commands = [ 'eval "$(ssh-agent -s)"', "ssh-add - <<< \"${#{match_deploy_key}}\"", "git clone git@github.com:#{params[:match_org]}/#{params[:match_repo]}.git", "ls #{params[:match_repo]}" ].map do |command| "#{spaces}#{command}" end.join("\n") end # # Secrets and commands # secrets = secret_names.map do |secret_name| "#{secret_name}: ${{ secrets.#{secret_name} }}" end if use_match secrets << 'GIT_SSH_COMMAND: "ssh -o StrictHostKeyChecking=no"' secrets << 'MATCH_READONLY: true' end secrets = secrets.map do |secret| "#{spaces}#{secret}" end.join("\n") commands = [] if use_match commands = [ 'eval "$(ssh-agent -s)"', "ssh-add - <<< \"${#{match_deploy_key}}\"", ] end commands << 'bundle exec fastlane test' commands = commands.map do |command| "#{spaces}#{command}" end.join("\n") puts "secret size: #{secrets.size}" workflow_template = Helper::GithubActionHelper.load("workflow_template") workflow_render = Helper::GithubActionHelper.render(workflow_template, { use_match: use_match, clone_test_secrets: clone_test_secrets, clone_test_commands: clone_test_commands, secrets: secrets, commands: commands }) FileUtils.mkdir_p(workflows_dir) File.write(workflow_path, workflow_render) end
is_supported?(platform)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 340 def self.is_supported?(platform) true end
match_deploy_key()
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 17 def self.match_deploy_key "MATCH_DEPLOY_KEY" end
match_repo_delete(params, path)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 259 def self.match_repo_delete(params, path) return other_action.github_api( server_url: params[:server_url], api_token: params[:api_token], http_method: "DELETE", path: "/repos/#{params[:match_org]}/#{params[:match_repo]}#{path}", body: {}, ) end
match_repo_get(params, path)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 239 def self.match_repo_get(params, path) return other_action.github_api( server_url: params[:server_url], api_token: params[:api_token], http_method: "GET", path: "/repos/#{params[:match_org]}/#{params[:match_repo]}#{path}", body: {}, ) end
match_repo_post(params, path, body)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 249 def self.match_repo_post(params, path, body) return other_action.github_api( server_url: params[:server_url], api_token: params[:api_token], http_method: "POST", path: "/repos/#{params[:match_org]}/#{params[:match_repo]}#{path}", body: body, ) end
parse_dotenvs(params)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 207 def self.parse_dotenvs(params) dotenv_paths = (params[:dotenv_paths] || []) if dotenv_paths.empty? UI.message "No dotenv paths to parse..." return {} end require "dotenv" return Dotenv.parse(*dotenv_paths) end
post_secrets(params, additional_secrets)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 170 def self.post_secrets(params, additional_secrets) public_key_resp = self.repo_get(params, "/actions/secrets/public-key") key_id = public_key_resp[:json]["key_id"] key64 = public_key_resp[:json]["key"] secrets = self.parse_dotenvs(params) secrets = secrets.merge(additional_secrets || {}) encrypted_secrets = {} secrets.each do |k,v| encrypted_value = self.encrypt_secret(key64, v) encrypted_secrets[k] = encrypted_value end existing_secrets_resp = self.repo_get(params, "/actions/secrets") existing_secret_names = existing_secrets_resp[:json]["secrets"].map do |secret| secret["name"].to_s end encrypted_secrets.reject! do |k,v| if existing_secret_names.include?(k.to_s) !UI.confirm("Overwrite #{k}?") end end encrypted_secrets.each do |k,v| body = { key_id: key_id, encrypted_value: v } self.repo_put(params, "/actions/secrets/#{k}", body) UI.message("Saving secret #{k}") end return secrets.keys end
repo_get(params, path)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 219 def self.repo_get(params, path) return other_action.github_api( server_url: params[:server_url], api_token: params[:api_token], http_method: "GET", path: "/repos/#{params[:org]}/#{params[:repo]}#{path}", body: {}, ) end
repo_put(params, path, body)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 229 def self.repo_put(params, path, body) return other_action.github_api( server_url: params[:server_url], api_token: params[:api_token], http_method: "PUT", path: "/repos/#{params[:org]}/#{params[:repo]}#{path}", body: body, ) end
run(params)
click to toggle source
# File lib/fastlane/plugin/github_action/actions/github_action_action.rb, line 7 def self.run(params) UI.message("The github_actions plugin is working!") self.check_for_setup_ci_in_fastfile additional_secrets = self.generate_deploy_key(params) secret_names = self.post_secrets(params, additional_secrets) self.generate_workflow_template(params, secret_names) end