Skip to content

Instantly share code, notes, and snippets.

@hoppsen
Last active January 30, 2023 17:10
Show Gist options
  • Save hoppsen/3bf03b64fba1cca11f459eb5f64e3289 to your computer and use it in GitHub Desktop.
Save hoppsen/3bf03b64fba1cca11f459eb5f64e3289 to your computer and use it in GitHub Desktop.
A hacky Fastlane lane to collect TestFlight feedback and create sub-tasks in Jira.
desc 'Collects TestFlight feedback and creates sub-tasks in Jira.'
desc '#### Example:'
desc "```\nbundle exec fastlane feedback api_key:1a2b3c4d parent:NA-123 build:456\n```"
desc '#### Options:'
desc ' * **`api_key`**: Your Jira API key. See https://id.atlassian.com/manage-profile/security/api-tokens'
desc ' * **`parent`**: The ticket number of the parent task the sub-tasks should be added to.'
desc ' * **`build`**: Filter TestFlight feedback by build number.'
lane :feedback do |options|
# Lookout for this to be resolved: https://jira.atlassian.com/browse/JSWCLOUD-18031
require 'net/http'
require 'uri'
require 'json'
fastlane_require 'spaceship'
Spaceship::Tunes.login
Spaceship::Tunes.select_team
app = Spaceship::ConnectAPI::App.find('com.domain.appidentifier')
feedbacks = app.get_beta_feedback
build = options[:build] || nil
# https://github.com/fastlane/fastlane/blob/master/spaceship/lib/spaceship/connect_api/models/beta_feedback.rb
feedbacks.each do |feedback|
next if build != nil && options[:build] != feedback.build.version
uri = URI.parse("https://<your-subdomain>.atlassian.net/rest/api/2/issue/")
request = Net::HTTP::Post.new(uri)
# For creating an API key see https://id.atlassian.com/manage-profile/security/api-tokens
request.basic_auth("user@domain.com", "#{options[:api_key]}")
request.content_type = "application/json"
# Formatting: https://jira.atlassian.com/secure/WikiRendererHelpAction.jspa?section=all
request.body = JSON.dump({
"fields" => {
"project" => {
"key" => "NA"
},
"parent" => {
"key" => "#{options[:parent]}"
},
"summary" => "[iOS] #{feedback.comment}",
"description" => "#{feedback.comment}
*name:* #{feedback.tester.first_name} #{feedback.tester.last_name}
*email:* #{feedback.tester.email}
*build:* #{feedback.build.version}
*device:* #{feedback.device_model}
*os:* #{feedback.os_version}",
"labels" => [
"iOS",
"TestFlight"
],
"issuetype" => {
"name" => "Sub-task"
}
}
})
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
jsonResponse = JSON.parse(response.body)
newIssueKey = jsonResponse["key"]
# Image upload
feedback.screenshots.each do |screenshot|
screenshot.image_assets.each do |image_asset|
next unless image_asset['url'].include?('original.jpg')
tempPath = "original.jpg"
URI.open(image_asset['url']) do |image|
File.open(tempPath, "wb") do |file|
file.write(image.read)
end
end
sh("curl -D- -u user@domain.com:#{options[:api_key]} -X POST -H 'X-Atlassian-Token: nocheck' -F 'file=@#{tempPath}' https://<your-subdomain>.atlassian.net/rest/api/2/issue/#{newIssueKey}/attachments")
File.delete(tempPath) if File.exist?(tempPath)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment