Skip to content

Commit

Permalink
Merge pull request #19 from EmergeTools/telkins/snapshot-action
Browse files Browse the repository at this point in the history
Add action to generate snapshot builds
  • Loading branch information
trevor-e authored Mar 19, 2024
2 parents f8dfd4c + b6e4703 commit 62910a6
Show file tree
Hide file tree
Showing 4 changed files with 256 additions and 85 deletions.
81 changes: 12 additions & 69 deletions lib/fastlane/plugin/emerge/actions/emerge_action.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def self.run(params)
FileUtils.cp(l, linkmap_folder)
end
end
copy_config(config_path, "#{d}/archive.xcarchive")
Helper::EmergeHelper.copy_config(config_path, "#{d}/archive.xcarchive")
FileUtils.cp_r(file_path, application_folder)
copy_dsyms("#{absolute_path.dirname}/*.dsym", dsym_folder)
copy_dsyms("#{absolute_path.dirname}/*/*.dsym", dsym_folder)
Expand All @@ -73,7 +73,7 @@ def self.run(params)
FileUtils.cp(l, linkmap_folder)
end
end
copy_config(config_path, file_path)
Helper::EmergeHelper.copy_config(config_path, file_path)
Actions::ZipAction.run(
path: file_path,
output_path: zip_path,
Expand All @@ -88,62 +88,18 @@ def self.run(params)
return
end

filename = File.basename(file_path)
url = 'https://api.emergetools.com/upload'
params = {
filename: filename
prNumber: pr_number,
branch: branch,
sha: sha,
baseSha: base_sha,
repoName: repo_name,
gitlabProjectId: gitlab_project_id,
orderFileVersion: order_file_version,
tag: tag || "default"
}
if pr_number
params[:prNumber] = pr_number
end
if branch
params[:branch] = branch
end
if sha
params[:sha] = sha
end
if base_sha
params[:baseSha] = base_sha
end
if repo_name
params[:repoName] = repo_name
end
if gitlab_project_id
params[:gitlabProjectId] = gitlab_project_id
end
if order_file_version
params[:orderFileVersion] = order_file_version
end
params[:tag] = tag || "default"
FastlaneCore::PrintTable.print_values(
config: params,
hide_keys: [],
title: "Summary for Emerge #{Fastlane::Emerge::VERSION}"
)
resp = Faraday.post(
url,
params.to_json,
'Content-Type' => 'application/json', 'X-API-Token' => api_token, 'User-Agent' => "fastlane-plugin-emerge/#{Fastlane::Emerge::VERSION}"
)
case resp.status
when 200
json = JSON.parse(resp.body)
upload_id = json["upload_id"]
upload_url = json["uploadURL"]
warning = json["warning"]
if warning
UI.important(warning)
end
return Helper::EmergeHelper.perform_upload(upload_url, upload_id, file_path)
when 403
UI.error("Invalid API token")
when 400
UI.error("Invalid parameters")
json = JSON.parse(resp.body)
UI.error("Error: #{json['errorMessage']}")
else
UI.error("Upload failed")
end
upload_id = Helper::EmergeHelper.perform_upload(api_token, params, file_path)
UI.success("🎉 Your app is processing, you can find the results at https://emergetools.com/build/#{upload_id}")
end

def self.copy_dsyms(from, to)
Expand All @@ -153,19 +109,6 @@ def self.copy_dsyms(from, to)
end
end

def self.copy_config(config_path, tmp_dir)
return if config_path.nil?

expanded_path = File.expand_path(config_path)
unless File.exist?(expanded_path)
UI.error("No config file found at path '#{expanded_path}'.\nUploading without config file")
return
end

emerge_config_path = "#{tmp_dir}/emerge_config.yaml"
FileUtils.cp(expanded_path, emerge_config_path)
end

def self.description
"Fastlane plugin for Emerge"
end
Expand Down
155 changes: 155 additions & 0 deletions lib/fastlane/plugin/emerge/actions/emerge_snapshot_action.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
require 'fastlane/action'
require 'fastlane_core/print_table'
require_relative '../helper/emerge_helper'
require_relative '../helper/git'
require_relative '../helper/github'
require 'pathname'
require 'tmpdir'
require 'json'
require 'fileutils'

module Fastlane
module Actions
class EmergeSnapshotAction < Action
def self.run(params)
api_token = params[:api_token]

git_params = Helper::EmergeHelper.make_git_params
pr_number = params[:pr_number] || git_params.pr_number
branch = params[:branch] || git_params.branch
sha = params[:sha] || git_params.sha
base_sha = params[:base_sha] || git_params.base_sha
repo_name = params[:repo_name] || git_params.repo_name
gitlab_project_id = params[:gitlab_project_id]
tag = params[:tag]
config_path = params[:config_path]
scheme = params[:scheme]
configuration = params[:configuration]
team_id = params[:team_id] || CredentialsManager::AppfileConfig.try_fetch_value(:team_id)

Dir.mktmpdir do |temp_dir|
archive_name = "#{scheme}-Emerge-Snapshots"
archive_path = "#{temp_dir}/build/#{archive_name}.xcarchive"
make_debug_build(
scheme: scheme,
configuration: configuration,
team_id: team_id,
archive_path: archive_path
)
Helper::EmergeHelper.copy_config(config_path, archive_path)
Xcodeproj::Plist.write_to_path({ "NAME" => "Emerge Upload" }, "#{archive_path}/Info.plist")

zip_file_path = "#{temp_dir}/build/#{archive_name}.xcarchive.zip"
ZipAction.run(
path: archive_path,
output_path: zip_file_path,
exclude: [],
include: []
)

params = {
appIdSuffix: 'snapshots',
prNumber: pr_number,
branch: branch,
sha: sha,
baseSha: base_sha,
repoName: repo_name,
gitlabProjectId: gitlab_project_id,
tag: tag || "default"
}
upload_id = Helper::EmergeHelper.perform_upload(api_token, params, zip_file_path)
UI.success("🎉 Your app is processing, you can find the results at https://emergetools.com/snapshot/#{upload_id}")
end
end

def self.make_debug_build(scheme:, configuration:, team_id:, archive_path:)
other_action.gym(
scheme: scheme,
configuration: configuration,
skip_codesigning: true,
clean: true,
export_method: "development",
export_team_id: team_id,
skip_package_ipa: true,
archive_path: archive_path
)
end

def self.description
"Fastlane plugin for Emerge to generate iOS snapshots"
end

def self.authors
["Emerge Tools"]
end

def self.return_value
"If successful, returns the upload id of the generated snapshot build"
end

def self.details
""
end

def self.available_options
[
FastlaneCore::ConfigItem.new(key: :api_token,
env_name: "EMERGE_API_TOKEN",
description: "An API token for Emerge",
optional: false,
type: String),
FastlaneCore::ConfigItem.new(key: :scheme,
description: "The scheme of your app to build",
optional: false,
type: String),
FastlaneCore::ConfigItem.new(key: :configuration,
description: "The configuration of your app to use",
optional: false,
default_value: "Debug",
type: String),
FastlaneCore::ConfigItem.new(key: :team_id,
env_name: "EXPORT_TEAM_ID",
description: "The Apple Team ID to use for exporting the archive. If not provided, we will try to use the team_id from the Appfile",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :config_path,
description: "Path to Emerge YAML config path",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :pr_number,
description: "The PR number that triggered this upload",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :branch,
description: "The current git branch",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :sha,
description: "The git SHA that triggered this build",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :base_sha,
description: "The git SHA of the base build",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :repo_name,
description: "Full name of the respository this upload was triggered from. For example: EmergeTools/Emerge",
optional: true,
type: String),
FastlaneCore::ConfigItem.new(key: :gitlab_project_id,
description: "Id of the gitlab project this upload was triggered from",
optional: true,
type: Integer),
FastlaneCore::ConfigItem.new(key: :tag,
description: "String to label the build. Useful for grouping builds together in our dashboard, like development, default, or pull-request",
optional: true,
type: String)
]
end

def self.is_supported?(platform)
platform == :ios
end
end
end
end
103 changes: 88 additions & 15 deletions lib/fastlane/plugin/emerge/helper/emerge_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,16 @@ def initialize(sha:, base_sha:, branch:, pr_number: nil, repo_name: nil)

module Helper
class EmergeHelper
def self.perform_upload(upload_url, upload_id, file_path)
UI.message("Starting upload")
response = Faraday.put(upload_url) do |req|
req.headers['Content-Type'] = 'application/zip'
req.headers['Content-Length'] = File.size(file_path).to_s
req.body = Faraday::UploadIO.new(file_path, 'application/zip')
end
case response.status
when 200
UI.success("🎉 Your app is processing, you can find the results at https://emergetools.com/build/#{upload_id}")
return upload_id
else
UI.error("Upload failed")
end
return nil
API_URL = 'https://api.emergetools.com/upload'.freeze

def self.perform_upload(api_token, params, file_path)
cleaned_params = clean_params(params)
print_summary(cleaned_params)

upload_response = create_upload(api_token, cleaned_params)
handle_upload_response(api_token, upload_response, file_path)
rescue StandardError => e
UI.user_error!(e.message)
end

def self.make_git_params
Expand All @@ -56,6 +51,84 @@ def self.make_git_params
UI.message("Got git result #{git_result.inspect}")
git_result
end

def self.copy_config(config_path, tmp_dir)
return if config_path.nil?

expanded_path = File.expand_path(config_path)
unless File.exist?(expanded_path)
UI.error("No config file found at path '#{expanded_path}'.\nUploading without config file")
return
end

emerge_config_path = "#{tmp_dir}/emerge_config.yaml"
FileUtils.cp(expanded_path, emerge_config_path)
end

private_class_method

def self.clean_params(params)
params.reject { |_, v| v.nil? }
end

def self.print_summary(params)
FastlaneCore::PrintTable.print_values(
config: params,
hide_keys: [],
title: "Summary for Emerge Upload #{Fastlane::Emerge::VERSION}"
)
end

def self.create_upload(api_token, params)
response = Faraday.post(API_URL, params.to_json, headers(api_token, params, 'application/json'))
parse_response(response)
end

def self.headers(api_token, params, content_type)
{
'Content-Type' => content_type,
'X-API-Token' => api_token,
'User-Agent' => "fastlane-plugin-emerge/#{Fastlane::Emerge::VERSION}"
}
end

def self.parse_response(response)
case response.status
when 200
JSON.parse(response.body)
when 400
error_message = JSON.parse(response.body)['errorMessage']
raise "Invalid parameters: #{error_message}"
when 401, 403
raise 'Invalid API token'
else
raise "Creating upload failed with status #{response.status}"
end
end

def self.handle_upload_response(api_token, response, file_path)
upload_url = response.fetch('uploadURL')
upload_id = response.fetch('upload_id')

warning = response.dig('warning')
if warning
UI.important(warning)
end

UI.message('Starting zip file upload')
upload_file(api_token, upload_url, file_path)
upload_id
end

def self.upload_file(api_token, upload_url, file_path)
response = Faraday.put(upload_url) do |req|
req.headers = headers(api_token, nil, 'application/zip')
req.headers['Content-Length'] = File.size(file_path).to_s
req.body = Faraday::UploadIO.new(file_path, 'application/zip')
end

raise "Uploading zip file failed #{response.status}" unless response.status == 200
end
end
end
end
2 changes: 1 addition & 1 deletion lib/fastlane/plugin/emerge/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Fastlane
module Emerge
VERSION = "0.8.0"
VERSION = "0.9.0"
end
end

0 comments on commit 62910a6

Please sign in to comment.