Skip to content

Commit 6caefb8

Browse files
authored
Merge pull request #54 from smartmobilefactory/nightly
Nightly
2 parents dcb4031 + 7f7cab2 commit 6caefb8

25 files changed

+2859
-1406
lines changed
109 KB
Loading
66 KB
Loading
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# SMF iOS Fastlane Commons - Release Notes v0.2.0
2+
3+
## New Features
4+
5+
### #1 Danger
6+
7+
All Pull Requests will be analysed with [Danger](http://danger.systems) per default now!
8+
9+
10+
###### Example: Danger report in the Strato macOS App
11+
<img width="400" alt="danger_comment_example" src="./danger_comment_example.png">
12+
13+
The following checks are performed and displayed in the pull request by default:
14+
15+
- Xcode warnings and errors
16+
- GitHub PR length
17+
- Code Coverage for modified files
18+
- Total Code Coverage
19+
- SwiftLint warnings for modified files
20+
21+
All checks can be disabled and modified in the configuration json:
22+
23+
```json
24+
...
25+
26+
"danger_config": {
27+
"xcode_build_warnings.use_feature": false,
28+
}
29+
30+
...
31+
```
32+
33+
The following default values are used otherwise:
34+
35+
```json
36+
{
37+
"xcode_build_warnings.use_feature": true,
38+
"github.pr.big_length.use_feature": true,
39+
"github.pr.big_length.lines_of_code": 10000,
40+
"code_coverage.slather.use_feature": true,
41+
"code_coverage.slather.notify_if_coverage_is_less_than": 0,
42+
"code_coverage.slather.notify_if_modified_file_is_less_than": 0,
43+
"code_coverage.slather.notify_level": "fail",
44+
"swiftlint.use_feature": true,
45+
"swiftlint.fail_on_error": true
46+
}
47+
```
48+
49+
If Danger shouldn't be performed, the file `Dangerfile` has to be removed from the project.
50+
51+
##### Known issues
52+
53+
- Code Coverage doesn't reflect the real coverage for framework projects
54+
55+
### #2 Xcode warnings, SwiftLint reports and Code Coverage is stored in MetaJSON
56+
57+
Xcode warnings, SwiftLint reports and Code Coverage is stored in MetaJSON once the app is deployed. These information is not yet used but might be added to status boards and Confluence later.
58+
59+
##### Known issues
60+
61+
- Code Coverage doesn't reflect the real coverage for framework projects
62+
63+
### #3 Better notifications - especially for builds with multiple build variants in a row and iTunes Connect uploads
64+
65+
HipChat and mail notifications are now send directly after some events happened and not at the end of the build job. See Breaking changes #1 for more details.
66+
67+
### #4 Device and Simulator builds can be attached to GitHub release to enable separated UI-Tests
68+
69+
Device and Simulator builds can be attached to GitHub releases to be used for UI-Tests later.
70+
71+
###### Example: GitHub release with attached build outputs
72+
<img width="400" alt="github_release_with_build_outputs" src="./github_release_with_build_outputs.png">
73+
74+
You need to enable this feature in the configuration json:
75+
76+
```json
77+
...
78+
79+
"build_variants": {
80+
"hidrive_alpha": {
81+
...
82+
"attach_build_outputs_to_github" : true
83+
},
84+
85+
...
86+
```
87+
88+
### #5 Added some custom prechecks before building apps for iTunes Connect
89+
90+
Build jobs will now directly be aborted before even building the app if the projects marketing version is not existing and editable in iTunes Connect.
91+
This prevents errors after the app is uploaded like: The app version is already in sale.
92+
93+
94+
## Breaking changes
95+
96+
### #1 Success and error messages are now handled by the Fastlane Commons code
97+
98+
Instead of sending error or success notifications once in the end of the build jobs, Fastlane Commons sends them now directly after certain events happen during the build job. This enables eg. build jobs which build multiple build variants in a row. After each build variants was build a notification is send, not only one once the build job has completed.
99+
100+
The notifications have to enabled in lanes if they are wanted before calling the real logic:
101+
102+
```ruby
103+
smf_set_should_send_deploy_notifications(true)
104+
105+
```
106+
107+
### #2 The complete Fastlane Commons repo is downloaded temporarily during the build process
108+
109+
Until now it was only possible to download Fastlane Action files and one Fastfile during the build process. This blocked us to move more code and files into the Fastlane Commons repo. With this release the complete Fastlane Commons repo is downloaded temporarily into the project which enables us to split the Fastlane code into multiple files and also use other default files like a Gemfile or Dangerfile.
110+
111+
The projects need to declare the Fastlane commons branch (`fastlane_commons_branch`) which should be used in the configurations JSON:
112+
113+
```json
114+
...
115+
116+
"project": {
117+
"project_name" : "SelfieStar",
118+
"hipchat_channel" : "Selfie iOS",
119+
"fastlane_commons_branch" : "master"
120+
},
121+
122+
...
123+
```
124+
125+
Also the download of the Commons repo has to be triggered in the projects Fastfile:
126+
127+
```ruby
128+
config = JSON.parse(File.read('Config.json'))
129+
130+
before_all do
131+
# Import the Fastlane Commons Repo
132+
fastlane_commons_branch = config["project"]["fastlane_commons_branch"]
133+
import_from_git(url: "git@github.com:smartmobilefactory/SMF-iOS-Fastlane-Commons.git", branch: fastlane_commons_branch)
134+
end
135+
```
136+
137+
### #3 In order to run Danger during PR checks a minimum commit of SMF-iOS-CommonProjectSetupFiles is needed
138+
139+
As SwiftLint was disabled for release builds before, at least the commit `b1b13b17655b91e25c7a06ba0d25751efb5a7fdd` of SMF-iOS-CommonProjectSetupFiles is needed if Danger is used (which is done by default).
140+
141+
### #4 Gemfile and Dangerfile are required
142+
143+
Danger requires the usage of a Gemfile and Dangerfile. They only need to contain code which refers to the shared Gemfile and Dangerfile which is contained in the Fastlane commons repo.
144+
145+
**Dangerfile**
146+
147+
```ruby
148+
# Import the Dangerfile of the SMF-iOS-Fastlane commons repo
149+
fastlane_commmons_folder = ENV['FASTLANE_COMMONS_FOLDER']
150+
danger.import_dangerfile(path: "#{fastlane_commmons_folder}/danger")
151+
152+
# Add custom logic here
153+
```
154+
155+
**Gemfile**
156+
157+
```ruby
158+
source "https://rubygems.org"
159+
160+
gem 'fastlane'
161+
gem 'cocoapods'
162+
163+
gemfile_local = './.fastlane-smf-commons/danger/Gemfile'
164+
165+
if File.readable?(gemfile_local)
166+
instance_eval(File.read(gemfile_local))
167+
end
168+
```
169+
170+
### #5 The configuration json is used instead of lane parameters if possible
171+
172+
Allmost all lane parameters are replaced by direct configuration json access deep inside the Fastlane Commons code. This is needed in some parts eg. for Danger where no direct access to the Fastlane Ruby code is given. It results in a more streamlined and clear configuration usage with one source of truth: the configuration json. Also the introduction of new features will require less changes in a project as all Fastlane Commons code has access to the configuration.
173+
174+
#### a) The path to the Fastlane configuration has to be provided
175+
176+
The projects Fastfile has to provide a lane which returns the path to the configuration json (formerly BuildVariants.json).
177+
178+
```ruby
179+
private_lane :fastlane_config_path do
180+
# Return the path to the Fastlane config file
181+
"#{Dir.pwd}/Config.json"
182+
end
183+
```
184+
185+
#### b) The build variant, git branch and notification setting has to be set before logic can be called
186+
187+
At least the build variant has to be set before any logic can be called.
188+
189+
```ruby
190+
lane :check_pr do
191+
192+
smf_set_build_variant("alpha")
193+
194+
# Now we can call the real logic - without providing any other configuration
195+
smf_check_pr
196+
end
197+
```
198+
199+
When deploying apps or publishing pods also the notification setting and git branch has to be set.
200+
201+
```ruby
202+
lane :deploy_app do |options|
203+
204+
smf_set_should_send_deploy_notifications(true)
205+
206+
smf_set_git_branch(options[:branch])
207+
smf_set_build_variant(options[:build_variant])
208+
209+
# Now we can call the real logic - without providing any other configuration
210+
smf_deploy_app
211+
end
212+
```
213+
214+
## Improvements
215+
216+
Many small bug fixes
217+
218 KB
Binary file not shown.

danger/Dangerfile

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
############################
2+
###### General config ######
3+
############################
4+
5+
ENV['BUILD_VARIANT'] == nil ? build_variant = "" : build_variant = ENV['BUILD_VARIANT']
6+
ENV['FASTLANE_CONFIG_PATH'] == nil ? fastlane_config_path = "fastlane/Config.json" : fastlane_config_path = ENV['FASTLANE_CONFIG_PATH']
7+
ENV['DID_RUN_UNIT_TESTS'] == nil ? did_run_unit_tests = "false" : did_run_unit_tests = ENV['DID_RUN_UNIT_TESTS']
8+
9+
@project_danger_config = nil
10+
@commons_danger_config = nil
11+
12+
message("Analysing build variant <b>#{build_variant}</b>")
13+
14+
configuration_message = ""
15+
16+
if File.file?(fastlane_config_path)
17+
fastlane_config = JSON.parse(File.read(fastlane_config_path), :symbolize_names => true)
18+
build_variant_config = fastlane_config[:build_variants][build_variant.to_sym]
19+
target_depended_config = build_variant_config[:danger_config_name]
20+
if target_depended_config
21+
@project_danger_config = fastlane_config[target_depended_config.to_sym]
22+
else
23+
@project_danger_config = fastlane_config[:danger_config]
24+
end
25+
else
26+
fail "Error: SMF Fastlane config couldn't be found in #{ENV['FASTLANE_CONFIG_PATH']}"
27+
end
28+
29+
if File.file?("#{ENV['FASTLANE_COMMONS_FOLDER']}/danger/danger_defaults.json")
30+
@commons_danger_config = JSON.parse(File.read("#{ENV['FASTLANE_COMMONS_FOLDER']}/danger/danger_defaults.json"), :symbolize_names => true)
31+
if @commons_danger_config.nil?
32+
fail "The default Danger config is nil"
33+
end
34+
else
35+
fail "The Fastlane commons repo doesn't contain danger/danger_defaults.json"
36+
end
37+
38+
###################
39+
##### Helpers #####
40+
###################
41+
42+
def get_config_value(key)
43+
if @project_danger_config != nil && @project_danger_config[key.to_sym] != nil
44+
return @project_danger_config[key.to_sym]
45+
else
46+
if @commons_danger_config == nil
47+
return nil
48+
else
49+
return @commons_danger_config[key.to_sym]
50+
end
51+
end
52+
end
53+
54+
#####################
55+
###### General ######
56+
#####################
57+
58+
if get_config_value("github.pr.big_length.use_feature")
59+
if git.lines_of_code > get_config_value("github.pr.big_length.lines_of_code")
60+
warn("There amount of changed code is huge (#{git.lines_of_code} lines). Please try to create many small pull requests instead of a few big ones!")
61+
end
62+
configuration_message += "<br />GitHub PR length is <b>enabled</b><br />- lines_of_code: <b>#{get_config_value("github.pr.big_length.lines_of_code")}</b>"
63+
else
64+
configuration_message += "<br />GitHub PR length is <b>disabled</b>"
65+
end
66+
67+
###################
68+
###### Xcode ######
69+
###################
70+
71+
if get_config_value("xcode_build_warnings.use_feature")
72+
if File.file?("build/reports/errors.json")
73+
xcode_summary.report 'build/reports/errors.json'
74+
configuration_message += "<br /><br />Xcode warnings are <b>enabled</b>"
75+
else
76+
configuration_message += "<br /><br />Xcode warnings are <b>disabled</b> as the build output couldn't be found"
77+
end
78+
else
79+
configuration_message += "<br /><br />Xcode warnings are <b>disabled</b>"
80+
end
81+
82+
#######################
83+
###### Swiftlint ######
84+
#######################
85+
86+
if get_config_value("swiftlint.use_feature")
87+
# Use the SwiftLint Pod if available. Otherwise the SwiftLint version from the Danger plugin is used.
88+
fail_on_error = get_config_value("swiftlint.fail_on_error")
89+
pods_swiftlint_binary = "Pods/SwiftLint/swiftlint"
90+
if File.file?(pods_swiftlint_binary)
91+
expanded_binary_path = File.expand_path(pods_swiftlint_binary)
92+
swiftlint.binary_path = expanded_binary_path
93+
end
94+
95+
swiftlint_config_message = "Exists in project"
96+
if File.file?(".swiftlint.yml")
97+
swiftlint.config_file = File.expand_path(".swiftlint.yml")
98+
end
99+
100+
# Run SwiftLint
101+
if fail_on_error
102+
swiftlint.lint_files fail_on_error: true
103+
else
104+
swiftlint.lint_files
105+
end
106+
107+
swiftlint.verbose = true
108+
109+
configuration_message += "<br /><br />SwiftLint is <b>enabled</b> (modified files only)<br />- binary: <b>#{swiftlint.binary_path}</b>,<br />- fail_on_error: <b>#{fail_on_error}</b>,<br />- SwiftLint configuration: <b>#{swiftlint.config_file}</b>"
110+
else
111+
configuration_message += "<br /><br />SwiftLint is <b>disabled</b>"
112+
end
113+
114+
#####################
115+
###### Slather ######
116+
#####################
117+
118+
if get_config_value("code_coverage.slather.use_feature")
119+
perform_unit_tests = (build_variant_config["pr.perform_unit_tests".to_sym].nil? ? true : build_variant_config["pr.perform_unit_tests".to_sym])
120+
if perform_unit_tests && did_run_unit_tests == "true"
121+
122+
project_name = fastlane_config[:project][:project_name]
123+
scheme = build_variant_config[:scheme]
124+
125+
slather.configure("#{project_name}.xcodeproj", scheme, options: {
126+
workspace: "#{project_name}.xcworkspace",
127+
output_directory: 'build/reports',
128+
})
129+
130+
min_total_coverage = get_config_value("code_coverage.slather.notify_if_coverage_is_less_than").to_i
131+
min_file_coverage = get_config_value("code_coverage.slather.notify_if_modified_file_is_less_than").to_i
132+
notify_level_string = get_config_value("code_coverage.slather.notify_level")
133+
notify_level = notify_level_string == "warn" ? :warn : :fail
134+
135+
slather.notify_if_coverage_is_less_than(minimum_coverage: min_total_coverage, notify_level: notify_level)
136+
slather.notify_if_modified_file_is_less_than(minimum_coverage: min_file_coverage, notify_level: notify_level)
137+
slather.show_coverage
138+
139+
configuration_message += "<br /><br />Slather is <b>enabled</b><br />- notify_if_coverage_is_less_than: <b>#{min_total_coverage}</b><br />- notify_if_modified_file_is_less_than: <b>#{min_file_coverage}</b><br />- notify_level: <b>#{notify_level_string}</b>"
140+
elsif did_run_unit_tests == "false"
141+
configuration_message += "<br /><br />Slather is <b>disabled</b> as unit tests weren't runned during the PR check"
142+
else
143+
configuration_message += "<br /><br />Slather is <b>disabled</b> as unit tests shouldn't be runned"
144+
end
145+
else
146+
warn("Slather is <b>disabled</b>")
147+
end
148+
149+
# Put the configuration message inside an expandable element
150+
configuration_message = "<details><summary>Danger configuration:</summary>#{configuration_message}</details>"
151+
152+
message(configuration_message)
153+

danger/Gemfile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
source "https://rubygems.org"
2+
3+
gem 'danger'
4+
gem 'slather'
5+
gem 'danger-swiftlint'
6+
gem 'danger-xcode_summary'
7+
gem 'danger-slather'
8+
gem 'xcpretty-json-formatter'

danger/danger_defaults.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"xcode_build_warnings.use_feature": true,
3+
"github.pr.big_length.use_feature": true,
4+
"github.pr.big_length.lines_of_code": 10000,
5+
"code_coverage.slather.use_feature": true,
6+
"code_coverage.slather.notify_if_coverage_is_less_than": 0,
7+
"code_coverage.slather.notify_if_modified_file_is_less_than": 0,
8+
"code_coverage.slather.notify_level": "fail",
9+
"swiftlint.use_feature": true,
10+
"swiftlint.fail_on_error": true
11+
}

0 commit comments

Comments
 (0)