Skip to content

Commit eec8dec

Browse files
authored
Merge pull request #4 from qawolf/gen-272-update-fastlane-plugin-to-require-uploaded-filename
breaking changes to help with test automation
2 parents 4a05840 + 017fc8b commit eec8dec

File tree

8 files changed

+114
-70
lines changed

8 files changed

+114
-70
lines changed

README.md

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To
66

77
```
88
# Add this to your Gemfile
9-
gem "fastlane-plugin-qawolf", git: "https://github.com/qawolf/fastlane-plugin-qawolf", tag: "0.2.0"
9+
gem "fastlane-plugin-qawolf", git: "https://github.com/qawolf/fastlane-plugin-qawolf", tag: "0.3.0"
1010
```
1111

1212
## About qawolf
@@ -15,9 +15,6 @@ Fastlane plugin for QA Wolf integration.
1515

1616
Uploads build artifacts (IPA, APK, or AAB) to QA Wolf storage for automated testing. Optionally triggers a test run on QA Wolf.
1717

18-
> [!CAUTION]
19-
> To ensure QA Wolf tests target the correct app build and help debugging issues, we require uploaded filenames to be unique in some way. The example below uses the git commit hash, but you can use another unique identifier such as the app version number if you wish.
20-
2118
> [!IMPORTANT]
2219
> Testing iOS apps (IPA) on QA Wolf is not yet available.
2320
@@ -27,12 +24,9 @@ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plu
2724

2825
```ruby
2926
lane :build do
30-
# The uploaded filename must be unique for your team on the QA Wolf platform.
31-
# One way to achieve that is to rely on the git commit hash.
32-
# Feel free to use a different mechanism if desired (e.g. app version).
27+
# It's recommended to only trigger builds with a clean git status.
3328
# See https://docs.fastlane.tools/actions/#source-control for other source control actions
3429
ensure_git_status_clean
35-
commit = last_git_commit
3630

3731
# Build your app
3832
# Ensure the APK/AAB file has been created. Your use case may vary.
@@ -47,10 +41,11 @@ lane :build do
4741
# Must be set or available as env var QAWOLF_API_KEY
4842
qawolf_api_key: "qawolf_...",
4943

50-
# You can omit this if your gradle build outputs the file with a unique filename.
51-
# If not, you'll want to do something like the following.
52-
# Make sure you use the right file extension!
53-
filename: "app_#{commit[:abbreviated_commit_hash]}.apk"
44+
# Must be set to guarantee the uploaded file is replaced.
45+
# Typically, this should include a git branch name or a QA Wolf environment name.
46+
# Reach out to QA Wolf if you're unsure.
47+
# Do NOT include a file extension, it'll be appended based on the build output file.
48+
executable_file_basename: "calculator_app_staging",
5449

5550
# Only set this if you have not built the artifact in the same lane,
5651
# e.g. via gradle or similar, check official Fastlane docs for details.
@@ -63,19 +58,39 @@ lane :build do
6358
# Must be set or available as env var QAWOLF_API_KEY
6459
qawolf_api_key: "qawolf_...",
6560

66-
# These fields are dependent on how triggers are setup within QA Wolf.
67-
# Reach out to support for help. All fields are optional.
68-
branch: nil,
69-
commit_url: nil,
70-
deduplication_key: nil,
71-
deployment_type: nil,
61+
# Optional, but set if requested by the QA Wolf team.
62+
# This is mostly to help distinguish between multiple apps within the same team/environment.
63+
executable_environment_key: "RUN_INPUT_PATH",
64+
65+
# Optional, defaults to the current git branch, if available. Set to false to skip.
66+
branch: git_branch,
67+
68+
# URL to your VCS commit URL
69+
commit_url: "https://github.com/team/repo/commit/ec78d7d81a6a66e9e89fd29f6e0616d5ba09840a",
70+
71+
# Set to cancel ongoing test runs with the same value
72+
deduplication_key: "some_idempotent_value",
73+
74+
# Must be set if configured in the QA Wolf deployment trigger
75+
deployment_type: "deployment_name",
76+
77+
# Can be left empty as it's mostly for web tests
78+
# If set, will be available as `process.env.URL`
7279
deployment_url: nil,
73-
hosting_service: nil,
74-
sha: nil,
75-
variables: nil,
80+
81+
# If configured in QA Wolf, set to GitHub or GitLab as needed
82+
hosting_service: "GitHub",
83+
84+
# Optional, defaults to current git commit hash if available. Set to false to skip
85+
sha: last_git_commit[:commit_hash],
86+
87+
# Additional hash of key-value pairs to set as environment variables for test runs
88+
variables: {
89+
FOO: "bar"
90+
},
7691

7792
# Only set this if your lane does not include `upload_to_qawolf`
78-
run_input_path: nil,
93+
executable_filename: "calculator_app_staging.apk",
7994
)
8095
end
8196
```
@@ -208,7 +223,9 @@ The instructions below are for maintainers of this plugin.
208223
gradle(task: "clean assembleRelease")
209224
210225
# relies on output of the gradle task and env var QAWOLF_API_KEY
211-
qawolf
226+
# see example above for options
227+
upload_to_qawolf
228+
notify_deploy_qawolf
212229
end
213230
end
214231
```

fastlane/Fastfile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
lane :test do
22
upload_to_qawolf(
3-
file_path: "./fastlane/fastlane-test-app-debug.apk"
3+
file_path: "./fastlane/fastlane-test-app-debug.apk",
4+
executable_file_basename: "fastlane_test"
45
)
56
notify_deploy_qawolf(
67
deployment_type: "android",
8+
sha: false,
9+
executable_environment_key: "ANDROID_APP",
710
variables: {
811
HELLO: "WORLD"
912
}

lib/fastlane/plugin/qawolf/actions/notify_deploy_qawolf_action.rb

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,28 @@ module SharedValues
1010

1111
# Casing is important for the action name!
1212
class NotifyDeployQawolfAction < Action
13+
BASE_PATH = "/home/wolf/run-inputs-executables/"
14+
1315
def self.run(params)
1416
qawolf_api_key = params[:qawolf_api_key] # Required
1517
qawolf_base_url = params[:qawolf_base_url]
1618

1719
UI.message("🐺 Calling QA Wolf deploy success webhook...")
1820

1921
variables = params[:variables] || {}
22+
executable_environment_key = params[:executable_environment_key]
23+
branch = params[:branch] if params[:branch].kind_of?(String) && !params[:branch].empty?
24+
sha = params[:sha] if params[:sha].kind_of?(String) && !params[:sha].empty?
2025

2126
options = {
22-
branch: params[:branch],
27+
branch: branch,
2328
commit_url: params[:commit_url],
2429
deployment_type: params[:deployment_type],
2530
deployment_url: params[:deployment_url],
2631
deduplication_key: params[:deduplication_key],
2732
hosting_service: params[:hosting_service],
28-
sha: params[:sha],
29-
variables: variables.merge({
30-
RUN_INPUT_PATH: run_input_path(params)
31-
})
33+
sha: sha,
34+
variables: variables.merge({ executable_environment_key => run_input_path(params) })
3235
}
3336

3437
run_id = Helper::QawolfHelper.notify_deploy(qawolf_api_key, qawolf_base_url, options)
@@ -42,11 +45,11 @@ def self.run(params)
4245
end
4346

4447
def self.run_input_path(params)
45-
if params[:run_input_path].nil?
46-
UI.user_error!("🐺 No run input path found. Please run the `upload_to_qawolf` action first or set the `run_input_path` option.")
48+
if params[:executable_filename].nil?
49+
UI.user_error!("🐺 No executable filename found. Please run the `upload_to_qawolf` action first or set the `executable_filename` option.")
4750
end
4851

49-
return params[:run_input_path]
52+
return "#{BASE_PATH}#{params[:executable_filename]}"
5053
end
5154

5255
def self.description
@@ -79,10 +82,16 @@ def self.available_options
7982
description: "Your QA Wolf base URL",
8083
optional: true,
8184
type: String),
82-
FastlaneCore::ConfigItem.new(key: :branch,
83-
description: "If using Git, set this to the branch name so it can be displayed in the QA Wolf UI and find any pull requests in the linked repo",
85+
FastlaneCore::ConfigItem.new(key: :executable_environment_key,
86+
description: "Sets the environment key to use for the executable. Will alias the executable file's absolute path in tests to, for example, `process.env.RUN_INPUT_PATH` Defaults to `RUN_INPUT_PATH`",
8487
optional: true,
88+
default_value: "RUN_INPUT_PATH",
8589
type: String),
90+
FastlaneCore::ConfigItem.new(key: :branch,
91+
description: "Defaults to the current git branch if available. Override by providing a custom value, or set it to false to send an empty value. Displayed in the QA Wolf UI to help find any pull requests in the linked repo",
92+
optional: true,
93+
default_value: Actions.git_branch,
94+
type: Object),
8695
FastlaneCore::ConfigItem.new(key: :commit_url,
8796
description: "If you do not specify a hosting service, include this and the `sha` option to ensure the commit hash is a clickable link in QA Wolf",
8897
optional: true,
@@ -104,16 +113,18 @@ def self.available_options
104113
optional: true,
105114
type: String),
106115
FastlaneCore::ConfigItem.new(key: :sha,
107-
description: "If a Git commit triggered this, include the commit hash so that we can create commit checks if you also have a GitHub repo linked. Also displayed in the QA Wolf UI",
116+
description: "Defaults to the current git commit hash. Override by providing a custom value, or set to false to send an empty value. We use it to create commit checks if you also have a GitHub repo linked. Also displayed in the QA Wolf UI",
108117
optional: true,
109-
type: String),
118+
default_value: Actions.last_git_commit_hash(false),
119+
type: Object),
110120
FastlaneCore::ConfigItem.new(key: :variables,
111121
description: "Optional key-value pairs to pass to the test run. These will be available as `process.env` in tests",
112122
optional: true,
113-
type: Object),
114-
FastlaneCore::ConfigItem.new(key: :run_input_path,
115-
env_name: "QAWOLF_RUN_INPUT_PATH",
116-
description: "The path of the run input file to run in QA Wolf. Set by the `upload_to_qawolf` action",
123+
default_value: {},
124+
type: Hash),
125+
FastlaneCore::ConfigItem.new(key: :executable_filename,
126+
env_name: "QAWOLF_EXECUTABLE_FILENAME",
127+
description: "The filename of the executable to use in QA Wolf. Set by the `upload_to_qawolf` action",
117128
optional: true,
118129
type: String)
119130
]
@@ -130,6 +141,8 @@ def self.example_code
130141
'notify_deploy_qawolf',
131142
'notify_deploy_qawolf(
132143
qawolf_api_key: ENV["QAWOLF_API_KEY"],
144+
executable_environment_key: "MY_APP",
145+
executable_filename: "<FILENAME>",
133146
branch: "<BRANCH_NAME>",
134147
commit_url: "<URL>",
135148
deployment_type: "<DEPLOYMENT_TYPE>",

lib/fastlane/plugin/qawolf/actions/upload_to_qawolf_action.rb

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
module Fastlane
66
module Actions
77
module SharedValues
8-
QAWOLF_RUN_INPUT_PATH = :QAWOLF_RUN_INPUT_PATH
8+
QAWOLF_EXECUTABLE_FILENAME = :QAWOLF_EXECUTABLE_FILENAME
99
end
1010

1111
# Casing is important for the action name!
@@ -16,20 +16,20 @@ def self.run(params)
1616
qawolf_api_key = params[:qawolf_api_key] # Required
1717
qawolf_base_url = params[:qawolf_base_url]
1818
file_path = params[:file_path] || default_file_path
19-
filename = params[:filename]
19+
executable_file_basename = params[:executable_file_basename]
2020

2121
validate_file_path(file_path)
2222

2323
UI.message("🐺 Uploading to QA Wolf...")
2424

25-
run_input_path = Helper::QawolfHelper.upload_file(qawolf_api_key, qawolf_base_url, file_path, filename)
25+
uploaded_filename = Helper::QawolfHelper.upload_file(qawolf_api_key, qawolf_base_url, file_path, executable_file_basename)
2626

27-
ENV["QAWOLF_RUN_INPUT_PATH"] = run_input_path
27+
ENV["QAWOLF_EXECUTABLE_FILENAME"] = uploaded_filename
2828

29-
UI.success("🐺 Uploaded #{file_path} to QA Wolf successfully. Run input path: #{run_input_path}")
30-
UI.success("🐺 Setting environment variable QAWOLF_RUN_INPUT_PATH = #{run_input_path}")
29+
UI.success("🐺 Uploaded #{file_path} to QA Wolf successfully. Executable filename: #{uploaded_filename}")
30+
UI.success("🐺 Setting environment variable QAWOLF_EXECUTABLE_FILENAME = #{uploaded_filename}")
3131

32-
Actions.lane_context[SharedValues::QAWOLF_RUN_INPUT_PATH] = run_input_path
32+
Actions.lane_context[SharedValues::QAWOLF_EXECUTABLE_FILENAME] = uploaded_filename
3333
end
3434

3535
# Validate file_path.
@@ -58,7 +58,7 @@ def self.details
5858

5959
def self.output
6060
[
61-
['QAWOLF_RUN_INPUT_PATH', 'Uploaded file location for the executable artifact.']
61+
['QAWOLF_EXECUTABLE_FILENAME', 'Uploaded filename for the executable artifact.']
6262
]
6363
end
6464

@@ -94,12 +94,16 @@ def self.available_options
9494
optional: true,
9595
type: String),
9696
FastlaneCore::ConfigItem.new(key: :file_path,
97-
description: "Path to the app file",
98-
optional: true,
99-
type: String),
100-
FastlaneCore::ConfigItem.new(key: :filename,
101-
description: "Optional uploaded filename to use instead of the original filename",
97+
description: "Path to the built app file",
10298
optional: true,
99+
type: String,
100+
verify_block: proc do |value|
101+
file_path = File.expand_path(value)
102+
UI.user_error!("Couldn't find file at path '#{file_path}'") unless File.exist?(file_path)
103+
end),
104+
FastlaneCore::ConfigItem.new(key: :executable_file_basename,
105+
description: "Required file basename for the uploaded executable",
106+
optional: false,
103107
type: String)
104108
]
105109
end
@@ -112,12 +116,13 @@ def self.is_supported?(platform)
112116

113117
def self.example_code
114118
[
115-
'qawolf',
116-
'upload_to_qawolf',
119+
'upload_to_qawolf(
120+
executable_file_basename: "my_app"
121+
)',
117122
'upload_to_qawolf(
118123
qawolf_api_key: ENV["QAWOLF_API_KEY"],
119124
file_path: "/path_to/app.apk",
120-
filename: "custom_filename.apk"
125+
executable_file_basename: "my_app"
121126
)'
122127
]
123128
end

lib/fastlane/plugin/qawolf/helper/qawolf_helper.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,21 @@ def self.get_signed_url(qawolf_api_key, qawolf_base_url, filename)
3535
# +qawolf_api_key+:: QA Wolf API key
3636
# +qawolf_base_url+:: QA Wolf API base URL
3737
# +file_path+:: Path to the file to be uploaded.
38-
# +filename+:: Optional filename to use instead of the file's basename.
39-
def self.upload_file(qawolf_api_key, qawolf_base_url, file_path, filename = nil)
38+
# +executable_file_basename+:: Name to use for the uploaded file without extension
39+
def self.upload_file(qawolf_api_key, qawolf_base_url, file_path, executable_file_basename)
40+
unless executable_file_basename
41+
UI.user_error!("`executable_file_basename` is required")
42+
end
43+
4044
file_content = File.open(file_path, "rb")
4145

4246
headers = {
4347
user_agent: "qawolf_fastlane_plugin",
4448
content_type: "application/octet-stream"
4549
}
4650

47-
signed_url, run_input_path = get_signed_url(qawolf_api_key, qawolf_base_url, filename || File.basename(file_path))
51+
uploaded_filename = "#{executable_file_basename}#{File.extname(file_path)}"
52+
signed_url, run_input_path = get_signed_url(qawolf_api_key, qawolf_base_url, uploaded_filename)
4853

4954
RestClient.put(signed_url, file_content, headers)
5055

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
module Fastlane
22
module Qawolf
3-
VERSION = "0.2.0"
3+
VERSION = "0.3.0"
44
end
55
end

spec/fastlane/actions/notify_deploy_qawolf_action_spec.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
describe Fastlane::Actions::NotifyDeployQawolfAction do
44
describe "#run" do
5-
let(:run_input_path) { "file.apk" }
5+
let(:executable_filename) { "file.apk" }
66
let(:params) do
77
{
88
qawolf_api_key: "api_key",
9-
run_input_path: run_input_path
9+
executable_filename: executable_filename
1010
}
1111
end
1212
let(:deploy_response) do
@@ -32,7 +32,7 @@
3232
end
3333

3434
context "with no run input path set" do
35-
let(:run_input_path) { nil }
35+
let(:executable_filename) { nil }
3636

3737
it "fails when no test run is triggered" do
3838
expect do

0 commit comments

Comments
 (0)