diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 39efb100f..8d16e103c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 + with: + fetch-depth: 150 # This action reads the Ruby version from .ruby-version - uses: ruby/setup-ruby@v1 diff --git a/.gitignore b/.gitignore index 9e5151dcc..447bc3e04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ .DS_Store /tmp +# JetBrains IDE files +.idea + # Ruby / Bundler .bundle/ vendor/bundle @@ -10,16 +13,19 @@ fastlane/README.md fastlane/report.xml # Testing -/test_results -/coverage +test_results/ +coverage/ + +# YARD Documentation +yard-doc/ # DrawText -/lib/drawText -/lib/drawText.bundle -/ext/drawText/drawText.xcodeproj/xcuserdata -/ext/drawText/drawText.xcodeproj/project.xcworkspace/xcuserdata -/ext/drawText/test-output -/default.profraw +lib/drawText +lib/drawText.bundle +ext/drawText/drawText.xcodeproj/xcuserdata +ext/drawText/drawText.xcodeproj/project.xcworkspace/xcuserdata +ext/drawText/test-output +default.profraw # L10n Linter vendor/swiftgen diff --git a/.rspec b/.rspec new file mode 100644 index 000000000..16f9cdb01 --- /dev/null +++ b/.rspec @@ -0,0 +1,2 @@ +--color +--format documentation diff --git a/.rubocop.yml b/.rubocop.yml index c4c087563..6475891c0 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,70 @@ +inherit_from: .rubocop_todo.yml + require: - rubocop-rspec -Metrics/BlockLength: +########## Lint / CodeStyle + +# This gem is included as part of the `Pluginfile`, which is `required` separately, +# so makes it hard to keep it ordered with the rest of the gems +Gemspec/OrderedDependencies: Exclude: - - 'spec/**/*.rb' + - 'fastlane-plugin-wpmreleasetoolkit.gemspec' + +# Especially for actions and methods like `self.run(params)` it's common to have the argument unused; but that +# comes with the parent class API / contract, so we feel it more readable to avoid the _ unused prefix for those. +Lint/UnusedMethodArgument: + Enabled: false + +# We have a couple of empty methods especially when we implement an API contract on our Action subclasses +# and those look nicer to us when still written as expended (in separate lines) to suggest us to fill them at some point +# rather than the compact representation of having them one-liner `def foo; end` that is rubocop's default. +Style/EmptyMethod: + EnforcedStyle: expanded + +# Trailing commas in array literals helps having smaller diffs when we want to add additional parameters +Style/TrailingCommaInArrayLiteral: + EnforcedStyleForMultiline: consistent_comma + +# Enabling the 'frozen_string_literal: true' comment is nice but should be done with extra care +# because enabling it on code that accidentally mutates string literals will crash at runtime +# (e.g. `name = 'Hello'` then later `name << ' world'` will crash if the comment is enabled) +# So we might enable it at some point, be we will need very careful review that this doesn't break everything. +Style/FrozenStringLiteralComment: + Enabled: false + +# Unicode is pretty standard by now, and we want to be able to use em-dash, ellipsis, and unicode characters +# to provide nice Monodraw.app graphs and similar, without being limited only by ascii. +Style/AsciiComments: + Enabled: false + +########## Metrics / Max Lengths Rules + +Metrics/LineLength: + Max: 300 + +Metrics/AbcSize: + Max: 140 + +Metrics/BlockLength: + Max: 80 + +Metrics/ClassLength: + Max: 300 + +Metrics/MethodLength: + Max: 100 + +Metrics/ModuleLength: + Max: 300 + +Metrics/ParameterLists: + Max: 10 + +########## Metrics / Complexity + +Metrics/CyclomaticComplexity: + Max: 20 + +Metrics/PerceivedComplexity: + Max: 20 diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 000000000..24a662e95 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,468 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2021-02-24 20:33:55 +0100 using RuboCop version 0.75.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 32 +Lint/IneffectiveAccessModifier: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + +# Offense count: 3 +Lint/NonLocalExitFromIterator: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + +# Offense count: 9 +# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods. +Lint/UselessAccessModifier: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + +# Offense count: 6 +Lint/UselessAssignment: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 9 +Naming/AccessorMethodName: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'spec/spec_helper.rb' + +# Offense count: 89 +# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist, MethodDefinitionMacros. +# NamePrefix: is_, has_, have_ +# NamePrefixBlacklist: is_, has_, have_ +# NameWhitelist: is_a? +# MethodDefinitionMacros: define_method, define_singleton_method +Naming/PredicateName: + Enabled: false + +# Offense count: 19 +# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. +# AllowedNames: io, id, to, by, on, in, at, ip, db +Naming/UncommunicativeMethodParamName: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 78 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, camelCase +Naming/VariableName: + Exclude: + - 'bin/drawText' + - 'ext/drawText/extconf.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + +# Offense count: 2 +# Configuration parameters: EnforcedStyle. +# SupportedStyles: snake_case, normalcase, non_integer +Naming/VariableNumber: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + +# Offense count: 5 +# Configuration parameters: Prefixes. +# Prefixes: when, with, without +RSpec/ContextWording: + Exclude: + - 'spec/ci_helper_spec.rb' + - 'spec/git_helper_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + +# Offense count: 25 +# Cop supports --auto-correct. +# Configuration parameters: SkipBlocks, EnforcedStyle. +# SupportedStyles: described_class, explicit +RSpec/DescribedClass: + Exclude: + - 'spec/ci_helper_spec.rb' + - 'spec/configuration_spec.rb' + - 'spec/encryption_helper_spec.rb' + - 'spec/file_reference_spec.rb' + - 'spec/git_helper_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + +# Offense count: 5 +# Configuration parameters: Max. +RSpec/ExampleLength: + Exclude: + - 'spec/ci_helper_spec.rb' + - 'spec/configuration_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + - 'spec/release_notes_helper_spec.rb' + +# Offense count: 9 +# Configuration parameters: CustomTransform, IgnoreMethods, SpecSuffixOnly. +RSpec/FilePath: + Exclude: + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/ci_helper_spec.rb' + - 'spec/configuration_spec.rb' + - 'spec/encryption_helper_spec.rb' + - 'spec/file_reference_spec.rb' + - 'spec/git_helper_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + - 'spec/release_notes_helper_spec.rb' + +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, each, example +RSpec/HookArgument: + Exclude: + - 'spec/configuration_spec.rb' + - 'spec/encryption_helper_spec.rb' + - 'spec/file_reference_spec.rb' + - 'spec/git_helper_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +RSpec/HooksBeforeExamples: + Exclude: + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + +# Offense count: 24 +# Configuration parameters: AssignmentOnly. +RSpec/InstanceVariable: + Exclude: + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/git_helper_spec.rb' + - 'spec/ios_lint_localizations_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +RSpec/LeadingSubject: + Exclude: + - 'spec/configuration_spec.rb' + +# Offense count: 18 +# Configuration parameters: . +# SupportedStyles: have_received, receive +RSpec/MessageSpies: + EnforcedStyle: receive + +# Offense count: 11 +RSpec/MultipleExpectations: + Max: 7 + +# Offense count: 35 +# Configuration parameters: IgnoreSharedExamples. +RSpec/NamedSubject: + Exclude: + - 'spec/ci_helper_spec.rb' + - 'spec/configuration_spec.rb' + - 'spec/file_reference_spec.rb' + +# Offense count: 5 +RSpec/SubjectStub: + Exclude: + - 'spec/file_reference_spec.rb' + +# Offense count: 4 +# Configuration parameters: IgnoreNameless, IgnoreSymbolicNames. +RSpec/VerifiedDoubles: + Exclude: + - 'spec/encryption_helper_spec.rb' + - 'spec/spec_helper.rb' + +# Offense count: 5 +Security/Open: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + +# Offense count: 95 +Style/Documentation: + Enabled: false + +# Offense count: 4 +# Configuration parameters: AllowedVariables. +Style/GlobalVars: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 10 +# Configuration parameters: MinBodyLength. +Style/GuardClause: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 2 +# Configuration parameters: AllowIfModifier. +Style/IfInsideElse: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + +# Offense count: 92 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +Style/MethodCallWithoutArgsParentheses: + Enabled: false + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: require_parentheses, require_no_parentheses, require_no_parentheses_except_multiline +Style/MethodDefParentheses: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + +# Offense count: 1 +Style/MixinUsage: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 5 +Style/MultilineBlockChain: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb' + +# Offense count: 15 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: literals, strict +Style/MutableConstant: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/version.rb' + - 'spec/release_notes_helper_spec.rb' + +# Offense count: 9 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, MinBodyLength. +# SupportedStyles: skip_modifier_ifs, always +Style/Next: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' + +# Offense count: 23 +# Cop supports --auto-correct. +# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods. +# SupportedStyles: predicate, comparison +Style/NumericPredicate: + Exclude: + - 'spec/**/*' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +Style/RedundantBegin: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 16 +# Cop supports --auto-correct. +Style/RedundantParentheses: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' + +# Offense count: 39 +# Cop supports --auto-correct. +# Configuration parameters: AllowMultipleReturnValues. +Style/RedundantReturn: + Enabled: false + +# Offense count: 39 +# Cop supports --auto-correct. +Style/RedundantSelf: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb' + - 'spec/android_merge_translators_strings_spec.rb' + - 'spec/ios_merge_translators_strings_spec.rb' + +# Offense count: 6 +# Cop supports --auto-correct. +Style/RescueModifier: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb' + +# Offense count: 13 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: implicit, explicit +Style/RescueStandardError: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: ConvertCodeThatCanStartToReturnNil, Whitelist. +# Whitelist: present?, blank?, presence, try, try! +Style/SafeNavigation: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + +# Offense count: 10 +# Cop supports --auto-correct. +Style/SelfAssignment: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: only_raise, only_fail, semantic +Style/SignalException: + Exclude: + - 'Dangerfile' + +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle. +# SupportedStyles: use_perl_names, use_english_names +Style/SpecialGlobalVars: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +# Configuration parameters: . +# SupportedStyles: percent, brackets +Style/SymbolArray: + EnforcedStyle: percent + MinSize: 3 + +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: IgnoredMethods. +# IgnoredMethods: respond_to, define_method +Style/SymbolProc: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb' + +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, AllowSafeAssignment. +# SupportedStyles: require_parentheses, require_no_parentheses, require_parentheses_when_complex +Style/TernaryParentheses: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb' + +# Offense count: 3 +# Cop supports --auto-correct. +Style/UnlessElse: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb' + +# Offense count: 4 +# Cop supports --auto-correct. +Style/ZeroLengthPredicate: + Exclude: + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb' + - 'lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb' diff --git a/.yardopts b/.yardopts new file mode 100644 index 000000000..395f27df8 --- /dev/null +++ b/.yardopts @@ -0,0 +1,5 @@ +--no-save +--private --protected +--name-tag env:"Environment Variables used" +--markup markdown +--output-dir yard-doc diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2b60e802c..5ad2bde76 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,7 +4,6 @@ First off, thank you for contributing! We're excited to collaborate with you! The following is a set of guidelines for the many ways you can join our collective effort. - ## Reporting Bugs, Asking Questions, and Suggesting Features Have a suggestion or feedback? Please go to [Issues](https://github.com/wordpress-mobile/release-toolkit/issues) and [open a new issue](https://github.com/wordpress-mobile/release-toolkit/issues/new). Prefix the title with a category like _"Bug:"_, _"Question:"_, or _"Feature Request:"_. Screenshots help us resolve issues and answer questions faster, so thanks for including some if you can. @@ -26,12 +25,24 @@ The core team monitors and reviews all pull requests. Depending on the changes, We do our best to respond quickly to all pull requests. If you don't get a response from us after a week, feel free to reach out to us via Slack. ## Code Style + While we don't have a full set of coding guidelines in place for this repository yet, here are a few guidelines that will make it more likely for your PR to be accepted: - New functionality should have appropriate test coverage. - Prefer expressing your intent using Ruby over calling out to `sh` to accomplish a task where possible – this makes it more likely that our code will work cross-platform, makes it possible to mock dependencies, and allows the project to explicitly define dependencies via the Gemfile (rather than implicitly via command-line calls to specific tools). - Bias towards producing verbose output – the tooling should give lots of information to the developer as it's accomplishing its task, and it should always be clear what step of the process is currently being executed. Most of the code will run on CI and build machines, so being able to go back and debug issues is top priority. +## Tips for working on the codebase + + - Don't forget to run `bundle install` + - If you're using VisualStudio Code, we recommend installing the [`rebornx.ruby` Ruby extension](https://marketplace.visualstudio.com/items?itemName=rebornix.Ruby). This allows syntax highlighting, shortcuts to add documentation comment blocks, quick Jump to Definition, and more. + - To run the unit tests, use `bundle exec rspec`. _Some default options are defined in the `.rspec` file for nice formatting of the report._ + - We use [YARD](https://yardoc.org/) to document ruby code. + - You can generate the documentation (and see potential warnings about undocumented methods or invalid doc) using `bundle exec yard doc`. + - The documentation is generated locally in the `yard-doc/` folder (which is `.gitignore`'d). + - You can see it in your Web Browser by using `open yard-doc/index.html`. + - To see a list of methods that are missing documentation and require you to add some, you can use `bundle exec yard stats --list-undoc`. + ## Getting in Touch If you have questions or just want to say hi, join the [WordPress Slack](https://make.wordpress.org/chat/) and drop a message on the `#mobile` channel. \ No newline at end of file diff --git a/Dangerfile b/Dangerfile index a8969cefa..98427dff6 100644 --- a/Dangerfile +++ b/Dangerfile @@ -1,5 +1,5 @@ def version - lib = File.expand_path("../lib", __FILE__) + lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'fastlane/plugin/wpmreleasetoolkit/version' Fastlane::Wpmreleasetoolkit::VERSION @@ -15,7 +15,7 @@ end `git checkout Gemfile.lock &> /dev/null` if version.to_s != gemfile_lock_version.to_s - message = %Q{ + message = %{ The version in the `Gemfile.lock` (`#{gemfile_lock_version}`) doesn't match the one in `version.rb` (`#{version}`). Please run `bundle install` to make sure they match. diff --git a/Gemfile b/Gemfile index 0fb84ff10..7455d6ec7 100644 --- a/Gemfile +++ b/Gemfile @@ -1,9 +1,15 @@ source('https://rubygems.org') gemspec -gem 'codecov', :require => false, :group => :test -gem "danger", "~> 8.0" -gem "webmock", :require => false, :group => :test + +gem 'danger', '~> 8.0' + +group :test do + gem 'codecov', require: false + gem 'rspec' + gem 'webmock', require: false, group: :test + gem 'yard' +end plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') eval_gemfile(plugins_path) if File.exist?(plugins_path) diff --git a/Gemfile.lock b/Gemfile.lock index 3df90f084..54a3fb472 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -311,6 +311,7 @@ GEM rouge (~> 2.0.7) xcpretty-travis-formatter (1.0.0) xcpretty (~> 0.2, >= 0.0.7) + yard (0.9.26) PLATFORMS ruby @@ -323,13 +324,14 @@ DEPENDENCIES fastlane-plugin-wpmreleasetoolkit! pry (~> 0.12.2) rmagick (~> 4.1) - rspec (~> 3.8) + rspec rspec_junit_formatter (~> 0.4.1) rubocop (= 0.75) rubocop-require_tools (~> 0.1.2) rubocop-rspec simplecov (~> 0.16.1) webmock + yard BUNDLED WITH 2.1.4 diff --git a/README.md b/README.md index 652171132..24553041e 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,8 @@ More details about the actions can be found [here](lib/fastlane/plugin/wpmreleas Read our [Contributing Guide](CONTRIBUTING.md) to learn about reporting issues, contributing code, and more ways to contribute. +This guide also includes some tips about configuring your environment and IDE (e.g. VSCode) and how to run tests and documentation. + ## Security If you happen to find a security vulnerability, we would appreciate you letting us know at https://hackerone.com/automattic and allowing us to respond before disclosing the issue publicly. diff --git a/Rakefile b/Rakefile index a4291d5aa..8493da563 100644 --- a/Rakefile +++ b/Rakefile @@ -3,7 +3,6 @@ require 'rake' begin require 'rubocop/rake_task' require 'rake/extensiontask' - rescue LoadError abort 'Please run this task using `bundle exec rake`' end @@ -12,5 +11,3 @@ RuboCop::RakeTask.new task default: %i[spec rubocop] Rake::ExtensionTask.new('drawText') - - diff --git a/bin/drawText b/bin/drawText index aca4881fb..483f0bbf7 100755 --- a/bin/drawText +++ b/bin/drawText @@ -1,24 +1,19 @@ #!/usr/bin/env ruby -require "rake" +require 'rake' require 'os' -unless OS.mac? then - abort 'Fatal Error: `drawText` can only be run on macOS.' -end - +abort 'Fatal Error: `drawText` can only be run on macOS.' unless OS.mac? plugin_path = Pathname(__FILE__).dirname.parent -executable_path = plugin_path + "lib/drawText" +executable_path = plugin_path + 'lib/drawText' # Run the script -allArgs = ARGV.map { |arg| - - argParts = arg.split("=") - argParts[1] = '"' + argParts[1] + '"' - - argParts.join("=") +allArgs = ARGV.map do |arg| + argParts = arg.split('=') + argParts[1] = '"' + argParts[1] + '"' -}.join(" ") + argParts.join('=') +end.join(' ') exec("#{executable_path} #{allArgs}") diff --git a/ext/drawText/extconf.rb b/ext/drawText/extconf.rb index aee7627db..0f7d1d8c3 100644 --- a/ext/drawText/extconf.rb +++ b/ext/drawText/extconf.rb @@ -4,30 +4,33 @@ drawTextDirectory = File.dirname(File.absolute_path(__FILE__)) compilationDirectory = Dir.pwd -libDirectory = File.dirname(File.dirname(drawTextDirectory)) + "/lib" +libDirectory = File.join(File.dirname(File.dirname(drawTextDirectory)), '/lib') # Copy the makefile required for compilation -FileUtils.cp(drawTextDirectory + "/makefile.example", compilationDirectory + "/Makefile") +FileUtils.cp(File.join(drawTextDirectory, 'makefile.example'), File.join(compilationDirectory, 'Makefile')) # Only compile drawText on macOS -unless OS.mac? then - exit 0 -end +exit 0 unless OS.mac? # Swift is needed to compile the extension find_executable('swift') find_executable('xcodebuild') +system( + 'xcodebuild', + '-project', File.join(drawTextDirectory, 'drawText.xcodeproj'), + '-scheme', 'drawText', + '-derivedDataPath', compilationDirectory, + '-configuration', 'RELEASE' +) -system("xcodebuild -project #{drawTextDirectory}/drawText.xcodeproj/ -scheme drawText -derivedDataPath #{compilationDirectory} -configuration RELEASE") - -compiledPath = compilationDirectory + "/Build/Products/Release/drawText" -destinationPath = libDirectory + "/drawText" +compiledPath = File.join(compilationDirectory, 'Build', 'Products', 'Release', 'drawText') +destinationPath = File.join(libDirectory, 'drawText') # Delete and overwrite the binary FileUtils.rm_rf(destinationPath) FileUtils.cp(compiledPath, destinationPath) # Delete and overwrite the bundle file -FileUtils.rm_rf(libDirectory + "/drawText.bundle") +FileUtils.rm_rf(File.join(libDirectory, 'drawText.bundle')) FileUtils.touch(File.join(compilationDirectory, 'drawText.' + RbConfig::CONFIG['DLEXT'])) diff --git a/fastlane-plugin-wpmreleasetoolkit.gemspec b/fastlane-plugin-wpmreleasetoolkit.gemspec index 8f77e5808..8222e97e4 100644 --- a/fastlane-plugin-wpmreleasetoolkit.gemspec +++ b/fastlane-plugin-wpmreleasetoolkit.gemspec @@ -1,6 +1,4 @@ -# coding: utf-8 - -lib = File.expand_path("../lib", __FILE__) +lib = File.expand_path('lib', __dir__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'fastlane/plugin/wpmreleasetoolkit/version' @@ -11,18 +9,18 @@ Gem::Specification.new do |spec| spec.email = 'lore.mattei@gmail.com' spec.summary = 'GitHub helper functions' - spec.homepage = "https://github.com/wordpress-mobile/release-toolkit" - spec.license = "MIT" + spec.homepage = 'https://github.com/wordpress-mobile/release-toolkit' + spec.license = 'MIT' - spec.files = Dir["lib/**/*"] + %w(README.md LICENSE) + spec.files = Dir['lib/**/*'] + %w[README.md LICENSE] spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.files << 'ext/drawText/extconf.rb' - spec.files << Dir["bin/*"] - spec.files << Dir["ext/*"] + spec.files << Dir['bin/*'] + spec.files << Dir['ext/*'] # Bring in any generated executables - spec.bindir = "bin" + spec.bindir = 'bin' spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } # These files are used to generate Makefile files which in turn are used diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb index cee637226..87a6da924 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_localize_libs_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/android_localize_helper' +require_relative '../../helper/android/android_localize_helper' module Fastlane module Actions @@ -9,42 +9,39 @@ def self.run(params) libraries_strings_path = params[:libs_strings_path] any_changes = false - libraries_strings_path.each do | lib | - any_changes = Fastlane::Helper::AndroidLocalizeHelper.merge_lib(main_strings_path, lib) or any_changes + libraries_strings_path.each do |lib| + (any_changes = Fastlane::Helper::AndroidLocalizeHelper.merge_lib(main_strings_path, lib)) || any_changes end - if (any_changes) - UI.message("Changes have been applied to #{main_strings_path}. Please, verify it!") - end + UI.message("Changes have been applied to #{main_strings_path}. Please, verify it!") if any_changes end def self.description - "Merges the strings to be localised from the libs into the main application file" + 'Merges the strings to be localised from the libs into the main application file' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value - end def self.details - "Merges the strings to be localised from the libs into the main application file" + 'Merges the strings to be localised from the libs into the main application file' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :app_strings_path, - description: "The path of the main strings file", - optional: false, - is_string: true), + description: 'The path of the main strings file', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :libs_strings_path, - env_name: "LOCALIZE_LIBS_STRINGS_PATH", - description: "The list of libs to merge", - optional: false, - is_string: false) + env_name: 'LOCALIZE_LIBS_STRINGS_PATH', + description: 'The list of libs to merge', + optional: false, + is_string: false), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb index 1fa443287..bd622ae6b 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_update_metadata_source_action.rb @@ -20,10 +20,10 @@ def self.run(params) UI.message "File #{params[:po_file_path]} updated!" end - # Verifies that all the source files are available + # Verifies that all the source files are available # to this action def self.check_source_files(source_files) - source_files.values.each do | file_path | + source_files.values.each do |file_path| UI.user_error!("Couldn't find file at path '#{file_path}'") unless File.exist?(file_path) end end @@ -37,70 +37,68 @@ def self.create_temp_po(params) target = self.create_target_file_path(orig) # Clear if older exists - File.delete(target) if File.exists? target + File.delete(target) if File.exist? target # Create the new one begin - File.open(target, "a") do |fw| - File.open(orig, "r").each do |fr| + File.open(target, 'a') do |fw| + File.open(orig, 'r').each do |fr| write_target_block(fw, fr) - end + end end - rescue - File.delete(target) if File.exists? target - raise - end + rescue + File.delete(target) if File.exist? target + raise + end - target + target end # Deletes the old po and moves the temp one # to the final location def self.swap_po(orig_file_path, temp_file_path) - File.delete(orig_file_path) if File.exists? orig_file_path + File.delete(orig_file_path) if File.exist? orig_file_path File.rename(temp_file_path, orig_file_path) end - # Generates the temp file path + # Generates the temp file path def self.create_target_file_path(orig_file_path) - "#{File.dirname(orig_file_path)}/#{File.basename(orig_file_path, ".*")}.tmp" + "#{File.dirname(orig_file_path)}/#{File.basename(orig_file_path, '.*')}.tmp" end # Creates the block instances def self.create_block_parsers(release_version, block_files) - @blocks = Array.new + @blocks = [] # Inits default handler - @blocks.push (Fastlane::Helper::UnknownMetadataBlock.new) + @blocks.push Fastlane::Helper::UnknownMetadataBlock.new # Init special handlers - block_files.each do | key, file_path | + block_files.each do |key, file_path| case key when :release_note - @blocks.push (Fastlane::Helper::ReleaseNoteMetadataBlock.new(key, file_path, release_version)) + @blocks.push Fastlane::Helper::ReleaseNoteMetadataBlock.new(key, file_path, release_version) when :release_note_short - @blocks.push (Fastlane::Helper::ReleaseNoteShortMetadataBlock.new(key, file_path, release_version)) + @blocks.push Fastlane::Helper::ReleaseNoteShortMetadataBlock.new(key, file_path, release_version) else - @blocks.push (Fastlane::Helper::StandardMetadataBlock.new(key, file_path)) + @blocks.push Fastlane::Helper::StandardMetadataBlock.new(key, file_path) end end - # Sets the default + # Sets the default @current_block = @blocks[0] end # Manages tags depending on the type def self.write_target_block(fw, line) - if (is_block_id(line)) + if is_block_id(line) key = line.split(' ')[1].tr('\"', '') - @blocks.each do | block | + @blocks.each do |block| @current_block = block if block.is_handler_for(key) end end - if (is_comment(line)) - @current_block = @blocks.first - end + @current_block = @blocks.first if is_comment(line) @current_block.handle_line(fw, line) end @@ -113,51 +111,48 @@ def self.is_comment(line) line.start_with?('#') end - - ##################################################### # @!group Documentation ##################################################### def self.description - "Updates a .po file with new data from .txt files" + 'Updates a .po file with new data from .txt files' end def self.details - "You can use this action to update the .po file that contains the string to load to GlotPress for localization." + 'You can use this action to update the .po file that contains the string to load to GlotPress for localization.' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :po_file_path, - env_name: "FL_UPDATE_METADATA_SOURCE_PO_FILE_PATH", - description: "The path of the .po file to update", + env_name: 'FL_UPDATE_METADATA_SOURCE_PO_FILE_PATH', + description: 'The path of the .po file to update', is_string: true, verify_block: proc do |value| - UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless (value and not value.empty?) - UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) + UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless value && (!value.empty?) + UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) end), FastlaneCore::ConfigItem.new(key: :release_version, - env_name: "FL_UPDATE_METADATA_SOURCE_RELEASE_VERSION", - description: "The release version of the app (to use to mark the release notes)", + env_name: 'FL_UPDATE_METADATA_SOURCE_RELEASE_VERSION', + description: 'The release version of the app (to use to mark the release notes)', verify_block: proc do |value| - UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless (value and not value.empty?) - end), + UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless value && (!value.empty?) + end), FastlaneCore::ConfigItem.new(key: :source_files, - env_name: "FL_UPDATE_METADATA_SOURCE_SOURCE_FILES", - description: "The hash with the path to the source files and the key to use to include their content", - is_string: false, - verify_block: proc do |value| - UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless (value and not value.empty?) - end) + env_name: 'FL_UPDATE_METADATA_SOURCE_SOURCE_FILES', + description: 'The hash with the path to the source files and the key to use to include their content', + is_string: false, + verify_block: proc do |value| + UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless value && (!value.empty?) + end), ] end def self.output - end def self.return_value @@ -165,7 +160,7 @@ def self.return_value end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb index fa4def673..6ce89ca78 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/an_validate_lib_strings_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/android_localize_helper' +require_relative '../../helper/android/android_localize_helper' module Fastlane module Actions @@ -10,49 +10,48 @@ def self.run(params) diff_url = params[:diff_url] source_diff = nil - if (diff_url.nil? == false) then + if diff_url.nil? == false data = open(params[:diff_url]) source_diff = data.read() end any_error = false - libraries_strings_path.each do | lib | - Fastlane::Helper::AndroidLocalizeHelper.verify_lib(main_strings_path, lib, source_diff) + libraries_strings_path.each do |lib| + Fastlane::Helper::AndroidLocalizeHelper.verify_lib(main_strings_path, lib, source_diff) end end def self.description - "Checks that the strings to be localised are updated from the libs into the main application file" + 'Checks that the strings to be localised are updated from the libs into the main application file' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value - end def self.details - "Checks that the strings to be localised are updated from the libs into the main application file" + 'Checks that the strings to be localised are updated from the libs into the main application file' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :app_strings_path, - description: "The path of the main strings file", - optional: false, - is_string: true), + description: 'The path of the main strings file', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :libs_strings_path, - env_name: "CHECK_LIBS_STRINGS_PATH", - description: "The list of libs to merge", - optional: false, - is_string: false), + env_name: 'CHECK_LIBS_STRINGS_PATH', + description: 'The list of libs to merge', + optional: false, + is_string: false), FastlaneCore::ConfigItem.new(key: :diff_url, - env_name: "CHECK_LIBS_DIFF_URL", - description: "The url of the diff to check", - optional: true, - is_string: true), + env_name: 'CHECK_LIBS_DIFF_URL', + description: 'The url of the diff to check', + optional: true, + is_string: true), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb index d7f881eb2..5a8da3982 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_betabuild_prechecks.rb @@ -4,41 +4,39 @@ class AndroidBetabuildPrechecksAction < Action def self.run(params) UI.message "Skip confirm: #{params[:skip_confirm]}" UI.message "Work on version: #{params[:base_version]}" unless params[:base_version].nil? - + require_relative '../../helper/android/android_version_helper.rb' require_relative '../../helper/android/android_git_helper.rb' # Checkout develop and update - Fastlane::Helpers::AndroidGitHelper::git_checkout_and_pull("develop") + Fastlane::Helper::GitHelper.checkout_and_pull('develop') # Check versions - release_version = Fastlane::Helpers::AndroidVersionHelper::get_release_version - message = "The following current version has been detected: #{release_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}\n" - alpha_release_version = Fastlane::Helpers::AndroidVersionHelper::get_alpha_version - message << "The following Alpha version has been detected: #{alpha_release_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}\n" unless alpha_release_version.nil? - + release_version = Fastlane::Helper::Android::VersionHelper.get_release_version + message = "The following current version has been detected: #{release_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}\n" + alpha_release_version = Fastlane::Helper::Android::VersionHelper.get_alpha_version + message << "The following Alpha version has been detected: #{alpha_release_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}\n" unless alpha_release_version.nil? + # Check branch - app_version = Fastlane::Helpers::AndroidVersionHelper::get_public_version - UI.user_error!("#{message}Release branch for version #{app_version} doesn't exist. Abort.") unless (!params[:base_version].nil? || Fastlane::Helpers::AndroidGitHelper::git_checkout_and_pull_release_branch_for(app_version)) - + app_version = Fastlane::Helper::Android::VersionHelper.get_public_version + UI.user_error!("#{message}Release branch for version #{app_version} doesn't exist. Abort.") unless !params[:base_version].nil? || Fastlane::Helper::GitHelper.checkout_and_pull(release: app_version) + # Check user overwrite - if (!params[:base_version].nil?) + unless params[:base_version].nil? overwrite_version = get_user_build_version(params[:base_version], message) release_version = overwrite_version[0] alpha_release_version = overwrite_version[1] end - next_beta_version = Fastlane::Helpers::AndroidVersionHelper::calc_next_beta_version(release_version, alpha_release_version) - next_alpha_version = Fastlane::Helpers::AndroidVersionHelper::calc_next_alpha_version(next_beta_version, alpha_release_version) unless alpha_release_version.nil? + next_beta_version = Fastlane::Helper::Android::VersionHelper.calc_next_beta_version(release_version, alpha_release_version) + next_alpha_version = Fastlane::Helper::Android::VersionHelper.calc_next_alpha_version(next_beta_version, alpha_release_version) unless alpha_release_version.nil? # Verify - message << "Updating branch to version: #{next_beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{next_beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}) " - message << "and #{next_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{next_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}).\n" unless alpha_release_version.nil? - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + message << "Updating branch to version: #{next_beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{next_beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}) " + message << "and #{next_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{next_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}).\n" unless alpha_release_version.nil? + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end @@ -50,11 +48,11 @@ def self.run(params) end def self.get_user_build_version(version, message) - UI.user_error!("Release branch for version #{version} doesn't exist. Abort.") unless Fastlane::Helpers::AndroidGitHelper::git_checkout_and_pull_release_branch_for(version) - release_version = Fastlane::Helpers::AndroidVersionHelper::get_release_version - message << "Looking at branch release/#{version} as requested by user. Detected version: #{release_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}.\n" - alpha_release_version = Fastlane::Helpers::AndroidVersionHelper::get_alpha_version - message << "and Alpha Version: #{alpha_release_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}\n" unless alpha_release_version.nil? + UI.user_error!("Release branch for version #{version} doesn't exist. Abort.") unless Fastlane::Helper::GitHelper.checkout_and_pull(release: version) + release_version = Fastlane::Helper::Android::VersionHelper.get_release_version + message << "Looking at branch release/#{version} as requested by user. Detected version: #{release_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}.\n" + alpha_release_version = Fastlane::Helper::Android::VersionHelper.get_alpha_version + message << "and Alpha Version: #{alpha_release_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}\n" unless alpha_release_version.nil? [release_version, alpha_release_version] end @@ -63,30 +61,29 @@ def self.get_user_build_version(version, message) ##################################################### def self.description - "Runs some prechecks before preparing for a new test build" + 'Runs some prechecks before preparing for a new test build' end def self.details - "Updates the relevant release branch, checks the app version and ensure the branch is clean" + 'Updates the relevant release branch, checks the app version and ensure the branch is clean' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :base_version, - env_name: "FL_ANDROID_BETABUILD_PRECHECKS_BASE_VERSION", - description: "The version to work on", # a short description of this parameter + env_name: 'FL_ANDROID_BETABUILD_PRECHECKS_BASE_VERSION', + description: 'The version to work on', # a short description of this parameter is_string: true, optional: true), # true: verifies the input is a string, false: every kind of value), FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_BETABUILD_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one + env_name: 'FL_ANDROID_BETABUILD_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one ] end def self.output - end def self.return_value @@ -95,7 +92,7 @@ def self.return_value def self.authors # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -103,4 +100,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb index c5af26f55..8cb12e567 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_prechecks.rb @@ -4,29 +4,23 @@ class AndroidBuildPrechecksAction < Action def self.run(params) require_relative '../../helper/android/android_version_helper.rb' - if (params[:final] and params[:beta]) - UI.user_error!("Can't build beta and final at the same time!") - end + UI.user_error!("Can't build beta and final at the same time!") if params[:final] && params[:beta] - Fastlane::Helpers::AndroidGitHelper.check_on_branch("release") unless other_action.is_ci() - - message = "" - beta_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version() unless !params[:beta] and !params[:final] - alpha_version = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() unless !params[:alpha] - - if (params[:final] and Fastlane::Helpers::AndroidVersionHelper.is_beta_version(beta_version)) - UI.user_error!("Can't build a final release out of this branch because it's configured as a beta release!") - end + Fastlane::Helper::GitHelper.ensure_on_branch!('release') unless other_action.is_ci() + + message = '' + beta_version = Fastlane::Helper::Android::VersionHelper.get_release_version() unless !params[:beta] && !params[:final] + alpha_version = Fastlane::Helper::Android::VersionHelper.get_alpha_version() if params[:alpha] - message << "Building version #{beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}) (for upload to Release Channel)\n" unless !params[:final] - message << "Building version #{beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{beta_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}) (for upload to Beta Channel)\n" unless !params[:beta] - message << "Building version #{alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}) (for upload to Alpha Channel)\n" unless !params[:alpha] + UI.user_error!("Can't build a final release out of this branch because it's configured as a beta release!") if params[:final] && Fastlane::Helper::Android::VersionHelper.is_beta_version?(beta_version) - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + message << "Building version #{beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}) (for upload to Release Channel)\n" if params[:final] + message << "Building version #{beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{beta_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}) (for upload to Beta Channel)\n" if params[:beta] + message << "Building version #{alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}) (for upload to Alpha Channel)\n" if params[:alpha] + + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end @@ -39,48 +33,46 @@ def self.run(params) ##################################################### def self.description - "Runs some prechecks before the build" + 'Runs some prechecks before the build' end def self.details - "Runs some prechecks before the build" + 'Runs some prechecks before the build' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_BUILD_PRECHECKS_SKIP_CONFIRM", - description: "True to avoid the system ask for confirmation", + env_name: 'FL_ANDROID_BUILD_PRECHECKS_SKIP_CONFIRM', + description: 'True to avoid the system ask for confirmation', is_string: false, default_value: false), FastlaneCore::ConfigItem.new(key: :alpha, - env_name: "FL_ANDROID_BUILD_PRECHECKS_ALPHA_BUILD", - description: "True if this is for an alpha build", - is_string: false, - default_value: false), + env_name: 'FL_ANDROID_BUILD_PRECHECKS_ALPHA_BUILD', + description: 'True if this is for an alpha build', + is_string: false, + default_value: false), FastlaneCore::ConfigItem.new(key: :beta, - env_name: "FL_ANDROID_BUILD_PRECHECKS_BETA_BUILD", - description: "True if this is for a beta build", - is_string: false, - default_value: false), + env_name: 'FL_ANDROID_BUILD_PRECHECKS_BETA_BUILD', + description: 'True if this is for a beta build', + is_string: false, + default_value: false), FastlaneCore::ConfigItem.new(key: :final, - env_name: "FL_ANDROID_BUILD_PRECHECKS_FINAL_BUILD", - description: "True if this is for a final build", - is_string: false, - default_value: false), + env_name: 'FL_ANDROID_BUILD_PRECHECKS_FINAL_BUILD', + description: 'True if this is for a final build', + is_string: false, + default_value: false), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -88,4 +80,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb index 43e0ea9b4..90e9ede6c 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_build_preflight.rb @@ -2,20 +2,19 @@ module Fastlane module Actions class AndroidBuildPreflightAction < Action def self.run(params) - # Validate mobile configuration secrets other_action.configure_apply # Check gems and pods are up to date. This will exit if it fails begin - Action.sh("bundle check") - rescue + Action.sh('bundle check') + rescue UI.user_error!("You should run 'bundle install' to make sure gems are up to date") raise end begin - Action.sh("command -v bundletool > /dev/null") + Action.sh('command -v bundletool > /dev/null') rescue UI.user_error!("bundletool is required to build the APKs. Install it with 'brew install bundletool'") raise @@ -27,27 +26,24 @@ def self.run(params) ##################################################### def self.description - "Clean the environment to ensure a safe build" + 'Clean the environment to ensure a safe build' end def self.details - "Clean the environment to ensure a safe build" + 'Clean the environment to ensure a safe build' end def self.available_options - end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -55,4 +51,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb index aa34efae4..cfc01cc5b 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_beta.rb @@ -2,20 +2,20 @@ module Fastlane module Actions class AndroidBumpVersionBetaAction < Action def self.run(params) - UI.message "Bumping app release version..." - + UI.message 'Bumping app release version...' + require_relative '../../helper/android/android_git_helper.rb' require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidGitHelper.check_on_branch("release") + Fastlane::Helper::GitHelper.ensure_on_branch!('release') create_config() show_config() - UI.message "Updating build.gradle..." - Fastlane::Helpers::AndroidVersionHelper.update_versions(@new_version_beta, @new_version_alpha) - UI.message "Done!" - - Fastlane::Helpers::AndroidGitHelper.bump_version_beta() + UI.message 'Updating build.gradle...' + Fastlane::Helper::Android::VersionHelper.update_versions(@new_version_beta, @new_version_alpha) + UI.message 'Done!' + + Fastlane::Helper::Android::GitHelper.commit_version_bump() end ##################################################### @@ -23,49 +23,47 @@ def self.run(params) ##################################################### def self.description - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.details - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.available_options - end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) platform == :android end - private - def self.create_config() - @current_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version() - @current_version_alpha = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() - @new_version_beta = Fastlane::Helpers::AndroidVersionHelper.calc_next_beta_version(@current_version, @current_version_alpha) - @new_version_alpha = ENV["HAS_ALPHA_VERSION"].nil? ? nil : Fastlane::Helpers::AndroidVersionHelper.calc_next_alpha_version(@new_version_beta, @current_version_alpha) + private + + def self.create_config + @current_version = Fastlane::Helper::Android::VersionHelper.get_release_version() + @current_version_alpha = Fastlane::Helper::Android::VersionHelper.get_alpha_version() + @new_version_beta = Fastlane::Helper::Android::VersionHelper.calc_next_beta_version(@current_version, @current_version_alpha) + @new_version_alpha = ENV['HAS_ALPHA_VERSION'].nil? ? nil : Fastlane::Helper::Android::VersionHelper.calc_next_alpha_version(@new_version_beta, @current_version_alpha) end - def self.show_config() - vname = Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME - vcode = Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE + def self.show_config + vname = Fastlane::Helper::Android::VersionHelper::VERSION_NAME + vcode = Fastlane::Helper::Android::VersionHelper::VERSION_CODE UI.message("Current version: #{@current_version[vname]}(#{@current_version[vcode]})") - UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV["HAS_ALPHA_VERSION"].nil? + UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV['HAS_ALPHA_VERSION'].nil? UI.message("New beta version: #{@new_version_beta[vname]}(#{@new_version_beta[vcode]})") - UI.message("New alpha version: #{@new_version_alpha[vname]}(#{@new_version_alpha[vcode]})") unless ENV["HAS_ALPHA_VERSION"].nil? + UI.message("New alpha version: #{@new_version_alpha[vname]}(#{@new_version_alpha[vcode]})") unless ENV['HAS_ALPHA_VERSION'].nil? end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb index ca8c955d0..bf40104b7 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_final_release.rb @@ -2,20 +2,20 @@ module Fastlane module Actions class AndroidBumpVersionFinalReleaseAction < Action def self.run(params) - UI.message "Bumping app release version..." - + UI.message 'Bumping app release version...' + require_relative '../../helper/android/android_git_helper.rb' require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidGitHelper.check_on_branch("release") + Fastlane::Helper::GitHelper.ensure_on_branch!('release') create_config() show_config() - UI.message "Updating gradle.properties..." - Fastlane::Helpers::AndroidVersionHelper.update_versions(@final_version, @current_version_alpha) - UI.message "Done!" - - Fastlane::Helpers::AndroidGitHelper.bump_version_final() + UI.message 'Updating gradle.properties...' + Fastlane::Helper::Android::VersionHelper.update_versions(@final_version, @current_version_alpha) + UI.message 'Done!' + + Fastlane::Helper::Android::GitHelper.commit_version_bump() end ##################################################### @@ -23,35 +23,36 @@ def self.run(params) ##################################################### def self.description - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.details - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) platform == :android end - private - def self.create_config() - @current_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version() - @current_version_alpha = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() - @final_version = Fastlane::Helpers::AndroidVersionHelper.calc_final_release_version(@current_version, @current_version_alpha) + private + + def self.create_config + @current_version = Fastlane::Helper::Android::VersionHelper.get_release_version() + @current_version_alpha = Fastlane::Helper::Android::VersionHelper.get_alpha_version() + @final_version = Fastlane::Helper::Android::VersionHelper.calc_final_release_version(@current_version, @current_version_alpha) end - def self.show_config() - vname = Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME - vcode = Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE + def self.show_config + vname = Fastlane::Helper::Android::VersionHelper::VERSION_NAME + vcode = Fastlane::Helper::Android::VersionHelper::VERSION_CODE UI.message("Current version: #{@current_version[vname]}(#{@current_version[vcode]})") - UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV["HAS_ALPHA_VERSION"].nil? + UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV['HAS_ALPHA_VERSION'].nil? UI.message("New release version: #{@final_version[vname]}(#{@final_version[vcode]})") end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb index c4a2fffdb..0557cb695 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_hotfix.rb @@ -2,20 +2,20 @@ module Fastlane module Actions class AndroidBumpVersionHotfixAction < Action def self.run(params) - UI.message "Bumping app release version for hotfix..." - + UI.message 'Bumping app release version for hotfix...' + require_relative '../../helper/android/android_git_helper.rb' - Fastlane::Helpers::AndroidGitHelper.branch_for_hotfix(params[:previous_version_name], params[:version_name]) + Fastlane::Helper::GitHelper.create_branch("release/#{params[:version_name]}", from: params[:previous_version_name]) create_config(params[:previous_version_name], params[:version_name], params[:version_code]) show_config() - - UI.message "Updating build.gradle..." - Fastlane::Helpers::AndroidVersionHelper.update_versions(@new_version, @current_version_alpha) - UI.message "Done!" - Fastlane::Helpers::AndroidGitHelper.bump_version_hotfix(params[:version_name]) - - UI.message "Done." + UI.message 'Updating build.gradle...' + Fastlane::Helper::Android::VersionHelper.update_versions(@new_version, @current_version_alpha) + UI.message 'Done!' + + Fastlane::Helper::Android::GitHelper.commit_version_bump() + + UI.message 'Done.' end ##################################################### @@ -23,52 +23,53 @@ def self.run(params) ##################################################### def self.description - "Bumps the version of the app and creates the new release branch" + 'Bumps the version of the app and creates the new release branch' end def self.details - "Bumps the version of the app and creates the new release branch" + 'Bumps the version of the app and creates the new release branch' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :version_name, - env_name: "FL_ANDROID_BUMP_VERSION_HOTFIX_VERSION", - description: "The version of the hotfix", + env_name: 'FL_ANDROID_BUMP_VERSION_HOTFIX_VERSION', + description: 'The version of the hotfix', is_string: true), FastlaneCore::ConfigItem.new(key: :version_code, - env_name: "FL_ANDROID_BUMP_VERSION_HOTFIX_CODE", - description: "The version of the hotfix"), + env_name: 'FL_ANDROID_BUMP_VERSION_HOTFIX_CODE', + description: 'The version of the hotfix'), FastlaneCore::ConfigItem.new(key: :previous_version_name, - env_name: "FL_ANDROID_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION", - description: "The version to branch from", - is_string: true) # the default value if the user didn't provide one + env_name: 'FL_ANDROID_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION', + description: 'The version to branch from', + is_string: true), # the default value if the user didn't provide one ] end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) platform == :android end - private + private + def self.create_config(previous_version, new_version_name, new_version_code) - @current_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version() - @current_version_alpha = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() - @new_version = Fastlane::Helpers::AndroidVersionHelper.calc_next_hotfix_version(new_version_name, new_version_code) + @current_version = Fastlane::Helper::Android::VersionHelper.get_release_version() + @current_version_alpha = Fastlane::Helper::Android::VersionHelper.get_alpha_version() + @new_version = Fastlane::Helper::Android::VersionHelper.calc_next_hotfix_version(new_version_name, new_version_code) @new_short_version = new_version_name @new_release_branch = "release/#{@new_short_version}" end - def self.show_config() - UI.message("Current version: #{@current_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{@current_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]})") - UI.message("New hotfix version: #{@new_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]}(#{@new_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]})") + def self.show_config + UI.message("Current version: #{@current_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{@current_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]})") + UI.message("New hotfix version: #{@new_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]}(#{@new_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]})") UI.message("Release branch: #{@new_release_branch}") end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb index 4c6f07863..0b6bc3781 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_bump_version_release.rb @@ -1,92 +1,89 @@ module Fastlane - module Actions - class AndroidBumpVersionReleaseAction < Action - def self.run(params) - # fastlane will take care of reading in the parameter and fetching the environment variable: - UI.message "Bumping app release version..." - - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/android/android_git_helper.rb' - - other_action.ensure_git_branch(branch: "develop") - - # Create new configuration - @new_short_version = Fastlane::Helpers::AndroidVersionHelper.bump_version_release() - create_config() - show_config() - - # Update local develop and branch - UI.message "Creating new branch..." - Fastlane::Helpers::AndroidGitHelper.do_release_branch(@new_release_branch) - UI.message "Done!" - - UI.message "Updating versions..." - Fastlane::Helpers::AndroidVersionHelper.update_versions(@new_version_beta, @new_version_alpha) - Fastlane::Helpers::AndroidGitHelper.bump_version_release() - UI.message "Done." - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Bumps the version of the app and creates the new release branch" - end - - def self.details - "Bumps the version of the app and creates the new release branch" - end - - def self.available_options - - end - - def self.output - - end - - def self.return_value - - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + module Actions + class AndroidBumpVersionReleaseAction < Action + def self.run(params) + # fastlane will take care of reading in the parameter and fetching the environment variable: + UI.message 'Bumping app release version...' + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/android/android_git_helper.rb' - private - def self.create_config() - @current_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version() - @current_version_alpha = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() - @new_version_beta = Fastlane::Helpers::AndroidVersionHelper.calc_next_release_version(@current_version, @current_version_alpha) - @new_version_alpha = ENV["HAS_ALPHA_VERSION"].nil? ? nil : Fastlane::Helpers::AndroidVersionHelper.calc_next_alpha_version(@new_version_beta, @current_version_alpha) - @new_release_branch = "release/#{@new_short_version}" - end + other_action.ensure_git_branch(branch: 'develop') - def self.show_config() - vname = Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME - vcode = Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE - UI.message("Current version: #{@current_version[vname]}(#{@current_version[vcode]})") - UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV["HAS_ALPHA_VERSION"].nil? - UI.message("New beta version: #{@new_version_beta[vname]}(#{@new_version_beta[vcode]})") - UI.message("New alpha version: #{@new_version_alpha[vname]}(#{@new_version_alpha[vcode]})") unless ENV["HAS_ALPHA_VERSION"].nil? - UI.message("New version: #{@new_short_version}") - UI.message("Release branch: #{@new_release_branch}") - end + # Create new configuration + @new_short_version = Fastlane::Helper::Android::VersionHelper.bump_version_release() + create_config() + show_config() + + # Update local develop and branch + UI.message 'Creating new branch...' + Fastlane::Helper::GitHelper.create_branch(@new_release_branch, from: 'develop') + UI.message 'Done!' + + UI.message 'Updating versions...' + Fastlane::Helper::Android::VersionHelper.update_versions(@new_version_beta, @new_version_alpha) + Fastlane::Helper::Android::GitHelper.commit_version_bump() + UI.message 'Done.' + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Bumps the version of the app and creates the new release branch' + end + + def self.details + 'Bumps the version of the app and creates the new release branch' + end + + def self.available_options + end + + def self.output + end + + def self.return_value + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android + end + + private + + def self.create_config + @current_version = Fastlane::Helper::Android::VersionHelper.get_release_version() + @current_version_alpha = Fastlane::Helper::Android::VersionHelper.get_alpha_version() + @new_version_beta = Fastlane::Helper::Android::VersionHelper.calc_next_release_version(@current_version, @current_version_alpha) + @new_version_alpha = ENV['HAS_ALPHA_VERSION'].nil? ? nil : Fastlane::Helper::Android::VersionHelper.calc_next_alpha_version(@new_version_beta, @current_version_alpha) + @new_release_branch = "release/#{@new_short_version}" + end + + def self.show_config + vname = Fastlane::Helper::Android::VersionHelper::VERSION_NAME + vcode = Fastlane::Helper::Android::VersionHelper::VERSION_CODE + UI.message("Current version: #{@current_version[vname]}(#{@current_version[vcode]})") + UI.message("Current alpha version: #{@current_version_alpha[vname]}(#{@current_version_alpha[vcode]})") unless ENV['HAS_ALPHA_VERSION'].nil? + UI.message("New beta version: #{@new_version_beta[vname]}(#{@new_version_beta[vcode]})") + UI.message("New alpha version: #{@new_version_alpha[vname]}(#{@new_version_alpha[vcode]})") unless ENV['HAS_ALPHA_VERSION'].nil? + UI.message("New version: #{@new_short_version}") + UI.message("Release branch: #{@new_release_branch}") + end - def self.update_glotpress_key() - dm_file = ENV["DOWNLOAD_METADATA"] - if (File.exist?(dm_file)) then - sh("sed -i '' \"s/let glotPressWhatsNewKey.*/let glotPressWhatsNewKey = \\\"v#{@new_short_version}-whats-new\\\"/\" #{dm_file}") - else - UI.user_error!("Can't find #{dm_file}.") - end + def self.update_glotpress_key + dm_file = ENV['DOWNLOAD_METADATA'] + if File.exist?(dm_file) + sh("sed -i '' \"s/let glotPressWhatsNewKey.*/let glotPressWhatsNewKey = \\\"v#{@new_short_version}-whats-new\\\"/\" #{dm_file}") + else + UI.user_error!("Can't find #{dm_file}.") end end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb index 1d0924eda..36e324dba 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_codefreeze_prechecks.rb @@ -1,82 +1,79 @@ module Fastlane - module Actions - class AndroidCodefreezePrechecksAction < Action - VERSION_RELEASE = "release" - VERSION_ALPHA = "alpha" + module Actions + class AndroidCodefreezePrechecksAction < Action + VERSION_RELEASE = 'release' + VERSION_ALPHA = 'alpha' - def self.run(params) - # fastlane will take care of reading in the parameter and fetching the environment variable: - UI.message "Skip confirm on code freeze: #{params[:skip_confirm]}" - - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/android/android_git_helper.rb' - - # Checkout develop and update - Fastlane::Helpers::AndroidGitHelper.git_checkout_and_pull("develop") + def self.run(params) + # fastlane will take care of reading in the parameter and fetching the environment variable: + UI.message "Skip confirm on code freeze: #{params[:skip_confirm]}" - # Create versions - current_version = Fastlane::Helpers::AndroidVersionHelper.get_release_version - current_alpha_version = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version - next_version = Fastlane::Helpers::AndroidVersionHelper.calc_next_release_version(current_version, current_alpha_version) - next_alpha_version = ENV["HAS_ALPHA_VERSION"].nil? ? nil : Fastlane::Helpers::AndroidVersionHelper.calc_next_alpha_version(next_version, current_alpha_version) + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/android/android_git_helper.rb' - # Ask user confirmation - if (!params[:skip_confirm]) - confirm_message = "Building a new release branch starting from develop.\nCurrent version is #{current_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]} (#{current_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}).\n" - confirm_message += ENV["HAS_ALPHA_VERSION"].nil? ? "No alpha version configured.\n" : "Current Alpha version is #{current_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]} (#{current_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}).\n" - confirm_message += "After codefreeze the new version will be: #{next_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]} (#{next_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}).\n" - confirm_message += ENV["HAS_ALPHA_VERSION"].nil? ? "" : "After codefreeze the new Alpha will be: #{next_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]} (#{next_alpha_version[Fastlane::Helpers::AndroidVersionHelper::VERSION_CODE]}).\n" - confirm_message += "Do you want to continue?" - if (!UI.confirm(confirm_message)) - UI.user_error!("Aborted by user request") - end - end - - # Check local repo status - other_action.ensure_git_status_clean() - - # Return the current version - Fastlane::Helpers::AndroidVersionHelper.get_public_version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before code freeze" - end - - def self.details - "Updates the develop branch, checks the app version and ensure the branch is clean" - end - - def self.available_options - # Define all options your action supports. - [ - FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_CODEFREEZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation before codefreeze", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one - ] - end - - def self.output - - end - - def self.return_value - "Version of the app before code freeze" - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android + # Checkout develop and update + Fastlane::Helper::GitHelper.checkout_and_pull('develop') + + # Create versions + current_version = Fastlane::Helper::Android::VersionHelper.get_release_version + current_alpha_version = Fastlane::Helper::Android::VersionHelper.get_alpha_version + next_version = Fastlane::Helper::Android::VersionHelper.calc_next_release_version(current_version, current_alpha_version) + next_alpha_version = ENV['HAS_ALPHA_VERSION'].nil? ? nil : Fastlane::Helper::Android::VersionHelper.calc_next_alpha_version(next_version, current_alpha_version) + + # Ask user confirmation + unless params[:skip_confirm] + confirm_message = "Building a new release branch starting from develop.\nCurrent version is #{current_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]} (#{current_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}).\n" + confirm_message += ENV['HAS_ALPHA_VERSION'].nil? ? "No alpha version configured.\n" : "Current Alpha version is #{current_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]} (#{current_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}).\n" + confirm_message += "After codefreeze the new version will be: #{next_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]} (#{next_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}).\n" + confirm_message += ENV['HAS_ALPHA_VERSION'].nil? ? '' : "After codefreeze the new Alpha will be: #{next_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]} (#{next_alpha_version[Fastlane::Helper::Android::VersionHelper::VERSION_CODE]}).\n" + confirm_message += 'Do you want to continue?' + UI.user_error!('Aborted by user request') unless UI.confirm(confirm_message) end + + # Check local repo status + other_action.ensure_git_status_clean() + + # Return the current version + Fastlane::Helper::Android::VersionHelper.get_public_version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before code freeze' + end + + def self.details + 'Updates the develop branch, checks the app version and ensure the branch is clean' + end + + def self.available_options + # Define all options your action supports. + [ + FastlaneCore::ConfigItem.new(key: :skip_confirm, + env_name: 'FL_ANDROID_CODEFREEZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation before codefreeze', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + ] + end + + def self.output + end + + def self.return_value + 'Version of the app before code freeze' + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb index edb1296c4..2b54f09ea 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_completecodefreeze_prechecks.rb @@ -1,71 +1,68 @@ module Fastlane - module Actions - class AndroidCompletecodefreezePrechecksAction < Action - def self.run(params) - UI.message "Skip confirm: #{params[:skip_confirm]}" - - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/android/android_git_helper.rb' - - UI.user_error!("This is not a release branch. Abort.") unless other_action.git_branch.start_with?("release/") - - version = Fastlane::Helpers::AndroidVersionHelper::get_public_version - message = "Completing code freeze for: #{version}\n" - unless params[:skip_confirm] - unless UI.confirm("#{message}Do you want to continue?") - UI.user_error!("Aborted by user request") - end - else - UI.message(message) - end - - # Check local repo status - other_action.ensure_git_status_clean() - - version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before finalizing a code freeze" - end - - def self.details - "Runs some prechecks before finalizing a code freeze" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_COMPLETECODEFREEZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one - ] - end - - def self.output - - end - - def self.return_type - :string - end - - def self.return_value - "The version number that has been prechecked." - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android + module Actions + class AndroidCompletecodefreezePrechecksAction < Action + def self.run(params) + UI.message "Skip confirm: #{params[:skip_confirm]}" + + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/android/android_git_helper.rb' + + UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/') + + version = Fastlane::Helper::Android::VersionHelper.get_public_version + message = "Completing code freeze for: #{version}\n" + unless params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else + UI.message(message) end + + # Check local repo status + other_action.ensure_git_status_clean() + + version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before finalizing a code freeze' + end + + def self.details + 'Runs some prechecks before finalizing a code freeze' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :skip_confirm, + env_name: 'FL_ANDROID_COMPLETECODEFREEZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + ] + end + + def self.output + end + + def self.return_type + :string + end + + def self.return_value + 'The version number that has been prechecked.' + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb index 4c62917a0..5a54275e5 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_create_xml_release_notes.rb @@ -4,12 +4,12 @@ class AndroidCreateXmlReleaseNotesAction < Action def self.run(params) require_relative '../../helper/android/android_git_helper.rb' - release_notes_path = params[:download_path] + "/release_notes.xml" - open(release_notes_path, 'w') { |f| - params[:locales].each do | loc | + release_notes_path = params[:download_path] + '/release_notes.xml' + open(release_notes_path, 'w') do |f| + params[:locales].each do |loc| puts "Looking for language: #{loc[1]}" complete_path = "#{params[:download_path]}/#{loc[1]}/changelogs/#{params[:build_number]}.txt" - if (File.exist?(complete_path)) + if File.exist?(complete_path) f.puts("<#{loc[1]}>") f.puts(File.open(complete_path).read) f.puts("\n") @@ -17,7 +17,7 @@ def self.run(params) UI.message("File #{complete_path} not found. Skipping language #{loc[1]}") end end - } + end end ##################################################### @@ -25,34 +25,34 @@ def self.run(params) ##################################################### def self.description - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.details - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :download_path, - env_name: "ANDROID_XML_NOTES_DOWNLOAD_PATH", - description: "The path to the folder with the release notes", - optional: false, + env_name: 'ANDROID_XML_NOTES_DOWNLOAD_PATH', + description: 'The path to the folder with the release notes', + optional: false, is_string: true), FastlaneCore::ConfigItem.new(key: :build_number, - env_name: "ANDROID_XML_NOTES_BUILD_NUMBER", - description: "The build number of the release notes", - optional: false, + env_name: 'ANDROID_XML_NOTES_BUILD_NUMBER', + description: 'The build number of the release notes', + optional: false, is_string: true), FastlaneCore::ConfigItem.new(key: :locales, - env_name: "FL_DOWNLOAD_METADATA_LOCALES", - description: "The hash with the GLotPress locale and the project locale association", - is_string: false), + env_name: 'FL_DOWNLOAD_METADATA_LOCALES', + description: 'The hash with the GLotPress locale and the project locale association', + is_string: false), ] end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -60,4 +60,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb index 825534aa4..8c1142e1d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_current_branch_is_hotfix.rb @@ -7,7 +7,7 @@ module SharedValues class AndroidCurrentBranchIsHotfixAction < Action def self.run(params) require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidVersionHelper::is_hotfix(Fastlane::Helpers::AndroidVersionHelper::get_release_version) + Fastlane::Helper::Android::VersionHelper.is_hotfix?(Fastlane::Helper::Android::VersionHelper.get_release_version) end ##################################################### @@ -15,27 +15,25 @@ def self.run(params) ##################################################### def self.description - "Checks if the current branch is for a hotfix" + 'Checks if the current branch is for a hotfix' end def self.details - "Checks if the current branch is for a hotfix" + 'Checks if the current branch is for a hotfix' end def self.available_options - end def self.output - end def self.return_value - "True if the branch is for a hotfix, false otherwise" + 'True if the branch is for a hotfix, false otherwise' end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -43,4 +41,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb index 6e8e692dc..ea3eb90a6 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_finalize_prechecks.rb @@ -1,74 +1,71 @@ module Fastlane - module Actions - module SharedValues - ANDROID_FINALIZE_PRECHECKS_CUSTOM_VALUE = :ANDROID_FINALIZE_PRECHECKS_CUSTOM_VALUE - end - - class AndroidFinalizePrechecksAction < Action - def self.run(params) - UI.message "Skip confirm: #{params[:skip_confirm]}" - - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/android/android_git_helper.rb' - - UI.user_error!("This is not a release branch. Abort.") unless other_action.git_branch.start_with?("release/") - - version = Fastlane::Helpers::AndroidVersionHelper::get_public_version - message = "Finalizing release: #{version}\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else - UI.message(message) - end - - # Check local repo status - other_action.ensure_git_status_clean() - - version[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME] - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before finalizing a release" - end - - def self.details - "Runs some prechecks before finalizing a release" - end - - def self.available_options - # Define all options your action supports. - - # Below a few examples - [ - FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_FINALIZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one - ] - end - - def self.output - - end - - def self.return_value - "The current app version" - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android + module Actions + module SharedValues + ANDROID_FINALIZE_PRECHECKS_CUSTOM_VALUE = :ANDROID_FINALIZE_PRECHECKS_CUSTOM_VALUE + end + + class AndroidFinalizePrechecksAction < Action + def self.run(params) + UI.message "Skip confirm: #{params[:skip_confirm]}" + + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/android/android_git_helper.rb' + + UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/') + + version = Fastlane::Helper::Android::VersionHelper.get_public_version + message = "Finalizing release: #{version}\n" + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else + UI.message(message) end + + # Check local repo status + other_action.ensure_git_status_clean() + + version[Fastlane::Helper::Android::VersionHelper::VERSION_NAME] + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before finalizing a release' + end + + def self.details + 'Runs some prechecks before finalizing a release' + end + + def self.available_options + # Define all options your action supports. + + # Below a few examples + [ + FastlaneCore::ConfigItem.new(key: :skip_confirm, + env_name: 'FL_ANDROID_FINALIZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + ] + end + + def self.output + end + + def self.return_value + 'The current app version' + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb index cd0f6690d..025a2b74b 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_alpha_version.rb @@ -1,45 +1,44 @@ module Fastlane - module Actions - class AndroidGetAlphaVersionAction < Action - def self.run(params) - require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Gets the alpha version of the app" - end - - def self.details - "Gets the alpha version of the app" - end - - def self.available_options - # Define all options your action supports. - end - - def self.output - # Define the shared values you are going to provide - - end - - def self.return_value - # If you method provides a return value, you can describe here what it does - "Return the alpha version of the app" - end - - def self.authors - # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + module Actions + class AndroidGetAlphaVersionAction < Action + def self.run(params) + require_relative '../../helper/android/android_version_helper.rb' + Fastlane::Helper::Android::VersionHelper.get_alpha_version() + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Gets the alpha version of the app' + end + + def self.details + 'Gets the alpha version of the app' + end + + def self.available_options + # Define all options your action supports. + end + + def self.output + # Define the shared values you are going to provide + end + + def self.return_value + # If you method provides a return value, you can describe here what it does + 'Return the alpha version of the app' + end + + def self.authors + # So no one will ever forget your contribution to fastlane :) You are awesome btw! + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb index 54cbe27a5..15c5a10b9 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_app_version.rb @@ -1,45 +1,44 @@ module Fastlane - module Actions - class AndroidGetAppVersionAction < Action - def self.run(params) - require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidVersionHelper::get_public_version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Gets the public version of the app" - end - - def self.details - "Gets the public version of the app" - end - - def self.available_options - # Define all options your action supports. - end - - def self.output - # Define the shared values you are going to provide - - end - - def self.return_value - # If you method provides a return value, you can describe here what it does - "Return the public version of the app" - end - - def self.authors - # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + module Actions + class AndroidGetAppVersionAction < Action + def self.run(params) + require_relative '../../helper/android/android_version_helper.rb' + Fastlane::Helper::Android::VersionHelper.get_public_version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Gets the public version of the app' + end + + def self.details + 'Gets the public version of the app' + end + + def self.available_options + # Define all options your action supports. + end + + def self.output + # Define the shared values you are going to provide + end + + def self.return_value + # If you method provides a return value, you can describe here what it does + 'Return the public version of the app' + end + + def self.authors + # So no one will ever forget your contribution to fastlane :) You are awesome btw! + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb index f2fb68dd2..10a9b266a 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_get_release_version.rb @@ -1,45 +1,44 @@ module Fastlane - module Actions - class AndroidGetReleaseVersionAction < Action - def self.run(params) - require_relative '../../helper/android/android_version_helper.rb' - Fastlane::Helpers::AndroidVersionHelper.get_release_version() - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Gets the public version of the app" - end - - def self.details - "Gets the public version of the app" - end - - def self.available_options - # Define all options your action supports. - end - - def self.output - # Define the shared values you are going to provide - - end - - def self.return_value - # If you method provides a return value, you can describe here what it does - "Return the public version of the app" - end - - def self.authors - # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + module Actions + class AndroidGetReleaseVersionAction < Action + def self.run(params) + require_relative '../../helper/android/android_version_helper.rb' + Fastlane::Helper::Android::VersionHelper.get_release_version() + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Gets the public version of the app' + end + + def self.details + 'Gets the public version of the app' + end + + def self.available_options + # Define all options your action supports. + end + + def self.output + # Define the shared values you are going to provide + end + + def self.return_value + # If you method provides a return value, you can describe here what it does + 'Return the public version of the app' + end + + def self.authors + # So no one will ever forget your contribution to fastlane :) You are awesome btw! + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb index 03f98e400..88c2d8419 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_hotifx_prechecks.rb @@ -3,35 +3,29 @@ module Actions class AndroidHotfixPrechecksAction < Action def self.run(params) UI.message "Skip confirm: #{params[:skip_confirm]}" - UI.message "" + UI.message '' require_relative '../../helper/android/android_version_helper.rb' require_relative '../../helper/android/android_git_helper.rb' # Evaluate previous tag new_ver = params[:version_name] - prev_ver = Fastlane::Helpers::AndroidVersionHelper::calc_prev_hotfix_version_name(new_ver) + prev_ver = Fastlane::Helper::Android::VersionHelper.calc_prev_hotfix_version_name(new_ver) # Confirm message = "Requested Hotfix version: #{new_ver}\n" message << "Branching from: #{prev_ver}\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end # Check tags - if other_action.git_tag_exists(tag: new_ver) - UI.crash!("Version #{new_ver} already exists! Abort!") - end + UI.crash!("Version #{new_ver} already exists! Abort!") if other_action.git_tag_exists(tag: new_ver) - if !other_action.git_tag_exists(tag: prev_ver) - UI.crash!("Version #{prev_ver} is not tagged! Can't branch. Abort!") - end + UI.crash!("Version #{prev_ver} is not tagged! Can't branch. Abort!") unless other_action.git_tag_exists(tag: prev_ver) # Check local repo status other_action.ensure_git_status_clean() @@ -45,37 +39,35 @@ def self.run(params) ##################################################### def self.description - "Runs some prechecks before preparing for a new hotfix" + 'Runs some prechecks before preparing for a new hotfix' end def self.details - "Checks out a new branch from a tag and updates tags" + 'Checks out a new branch from a tag and updates tags' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :version_name, - env_name: "FL_ANDROID_HOTFIX_PRECHECKS_VERSION", - description: "The version to work on", # a short description of this parameter + env_name: 'FL_ANDROID_HOTFIX_PRECHECKS_VERSION', + description: 'The version to work on', # a short description of this parameter is_string: true), FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_ANDROID_HOTFIX_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one + env_name: 'FL_ANDROID_HOTFIX_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb index 4963d0403..be7a51a27 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_merge_translators_strings.rb @@ -1,6 +1,6 @@ require 'fastlane/action' require 'date' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' require_relative '../../helper/ios/ios_version_helper' require_relative '../../helper/android/android_version_helper' module Fastlane @@ -9,31 +9,31 @@ class AndroidMergeTranslatorsStringsAction < Action def self.run(params) folder_path = File.expand_path(params[:strings_folder]) - subfolders = Dir.entries("#{folder_path}") - subfolders.each do | strings_folder | - merge_folder(File.join(folder_path, strings_folder)) if strings_folder.start_with?("values") + subfolders = Dir.entries(folder_path) + subfolders.each do |strings_folder| + merge_folder(File.join(folder_path, strings_folder)) if strings_folder.start_with?('values') end end def self.merge_folder(strings_folder) - main_file = File.join(strings_folder, "strings.xml") + main_file = File.join(strings_folder, 'strings.xml') return unless File.exist?(main_file) UI.message("Merging in: #{strings_folder}") - tmp_main_file = main_file + ".tmp" + tmp_main_file = main_file + '.tmp' FileUtils.cp(main_file, tmp_main_file) - join_files = Dir.glob(File.join("#{strings_folder}", "strings-*.xml")) - extra_strings = Array.new - extra_keys = Array.new - join_files.each do | join_strings | + join_files = Dir.glob(File.join(strings_folder, 'strings-*.xml')) + extra_strings = [] + extra_keys = [] + join_files.each do |join_strings| my_strings = File.read(join_strings).split("\n") - my_strings.each do | string | - if string.include?("").first - if (!extra_keys.include?(string_key)) - extra_strings << string + my_strings.each do |string| + if string.include?('').first + unless extra_keys.include?(string_key) + extra_strings << string extra_keys << string_key end end @@ -42,10 +42,9 @@ def self.merge_folder(strings_folder) File.delete(join_strings) end - File.open(main_file, "w") do | f | - File.open(tmp_main_file).each do | line | - - f.puts(extra_strings) if (line.strip == "") + File.open(main_file, 'w') do |f| + File.open(tmp_main_file).each do |line| + f.puts(extra_strings) if line.strip == '' f.puts(check_line(line, extra_strings)) end end @@ -54,24 +53,22 @@ def self.merge_folder(strings_folder) end def self.check_line(line, extra_strings) - return line unless (line.include?("").first - extra_strings.each do | overwrite_string | - if (overwrite_string.strip.split(">").first == test_line) then - return "" - end + return line unless line.include?('').first + extra_strings.each do |overwrite_string| + return '' if overwrite_string.strip.split('>').first == test_line end return line end def self.description - "Merge strings for translators" + 'Merge strings for translators' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -80,15 +77,15 @@ def self.return_value def self.details # Optional: - "Merges waiting and fuzzy strings into the main file for translators" + 'Merges waiting and fuzzy strings into the main file for translators' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :strings_folder, - env_name: "AMTS_STRING_FOLDER", - description: "The folder that contains all the translations", - optional: false, + env_name: 'AMTS_STRING_FOLDER', + description: 'The folder that contains all the translations', + optional: false, type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb index aa6153800..8b4b7a493 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_tag_build.rb @@ -1,52 +1,51 @@ module Fastlane - module Actions - class AndroidTagBuildAction < Action - def self.run(params) - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/android/android_git_helper.rb' - - release_ver = Fastlane::Helpers::AndroidVersionHelper.get_release_version() - alpha_ver = Fastlane::Helpers::AndroidVersionHelper.get_alpha_version() unless ENV["HAS_ALPHA_VERSION"].nil? - Fastlane::Helpers::AndroidGitHelper.tag_build(release_ver[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME], (ENV["HAS_ALPHA_VERSION"].nil? or (params[:tag_alpha] == false)) ? nil : alpha_ver[Fastlane::Helpers::AndroidVersionHelper::VERSION_NAME]) - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Tags the current build" - end - - def self.details - "Tags the current build" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :tag_alpha, - env_name: "FL_ANDROID_TAG_BUILD_ALPHA", - description: "True to skip tagging the alpha version", - is_string: false, - default_value: true) - ] - end - - def self.output - - end - - def self.return_value - - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + module Actions + class AndroidTagBuildAction < Action + def self.run(params) + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/android/android_git_helper.rb' + + release_ver = Fastlane::Helper::Android::VersionHelper.get_release_version() + alpha_ver = Fastlane::Helper::Android::VersionHelper.get_alpha_version() unless ENV['HAS_ALPHA_VERSION'].nil? + Fastlane::Helper::GitHelper.create_tag(release_ver[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]) + Fastlane::Helper::GitHelper.create_tag(alpha_ver[Fastlane::Helper::Android::VersionHelper::VERSION_NAME]) unless ENV['HAS_ALPHA_VERSION'].nil? || (params[:tag_alpha] == false) + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Tags the current build' + end + + def self.details + 'Tags the current build' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :tag_alpha, + env_name: 'FL_ANDROID_TAG_BUILD_ALPHA', + description: 'True to skip tagging the alpha version', + is_string: false, + default_value: true), + ] + end + + def self.output + end + + def self.return_value + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb index a1167fc0d..7dacaa89e 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_metadata.rb @@ -8,7 +8,7 @@ class AndroidUpdateMetadataAction < Action def self.run(params) require_relative '../../helper/android/android_git_helper.rb' - Fastlane::Helpers::AndroidGitHelper.update_metadata(ENV["validate_translations"]) + Fastlane::Helper::Android::GitHelper.update_metadata(ENV['validate_translations']) end ##################################################### @@ -16,27 +16,24 @@ def self.run(params) ##################################################### def self.description - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.details - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.available_options - end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -44,4 +41,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb index 3b30cfc09..cbafdc2ce 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/android/android_update_release_notes.rb @@ -1,58 +1,56 @@ module Fastlane - module Actions - class AndroidUpdateReleaseNotesAction < Action - def self.run(params) - UI.message "Updating the release notes..." - - require_relative '../../helper/android/android_version_helper.rb' - require_relative '../../helper/release_notes_helper.rb' - require_relative '../../helper/git_helper.rb' - - path = File.join(ENV["PROJECT_ROOT_FOLDER"] || '.', 'RELEASE-NOTES.txt') - next_version = Fastlane::Helpers::AndroidVersionHelper.calc_next_release_short_version(params[:new_version]) - - Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: path, section_title: next_version) - Fastlane::Helper::GitHelper.commit(message: "Release Notes: add new section for next version (#{next_version})", files: path, push: true) - - UI.message "Done." - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Updates the release notes file for the next app version" - end - - def self.details - "Updates the release notes file for the next app version" - end - - def self.available_options + module Actions + class AndroidUpdateReleaseNotesAction < Action + def self.run(params) + UI.message 'Updating the release notes...' + + require_relative '../../helper/android/android_version_helper.rb' + require_relative '../../helper/release_notes_helper.rb' + require_relative '../../helper/git_helper.rb' + + path = File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'RELEASE-NOTES.txt') + next_version = Fastlane::Helper::Android::VersionHelper.calc_next_release_short_version(params[:new_version]) + + Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: path, section_title: next_version) + Fastlane::Helper::GitHelper.commit(message: "Release Notes: add new section for next version (#{next_version})", files: path, push: true) + + UI.message 'Done.' + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Updates the release notes file for the next app version' + end + + def self.details + 'Updates the release notes file for the next app version' + end + + def self.available_options [ FastlaneCore::ConfigItem.new(key: :new_version, - env_name: "FL_ANDROID_UPDATE_RELEASE_NOTES_VERSION", - description: "The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes", - is_string: true) + env_name: 'FL_ANDROID_UPDATE_RELEASE_NOTES_VERSION', + description: 'The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes', + is_string: true), ] - end - - def self.output - - end - - def self.return_value - - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :android - end + end + + def self.output + end + + def self.return_value + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :android end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb index 39ca9da6f..8653961d8 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/circleci_trigger_job_action.rb @@ -13,7 +13,7 @@ def self.run(params) ) res = ci_helper.trigger_job(branch: params[:branch], parameters: params[:job_params]) - (res.code == "201") ? UI.message('Done!') : UI.user_error!("Failed to start job\nError: [#{res.code}] #{res.message}") + res.code == '201' ? UI.message('Done!') : UI.user_error!("Failed to start job\nError: [#{res.code}] #{res.message}") end ##################################################### @@ -21,38 +21,38 @@ def self.run(params) ##################################################### def self.description - "Triggers a job on CircleCI" + 'Triggers a job on CircleCI' end def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :circle_ci_token, - env_name: "FL_CIRCLECI_TOKEN", - description: "CircleCI token", - type: String), - FastlaneCore::ConfigItem.new(key: :organization, - env_name: "FL_CIRCLECI_ORGANIZATION", - description: "The GitHub organization which hosts the repository you want to work on", - type: String, - default_value: "wordpress-mobile"), - FastlaneCore::ConfigItem.new(key: :repository, - env_name: "FL_CIRCLECI_REPOSITORY", - description: "The GitHub repository you want to work on", - type: String), - FastlaneCore::ConfigItem.new(key: :branch, - env_name: "FL_CIRCLECI_BRANCH", - description: "The branch on which you want to work on", - type: String), - FastlaneCore::ConfigItem.new(key: :job_params, - env_name: "FL_CIRCLECI_JOB_PARAMS", - description: "Parameters to send to the CircleCI pipeline", - type: Hash, - default_value: nil), - ] + [ + FastlaneCore::ConfigItem.new(key: :circle_ci_token, + env_name: 'FL_CIRCLECI_TOKEN', + description: 'CircleCI token', + type: String), + FastlaneCore::ConfigItem.new(key: :organization, + env_name: 'FL_CIRCLECI_ORGANIZATION', + description: 'The GitHub organization which hosts the repository you want to work on', + type: String, + default_value: 'wordpress-mobile'), + FastlaneCore::ConfigItem.new(key: :repository, + env_name: 'FL_CIRCLECI_REPOSITORY', + description: 'The GitHub repository you want to work on', + type: String), + FastlaneCore::ConfigItem.new(key: :branch, + env_name: 'FL_CIRCLECI_BRANCH', + description: 'The branch on which you want to work on', + type: String), + FastlaneCore::ConfigItem.new(key: :job_params, + env_name: 'FL_CIRCLECI_JOB_PARAMS', + description: 'Parameters to send to the CircleCI pipeline', + type: Hash, + default_value: nil), + ] end def self.authors - ["loremattei"] + ['loremattei'] end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb index 2490729cf..9a6653722 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/close_milestone_action.rb @@ -1,6 +1,6 @@ require 'fastlane/action' require 'date' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' require_relative '../../helper/ios/ios_version_helper' require_relative '../../helper/android/android_version_helper' module Fastlane @@ -10,20 +10,18 @@ def self.run(params) repository = params[:repository] milestone_title = params[:milestone] - milestone = Fastlane::Helper::GhhelperHelper.get_milestone(repository, milestone_title) - if (milestone.nil?) - UI.user_error!("Milestone #{milestone_title} not found.") - end + milestone = Fastlane::Helper::GithubHelper.get_milestone(repository, milestone_title) + UI.user_error!("Milestone #{milestone_title} not found.") if milestone.nil? - Fastlane::Helper::GhhelperHelper.GHClient().update_milestone(repository, milestone[:number], {:state => "closed"}) + Fastlane::Helper::GithubHelper.github_client().update_milestone(repository, milestone[:number], state: 'closed') end def self.description - "Closes an existing milestone in the project" + 'Closes an existing milestone in the project' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -32,21 +30,21 @@ def self.return_value def self.details # Optional: - "Closes an existing milestone in the project" + 'Closes an existing milestone in the project' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :milestone, - env_name: "GHHELPER_MILESTONE", - description: "The GitHub milestone", - optional: false, - type: String), + env_name: 'GHHELPER_MILESTONE', + description: 'The GitHub milestone', + optional: false, + type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb index 621f90b54..d30f04b57 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_new_milestone_action.rb @@ -1,6 +1,6 @@ require 'fastlane/action' require 'date' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' require_relative '../../helper/ios/ios_version_helper' require_relative '../../helper/android/android_version_helper' module Fastlane @@ -9,21 +9,21 @@ class CreateNewMilestoneAction < Action def self.run(params) repository = params[:repository] - last_stone = Fastlane::Helper::GhhelperHelper.get_last_milestone(repository) + last_stone = Fastlane::Helper::GithubHelper.get_last_milestone(repository) UI.message("Last detected milestone: #{last_stone[:title]} due on #{last_stone[:due_on]}.") milestone_duedate = last_stone[:due_on] newmilestone_duedate = (milestone_duedate.to_datetime.next_day(14).to_time).utc - newmilestone_number = Fastlane::Helpers::IosVersionHelper.calc_next_release_version(last_stone[:title]) + newmilestone_number = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(last_stone[:title]) UI.message("Next milestone: #{newmilestone_number} due on #{newmilestone_duedate}.") - Fastlane::Helper::GhhelperHelper.create_milestone(repository, newmilestone_number, newmilestone_duedate, params[:need_appstore_submission]) + Fastlane::Helper::GithubHelper.create_milestone(repository, newmilestone_number, newmilestone_duedate, params[:need_appstore_submission]) end def self.description - "Creates a new milestone for the project" + 'Creates a new milestone for the project' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -32,22 +32,22 @@ def self.return_value def self.details # Optional: - "Creates a new milestone for the project" + 'Creates a new milestone for the project' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :need_appstore_submission, - env_name: "GHHELPER_NEED_APPSTORE_SUBMISSION", - description: "True if the app needs to be submitted", - optional: true, - is_string: false, - default_value: false), + env_name: 'GHHELPER_NEED_APPSTORE_SUBMISSION', + description: 'True if the app needs to be submitted', + optional: true, + is_string: false, + default_value: false), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb index bbfe8d1b9..f6208eda4 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/create_release_action.rb @@ -1,6 +1,6 @@ require 'fastlane/action' require 'date' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' require_relative '../../helper/ios/ios_version_helper' require_relative '../../helper/android/android_version_helper' module Fastlane @@ -10,25 +10,25 @@ def self.run(params) repository = params[:repository] version = params[:version] assets = params[:release_assets] - release_notes = params[:release_notes_file_path].nil? ? "" : IO.read(params[:release_notes_file_path]) + release_notes = params[:release_notes_file_path].nil? ? '' : IO.read(params[:release_notes_file_path]) prerelease = params[:prerelease] UI.message("Creating draft release #{version} in #{repository}.") # Verify assets - assets.each do | file_path | + assets.each do |file_path| UI.user_error!("Can't find file #{file_path}!") unless File.exist?(file_path) end - - Fastlane::Helper::GhhelperHelper.create_release(repository, version, release_notes, assets, prerelease) - UI.message("Done") + + Fastlane::Helper::GithubHelper.create_release(repository, version, release_notes, assets, prerelease) + UI.message('Done') end def self.description - "Creates a release and uploads the provided assets" + 'Creates a release and uploads the provided assets' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -37,38 +37,37 @@ def self.return_value def self.details # Optional: - "Creates a release and uploads the provided assets" + 'Creates a release and uploads the provided assets' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, - type: String), + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, + type: String), FastlaneCore::ConfigItem.new(key: :version, - env_name: "GHHELPER_CREATE_RELEASE_VERSION", - description: "The version of the release", - optional: false, - is_string: true), + env_name: 'GHHELPER_CREATE_RELEASE_VERSION', + description: 'The version of the release', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :release_notes_file_path, - env_name: "GHHELPER_CREATE_RELEASE_NOTES", - description: "The path to the file that contains the release notes", - optional: true, - is_string: true), + env_name: 'GHHELPER_CREATE_RELEASE_NOTES', + description: 'The path to the file that contains the release notes', + optional: true, + is_string: true), FastlaneCore::ConfigItem.new(key: :release_assets, - env_name: "GHHELPER_CREATE_RELEASE_ASSETS", - description: "Assets to upload", - type: Array, - optional: false, - ), + env_name: 'GHHELPER_CREATE_RELEASE_ASSETS', + description: 'Assets to upload', + type: Array, + optional: false), FastlaneCore::ConfigItem.new(key: :prerelease, - env_name: "GHHELPER_CREATE_RELEASE_PRERELEASE", - description: "True if this is a pre-release", - optional: true, - default_value: false, - is_string: false), + env_name: 'GHHELPER_CREATE_RELEASE_PRERELEASE', + description: 'True if this is a pre-release', + optional: true, + default_value: false, + is_string: false), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb index d7a09ac64..6ae0bb87f 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/extract_release_notes_for_version_action.rb @@ -10,32 +10,30 @@ def self.run(params) extracted_notes_file = File.open(extracted_notes_file_path, 'w') unless extracted_notes_file_path.blank? - extract_notes(release_notes_file_path, version) do | line | + extract_notes(release_notes_file_path, version) do |line| extracted_notes_file.nil? ? puts(line) : extracted_notes_file.write(line) - end + end unless extracted_notes_file.nil? - extracted_notes_file.close() + extracted_notes_file.close() check_and_commit_extracted_notes_file(extracted_notes_file_path, version) - end + end end def self.extract_notes(release_notes_file_path, version) state = :discarding - File.open(release_notes_file_path).each do | line | + File.open(release_notes_file_path).each do |line| case state when :discarding - if (line.match(/^(\d+\.)?(\d+\.)?(\*|\d+)$/)) and (line.strip() == version) - state = :evaluating - end + state = :evaluating if (line.match(/^(\d+\.)?(\d+\.)?(\*|\d+)$/)) && (line.strip() == version) when :evaluating state = (line.match(/-/)) ? :extracting : :discarding when :extracting - if (line.match(/^(\d+\.)?(\d+\.)?(\*|\d+)$/)) + if line.match(/^(\d+\.)?(\d+\.)?(\*|\d+)$/) state = :discarding return else - yield(line) + yield(line) end end end @@ -47,11 +45,11 @@ def self.check_and_commit_extracted_notes_file(file_path, version) end def self.description - "Extract the release notes for a specific version" + 'Extract the release notes for a specific version' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -60,26 +58,26 @@ def self.return_value def self.details # Optional: - "Creates a release and uploads the provided assets" + 'Creates a release and uploads the provided assets' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :version, - env_name: "GHHELPER_EXTRACT_NOTES_VERSION", - description: "The version of the release", - optional: false, - is_string: true), + env_name: 'GHHELPER_EXTRACT_NOTES_VERSION', + description: 'The version of the release', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :release_notes_file_path, - env_name: "GHHELPER_EXTRACT_NOTES_FILE_PATH", - description: "The path to the file that contains the release notes", - optional: false, - is_string: true), + env_name: 'GHHELPER_EXTRACT_NOTES_FILE_PATH', + description: 'The path to the file that contains the release notes', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :extracted_notes_file_path, - env_name: "GHHELPER_EXTRACT_NOTES_EXTRACTED_FILE_PATH", - description: "The path to the file that will contain the extracted release notes", - optional: true, - is_string: true), + env_name: 'GHHELPER_EXTRACT_NOTES_EXTRACTED_FILE_PATH', + description: 'The path to the file that will contain the extracted release notes', + optional: true, + is_string: true), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb index 3118ce269..10237d0c5 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/get_prs_list_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' module Fastlane module Actions @@ -15,33 +15,33 @@ def self.run(params) # Extract PRs pr_list = [] - commit_list.split("\n").each do | commit | - if (commit.include?("Merge pull request #")) + commit_list.split("\n").each do |commit| + if commit.include?('Merge pull request #') # PR found, so extract PR number pr_list.push(commit.partition('#').last.split(' ')[0]) end end # Get infos from GitHub and put into the target file - client = Fastlane::Helper::GhhelperHelper.GHClient() - File.open(report_path, "w") do | file | - pr_list.each do | pr_number | + client = Fastlane::Helper::GithubHelper.github_client() + File.open(report_path, 'w') do |file| + pr_list.each do |pr_number| begin data = client.pull_request(repository, pr_number.to_i) file.puts("##{data[:number]}: #{data[:title]} @#{data[:user][:login]} #{data[:html_url]}") rescue UI.message("Could not find a PR with number #{pr_number.to_i}. Usually this is due to a bad reference in a commit message, but you probably want to check.") end - end - end + end + end end def self.description - "Generate the list of the PRs from `start_tag` to `end_tag`" + 'Generate the list of the PRs from `start_tag` to `end_tag`' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -50,30 +50,30 @@ def self.return_value def self.details # Optional: - "Generate the list of the PRs from `start_tag` to `end_tag`" + 'Generate the list of the PRs from `start_tag` to `end_tag`' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :start_tag, - description: "The tag from which the report starts", - optional: false, - is_string: true), + description: 'The tag from which the report starts', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :end_tag, - description: "The tag to which the report ends", - optional: true, - default_value: ".", - is_string: true), - FastlaneCore::ConfigItem.new(key: :report_path, - env_name: "GHHELPER_REPORTPATH", - description: "The path of the report file", - optional: false, - is_string: true) + description: 'The tag to which the report ends', + optional: true, + default_value: '.', + is_string: true), + FastlaneCore::ConfigItem.new(key: :report_path, + env_name: 'GHHELPER_REPORTPATH', + description: 'The path of the report file', + optional: false, + is_string: true), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb index a590c16c5..119204699 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_downloadmetadata_action.rb @@ -10,22 +10,21 @@ def self.run(params) UI.message "Locales: #{params[:locales].inspect}" UI.message "Source locale: #{params[:source_locale].nil? ? '-' : params[:source_locale]}" UI.message "Path: #{params[:download_path]}" - + # Check download path - Dir.mkdir(params[:download_path]) unless File.exists?(params[:download_path]) + Dir.mkdir(params[:download_path]) unless File.exist?(params[:download_path]) # Download downloader = Fastlane::Helper::MetadataDownloader.new(params[:download_path], params[:target_files]) - params[:locales].each do | loc | - - if loc.kind_of?(Array) then + params[:locales].each do |loc| + if loc.is_a?(Array) puts "Downloading language: #{loc[1]}" complete_url = "#{params[:project_url]}#{loc[0]}/default/export-translations?filters[status]=current&format=json" downloader.download(loc[1], complete_url, loc[1] == params[:source_locale]) end - if loc.kind_of?(String) then + if loc.is_a?(String) puts "Downloading language: #{loc}" complete_url = "#{params[:project_url]}#{loc}/default/export-translations?filters[status]=current&format=json" downloader.download(loc, complete_url, loc == params[:source_locale]) @@ -38,42 +37,41 @@ def self.run(params) ##################################################### def self.description - "Download translated metadata" + 'Download translated metadata' end def self.details - "Downloads tranlated metadata from GlotPress and updates local files" + 'Downloads tranlated metadata from GlotPress and updates local files' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :project_url, - env_name: "FL_DOWNLOAD_METADATA_PROJECT_URL", # The name of the environment variable - description: "GlotPress project URL"), + env_name: 'FL_DOWNLOAD_METADATA_PROJECT_URL', # The name of the environment variable + description: 'GlotPress project URL'), FastlaneCore::ConfigItem.new(key: :target_files, - env_name: "FL_DOWNLOAD_METADATA_TARGET_FILES", - description: "The hash with the path to the target files and the key to use to extract their content", - is_string: false), + env_name: 'FL_DOWNLOAD_METADATA_TARGET_FILES', + description: 'The hash with the path to the target files and the key to use to extract their content', + is_string: false), FastlaneCore::ConfigItem.new(key: :locales, - env_name: "FL_DOWNLOAD_METADATA_LOCALES", - description: "The hash with the GLotPress locale and the project locale association", - is_string: false), + env_name: 'FL_DOWNLOAD_METADATA_LOCALES', + description: 'The hash with the GLotPress locale and the project locale association', + is_string: false), FastlaneCore::ConfigItem.new(key: :source_locale, - env_name: "FL_DOWNLOAD_METADATA_SOURCE_LOCALE", - description: "The source locale code", - optional: true), + env_name: 'FL_DOWNLOAD_METADATA_SOURCE_LOCALE', + description: 'The source locale code', + optional: true), FastlaneCore::ConfigItem.new(key: :download_path, - env_name: "FL_DOWNLOAD_METADATA_DOWNLOAD_PATH", - description: "The path of the target files", - is_string: true) + env_name: 'FL_DOWNLOAD_METADATA_DOWNLOAD_PATH', + description: 'The path of the target files', + is_string: true), ] end def self.output - end def self.return_value @@ -81,7 +79,7 @@ def self.return_value end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb index 24c43cf99..11c6a6269 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/gp_update_metadata_source.rb @@ -20,10 +20,10 @@ def self.run(params) UI.message "File #{params[:po_file_path]} updated!" end - # Verifies that all the source files are available + # Verifies that all the source files are available # to this action def self.check_source_files(source_files) - source_files.values.each do | file_path | + source_files.values.each do |file_path| UI.user_error!("Couldn't find file at path '#{file_path}'") unless File.exist?(file_path) end end @@ -37,69 +37,67 @@ def self.create_temp_po(params) target = self.create_target_file_path(orig) # Clear if older exists - File.delete(target) if File.exists? target + File.delete(target) if File.exist? target # Create the new one begin - File.open(target, "a") do |fw| - File.open(orig, "r").each do |fr| + File.open(target, 'a') do |fw| + File.open(orig, 'r').each do |fr| write_target_block(fw, fr) - end + end end - rescue - File.delete(target) if File.exists? target - raise - end + rescue + File.delete(target) if File.exist? target + raise + end - target + target end # Deletes the old po and moves the temp one # to the final location def self.swap_po(orig_file_path, temp_file_path) - File.delete(orig_file_path) if File.exists? orig_file_path + File.delete(orig_file_path) if File.exist? orig_file_path File.rename(temp_file_path, orig_file_path) end - # Generates the temp file path + # Generates the temp file path def self.create_target_file_path(orig_file_path) - "#{File.dirname(orig_file_path)}/#{File.basename(orig_file_path, ".*")}.tmp" + "#{File.dirname(orig_file_path)}/#{File.basename(orig_file_path, '.*')}.tmp" end # Creates the block instances def self.create_block_parsers(release_version, block_files) - @blocks = Array.new + @blocks = [] # Inits default handler - @blocks.push (Fastlane::Helper::UnknownMetadataBlock.new) + @blocks.push Fastlane::Helper::UnknownMetadataBlock.new # Init special handlers - block_files.each do | key, file_path | - if (key == :release_note) - @blocks.push (Fastlane::Helper::ReleaseNoteMetadataBlock.new(key, file_path, release_version)) - elsif (key == :whats_new) - @blocks.push (Fastlane::Helper::WhatsNewMetadataBlock.new(key, file_path, release_version)) + block_files.each do |key, file_path| + if key == :release_note + @blocks.push Fastlane::Helper::ReleaseNoteMetadataBlock.new(key, file_path, release_version) + elsif key == :whats_new + @blocks.push Fastlane::Helper::WhatsNewMetadataBlock.new(key, file_path, release_version) else - @blocks.push (Fastlane::Helper::StandardMetadataBlock.new(key, file_path)) + @blocks.push Fastlane::Helper::StandardMetadataBlock.new(key, file_path) end end - # Sets the default + # Sets the default @current_block = @blocks[0] end # Manages tags depending on the type def self.write_target_block(fw, line) - if (is_block_id(line)) + if is_block_id(line) key = line.split(' ')[1].tr('\"', '') - @blocks.each do | block | + @blocks.each do |block| @current_block = block if block.is_handler_for(key) end end - if (is_comment(line)) - @current_block = @blocks.first - end + @current_block = @blocks.first if is_comment(line) @current_block.handle_line(fw, line) end @@ -112,51 +110,48 @@ def self.is_comment(line) line.start_with?('#') end - - ##################################################### # @!group Documentation ##################################################### def self.description - "Updates a .po file with new data from .txt files" + 'Updates a .po file with new data from .txt files' end def self.details - "You can use this action to update the .po file that contains the string to load to GlotPress for localization." + 'You can use this action to update the .po file that contains the string to load to GlotPress for localization.' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :po_file_path, - env_name: "FL_UPDATE_METADATA_SOURCE_PO_FILE_PATH", - description: "The path of the .po file to update", + env_name: 'FL_UPDATE_METADATA_SOURCE_PO_FILE_PATH', + description: 'The path of the .po file to update', is_string: true, verify_block: proc do |value| - UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless (value and not value.empty?) - UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) + UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless value && (!value.empty?) + UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) end), FastlaneCore::ConfigItem.new(key: :release_version, - env_name: "FL_UPDATE_METADATA_SOURCE_RELEASE_VERSION", - description: "The release version of the app (to use to mark the release notes)", + env_name: 'FL_UPDATE_METADATA_SOURCE_RELEASE_VERSION', + description: 'The release version of the app (to use to mark the release notes)', verify_block: proc do |value| - UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless (value and not value.empty?) - end), + UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless value && (!value.empty?) + end), FastlaneCore::ConfigItem.new(key: :source_files, - env_name: "FL_UPDATE_METADATA_SOURCE_SOURCE_FILES", - description: "The hash with the path to the source files and the key to use to include their content", - is_string: false, - verify_block: proc do |value| - UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless (value and not value.empty?) - end) + env_name: 'FL_UPDATE_METADATA_SOURCE_SOURCE_FILES', + description: 'The hash with the path to the source files and the key to use to include their content', + is_string: false, + verify_block: proc do |value| + UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless value && (!value.empty?) + end), ] end def self.output - end def self.return_value @@ -164,11 +159,11 @@ def self.return_value end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) - [:ios, :android].include?(platform) + [:ios, :android].include?(platform) end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb index 5135a84f2..288a48df9 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/promo_screenshots_action.rb @@ -7,7 +7,7 @@ module Fastlane module Actions class PromoScreenshotsAction < Action def self.run(params) - UI.message "Creating Promo Screenshots" + UI.message 'Creating Promo Screenshots' UI.message "#{self.check_path(params[:orig_folder])} Original Screenshot Source: #{params[:orig_folder]}" UI.message "#{self.check_path(params[:metadata_folder])} Translation source: #{params[:metadata_folder]}" @@ -16,104 +16,50 @@ def self.run(params) translationDirectories = subdirectories_for_path(params[:metadata_folder]) imageDirectories = subdirectories_for_path(params[:orig_folder]) - unless helper.can_resolve_path(params[:output_folder]) then + unless helper.can_resolve_path(params[:output_folder]) UI.message "✅ Created Output Folder: #{params[:output_folder]}" FileUtils.mkdir_p(params[:output_folder]) else UI.message "#{self.check_path(params[:output_folder])} Output Folder: #{params[:output_folder]}" end - outputDirectory = helper.resolve_path( params[:output_folder] ) + outputDirectory = helper.resolve_path(params[:output_folder]) ## If there are no translated screenshot images (whether it's because they haven't been generated yet, ## or because we aren't using them), just use the translated directories. - if imageDirectories == [] - languages = translationDirectories - ## And vice-versa. - elsif translationDirectories == [] - languages = imageDirectories - ## If there are original screenshots and translations available, use only locales that exist in both. - else - languages = imageDirectories & translationDirectories - end + languages = if imageDirectories == [] + translationDirectories + ## And vice-versa. + elsif translationDirectories == [] + imageDirectories + ## If there are original screenshots and translations available, use only locales that exist in both. + else + imageDirectories & translationDirectories + end - UI.message("💙 Creating Promo Screenshots for: #{languages.join(", ")}") + UI.message("💙 Creating Promo Screenshots for: #{languages.join(', ')}") - unless params[:force] then - confirm_directory_overwrite(params[:output_folder], "the existing promo screenshots") - end + confirm_directory_overwrite(params[:output_folder], 'the existing promo screenshots') unless params[:force] # Create a hash of devices, keyed by device name - devices = config["devices"] - devices = Hash[devices.map { |device| device["name"] }.zip(devices)] - - stylesheet_path = config["stylesheet"] - - entries = config["entries"] - .flat_map { |entry| - - languages.map { |language| - - newEntry = entry.deep_dup + devices = config['devices'] + devices = Hash[devices.map { |device| device['name'] }.zip(devices)] - # Not every output file will have a screenshot, so handle cases where no - # screenshot file is defined - if entry["screenshot"] != nil && entry["filename"] != nil - newEntry["screenshot"] = helper.resolve_path(params[:orig_folder]) + language + entry["screenshot"] - newEntry["filename"] = outputDirectory + language + entry["filename"] - elsif entry["screenshot"] != nil && entry["filename"] == nil - newEntry["screenshot"] = helper.resolve_path(params[:orig_folder]) + language + entry["screenshot"] - newEntry["filename"] = outputDirectory + language + entry["screenshot"] - elsif entry["screenshot"] == nil && entry["filename"] != nil - newEntry["filename"] = outputDirectory + language + entry["filename"] - else - puts newEntry - abort "Unable to find output file names" - end - - newEntry["locale"] = language - - # Localize file paths for text - if entry["text"] != nil - newEntry["text"].sub!("{locale}", language.dup) - end + stylesheet_path = config['stylesheet'] - # Map attachments paths to their localized versions - if newEntry["attachments"] == nil - newEntry["attachments"] = [] - end - - newEntry["attachments"].each { |attachment| - if attachment["file"] != nil - attachment["file"].sub!("{locale}", language.dup) - end - - if attachment["text"] != nil - attachment["text"].sub!("{locale}", language.dup) - end - } - - newEntry - } - } - .sort { |x,y| - x["filename"] <=> y["filename"] - } + entries = build_entries(config['entries'], languages, outputDirectory, params) bar = ProgressBar.new(entries.count, :bar, :counter, :eta, :rate) - Parallel.map(entries, finish: -> (item, i, result) { + Parallel.map(entries, finish: lambda { |_item, _i, _result| bar.increment! }) do |entry| + device = devices[entry['device']] - device = devices[entry["device"]] + UI.message("Unable to find device #{entry['device']}.") if device.nil? - if device == nil - UI.message("Unable to find device #{entry["device"]}.") - end - - width = device["canvas_size"][0] - height = device["canvas_size"][1] + width = device['canvas_size'][0] + height = device['canvas_size'][1] canvas = helper.create_image(width, height) canvas = helper.draw_background_to_canvas(canvas, entry) @@ -124,25 +70,22 @@ def self.run(params) canvas = helper.draw_attachments_to_canvas(entry, canvas) # Automatically create intermediate directories for output - output_filename = entry["filename"] + output_filename = entry['filename'] dirname = File.dirname(output_filename) - unless File.directory?(dirname) - FileUtils.mkdir_p(dirname) - end + FileUtils.mkdir_p(dirname) unless File.directory?(dirname) canvas.write(output_filename) canvas.destroy! # Run the GC in the same thread to clean up after RMagick GC.start - end end def self.confirm_directory_overwrite(path, description) - if (File.exists?(path)) then - if UI.confirm("Do you want to overwrite #{description}?") then + if File.exist?(path) + if UI.confirm("Do you want to overwrite #{description}?") FileUtils.rm_rf(path) Dir.mkdir(path) else @@ -154,24 +97,21 @@ def self.confirm_directory_overwrite(path, description) end def self.subdirectories_for_path(path) - subdirectories = [] - unless helper.can_resolve_path( path ) then - return [] - end + return [] unless helper.can_resolve_path(path) - resolved_path = helper.resolve_path( path ) + resolved_path = helper.resolve_path(path) Dir.chdir(resolved_path) do - subdirectories = Dir["*"].reject{|o| not File.directory?(o)}.sort + subdirectories = Dir['*'].select { |o| File.directory?(o) }.sort end subdirectories end def self.check_path(path) - self.helper.can_resolve_path(path) ? "✅" : "🚫" + self.helper.can_resolve_path(path) ? '✅' : '🚫' end def self.helper @@ -179,11 +119,11 @@ def self.helper end def self.description - "Generate promo screenshots" + 'Generate promo screenshots' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -192,47 +132,116 @@ def self.return_value def self.details # Optional: - "Creates promo screenshots starting from standard ones" + 'Creates promo screenshots starting from standard ones' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :orig_folder, - env_name: "PROMOSS_ORIG", - description: "The directory containing the original screenshots", - optional: false, - is_string: true), + env_name: 'PROMOSS_ORIG', + description: 'The directory containing the original screenshots', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :output_folder, - env_name: "PROMOSS_OUTPUT", - description: "The path of the folder to save the promo screenshots", - optional: false, - is_string: true), + env_name: 'PROMOSS_OUTPUT', + description: 'The path of the folder to save the promo screenshots', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :metadata_folder, - env_name: "PROMOSS_METADATA_FOLDER", - description: "The directory containing the translation data", - optional: false, - is_string: true), + env_name: 'PROMOSS_METADATA_FOLDER', + description: 'The directory containing the translation data', + optional: false, + is_string: true), FastlaneCore::ConfigItem.new(key: :config_file, - env_name: "PROMOSS_CONFIG_FILE", - description: "The path to the file containing the promo screenshot configuration", - optional: true, + env_name: 'PROMOSS_CONFIG_FILE', + description: 'The path to the file containing the promo screenshot configuration', + optional: true, is_string: true, - default_value: "screenshots.json"), + default_value: 'screenshots.json'), FastlaneCore::ConfigItem.new(key: :force, - env_name: "PROMOSS_FORCE_CREATION", - description: "Overwrite existing promo screenshots without asking first?", - optional: true, + env_name: 'PROMOSS_FORCE_CREATION', + description: 'Overwrite existing promo screenshots without asking first?', + optional: true, is_string: false, - default_value: false), + default_value: false), ] end def self.is_supported?(platform) true end + + def self.build_entries(config_entries, languages, output_directory, params) + config_entries + .flat_map do |entry| + languages.map do |language| + newEntry = entry.deep_dup + + # Not every output file will have a screenshot, so handle cases where no + # screenshot file is defined + if !entry['screenshot'].nil? && !entry['filename'].nil? + newEntry['screenshot'] = helper.resolve_path(params[:orig_folder]) + language + entry['screenshot'] + newEntry['filename'] = output_directory + language + entry['filename'] + elsif !entry['screenshot'].nil? && entry['filename'].nil? + newEntry['screenshot'] = helper.resolve_path(params[:orig_folder]) + language + entry['screenshot'] + newEntry['filename'] = output_directory + language + entry['screenshot'] + elsif entry['screenshot'].nil? && !entry['filename'].nil? + newEntry['filename'] = output_directory + language + entry['filename'] + else + puts newEntry + abort 'Unable to find output file names' + end + + newEntry['locale'] = language + + # Localize file paths for text + newEntry['text'].sub!('{locale}', language.dup) unless entry['text'].nil? + + # Map attachments paths to their localized versions + newEntry['attachments'] = [] if newEntry['attachments'].nil? + + newEntry['attachments'].each do |attachment| + ## If there are no translated screenshot images (whether it's because they haven't been generated yet, + ## or because we aren't using them), just use the translated directories. + ## And vice-versa. + ## If there are original screenshots and translations available, use only locales that exist in both. + # Create a hash of devices, keyed by device name + # Not every output file will have a screenshot, so handle cases where no + # screenshot file is defined + # Localize file paths for text + # Map attachments paths to their localized versions + # Automatically create intermediate directories for output + # Run the GC in the same thread to clean up after RMagick + # If your method provides a return value, you can describe here what it does + # Optional: + attachment['file']&.sub!('{locale}', language.dup) + + ## If there are no translated screenshot images (whether it's because they haven't been generated yet, + ## or because we aren't using them), just use the translated directories. + ## And vice-versa. + ## If there are original screenshots and translations available, use only locales that exist in both. + # Create a hash of devices, keyed by device name + # Not every output file will have a screenshot, so handle cases where no + # screenshot file is defined + # Localize file paths for text + # Map attachments paths to their localized versions + # Automatically create intermediate directories for output + # Run the GC in the same thread to clean up after RMagick + # If your method provides a return value, you can describe here what it does + # Optional: + attachment['text']&.sub!('{locale}', language.dup) + end + + newEntry + end + end + .sort do |x, y| + x['filename'] <=> y['filename'] + end + end end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb index d41dc27ee..7e23bcd01 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/removebranchprotection_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' module Fastlane module Actions @@ -10,11 +10,11 @@ def self.run(params) branch_prot = {} branch_url = "https://api.github.com/repos/#{repository}/branches/" + branch_name - branch_prot[:restrictions] = {:url=>branch_url + "/protection/restrictions", :users_url=>branch_url + "/protection/restrictions/users", :teams_url=>branch_url + "/protection/restrictions/teams", :users=>[], :teams=>[]} + branch_prot[:restrictions] = { url: branch_url + '/protection/restrictions', users_url: branch_url + '/protection/restrictions/users', teams_url: branch_url + '/protection/restrictions/teams', users: [], teams: [] } branch_prot[:enforce_admins] = nil - branch_prot[:required_pull_request_reviews] = {:url=>branch_url + "/protection/required_pull_request_reviews", :dismiss_stale_reviews=>false, :require_code_owner_reviews=>false} + branch_prot[:required_pull_request_reviews] = { url: branch_url + '/protection/required_pull_request_reviews', dismiss_stale_reviews: false, require_code_owner_reviews: false } - Fastlane::Helper::GhhelperHelper.GHClient().unprotect_branch(repository, branch_name, branch_prot) + Fastlane::Helper::GithubHelper.github_client().unprotect_branch(repository, branch_name, branch_prot) end def self.description @@ -22,7 +22,7 @@ def self.description end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -37,15 +37,15 @@ def self.details def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :branch, - env_name: "GHHELPER_BRANCH", - description: "The branch to unprotect", - optional: false, - type: String) + env_name: 'GHHELPER_BRANCH', + description: 'The branch to unprotect', + optional: false, + type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb index 2cfc9aa73..d775b860c 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setbranchprotection_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' module Fastlane module Actions @@ -10,10 +10,10 @@ def self.run(params) branch_prot = {} branch_url = "https://api.github.com/repos/#{repository}/branches/" + branch_name - branch_prot[:restrictions] = {:url=>branch_url + "/protection/restrictions", :users_url=>branch_url + "/protection/restrictions/users", :teams_url=>branch_url + "/protection/restrictions/teams", :users=>[], :teams=>[]} + branch_prot[:restrictions] = { url: branch_url + '/protection/restrictions', users_url: branch_url + '/protection/restrictions/users', teams_url: branch_url + '/protection/restrictions/teams', users: [], teams: [] } branch_prot[:enforce_admins] = nil - branch_prot[:required_pull_request_reviews] = {:url=>branch_url + "/protection/required_pull_request_reviews", :dismiss_stale_reviews=>false, :require_code_owner_reviews=>false} - Fastlane::Helper::GhhelperHelper.GHClient().protect_branch(repository, branch_name, branch_prot) + branch_prot[:required_pull_request_reviews] = { url: branch_url + '/protection/required_pull_request_reviews', dismiss_stale_reviews: false, require_code_owner_reviews: false } + Fastlane::Helper::GithubHelper.github_client().protect_branch(repository, branch_name, branch_prot) end def self.description @@ -21,7 +21,7 @@ def self.description end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -36,15 +36,15 @@ def self.details def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :branch, - env_name: "GHHELPER_BRANCH", - description: "The branch to protect", - optional: false, - type: String) + env_name: 'GHHELPER_BRANCH', + description: 'The branch to protect', + optional: false, + type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb index 1c1e8558a..d97dd06e6 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/common/setfrozentag_action.rb @@ -1,5 +1,5 @@ require 'fastlane/action' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' module Fastlane module Actions @@ -9,43 +9,39 @@ def self.run(params) milestone_title = params[:milestone] freeze = params[:freeze] - milestone = Fastlane::Helper::GhhelperHelper.get_milestone(repository, milestone_title) - if (milestone.nil?) - UI.user_error!("Milestone #{milestone_title} not found.") - end + milestone = Fastlane::Helper::GithubHelper.get_milestone(repository, milestone_title) + UI.user_error!("Milestone #{milestone_title} not found.") if milestone.nil? mile_title = milestone[:title] puts freeze if freeze - # Check if the state needs changes - if (is_frozen(milestone)) + # Check if the state needs changes + if is_frozen(milestone) UI.message("Milestone #{mile_title} is already frozen. Nothing to do") - return # Already frozen: nothing to do + return # Already frozen: nothing to do end - mile_title = mile_title + " ❄️" + mile_title = mile_title + ' ❄️' else mile_title = milestone_title end UI.message("New milestone: #{mile_title}") - Fastlane::Helper::GhhelperHelper.GHClient().update_milestone(repository, milestone[:number], {:title => mile_title}) + Fastlane::Helper::GithubHelper.github_client().update_milestone(repository, milestone[:number], title: mile_title) end def self.is_frozen(milestone) - unless (milestone.nil?) - return milestone[:title].include?("❄️") - end - + return milestone[:title].include?('❄️') unless milestone.nil? + return false end def self.description - "Sets the frozen tag for the specified milestone" + 'Sets the frozen tag for the specified milestone' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -54,26 +50,26 @@ def self.return_value def self.details # Optional: - "Sets the frozen tag for the specified milestone" + 'Sets the frozen tag for the specified milestone' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :repository, - env_name: "GHHELPER_REPOSITORY", - description: "The remote path of the GH repository on which we work", - optional: false, + env_name: 'GHHELPER_REPOSITORY', + description: 'The remote path of the GH repository on which we work', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :milestone, - env_name: "GHHELPER_MILESTORE", - description: "The GitHub milestone", - optional: false, + env_name: 'GHHELPER_MILESTORE', + description: 'The GitHub milestone', + optional: false, type: String), FastlaneCore::ConfigItem.new(key: :freeze, - description: "The GitHub milestone", - optional: false, - default_value: true, - is_string: false) + description: 'The GitHub milestone', + optional: false, + default_value: true, + is_string: false), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb index 1b3a31ee8..ceed994a4 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_add_files_to_copy_action.rb @@ -10,16 +10,13 @@ module Fastlane module Actions class ConfigureAddFilesToCopyAction < Action def self.run(params = {}) - continue = true - while(continue) + while continue - confirmation = "Do you want to specify a file that should be copied from the secrets repository into your project?" + confirmation = 'Do you want to specify a file that should be copied from the secrets repository into your project?' - if Fastlane::Helper::ConfigureHelper.has_files - confirmation = "Do you want to specify additional files that should be copied from the secrets repository into your project?" - end + confirmation = 'Do you want to specify additional files that should be copied from the secrets repository into your project?' if Fastlane::Helper::ConfigureHelper.has_files if UI.confirm(confirmation) add_file @@ -36,14 +33,13 @@ def self.run(params = {}) ### Walks the user through adding a file to the project's `/.configure `file. ### def self.add_file - invalid_file = true while invalid_file - UI.header "Please provide the location of the source file relative to the secrets repository" - UI.message "Example: google-services.json" + UI.header 'Please provide the location of the source file relative to the secrets repository' + UI.message 'Example: google-services.json' - source = UI.input("Source File Path:") + source = UI.input('Source File Path:') sourcePath = absolute_secret_store_path(source) # Transform the relative path into an absolute path. # Don't allow the developer to accidentally specify an invalid file, otherwise validation will never succeed. @@ -54,46 +50,46 @@ def self.add_file end end - UI.header "Please provide the destination of the file relative to the project root" - UI.message "Example: WordPress/google-services.json" + UI.header 'Please provide the destination of the file relative to the project root' + UI.message 'Example: WordPress/google-services.json' - destination = UI.input("Destination File Path:") # Leave the destination as a relative path, as no validation is required. + destination = UI.input('Destination File Path:') # Leave the destination as a relative path, as no validation is required. - encrypt = UI.confirm("Encrypt file?:") + encrypt = UI.confirm('Encrypt file?:') Fastlane::Helper::ConfigureHelper.add_file(source: source, destination: destination, encrypt: encrypt) end def self.secret_store_dir - Fastlane::Helper::FilesystemHelper.secret_store_dir + Fastlane::Helper::FilesystemHelper.secret_store_dir end def self.absolute_secret_store_path(relative_path) - Fastlane::Helper::FilesystemHelper.absolute_secret_store_path(relative_path) + Fastlane::Helper::FilesystemHelper.absolute_secret_store_path(relative_path) end def self.description - "Interactively add files to the `files_to_copy` list in .configure." + 'Interactively add files to the `files_to_copy` list in .configure.' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.return_value - # If your method provides a return value, you can describe here what it does + # If your method provides a return value, you can describe here what it does end def self.details - "Interactively add files to the `files_to_copy` list in .configure." + 'Interactively add files to the `files_to_copy` list in .configure.' end def self.available_options - [] + [] end def self.is_supported?(platform) - true + true end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb index 64bf3ccd0..ff8b05c5a 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_apply_action.rb @@ -10,9 +10,8 @@ module Fastlane module Actions class ConfigureApplyAction < Action def self.run(params = {}) - # Preflight - UI.user_error!("Decryption key could not be found") if Fastlane::Helper::ConfigureHelper.encryption_key.nil? + UI.user_error!('Decryption key could not be found') if Fastlane::Helper::ConfigureHelper.encryption_key.nil? # Checkout the right commit hash etc. before applying the configuration prepare_repository do @@ -21,11 +20,11 @@ def self.run(params = {}) apply_file(file_reference, params[:force]) end end - UI.success "Applied configuration" + UI.success 'Applied configuration' end def self.prepare_repository - secrets_respository_exists = File.exists?(repository_path) + secrets_respository_exists = File.exist?(repository_path) # If the secrets repo doesn't exist, just run the block unless secrets_respository_exists @@ -42,14 +41,12 @@ def self.prepare_repository original_repo_ref = Fastlane::Helper::ConfigureHelper.repo_branch_name original_repo_ref = repo_hash if original_repo_ref.nil? - unless repo_hash == file_hash - other_action.sh(command: "cd #{repository_path} && git fetch && git checkout #{file_hash}", log: false) - end + other_action.sh(command: "cd #{repository_path} && git fetch && git checkout #{file_hash}", log: false) unless repo_hash == file_hash # Run the provided block yield - - ### Restore secrets repo to original branch. If it was originally in a + + ### Restore secrets repo to original branch. If it was originally in a ### detached HEAD state, we need to use the hash since there's no branch name. other_action.sh(command: "cd #{repository_path} && git checkout #{original_repo_ref}", log: false) end @@ -60,38 +57,36 @@ def self.apply_file(file_reference, force) # If the file doesn't exist or force is true, we don't need to confirm if !File.file?(file_reference.destination) || force file_reference.apply - return # Don't continue if we were able to copy the file without conflict + return # Don't continue if we were able to copy the file without conflict end unless file_reference.needs_apply? return # Nothing to do if the files are identical end - if UI.confirm("#{file_reference.destination} has changes that need to be merged. Would you like to see a diff?") - puts Diffy::Diff.new(file_reference.destination_contents, file_reference.source_contents) - end + puts Diffy::Diff.new(file_reference.destination_contents, file_reference.source_contents) if UI.confirm("#{file_reference.destination} has changes that need to be merged. Would you like to see a diff?") if UI.confirm("Would you like to make a backup of #{file_reference.destination}?") - extension = File.extname(file_reference.destination) - base = File.basename(Pathname.new(file_reference.destination), extension) + extension = File.extname(file_reference.destination) + base = File.basename(Pathname.new(file_reference.destination), extension) - date_string = Time.now.strftime('%m-%d-%Y--%H-%M-%S') + date_string = Time.now.strftime('%m-%d-%Y--%H-%M-%S') - backup_path = base - .concat("-") # Handy-dandy separator - .concat(date_string) # date string to allow multiple backups - .concat(extension) # and the original file extension - .concat(".bak") # add the .bak file extension - easier to .gitignore + backup_path = base + .concat('-') # Handy-dandy separator + .concat(date_string) # date string to allow multiple backups + .concat(extension) # and the original file extension + .concat('.bak') # add the .bak file extension - easier to .gitignore - # Create the destination directory if it doesn't exist - FileUtils.mkdir_p(Pathname.new(file_reference.destination).dirname) - FileUtils.cp(file_reference.destination, backup_path) + # Create the destination directory if it doesn't exist + FileUtils.mkdir_p(Pathname.new(file_reference.destination).dirname) + FileUtils.cp(file_reference.destination, backup_path) end if UI.confirm("Would you like to overwrite #{file_reference.destination}?") - file_reference.apply + file_reference.apply else - UI.message "Skipping #{file_reference.destination}" + UI.message "Skipping #{file_reference.destination}" end end @@ -112,25 +107,25 @@ def self.absolute_secret_store_path(relative_path) end def self.description - "Copy files specified in `.config` from the secrets repository to the project. Specify force:true to avoid confirmation" + 'Copy files specified in `.config` from the secrets repository to the project. Specify force:true to avoid confirmation' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.details - "Copy files specified in `.config` from the secrets repository to the project. Specify force:true to avoid confirmation" + 'Copy files specified in `.config` from the secrets repository to the project. Specify force:true to avoid confirmation' end def self.available_options [ - FastlaneCore::ConfigItem.new(key: :force, - env_name: "FORCE_OVERWRITE", - description: "Overwrite copied files without confirmation", - optional: true, - default_value: false, - is_string: false), + FastlaneCore::ConfigItem.new(key: :force, + env_name: 'FORCE_OVERWRITE', + description: 'Overwrite copied files without confirmation', + optional: true, + default_value: false, + is_string: false), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb index 4db0d1612..29c8606e3 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_download_action.rb @@ -6,26 +6,23 @@ module Fastlane module Actions class ConfigureDownloadAction < Action def self.run(params = {}) - - UI.message "Running Configure Download" + UI.message 'Running Configure Download' # If the `~/.mobile-secrets` repository doesn't exist - unless File.directory?("#{secrets_dir}") - UI.user_error!("The local secrets store does not exist. Please clone it to #{secrets_dir} before continuing.") + unless File.directory?(secrets_dir) + UI.user_error!("The local secrets store does not exist. Please clone it to #{secrets_dir} before continuing.") else update_repository # If the repo already exists, just update it end end - + # Ensure the git repository at `~/.mobile-secrets` is up to date. # If the secrets repo is in a detached HEAD state, skip the pull, # since it will fail. def self.update_repository secrets_repo_branch = Fastlane::Helper::ConfigureHelper.repo_branch_name - unless secrets_repo_branch == nil - sh("cd #{secrets_dir} && git pull") - end + sh("cd #{secrets_dir} && git pull") unless secrets_repo_branch.nil? end def self.secrets_dir @@ -33,11 +30,11 @@ def self.secrets_dir end def self.description - "Updates the mobile secrets." + 'Updates the mobile secrets.' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.return_value @@ -45,7 +42,7 @@ def self.return_value end def self.details - "Pulls down the latest remote changes to the ~/.mobile-secrets repository." + 'Pulls down the latest remote changes to the ~/.mobile-secrets repository.' end def self.available_options diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_setup_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_setup_action.rb index ae17e54df..dc3285285 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_setup_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_setup_action.rb @@ -9,24 +9,18 @@ module Fastlane module Actions class ConfigureSetupAction < Action - def self.run(params = {}) - # Check to see if the local secret storage is set up at ~/.mobile-secrets. - unless File.directory?(repository_path) - UI.user_error!("The local secrets store does not exist. Please clone it to ~/.mobile-secrets before continuing.") - end + UI.user_error!('The local secrets store does not exist. Please clone it to ~/.mobile-secrets before continuing.') unless File.directory?(repository_path) # Checks to see if .configure exists. If so, exit – there’s no need to continue as everything is set up. if configuration_file_exists - UI.success "Configure file exists – exiting." + UI.success 'Configure file exists – exiting.' return end # The mobile secrets repo must be up to date in order to generate and save the encryption key - if Fastlane::Helper::ConfigureHelper.repo_is_behind_remote - prompt_to_update_to_most_recent_version - end + prompt_to_update_to_most_recent_version if Fastlane::Helper::ConfigureHelper.repo_is_behind_remote # Generate an encryption key for the new project, if needed Fastlane::Helper::ConfigureHelper.update_project_encryption_key if Fastlane::Helper::ConfigureHelper.project_encryption_key.nil? @@ -35,19 +29,19 @@ def self.run(params = {}) Fastlane::Helper::ConfigureHelper.update_configure_file_from_repository # Walk the user through adding files to copy to the `.configure` file. - ConfigureAddFilesToCopyAction::run + ConfigureAddFilesToCopyAction.run # Copy the files we just walked the user through setting up. - ConfigureApplyAction::run + ConfigureApplyAction.run - UI.success "Created .configure file" + UI.success 'Created .configure file' end def self.prompt_to_update_to_most_recent_version if UI.confirm("The current branch is #{Fastlane::Helper::ConfigureHelper.repo_commits_behind_remote} commit(s) behind. It must be updated to complete the setup. Would you like to continue?") update_branch else - UI.user_error!("Cannot complete setup when the repo is not up to date.") + UI.user_error!('Cannot complete setup when the repo is not up to date.') end end @@ -65,11 +59,11 @@ def self.repository_path end def self.description - "Set up the .configure file" + 'Set up the .configure file' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.return_value @@ -77,7 +71,7 @@ def self.return_value end def self.details - "Interactively walks the user through setting up the `.configure` file. Assumes the ~/.mobile-secrets directory exists" + 'Interactively walks the user through setting up the `.configure` file. Assumes the ~/.mobile-secrets directory exists' end def self.available_options diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb index e804c2029..709a8dafc 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_update_action.rb @@ -7,9 +7,7 @@ module Fastlane module Actions class ConfigureUpdateAction < Action - def self.run(params = {}) - prompt_to_switch_branches if repo_is_ahead_of_remote @@ -17,9 +15,7 @@ def self.run(params = {}) Please fix this issue before continuing") end - if repo_is_behind_remote - prompt_to_update_to_most_recent_version - end + prompt_to_update_to_most_recent_version if repo_is_behind_remote if configure_file_is_behind_repo prompt_to_update_configure_file_to_most_recent_hash @@ -32,9 +28,7 @@ def self.run(params = {}) # If there is no encryption key for the project, generate one if Fastlane::Helper::ConfigureHelper.project_encryption_key.nil? # If the user chose not to update the repo but there is no encryption key, throw an error - if repo_is_behind_remote - UI.user_error!("The local secrets behind the remote but it is missing a keys.json entry for this project. Please update it to the latest commit.") - end + UI.user_error!('The local secrets behind the remote but it is missing a keys.json entry for this project. Please update it to the latest commit.') if repo_is_behind_remote Fastlane::Helper::ConfigureHelper.update_project_encryption_key # Update the configure file to the new hash update_configure_file @@ -51,15 +45,13 @@ def self.run(params = {}) end def self.prompt_to_switch_branches - branch_name_to_display = current_branch == nil ? current_hash : current_branch + branch_name_to_display = current_branch.nil? ? current_hash : current_branch if UI.confirm("The current branch is `#{branch_name_to_display}`. Would you like to switch branches?") new_branch = UI.select("Select the branch you'd like to switch to: ", get_branches) checkout_branch(new_branch) update_configure_file else - if current_branch == nil - UI.user_error!("The local secrets store is in a deatched HEAD state. Please check out a branch and try again.") - end + UI.user_error!('The local secrets store is in a deatched HEAD state. Please check out a branch and try again.') if current_branch.nil? end end @@ -71,9 +63,7 @@ def self.prompt_to_update_to_most_recent_version end def self.prompt_to_update_configure_file_to_most_recent_hash - if UI.confirm("The `.configure` file is #{configure_file_commits_behind_repo} commit hash(es) behind the repo. Would you like to update it?") - update_configure_file - end + update_configure_file if UI.confirm("The `.configure` file is #{configure_file_commits_behind_repo} commit hash(es) behind the repo. Would you like to update it?") end def self.current_branch @@ -111,8 +101,8 @@ def self.configure_file_commits_behind_repo def self.get_branches branches = sh("cd #{absolute_secret_store_path} && git branch -r") branches.split("\n") - .map { |s| s.strip!.split("/")[1] } - .reject { |s| s.include? "HEAD" } + .map { |s| s.strip!.split('/')[1] } + .reject { |s| s.include? 'HEAD' } end ### Switch to the given branch, but don't ensure that it's up-to-date – that's for another step @@ -130,15 +120,15 @@ def self.absolute_secret_store_path end def self.description - "Ensure that the local secrets repository is up to date." + 'Ensure that the local secrets repository is up to date.' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.details - "Ensure that the local secrets repository is up to date, and lets you test alternative branches." + 'Ensure that the local secrets repository is up to date, and lets you test alternative branches.' end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb index 222cfe58b..dca193f2c 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/configure/configure_validate_action.rb @@ -7,9 +7,7 @@ module Fastlane module Actions class ConfigureValidateAction < Action - def self.run(params = {}) - # Start by ensuring that we've set up the project for configuration validate_that_configure_file_exists @@ -19,7 +17,7 @@ def self.run(params = {}) # Update the repository to get the latest version of the configuration secrets – that's # how we'll know if we're behind in subsequent validations - ConfigureDownloadAction::run + ConfigureDownloadAction.run validate_that_branches_match @@ -29,7 +27,7 @@ def self.run(params = {}) validate_that_all_copied_files_match - UI.success "Configuration is valid" + UI.success 'Configuration is valid' end ### @@ -39,14 +37,13 @@ def self.run(params = {}) ### Validate that the branch specified in .configure matches the branch ### checked out in ~/.mobile-secrets. def self.validate_that_branches_match - repo_branch_name = Fastlane::Helper::ConfigureHelper.repo_branch_name file_branch_name = Fastlane::Helper::ConfigureHelper.configure_file_branch_name unless repo_branch_name == file_branch_name UI.user_error!([ - "The branch specified in `.configure` is not the currently checked out branch in the secrets repository.", + 'The branch specified in `.configure` is not the currently checked out branch in the secrets repository.', "To fix this issue, switch back to the `#{file_branch_name}` branch in the mobile secrets repository.", ].join("\n")) end @@ -61,7 +58,7 @@ def self.validate_that_hashes_match unless repo_hash == file_hash UI.user_error!([ - "The pinned_hash specified in `.configure` is not the currently checked out hash in the secrets repository.", + 'The pinned_hash specified in `.configure` is not the currently checked out hash in the secrets repository.', "To fix this issue, check out the `#{file_hash}` hash in the mobile secrets repository.", ].join("\n")) end @@ -77,43 +74,32 @@ def self.validate_that_no_dependent_files_have_changed dependencies = Fastlane::Helper::ConfigureHelper.file_dependencies new_files = Fastlane::Helper::ConfigureHelper.new_files_in(changed_files) - changed_dependencies = changed_files & dependencies #calculate array intersection + changed_dependencies = changed_files & dependencies # calculate array intersection - unless changed_dependencies.empty? - UI.user_error!("The following files are out of date. Please run `bundle exec fastlane run configure_update` before continuing:\n\n#{changed_dependencies.to_s}") - end + UI.user_error!("The following files are out of date. Please run `bundle exec fastlane run configure_update` before continuing:\n\n#{changed_dependencies}") unless changed_dependencies.empty? - unless new_files.empty? - UI.user_error!("The following files are in the secrets repository, but aren't available for your project. Please run `bundle exec fastlane run configure_update` before continuing:\n\n#{new_files}") - end + UI.user_error!("The following files are in the secrets repository, but aren't available for your project. Please run `bundle exec fastlane run configure_update` before continuing:\n\n#{new_files}") unless new_files.empty? end ### Validate that the secrets repo doesn't have any local changes def self.validate_that_secrets_repo_is_clean - unless Fastlane::Helper::ConfigureHelper.repo_has_changes - UI.user_error!("The secrets repository has uncommitted changes. Please commit or discard them before continuing.") - end + UI.user_error!('The secrets repository has uncommitted changes. Please commit or discard them before continuing.') unless Fastlane::Helper::ConfigureHelper.repo_has_changes end def self.validate_that_all_copied_files_match - Fastlane::Helper::ConfigureHelper.files_to_copy.each{ |x| - - source = absolute_secret_store_path(x.file) - destination = absolute_project_path(x.destination) + Fastlane::Helper::ConfigureHelper.files_to_copy.each do |x| + source = absolute_secret_store_path(x.file) + destination = absolute_project_path(x.destination) - sourceHash = file_hash(source) - destinationHash = file_hash(destination) + sourceHash = file_hash(source) + destinationHash = file_hash(destination) - unless sourceHash == destinationHash - UI.user_error!("`#{x.destination} doesn't match the file in the secrets repository (#{x.file}) – unable to continue") - end - } + UI.user_error!("`#{x.destination} doesn't match the file in the secrets repository (#{x.file}) – unable to continue") unless sourceHash == destinationHash + end end def self.validate_that_configure_file_exists - unless Fastlane::Helper::ConfigureHelper.configuration_path_exists - UI.user_error!("Couldn't find `.configure` file. Please set up this project for `configure` by running `bundle exec fastlane run configure_setup`") - end + UI.user_error!("Couldn't find `.configure` file. Please set up this project for `configure` by running `bundle exec fastlane run configure_setup`") unless Fastlane::Helper::ConfigureHelper.configuration_path_exists end def self.absolute_project_path(relative_path) @@ -129,15 +115,15 @@ def self.file_hash(absolute_path) end def self.description - "Ensure that the configuration is valid" + 'Ensure that the configuration is valid' end def self.authors - ["Jeremy Massel"] + ['Jeremy Massel'] end def self.details - "Ensure that the configuration is valid" + 'Ensure that the configuration is valid' end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb index ffd0792ee..beaefb587 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_development_certificates_to_provisioning_profiles.rb @@ -7,25 +7,24 @@ def self.run(params) Spaceship.login Spaceship.select_team(team_id: params[:team_id]) - all_certificates = Spaceship.certificate.all(mac: false).select { |certificate| + all_certificates = Spaceship.certificate.all(mac: false).select do |certificate| certificate.owner_type == 'teamMember' - } + end - params[:app_identifier].each { |identifier| + params[:app_identifier].each do |identifier| Spaceship.provisioning_profile.find_by_bundle_id(bundle_id: identifier) - .select { |profile| - profile.kind_of? Spaceship::Portal::ProvisioningProfile::Development - } - .tap { |profiles| - UI.important "Warning: Unable to find any profiles associated with #{identifier}" unless profiles.length > 0 - } - .each { |profile| - profile.certificates = all_certificates - profile.update! - UI.success "Applied #{all_certificates.length} certificates to #{profile.name}" - } - } - + .select do |profile| + profile.is_a? Spaceship::Portal::ProvisioningProfile::Development + end + .tap do |profiles| + UI.important "Warning: Unable to find any profiles associated with #{identifier}" unless profiles.length > 0 + end + .each do |profile| + profile.certificates = all_certificates + profile.update! + UI.success "Applied #{all_certificates.length} certificates to #{profile.name}" + end + end end ##################################################### @@ -33,7 +32,7 @@ def self.run(params) ##################################################### def self.description - "Add dev certificates to provisioning profiles" + 'Add dev certificates to provisioning profiles' end def self.details @@ -43,17 +42,17 @@ def self.details def self.available_options [ FastlaneCore::ConfigItem.new(key: :app_identifier, - description: "List of App Identifiers that should contain the new device identifier", - is_string: false, - verify_block: proc do |value| - UI.user_error!("You must provide an array of bundle identifiers in `app_identifier`") unless not value.empty? - end), + description: 'List of App Identifiers that should contain the new device identifier', + is_string: false, + verify_block: proc do |value| + UI.user_error!('You must provide an array of bundle identifiers in `app_identifier`') if value.empty? + end), FastlaneCore::ConfigItem.new(key: :team_id, - description: "The team_id for the provisioning profiles", - is_string: true, - verify_block: proc do |value| - UI.user_error!("You must provide a team ID in `team_id`") unless (value and not value.empty?) - end), + description: 'The team_id for the provisioning profiles', + is_string: true, + verify_block: proc do |value| + UI.user_error!('You must provide a team ID in `team_id`') unless value && (!value.empty?) + end), ] end @@ -67,7 +66,7 @@ def self.return_value def self.authors # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["jkmassel"] + ['jkmassel'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb index fb7122b92..a661ad8a9 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/add_devices_to_provisioning_profiles.rb @@ -9,20 +9,20 @@ def self.run(params) devices = Spaceship.device.all_ios_profile_devices - params[:app_identifier].each { |identifier| + params[:app_identifier].each do |identifier| Spaceship.provisioning_profile.find_by_bundle_id(bundle_id: identifier) - .select { |profile| - profile.kind_of? Spaceship::Portal::ProvisioningProfile::Development - } - .tap { |profiles| - UI.important "Warning: Unable to find any profiles associated with #{identifier}" unless profiles.length > 0 - } - .each { |profile| - profile.devices = devices - profile.update! - UI.success "Applied #{devices.length} devices to #{profile.name}" - } - } + .select do |profile| + profile.is_a? Spaceship::Portal::ProvisioningProfile::Development + end + .tap do |profiles| + UI.important "Warning: Unable to find any profiles associated with #{identifier}" unless profiles.length > 0 + end + .each do |profile| + profile.devices = devices + profile.update! + UI.success "Applied #{devices.length} devices to #{profile.name}" + end + end end ##################################################### @@ -30,29 +30,29 @@ def self.run(params) ##################################################### def self.description - "Add devices to provisioning profiles" + 'Add devices to provisioning profiles' end def self.details - "Add all iOS devices to any profiles associated with the provided bundle identifiers" + 'Add all iOS devices to any profiles associated with the provided bundle identifiers' end def self.available_options [ FastlaneCore::ConfigItem.new( key: :app_identifier, - description: "List of App Identifiers that should contain the new device identifier", + description: 'List of App Identifiers that should contain the new device identifier', is_string: false, verify_block: proc do |value| - UI.user_error!("You must provide an array of bundle identifiers in `app_identifier`") unless not value.empty? + UI.user_error!('You must provide an array of bundle identifiers in `app_identifier`') if value.empty? end ), FastlaneCore::ConfigItem.new( key: :team_id, - description: "The team_id for the provisioning profiles", + description: 'The team_id for the provisioning profiles', is_string: true, verify_block: proc do |value| - UI.user_error!("You must provide a team ID in `team_id`") unless (value and not value.empty?) + UI.user_error!('You must provide a team ID in `team_id`') unless value && (!value.empty?) end ), ] @@ -68,7 +68,7 @@ def self.return_value def self.authors # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["jkmassel"] + ['jkmassel'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb index 2674df114..a4c6feea3 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_betabuild_prechecks.rb @@ -4,32 +4,30 @@ class IosBetabuildPrechecksAction < Action def self.run(params) UI.message "Skip confirm: #{params[:skip_confirm]}" UI.message "Work on version: #{params[:base_version]}" unless params[:base_version].nil? - + require_relative '../../helper/ios/ios_version_helper.rb' require_relative '../../helper/ios/ios_git_helper.rb' # Checkout develop and update - Fastlane::Helpers::IosGitHelper::git_checkout_and_pull("develop") + Fastlane::Helper::GitHelper.checkout_and_pull('develop') # Check versions - build_version = Fastlane::Helpers::IosVersionHelper::get_build_version + build_version = Fastlane::Helper::Ios::VersionHelper.get_build_version message = "The following current version has been detected: #{build_version}\n" - + # Check branch - app_version = Fastlane::Helpers::IosVersionHelper::get_public_version - UI.user_error!("#{message}Release branch for version #{app_version} doesn't exist. Abort.") unless (!params[:base_version].nil? || Fastlane::Helpers::IosGitHelper::git_checkout_and_pull_release_branch_for(app_version)) - + app_version = Fastlane::Helper::Ios::VersionHelper.get_public_version + UI.user_error!("#{message}Release branch for version #{app_version} doesn't exist. Abort.") unless !params[:base_version].nil? || Fastlane::Helper::GitHelper.checkout_and_pull(release: app_version) + # Check user overwrite build_version = get_user_build_version(params[:base_version], message) unless params[:base_version].nil? - next_version = Fastlane::Helpers::IosVersionHelper::calc_next_build_version(build_version) + next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_build_version(build_version) # Verify message << "Updating branch to version: #{next_version}.\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end @@ -41,8 +39,8 @@ def self.run(params) end def self.get_user_build_version(version, message) - UI.user_error!("Release branch for version #{version} doesn't exist. Abort.") unless Fastlane::Helpers::IosGitHelper::git_checkout_and_pull_release_branch_for(version) - build_version = Fastlane::Helpers::IosVersionHelper::get_build_version + UI.user_error!("Release branch for version #{version} doesn't exist. Abort.") unless Fastlane::Helper::GitHelper.checkout_and_pull(release: version) + build_version = Fastlane::Helper::Ios::VersionHelper.get_build_version message << "Looking at branch release/#{version} as requested by user. Detected version: #{build_version}.\n" build_version end @@ -52,30 +50,29 @@ def self.get_user_build_version(version, message) ##################################################### def self.description - "Runs some prechecks before preparing for a new test build" + 'Runs some prechecks before preparing for a new test build' end def self.details - "Updates the relevant release branch, checks the app version and ensure the branch is clean" + 'Updates the relevant release branch, checks the app version and ensure the branch is clean' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :base_version, - env_name: "FL_IOS_BETABUILD_PRECHECKS_BASE_VERSION", - description: "The version to work on", # a short description of this parameter + env_name: 'FL_IOS_BETABUILD_PRECHECKS_BASE_VERSION', + description: 'The version to work on', # a short description of this parameter is_string: true, optional: true), # true: verifies the input is a string, false: every kind of value), FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_BETABUILD_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one + env_name: 'FL_IOS_BETABUILD_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one ] end def self.output - end def self.return_value @@ -84,7 +81,7 @@ def self.return_value def self.authors # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -92,4 +89,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb index 6c22c0ec3..6513f0919 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_prechecks.rb @@ -4,16 +4,14 @@ class IosBuildPrechecksAction < Action def self.run(params) require_relative '../../helper/ios/ios_version_helper.rb' - message = "" - message << "Building version #{Fastlane::Helpers::IosVersionHelper.get_internal_version()} and uploading to App Center\n" unless !params[:internal] - message << "Building version #{Fastlane::Helpers::IosVersionHelper.get_build_version()} and uploading to App Center\n" unless !params[:internal_on_single_version] - message << "Building version #{Fastlane::Helpers::IosVersionHelper.get_build_version()} and uploading to TestFlight\n" unless !params[:external] + message = '' + message << "Building version #{Fastlane::Helper::Ios::VersionHelper.get_internal_version()} and uploading to App Center\n" if params[:internal] + message << "Building version #{Fastlane::Helper::Ios::VersionHelper.get_build_version()} and uploading to App Center\n" if params[:internal_on_single_version] + message << "Building version #{Fastlane::Helper::Ios::VersionHelper.get_build_version()} and uploading to TestFlight\n" if params[:external] - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end @@ -26,48 +24,46 @@ def self.run(params) ##################################################### def self.description - "Runs some prechecks before the build" + 'Runs some prechecks before the build' end def self.details - "Runs some prechecks before the build" + 'Runs some prechecks before the build' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_BUILD_PRECHECKS_SKIP_CONFIRM", - description: "True to avoid the system ask for confirmation", + env_name: 'FL_IOS_BUILD_PRECHECKS_SKIP_CONFIRM', + description: 'True to avoid the system ask for confirmation', is_string: false, default_value: false), FastlaneCore::ConfigItem.new(key: :internal, - env_name: "FL_IOS_BUILD_PRECHECKS_INTERNAL_BUILD", - description: "True if this is for an internal build", - is_string: false, - default_value: false), + env_name: 'FL_IOS_BUILD_PRECHECKS_INTERNAL_BUILD', + description: 'True if this is for an internal build', + is_string: false, + default_value: false), FastlaneCore::ConfigItem.new(key: :external, - env_name: "FL_IOS_BUILD_PRECHECKS_EXTERNAL_BUILD", - description: "True if this is for a public build", - is_string: false, - default_value: false), + env_name: 'FL_IOS_BUILD_PRECHECKS_EXTERNAL_BUILD', + description: 'True if this is for a public build', + is_string: false, + default_value: false), FastlaneCore::ConfigItem.new(key: :internal_on_single_version, - env_name: "FL_IOS_BUILD_PRECHECKS_INTERNAL_SV_BUILD", - description: "True if this is for an internal build that follows the same versioning of the external", - is_string: false, - default_value: false) + env_name: 'FL_IOS_BUILD_PRECHECKS_INTERNAL_SV_BUILD', + description: 'True if this is for an internal build that follows the same versioning of the external', + is_string: false, + default_value: false), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -75,4 +71,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb index 9c4f60778..ad255cc2d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_build_preflight.rb @@ -2,7 +2,6 @@ module Fastlane module Actions class IosBuildPreflightAction < Action def self.run(params) - # Validate mobile configuration secrets other_action.configure_apply @@ -11,30 +10,30 @@ def self.run(params) # Verify that ImageMagick exists on this machine and can be called from the command-line. # Internal Builds use it to generate the App Icon as part of the build process begin - Action.sh("which convert") + Action.sh('which convert') rescue - UI.user_error!("Couldn't find ImageMagick. Please install it by running `brew install imagemagick`") - raise + UI.user_error!("Couldn't find ImageMagick. Please install it by running `brew install imagemagick`") + raise end # Verify that Ghostscript exists on this machine and can be called from the command-line. # Internal Builds use it to generate the App Icon as part of the build process begin - Action.sh("which gs") + Action.sh('which gs') rescue - UI.user_error!("Couldn't find Ghostscript. Please install it by running `brew install ghostscript`") - raise + UI.user_error!("Couldn't find Ghostscript. Please install it by running `brew install ghostscript`") + raise end # Check gems and pods are up to date. This will exit if it fails begin - Action.sh("bundle check") - rescue + Action.sh('bundle check') + rescue UI.user_error!("You should run 'rake dependencies' to make sure gems are up to date") raise end - Action.sh("rake dependencies:pod:clean") + Action.sh('rake dependencies:pod:clean') other_action.cocoapods() end @@ -43,33 +42,32 @@ def self.run(params) ##################################################### def self.description - "Clean the environment to ensure a safe build" + 'Clean the environment to ensure a safe build' end def self.details - "Clean the environment to ensure a safe build" + 'Clean the environment to ensure a safe build' end def self.available_options [ - FastlaneCore::ConfigItem.new(key: :derived_data_path, - description: "The path to the DerivedData directory for the project. Should match what's used in the `gym` action", - is_string: true, - default_value: "~/Library/Developer/Xcode/DerivedData" - ) + FastlaneCore::ConfigItem.new( + key: :derived_data_path, + description: "The path to the DerivedData directory for the project. Should match what's used in the `gym` action", + is_string: true, + default_value: '~/Library/Developer/Xcode/DerivedData' + ), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb index 56780ca5a..69382bf53 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_beta.rb @@ -2,20 +2,20 @@ module Fastlane module Actions class IosBumpVersionBetaAction < Action def self.run(params) - UI.message "Bumping app release version..." - + UI.message 'Bumping app release version...' + require_relative '../../helper/ios/ios_git_helper.rb' require_relative '../../helper/ios/ios_version_helper.rb' - Fastlane::Helpers::IosGitHelper.check_on_branch("release") + Fastlane::Helper::GitHelper.ensure_on_branch!('release') create_config() show_config() - UI.message "Updating XcConfig..." - Fastlane::Helpers::IosVersionHelper.update_xc_configs(@new_beta_version, @short_version, @new_internal_version) - UI.message "Done!" - - Fastlane::Helpers::IosGitHelper.bump_version_beta + UI.message 'Updating XcConfig...' + Fastlane::Helper::Ios::VersionHelper.update_xc_configs(@new_beta_version, @short_version, @new_internal_version) + UI.message 'Done!' + + Fastlane::Helper::Ios::GitHelper.commit_version_bump(include_deliverfile: false, include_metadata: false) end ##################################################### @@ -23,48 +23,46 @@ def self.run(params) ##################################################### def self.description - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.details - "Bumps the version of the app for a new beta" + 'Bumps the version of the app for a new beta' end def self.available_options - end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) platform == :ios end - private - def self.create_config() - @current_version = Fastlane::Helpers::IosVersionHelper.get_build_version() - @current_version_internal = Fastlane::Helpers::IosVersionHelper.get_internal_version() unless ENV["INTERNAL_CONFIG_FILE"].nil? - @new_internal_version = Fastlane::Helpers::IosVersionHelper.create_internal_version(@current_version) unless ENV["INTERNAL_CONFIG_FILE"].nil? - @new_beta_version = Fastlane::Helpers::IosVersionHelper.calc_next_build_version(@current_version) - @short_version = Fastlane::Helpers::IosVersionHelper.get_short_version_string(@new_beta_version) + private + + def self.create_config + @current_version = Fastlane::Helper::Ios::VersionHelper.get_build_version() + @current_version_internal = Fastlane::Helper::Ios::VersionHelper.get_internal_version() unless ENV['INTERNAL_CONFIG_FILE'].nil? + @new_internal_version = Fastlane::Helper::Ios::VersionHelper.create_internal_version(@current_version) unless ENV['INTERNAL_CONFIG_FILE'].nil? + @new_beta_version = Fastlane::Helper::Ios::VersionHelper.calc_next_build_version(@current_version) + @short_version = Fastlane::Helper::Ios::VersionHelper.get_short_version_string(@new_beta_version) end - def self.show_config() + def self.show_config UI.message("Current build version: #{@current_version}") - UI.message("Current internal version: #{@current_version_internal}") unless ENV["INTERNAL_CONFIG_FILE"].nil? + UI.message("Current internal version: #{@current_version_internal}") unless ENV['INTERNAL_CONFIG_FILE'].nil? UI.message("New beta version: #{@new_beta_version}") - UI.message("New internal version: #{@new_internal_version}") unless ENV["INTERNAL_CONFIG_FILE"].nil? + UI.message("New internal version: #{@new_internal_version}") unless ENV['INTERNAL_CONFIG_FILE'].nil? end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb index 95b760ead..fb7fa285f 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_hotfix.rb @@ -2,23 +2,23 @@ module Fastlane module Actions class IosBumpVersionHotfixAction < Action def self.run(params) - UI.message "Bumping app release version for hotfix..." - + UI.message 'Bumping app release version for hotfix...' + require_relative '../../helper/ios/ios_git_helper.rb' - Fastlane::Helpers::IosGitHelper.branch_for_hotfix(params[:previous_version], params[:version]) + Fastlane::Helper::GitHelper.create_branch("release/#{params[:version]}", from: params[:previous_version]) create_config(params[:previous_version], params[:version]) show_config() - - UI.message "Updating Fastlane deliver file..." - Fastlane::Helpers::IosVersionHelper.update_fastlane_deliver(@new_short_version) - UI.message "Done!" - UI.message "Updating XcConfig..." - Fastlane::Helpers::IosVersionHelper.update_xc_configs(@new_version, @new_short_version, @new_version_internal) - UI.message "Done!" - - Fastlane::Helpers::IosGitHelper.bump_version_hotfix(params[:version]) - - UI.message "Done." + + UI.message 'Updating Fastlane deliver file...' + Fastlane::Helper::Ios::VersionHelper.update_fastlane_deliver(@new_short_version) + UI.message 'Done!' + UI.message 'Updating XcConfig...' + Fastlane::Helper::Ios::VersionHelper.update_xc_configs(@new_version, @new_short_version, @new_version_internal) + UI.message 'Done!' + + Fastlane::Helper::Ios::GitHelper.commit_version_bump(include_deliverfile: true, include_metadata: false) + + UI.message 'Done.' end ##################################################### @@ -26,60 +26,59 @@ def self.run(params) ##################################################### def self.description - "Bumps the version of the app and creates the new release branch" + 'Bumps the version of the app and creates the new release branch' end def self.details - "Bumps the version of the app and creates the new release branch" + 'Bumps the version of the app and creates the new release branch' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :version, - env_name: "FL_IOS_BUMP_VERSION_HOTFIX_VERSION", - description: "The version of the hotfix", + env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_VERSION', + description: 'The version of the hotfix', is_string: true), FastlaneCore::ConfigItem.new(key: :previous_version, - env_name: "FL_IOS_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION", - description: "The version to branch from", - is_string: true) # the default value if the user didn't provide one + env_name: 'FL_IOS_BUMP_VERSION_HOTFIX_PREVIOUS_VERSION', + description: 'The version to branch from', + is_string: true), # the default value if the user didn't provide one ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) platform == :ios end - private + private + def self.create_config(previous_version, new_short_version) @current_version = previous_version - @current_version_internal = Fastlane::Helpers::IosVersionHelper.get_internal_version() unless ENV["INTERNAL_CONFIG_FILE"].nil? + @current_version_internal = Fastlane::Helper::Ios::VersionHelper.get_internal_version() unless ENV['INTERNAL_CONFIG_FILE'].nil? @new_version = "#{new_short_version}.0" - @new_version_internal = Fastlane::Helpers::IosVersionHelper.create_internal_version(@new_version) unless ENV["INTERNAL_CONFIG_FILE"].nil? + @new_version_internal = Fastlane::Helper::Ios::VersionHelper.create_internal_version(@new_version) unless ENV['INTERNAL_CONFIG_FILE'].nil? @new_short_version = new_short_version @new_release_branch = "release/#{@new_short_version}" end - def self.show_config() + def self.show_config UI.message("Current build version: #{@current_version}") - UI.message("Current internal version: #{@current_version_internal}") unless ENV["INTERNAL_CONFIG_FILE"].nil? + UI.message("Current internal version: #{@current_version_internal}") unless ENV['INTERNAL_CONFIG_FILE'].nil? UI.message("New build version: #{@new_version}") - UI.message("New internal version: #{@new_version_internal}") unless ENV["INTERNAL_CONFIG_FILE"].nil? + UI.message("New internal version: #{@new_version_internal}") unless ENV['INTERNAL_CONFIG_FILE'].nil? UI.message("New short version: #{@new_short_version}") UI.message("Release branch: #{@new_release_branch}") end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb index b8283996d..d770d903e 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_bump_version_release.rb @@ -1,113 +1,114 @@ module Fastlane - module Actions - class IosBumpVersionReleaseAction < Action - def self.run(params) - # fastlane will take care of reading in the parameter and fetching the environment variable: - UI.message "Bumping app release version..." - - require_relative '../../helper/ios/ios_version_helper.rb' - require_relative '../../helper/ios/ios_git_helper.rb' - - other_action.ensure_git_branch(branch: "develop") - - # Create new configuration - @new_version = Fastlane::Helpers::IosVersionHelper.bump_version_release() - create_config() - show_config() - - # Update local develop and branch - Fastlane::Helpers::IosGitHelper.git_checkout_and_pull("develop") - Fastlane::Helpers::IosGitHelper.do_release_branch(@new_release_branch) - UI.message "Done!" - - UI.message "Updating glotPressKeys..." unless params[:skip_glotpress] - update_glotpress_key unless params [:skip_glotpress] - UI.message "Done" unless params [:skip_glotpress] - - UI.message "Updating Fastlane deliver file..." unless params[:skip_deliver] - Fastlane::Helpers::IosVersionHelper.update_fastlane_deliver(@new_short_version) unless params[:skip_deliver] - UI.message "Done!" unless params [:skip_deliver] - - UI.message "Updating XcConfig..." - Fastlane::Helpers::IosVersionHelper.update_xc_configs(@new_version, @new_short_version, @new_version_internal) - UI.message "Done!" - - Fastlane::Helpers::IosGitHelper.bump_version_release(params[:skip_deliver], params[:skip_glotpress]) - - UI.message "Done." - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Bumps the version of the app and creates the new release branch" - end - - def self.details - "Bumps the version of the app and creates the new release branch" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :skip_glotpress, - env_name: "FL_IOS_CODEFREEZE_BUMP_SKIPGLOTPRESS", - description: "Skips GlotPress key update", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false), # the default value if the user didn't provide one - FastlaneCore::ConfigItem.new(key: :skip_deliver, - env_name: "FL_IOS_CODEFREEZE_BUMP_SKIPDELIVER", - description: "Skips Deliver key update", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false), # the default value if the user didn't provide one - - ] - end - - def self.output - - end - - def self.return_value - - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :ios - end + module Actions + class IosBumpVersionReleaseAction < Action + def self.run(params) + # fastlane will take care of reading in the parameter and fetching the environment variable: + UI.message 'Bumping app release version...' + require_relative '../../helper/ios/ios_version_helper.rb' + require_relative '../../helper/ios/ios_git_helper.rb' - private - def self.create_config() - @current_version = Fastlane::Helpers::IosVersionHelper.get_build_version() - @current_version_internal = Fastlane::Helpers::IosVersionHelper.get_internal_version() unless ENV["INTERNAL_CONFIG_FILE"].nil? - @new_version_internal = Fastlane::Helpers::IosVersionHelper.create_internal_version(@new_version) unless ENV["INTERNAL_CONFIG_FILE"].nil? - @new_short_version = Fastlane::Helpers::IosVersionHelper.get_short_version_string(@new_version) - @new_release_branch = "release/#{@new_short_version}" - end + other_action.ensure_git_branch(branch: 'develop') - def self.show_config() - UI.message("Current build version: #{@current_version}") - UI.message("Current internal version: #{@current_version_internal}") unless ENV["INTERNAL_CONFIG_FILE"].nil? - UI.message("New build version: #{@new_version}") - UI.message("New internal version: #{@new_version_internal}") unless ENV["INTERNAL_CONFIG_FILE"].nil? - UI.message("New short version: #{@new_short_version}") - UI.message("Release branch: #{@new_release_branch}") - end + # Create new configuration + @new_version = Fastlane::Helper::Ios::VersionHelper.bump_version_release() + create_config() + show_config() + + # Update local develop and branch + Fastlane::Helper::GitHelper.checkout_and_pull('develop') + Fastlane::Helper::GitHelper.create_branch(@new_release_branch, from: 'develop') + UI.message 'Done!' + + UI.message 'Updating glotPressKeys...' unless params[:skip_glotpress] + update_glotpress_key unless params [:skip_glotpress] + UI.message 'Done' unless params [:skip_glotpress] + + UI.message 'Updating Fastlane deliver file...' unless params[:skip_deliver] + Fastlane::Helper::Ios::VersionHelper.update_fastlane_deliver(@new_short_version) unless params[:skip_deliver] + UI.message 'Done!' unless params [:skip_deliver] + + UI.message 'Updating XcConfig...' + Fastlane::Helper::Ios::VersionHelper.update_xc_configs(@new_version, @new_short_version, @new_version_internal) + UI.message 'Done!' + + Fastlane::Helper::Ios::GitHelper.commit_version_bump( + include_deliverfile: !params[:skip_deliver], + include_metadata: !params[:skip_glotpress] + ) + + UI.message 'Done.' + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Bumps the version of the app and creates the new release branch' + end + + def self.details + 'Bumps the version of the app and creates the new release branch' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :skip_glotpress, + env_name: 'FL_IOS_CODEFREEZE_BUMP_SKIPGLOTPRESS', + description: 'Skips GlotPress key update', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + FastlaneCore::ConfigItem.new(key: :skip_deliver, + env_name: 'FL_IOS_CODEFREEZE_BUMP_SKIPDELIVER', + description: 'Skips Deliver key update', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + + ] + end + + def self.output + end + + def self.return_value + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :ios + end + + private + + def self.create_config + @current_version = Fastlane::Helper::Ios::VersionHelper.get_build_version() + @current_version_internal = Fastlane::Helper::Ios::VersionHelper.get_internal_version() unless ENV['INTERNAL_CONFIG_FILE'].nil? + @new_version_internal = Fastlane::Helper::Ios::VersionHelper.create_internal_version(@new_version) unless ENV['INTERNAL_CONFIG_FILE'].nil? + @new_short_version = Fastlane::Helper::Ios::VersionHelper.get_short_version_string(@new_version) + @new_release_branch = "release/#{@new_short_version}" + end + + def self.show_config + UI.message("Current build version: #{@current_version}") + UI.message("Current internal version: #{@current_version_internal}") unless ENV['INTERNAL_CONFIG_FILE'].nil? + UI.message("New build version: #{@new_version}") + UI.message("New internal version: #{@new_version_internal}") unless ENV['INTERNAL_CONFIG_FILE'].nil? + UI.message("New short version: #{@new_short_version}") + UI.message("Release branch: #{@new_release_branch}") + end - def self.update_glotpress_key() - dm_file = ENV["DOWNLOAD_METADATA"] - if (File.exist?(dm_file)) then - sh("sed -i '' \"s/let glotPressWhatsNewKey.*/let glotPressWhatsNewKey = \\\"v#{@new_short_version}-whats-new\\\"/\" #{dm_file}") - else - UI.user_error!("Can't find #{dm_file}.") - end + def self.update_glotpress_key + dm_file = ENV['DOWNLOAD_METADATA'] + if File.exist?(dm_file) + sh("sed -i '' \"s/let glotPressWhatsNewKey.*/let glotPressWhatsNewKey = \\\"v#{@new_short_version}-whats-new\\\"/\" #{dm_file}") + else + UI.user_error!("Can't find #{dm_file}.") end end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb index 8d681609c..60500ebca 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_check_beta_deps.rb @@ -1,63 +1,62 @@ module Fastlane - module Actions - class IosCheckBetaDepsAction < Action - def self.run(params) - require_relative '../../helper/ios/ios_version_helper.rb' - require_relative '../../helper/ios/ios_git_helper.rb' - - beta_pods = [] - File.open(params[:podfile]).each do | li | - beta_pods << li if (li.match('^\s*\t*pod.*beta')) - end - - if beta_pods.count == 0 - UI.message("No beta pods found. You can continue with the code freeze.") - else - message = "The following pods are still in beta:\n" - beta_pods.each do | bpod | - message << "#{bpod}\n" - end - message << "Please update to the released version before continuing with the code freeze." - end - UI.important(message) - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before finalizing a release" - end - - def self.details - "Runs some prechecks before finalizing a release" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :podfile, - env_name: "FL_IOS_CHECKBETADEPS_PODFILE", - description: "Path to the Podfile to analyse", - is_string: true), - ] - end - - def self.output - - end - - def self.return_value - "" - end - - def self.authors - ["loremattei"] + module Actions + class IosCheckBetaDepsAction < Action + def self.run(params) + require_relative '../../helper/ios/ios_version_helper.rb' + require_relative '../../helper/ios/ios_git_helper.rb' + + beta_pods = [] + File.open(params[:podfile]).each do |li| + beta_pods << li if li.match('^\s*\t*pod.*beta') end - - def self.is_supported?(platform) - platform == :ios + + if beta_pods.count == 0 + UI.message('No beta pods found. You can continue with the code freeze.') + else + message = "The following pods are still in beta:\n" + beta_pods.each do |bpod| + message << "#{bpod}\n" + end + message << 'Please update to the released version before continuing with the code freeze.' end + UI.important(message) + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before finalizing a release' + end + + def self.details + 'Runs some prechecks before finalizing a release' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :podfile, + env_name: 'FL_IOS_CHECKBETADEPS_PODFILE', + description: 'Path to the Podfile to analyse', + is_string: true), + ] + end + + def self.output + end + + def self.return_value + '' + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :ios end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb index fff2c0340..3f7cd0963 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_clear_intermediate_tags.rb @@ -3,10 +3,20 @@ module Actions class IosClearIntermediateTagsAction < Action def self.run(params) UI.message("Deleting tags for version: #{params[:version]}") - - require_relative '../../helper/ios/ios_git_helper.rb' - Fastlane::Helpers::IosGitHelper.delete_tags(params[:version]) + require_relative '../../helper/git_helper.rb' + Fastlane::Helper::Ios::GitHelper.delete_tags(params[:version]) + + # Cleanup local tags and refetch them to make sure we're up-to-date with remote + local_tags = Fastlane::Helper::GitHelper.list_local_tags() + Fastlane::Helper::GitHelper.delete_tags(local_tags, delete_on_remote: true) + Fastlane::Helper::GitHelper.fetch_all_tags() + + # Now delete intermediate tags (4-parts version names starting with our version number) + parts = params[:version].split('.') + pattern = parts.fill('*', parts.length...4).join('.') # "1.2.*.*" or "1.2.3.*" + intermediate_tags = Fastlane::Helper::GitHelper.list_local_tags(matching: pattern) + Fastlane::Helper::GitHelper.delete_tags(intermediate_tags, delete_on_remote: true) end ##################################################### @@ -14,32 +24,30 @@ def self.run(params) ##################################################### def self.description - "Cleans all the intermediate tags for the given version" + 'Cleans all the intermediate tags for the given version' end def self.details - "Cleans all the intermediate tags for the given version" + 'Cleans all the intermediate tags for the given version' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :version, - env_name: "FL_IOS_CLEAN_INTERMEDIATE_TAGS_VERSION", - description: "The version of the tags to clear", - is_string: true) + env_name: 'FL_IOS_CLEAN_INTERMEDIATE_TAGS_VERSION', + description: 'The version of the tags to clear', + is_string: true), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -47,4 +55,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb index e6f0f417e..311e0d0d5 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_codefreeze_prechecks.rb @@ -1,73 +1,70 @@ module Fastlane - module Actions - class IosCodefreezePrechecksAction < Action - def self.run(params) - # fastlane will take care of reading in the parameter and fetching the environment variable: - UI.message "Skip confirm on code freeze: #{params[:skip_confirm]}" - - require_relative '../../helper/ios/ios_version_helper.rb' - require_relative '../../helper/ios/ios_git_helper.rb' - - # Checkout develop and update - Fastlane::Helpers::IosGitHelper.git_checkout_and_pull("develop") - - # Create versions - current_version = Fastlane::Helpers::IosVersionHelper.get_public_version - current_build_version = Fastlane::Helpers::IosVersionHelper.get_build_version - next_version = Fastlane::Helpers::IosVersionHelper.calc_next_release_version(current_version) - - # Ask user confirmation - if (!params[:skip_confirm]) - if (!UI.confirm("Building a new release branch starting from develop.\nCurrent version is #{current_version} (#{current_build_version}).\nAfter codefreeze the new version will be: #{next_version}.\nDo you want to continue?")) - UI.user_error!("Aborted by user request") - end - end - - # Check local repo status - other_action.ensure_git_status_clean() - - # Return the current version - current_version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before code freeze" - end - - def self.details - "Updates the develop branch, checks the app version and ensure the branch is clean" - end - - def self.available_options - # Define all options your action supports. - [ - FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_CODEFREEZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation before codefreeze", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one - ] - end - - def self.output - - end - - def self.return_value - "Version of the app before code freeze" - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :ios + module Actions + class IosCodefreezePrechecksAction < Action + def self.run(params) + # fastlane will take care of reading in the parameter and fetching the environment variable: + UI.message "Skip confirm on code freeze: #{params[:skip_confirm]}" + + require_relative '../../helper/ios/ios_version_helper.rb' + require_relative '../../helper/ios/ios_git_helper.rb' + + # Checkout develop and update + Fastlane::Helper::GitHelper.checkout_and_pull('develop') + + # Create versions + current_version = Fastlane::Helper::Ios::VersionHelper.get_public_version + current_build_version = Fastlane::Helper::Ios::VersionHelper.get_build_version + next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(current_version) + + # Ask user confirmation + unless params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("Building a new release branch starting from develop.\nCurrent version is #{current_version} (#{current_build_version}).\nAfter codefreeze the new version will be: #{next_version}.\nDo you want to continue?") end + + # Check local repo status + other_action.ensure_git_status_clean() + + # Return the current version + current_version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before code freeze' + end + + def self.details + 'Updates the develop branch, checks the app version and ensure the branch is clean' + end + + def self.available_options + # Define all options your action supports. + [ + FastlaneCore::ConfigItem.new(key: :skip_confirm, + env_name: 'FL_IOS_CODEFREEZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation before codefreeze', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + ] + end + + def self.output + end + + def self.return_value + 'Version of the app before code freeze' + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :ios end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb index 21c85c7cb..a07abfb09 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_completecodefreeze_prechecks.rb @@ -1,67 +1,63 @@ module Fastlane - module Actions - class IosCompletecodefreezePrechecksAction < Action - def self.run(params) - UI.message "Skip confirm: #{params[:skip_confirm]}" - - require_relative '../../helper/ios/ios_version_helper.rb' - require_relative '../../helper/ios/ios_git_helper.rb' - - UI.user_error!("This is not a release branch. Abort.") unless other_action.git_branch.start_with?("release/") - - version = Fastlane::Helpers::IosVersionHelper::get_public_version - message = "Completing code freeze for: #{version}\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else - UI.message(message) - end - - # Check local repo status - other_action.ensure_git_status_clean() - - version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Runs some prechecks before finalizing a code freeze" - end - - def self.details - "Runs some prechecks before finalizing a code freeze" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_COMPLETECODEFREEZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one - ] - end - - def self.output - - end - - def self.return_value - - end - - def self.authors - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :ios - end + module Actions + class IosCompletecodefreezePrechecksAction < Action + def self.run(params) + UI.message "Skip confirm: #{params[:skip_confirm]}" + + require_relative '../../helper/ios/ios_version_helper.rb' + require_relative '../../helper/ios/ios_git_helper.rb' + + UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/') + + version = Fastlane::Helper::Ios::VersionHelper.get_public_version + message = "Completing code freeze for: #{version}\n" + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else + UI.message(message) + end + + # Check local repo status + other_action.ensure_git_status_clean() + + version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Runs some prechecks before finalizing a code freeze' + end + + def self.details + 'Runs some prechecks before finalizing a code freeze' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new(key: :skip_confirm, + env_name: 'FL_IOS_COMPLETECODEFREEZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one + ] + end + + def self.output + end + + def self.return_value + end + + def self.authors + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :ios end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb index bfa2bbdab..e2213fdd0 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_current_branch_is_hotfix.rb @@ -3,7 +3,7 @@ module Actions class IosCurrentBranchIsHotfixAction < Action def self.run(params) require_relative '../../helper/ios/ios_version_helper.rb' - Fastlane::Helpers::IosVersionHelper::is_hotfix(Fastlane::Helpers::IosVersionHelper::get_public_version) + Fastlane::Helper::Ios::VersionHelper.is_hotfix?(Fastlane::Helper::Ios::VersionHelper.get_public_version) end ##################################################### @@ -11,27 +11,25 @@ def self.run(params) ##################################################### def self.description - "Checks if the current branch is for a hotfix" + 'Checks if the current branch is for a hotfix' end def self.details - "Checks if the current branch is for a hotfix" + 'Checks if the current branch is for a hotfix' end def self.available_options - end def self.output - end def self.return_value - "True if the branch is for a hotfix, false otherwise" + 'True if the branch is for a hotfix, false otherwise' end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -39,4 +37,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb index 6b322d745..ab7bdcfa2 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_final_tag.rb @@ -4,12 +4,12 @@ class IosFinalTagAction < Action def self.run(params) require_relative '../../helper/ios/ios_git_helper.rb' require_relative '../../helper/ios/ios_version_helper.rb' - version = Fastlane::Helpers::IosVersionHelper::get_public_version - + version = Fastlane::Helper::Ios::VersionHelper.get_public_version + UI.message("Tagging final #{version}...") - Fastlane::Helpers::IosGitHelper.final_tag(version) - + Fastlane::Helper::GitHelper.create_tag(version) + other_action.ios_clear_intermediate_tags(version: version) end @@ -18,32 +18,30 @@ def self.run(params) ##################################################### def self.description - "Finalize a relasae" + 'Finalize a relasae' end def self.details - "Removes the temp tags and pushes the final one" + 'Removes the temp tags and pushes the final one' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :version, - env_name: "FL_IOS_FINAL_TAG_VERSION", - description: "The version of the release to finalize", - is_string: true) + env_name: 'FL_IOS_FINAL_TAG_VERSION', + description: 'The version of the release to finalize', + is_string: true), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -51,4 +49,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb index 8e999896c..7fa33c312 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_finalize_prechecks.rb @@ -3,19 +3,17 @@ module Actions class IosFinalizePrechecksAction < Action def self.run(params) UI.message "Skip confirm: #{params[:skip_confirm]}" - + require_relative '../../helper/ios/ios_version_helper.rb' require_relative '../../helper/ios/ios_git_helper.rb' - UI.user_error!("This is not a release branch. Abort.") unless other_action.git_branch.start_with?("release/") + UI.user_error!('This is not a release branch. Abort.') unless other_action.git_branch.start_with?('release/') - version = Fastlane::Helpers::IosVersionHelper::get_public_version + version = Fastlane::Helper::Ios::VersionHelper.get_public_version message = "Finalizing release: #{version}\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end @@ -30,33 +28,32 @@ def self.run(params) ##################################################### def self.description - "Runs some prechecks before finalizing a release" + 'Runs some prechecks before finalizing a release' end def self.details - "Runs some prechecks before finalizing a release" + 'Runs some prechecks before finalizing a release' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_FINALIZE_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", + env_name: 'FL_IOS_FINALIZE_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one + default_value: false), # the default value if the user didn't provide one ] end def self.output - end def self.return_value - "The current app version" + 'The current app version' end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -64,4 +61,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb index 6864613ee..c798d9f71 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_app_version.rb @@ -1,45 +1,44 @@ module Fastlane - module Actions - class IosGetAppVersionAction < Action - def self.run(params) - require_relative '../../helper/ios/ios_version_helper.rb' - Fastlane::Helpers::IosVersionHelper::get_public_version - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Gets the public version of the app" - end - - def self.details - "Gets the public version of the app" - end - - def self.available_options - # Define all options your action supports. - end - - def self.output - # Define the shared values you are going to provide - - end - - def self.return_value - # If you method provides a return value, you can describe here what it does - "Return the public version of the app" - end - - def self.authors - # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["loremattei"] - end - - def self.is_supported?(platform) - platform == :ios - end + module Actions + class IosGetAppVersionAction < Action + def self.run(params) + require_relative '../../helper/ios/ios_version_helper.rb' + Fastlane::Helper::Ios::VersionHelper.get_public_version + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Gets the public version of the app' + end + + def self.details + 'Gets the public version of the app' + end + + def self.available_options + # Define all options your action supports. + end + + def self.output + # Define the shared values you are going to provide + end + + def self.return_value + # If you method provides a return value, you can describe here what it does + 'Return the public version of the app' + end + + def self.authors + # So no one will ever forget your contribution to fastlane :) You are awesome btw! + ['loremattei'] + end + + def self.is_supported?(platform) + platform == :ios end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb index 2c4c57885..3abeed81d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_get_store_app_sizes.rb @@ -1,123 +1,121 @@ require_relative '../../helper/ios/ios_adc_app_sizes_helper.rb' module Fastlane - module Actions - class IosGetStoreAppSizesAction < Action - Helper = Fastlane::Helpers::IosADCAppSizesHelper + module Actions + class IosGetStoreAppSizesAction < Action + Helper = Fastlane::Helper::Ios::ADCAppSizesHelper - def self.run(params) - app_sizes = Helper::get_adc_sizes( - adc_user: params[:adc_user], - adc_team: params[:adc_team], - bundle_id: params[:bundle_id], - only_version: params[:version], - limit: params[:limit] - ) + def self.run(params) + app_sizes = Helper.get_adc_sizes( + adc_user: params[:adc_user], + adc_team: params[:adc_team], + bundle_id: params[:bundle_id], + only_version: params[:version], + limit: params[:limit] + ) - devices = params[:devices] + devices = params[:devices] - case params[:format] - when 'csv' - csv = Helper::format_csv(app_sizes, devices: devices) - UI.message "Result (CSV)\n\n#{csv}\n" - when 'markdown' - tables = Helper::format_markdown(app_sizes, devices: devices) - tables.each do |table| - UI.message "Result (Markdown)\n\n#{table}\n" - end + case params[:format] + when 'csv' + csv = Helper.format_csv(app_sizes, devices: devices) + UI.message "Result (CSV)\n\n#{csv}\n" + when 'markdown' + tables = Helper.format_markdown(app_sizes, devices: devices) + tables.each do |table| + UI.message "Result (Markdown)\n\n#{table}\n" end - - return app_sizes - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Gets the size of the app as reported in Apple Developer Portal for recent versions" - end - - def self.details - "Gets the download + installed size of the app from the Apple Developer Portail for various app versions release to AppStore and various device types" - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new( - key: :adc_user, - env_name: "FL_IOS_STOREAPPSIZES_USER", - description: "The ADC user to use to log into ADC", - type: String - ), - FastlaneCore::ConfigItem.new( - key: :adc_team, - env_name: "FL_IOS_STOREAPPSIZES_TEAM", - description: "The ADC team name to use to log into ADC", - type: String, - optional: true, - default_value: "Automattic, Inc." - ), - FastlaneCore::ConfigItem.new( - key: :bundle_id, - env_name: "FL_IOS_STOREAPPSIZES_BUNDLEID", - description: "The bundleID of the app to retrieve sizes from", - type: String - ), - FastlaneCore::ConfigItem.new( - key: :version, - env_name: "FL_IOS_STOREAPPSIZES_VERSION", - description: "The version to retrive the data for. Keep nil to retrieve data for all the last {limit} versions", - type: String, - optional: true - ), - FastlaneCore::ConfigItem.new( - key: :limit, - env_name: "FL_IOS_STOREAPPSIZES_LIMIT", - description: "The maximum number of past versions to retrieve information from", - type: Integer, - optional: true, - default_value: 10 - ), - FastlaneCore::ConfigItem.new( - key: :devices, - env_name: "FL_IOS_STOREAPPSIZES_DEVICES", - description: "The list of devices to print the app size for. If nil, will print data for all device types returned by ADC", - type: Array, - optional: true - ), - FastlaneCore::ConfigItem.new( - key: :format, - env_name: "FL_IOS_STOREAPPSIZES_FORMAT", - description: "The output format used to print the result. Can be one of 'csv' or 'markdown', or nil to print nothing (raw data will always be available as the the action's return value)", - type: String, - optional: true, - ), - ] - end - - def self.output - # Define the shared values you are going to provide - end - def self.return_type - :hash - end - - def self.return_value - "Return a Hash containing the details of download and install app size, for various device models, all that for each requested version of the app" - end - - def self.authors - # So no one will ever forget your contribution to fastlane :) You are awesome btw! - ["AliSoftware"] - end - - def self.is_supported?(platform) - [:ios, :mac].include?(platform) - end + return app_sizes + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Gets the size of the app as reported in Apple Developer Portal for recent versions' + end + + def self.details + 'Gets the download + installed size of the app from the Apple Developer Portail for various app versions release to AppStore and various device types' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new( + key: :adc_user, + env_name: 'FL_IOS_STOREAPPSIZES_USER', + description: 'The ADC user to use to log into ADC', + type: String + ), + FastlaneCore::ConfigItem.new( + key: :adc_team, + env_name: 'FL_IOS_STOREAPPSIZES_TEAM', + description: 'The ADC team name to use to log into ADC', + type: String, + optional: true, + default_value: 'Automattic, Inc.' + ), + FastlaneCore::ConfigItem.new( + key: :bundle_id, + env_name: 'FL_IOS_STOREAPPSIZES_BUNDLEID', + description: 'The bundleID of the app to retrieve sizes from', + type: String + ), + FastlaneCore::ConfigItem.new( + key: :version, + env_name: 'FL_IOS_STOREAPPSIZES_VERSION', + description: 'The version to retrive the data for. Keep nil to retrieve data for all the last {limit} versions', + type: String, + optional: true + ), + FastlaneCore::ConfigItem.new( + key: :limit, + env_name: 'FL_IOS_STOREAPPSIZES_LIMIT', + description: 'The maximum number of past versions to retrieve information from', + type: Integer, + optional: true, + default_value: 10 + ), + FastlaneCore::ConfigItem.new( + key: :devices, + env_name: 'FL_IOS_STOREAPPSIZES_DEVICES', + description: 'The list of devices to print the app size for. If nil, will print data for all device types returned by ADC', + type: Array, + optional: true + ), + FastlaneCore::ConfigItem.new( + key: :format, + env_name: 'FL_IOS_STOREAPPSIZES_FORMAT', + description: "The output format used to print the result. Can be one of 'csv' or 'markdown', or nil to print nothing (raw data will always be available as the the action's return value)", + type: String, + optional: true + ), + ] + end + + def self.output + # Define the shared values you are going to provide + end + + def self.return_type + :hash + end + + def self.return_value + 'Return a Hash containing the details of download and install app size, for various device models, all that for each requested version of the app' + end + + def self.authors + # So no one will ever forget your contribution to fastlane :) You are awesome btw! + ['AliSoftware'] + end + + def self.is_supported?(platform) + [:ios, :mac].include?(platform) end end end - +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_hotifx_prechecks.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_hotifx_prechecks.rb index d3240a064..6df1ce590 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_hotifx_prechecks.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_hotifx_prechecks.rb @@ -3,35 +3,29 @@ module Actions class IosHotfixPrechecksAction < Action def self.run(params) UI.message "Skip confirm: #{params[:skip_confirm]}" - UI.message "" + UI.message '' require_relative '../../helper/ios/ios_version_helper.rb' require_relative '../../helper/ios/ios_git_helper.rb' # Evaluate previous tag new_ver = params[:version] - prev_ver = Fastlane::Helpers::IosVersionHelper::calc_prev_hotfix_version(new_ver) + prev_ver = Fastlane::Helper::Ios::VersionHelper.calc_prev_hotfix_version(new_ver) # Confirm message = "Requested Hotfix version: #{new_ver}\n" message << "Branching from: #{prev_ver}\n" - if (!params[:skip_confirm]) - if (!UI.confirm("#{message}Do you want to continue?")) - UI.user_error!("Aborted by user request") - end - else + if !params[:skip_confirm] + UI.user_error!('Aborted by user request') unless UI.confirm("#{message}Do you want to continue?") + else UI.message(message) end # Check tags - if other_action.git_tag_exists(tag: new_ver) - UI.crash!("Version #{new_ver} already exists! Abort!") - end + UI.crash!("Version #{new_ver} already exists! Abort!") if other_action.git_tag_exists(tag: new_ver) - if !other_action.git_tag_exists(tag: prev_ver) - UI.crash!("Version #{prev_ver} is not tagged! Can't branch. Abort!") - end + UI.crash!("Version #{prev_ver} is not tagged! Can't branch. Abort!") unless other_action.git_tag_exists(tag: prev_ver) # Check local repo status other_action.ensure_git_status_clean() @@ -45,37 +39,35 @@ def self.run(params) ##################################################### def self.description - "Runs some prechecks before preparing for a new hotfix" + 'Runs some prechecks before preparing for a new hotfix' end def self.details - "Checks out a new branch from a tag and updates tags" + 'Checks out a new branch from a tag and updates tags' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :version, - env_name: "FL_IOS_HOTFIX_PRECHECKS_VERSION", - description: "The version to work on", # a short description of this parameter + env_name: 'FL_IOS_HOTFIX_PRECHECKS_VERSION', + description: 'The version to work on', # a short description of this parameter is_string: true), FastlaneCore::ConfigItem.new(key: :skip_confirm, - env_name: "FL_IOS_HOTFIX_PRECHECKS_SKIPCONFIRM", - description: "Skips confirmation", - is_string: false, # true: verifies the input is a string, false: every kind of value - default_value: false) # the default value if the user didn't provide one + env_name: 'FL_IOS_HOTFIX_PRECHECKS_SKIPCONFIRM', + description: 'Skips confirmation', + is_string: false, # true: verifies the input is a string, false: every kind of value + default_value: false), # the default value if the user didn't provide one ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb index af6697203..f0eefa2fa 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_lint_localizations.rb @@ -1,169 +1,167 @@ module Fastlane - module Actions - class IosLintLocalizationsAction < Action - def self.run(params) - violations = {} + module Actions + class IosLintLocalizationsAction < Action + def self.run(params) + violations = {} - loop do - violations = self.run_linter(params) - break unless !violations.empty? && params[:allow_retry] && UI.confirm(RETRY_MESSAGE) - end + loop do + violations = self.run_linter(params) + break unless !violations.empty? && params[:allow_retry] && UI.confirm(RETRY_MESSAGE) + end - if !violations.empty? && params[:abort_on_violations] - UI.abort_with_message!(ABORT_MESSAGE) - end + UI.abort_with_message!(ABORT_MESSAGE) if !violations.empty? && params[:abort_on_violations] - violations - end + violations + end + + def self.run_linter(params) + UI.message 'Linting localizations for parameter placeholders consistency...' + + require_relative '../../helper/ios/ios_l10n_helper.rb' + helper = Fastlane::Helper::Ios::L10nHelper.new( + install_path: resolve_path(params[:install_path]), + version: params[:version] + ) + violations = helper.run( + input_dir: resolve_path(params[:input_dir]), + base_lang: params[:base_lang], + only_langs: params[:only_langs] + ) - def self.run_linter(params) - UI.message "Linting localizations for parameter placeholders consistency..." - - require_relative '../../helper/ios/ios_l10n_helper.rb' - helper = Fastlane::Helpers::IosL10nHelper.new( - install_path: resolve_path(params[:install_path]), - version: params[:version] - ) - violations = helper.run( - input_dir: resolve_path(params[:input_dir]), - base_lang: params[:base_lang], - only_langs: params[:only_langs] - ) - - violations.each do |lang, diff| - UI.error "Inconsistencies found between '#{params[:base_lang]}' and '#{lang}':\n\n#{diff}\n" - end - - violations + violations.each do |lang, diff| + UI.error "Inconsistencies found between '#{params[:base_lang]}' and '#{lang}':\n\n#{diff}\n" end - RETRY_MESSAGE = <<~MSG - Inconsistencies found during Localization linting. - You need to fix them before continuing. From this point on, you should either: + violations + end - - Cancel this lane (reply 'No' below), then work with polyglots in #i18n - to fix those directly in GlotPress – by rejecting the inconsistent - translations, or by submitting a fixed copy. Rerun the lane when everything - has been fixed. + RETRY_MESSAGE = <<~MSG + Inconsistencies found during Localization linting. + You need to fix them before continuing. From this point on, you should either: - This is the recommended way to go, as it will fix the issues at their source. + - Cancel this lane (reply 'No' below), then work with polyglots in #i18n + to fix those directly in GlotPress – by rejecting the inconsistent + translations, or by submitting a fixed copy. Rerun the lane when everything + has been fixed. - - Or manually edit the `Localizable.strings` files to fix the inconsistencies - locally, commit them, then reply 'Yes' below to re-lint and validate that all - inconsistencies have been fixed locally so you can continue with the build. + This is the recommended way to go, as it will fix the issues at their source. - This is only a workaround to allow you to submit a build if translators are - not available to help you fix the issues in GlotPress in time. You will still - need to let the translators know that they will need to fix those copies - at some point before the next build to fix the root of the issue. + - Or manually edit the `Localizable.strings` files to fix the inconsistencies + locally, commit them, then reply 'Yes' below to re-lint and validate that all + inconsistencies have been fixed locally so you can continue with the build. - Did you fix the `.strings` files locally and want to lint them again? - MSG + This is only a workaround to allow you to submit a build if translators are + not available to help you fix the issues in GlotPress in time. You will still + need to let the translators know that they will need to fix those copies + at some point before the next build to fix the root of the issue. - ABORT_MESSAGE = <<~MSG - Inconsistencies found during Localization linting. Aborting. - MSG + Did you fix the `.strings` files locally and want to lint them again? + MSG - def self.repo_root - @repo_root || `git rev-parse --show-toplevel`.chomp - end + ABORT_MESSAGE = <<~MSG + Inconsistencies found during Localization linting. Aborting. + MSG - # If the path is relative, makes the path absolute by resolving it relative to the repository's root. - # If the path is already absolute, it will not affect it and return it as-is. - def self.resolve_path(path) - File.absolute_path(path, repo_root) - end - - ##################################################### - # @!group Documentation - ##################################################### - - def self.description - "Lint the different *.lproj/.strings files for each locale and ensure the parameter placeholders are consistent." - end - - def self.details - "Compares the translations against a base language to find potential mismatches for the %s/%d/… parameter placeholders between locales." - end - - def self.available_options - [ - FastlaneCore::ConfigItem.new( - key: :install_path, - env_name: "FL_IOS_LINT_TRANSLATIONS_INSTALL_PATH", - description: "The path where to install the SwiftGen tooling needed to run the linting process. If a relative path, should be relative to your repo_root", - type: String, - optional: true, - default_value: "vendor/swiftgen/#{Fastlane::Helpers::IosL10nHelper::SWIFTGEN_VERSION}" - ), - FastlaneCore::ConfigItem.new( - key: :version, - env_name: "FL_IOS_LINT_TRANSLATIONS_SWIFTGEN_VERSION", - description: "The version of SwiftGen to install and use for linting", - type: String, - optional: true, - default_value: Fastlane::Helpers::IosL10nHelper::SWIFTGEN_VERSION - ), - FastlaneCore::ConfigItem.new( - key: :input_dir, - env_name: "FL_IOS_LINT_TRANSLATIONS_INPUT_DIR", - description: "The path to the directory containing the .lproj folders to lint, relative to your git repo root", - type: String, - optional: false - ), - FastlaneCore::ConfigItem.new( - key: :base_lang, - env_name: "FL_IOS_LINT_TRANSLATIONS_BASE_LANG", - description: "The language that should be used as the base language that every other language will be compared against", - type: String, - optional: true, - default_value: Fastlane::Helpers::IosL10nHelper::DEFAULT_BASE_LANG - ), - FastlaneCore::ConfigItem.new( - key: :only_langs, - env_name: "FL_IOS_LINT_TRANSLATIONS_ONLY_LANGS", - description: "The list of languages to limit the analysis to", - type: Array, - optional: true - ), - FastlaneCore::ConfigItem.new( - key: :abort_on_violations, - env_name: "FL_IOS_LINT_TRANSLATIONS_ABORT", - description: "Should we abort the rest of the lane with a global error if any violations are found?", - optional: true, - default_value: true, - is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters - ), - FastlaneCore::ConfigItem.new( - key: :allow_retry, - env_name: "FL_IOS_LINT_TRANSLATIONS_ALLOW_RETRY", - description: "If any violations are found, show an interactive prompt allowing the user to manually fix the issues locally and retry the linting", - optional: true, - default_value: false, - is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters - ), - ] - end - - def self.output - nil - end - - def self.return_type - :hash_of_strings - end + def self.repo_root + @repo_root || `git rev-parse --show-toplevel`.chomp + end - def self.return_value - "A hash, keyed by language code, whose values are the diff found for said language" - end - - def self.authors - ["AliSoftware"] - end - - def self.is_supported?(platform) - [:ios, :mac].include?(platform) - end + # If the path is relative, makes the path absolute by resolving it relative to the repository's root. + # If the path is already absolute, it will not affect it and return it as-is. + def self.resolve_path(path) + File.absolute_path(path, repo_root) + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Lint the different *.lproj/.strings files for each locale and ensure the parameter placeholders are consistent.' + end + + def self.details + 'Compares the translations against a base language to find potential mismatches for the %s/%d/… parameter placeholders between locales.' + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new( + key: :install_path, + env_name: 'FL_IOS_LINT_TRANSLATIONS_INSTALL_PATH', + description: 'The path where to install the SwiftGen tooling needed to run the linting process. If a relative path, should be relative to your repo_root', + type: String, + optional: true, + default_value: "vendor/swiftgen/#{Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION}" + ), + FastlaneCore::ConfigItem.new( + key: :version, + env_name: 'FL_IOS_LINT_TRANSLATIONS_SWIFTGEN_VERSION', + description: 'The version of SwiftGen to install and use for linting', + type: String, + optional: true, + default_value: Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION + ), + FastlaneCore::ConfigItem.new( + key: :input_dir, + env_name: 'FL_IOS_LINT_TRANSLATIONS_INPUT_DIR', + description: 'The path to the directory containing the .lproj folders to lint, relative to your git repo root', + type: String, + optional: false + ), + FastlaneCore::ConfigItem.new( + key: :base_lang, + env_name: 'FL_IOS_LINT_TRANSLATIONS_BASE_LANG', + description: 'The language that should be used as the base language that every other language will be compared against', + type: String, + optional: true, + default_value: Fastlane::Helper::Ios::L10nHelper::DEFAULT_BASE_LANG + ), + FastlaneCore::ConfigItem.new( + key: :only_langs, + env_name: 'FL_IOS_LINT_TRANSLATIONS_ONLY_LANGS', + description: 'The list of languages to limit the analysis to', + type: Array, + optional: true + ), + FastlaneCore::ConfigItem.new( + key: :abort_on_violations, + env_name: 'FL_IOS_LINT_TRANSLATIONS_ABORT', + description: 'Should we abort the rest of the lane with a global error if any violations are found?', + optional: true, + default_value: true, + is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters + ), + FastlaneCore::ConfigItem.new( + key: :allow_retry, + env_name: 'FL_IOS_LINT_TRANSLATIONS_ALLOW_RETRY', + description: 'If any violations are found, show an interactive prompt allowing the user to manually fix the issues locally and retry the linting', + optional: true, + default_value: false, + is_string: false # https://docs.fastlane.tools/advanced/actions/#boolean-parameters + ), + ] + end + + def self.output + nil + end + + def self.return_type + :hash_of_strings + end + + def self.return_value + 'A hash, keyed by language code, whose values are the diff found for said language' + end + + def self.authors + ['AliSoftware'] + end + + def self.is_supported?(platform) + [:ios, :mac].include?(platform) end end end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb index ced3272fb..750fcd0e4 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_localize_project.rb @@ -2,46 +2,43 @@ module Fastlane module Actions class IosLocalizeProjectAction < Action def self.run(params) - UI.message "Updating project localisation..." - + UI.message 'Updating project localisation...' + require_relative '../../helper/ios/ios_git_helper.rb' other_action.cocoapods() - Fastlane::Helpers::IosGitHelper.localize_project() - - UI.message "Done." + Fastlane::Helper::Ios::GitHelper.localize_project() + + UI.message 'Done.' end - + ##################################################### # @!group Documentation ##################################################### - + def self.description - "Gathers the string to localise" + 'Gathers the string to localise' end - + def self.details - "Gathers the string to localise" + 'Gathers the string to localise' end - + def self.available_options - end - + def self.output - end - + def self.return_value - end - + def self.authors - ["loremattei"] + ['loremattei'] end - + def self.is_supported?(platform) platform == :ios end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb index 2152f21ed..a8b3af2eb 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_merge_translators_strings.rb @@ -1,6 +1,6 @@ require 'fastlane/action' require 'date' -require_relative '../../helper/ghhelper_helper' +require_relative '../../helper/github_helper' require_relative '../../helper/ios/ios_version_helper' module Fastlane module Actions @@ -8,29 +8,29 @@ class IosMergeTranslatorsStringsAction < Action def self.run(params) folder_path = File.expand_path(params[:strings_folder]) - subfolders = Dir.entries("#{folder_path}") - subfolders.each do | strings_folder | - merge_folder(File.join(folder_path, strings_folder)) if strings_folder.ends_with?(".lproj") + subfolders = Dir.entries(folder_path) + subfolders.each do |strings_folder| + merge_folder(File.join(folder_path, strings_folder)) if strings_folder.ends_with?('.lproj') end end def self.merge_folder(strings_folder) - main_file = File.join(strings_folder, "Localizable.strings") - tmp_main_file = File.join(strings_folder, "Localizable_current.strings") - return unless (File.exist?(main_file) && File.exist?(tmp_main_file)) + main_file = File.join(strings_folder, 'Localizable.strings') + tmp_main_file = File.join(strings_folder, 'Localizable_current.strings') + return unless File.exist?(main_file) && File.exist?(tmp_main_file) UI.message("Merging in: #{strings_folder}") - join_files = Dir.glob(File.join("#{strings_folder}", "Localizable_*.strings")) - [tmp_main_file] - extra_strings = Array.new - extra_keys = Array.new - join_files.each do | join_strings | + join_files = Dir.glob(File.join(strings_folder, 'Localizable_*.strings')) - [tmp_main_file] + extra_strings = [] + extra_keys = [] + join_files.each do |join_strings| my_strings = File.read(join_strings).split("\n") - my_strings.each do | string | - if string[/^\"(.*)\" = \"(.*)\";$/] + my_strings.each do |string| + if string[/^\"(.*)\" = \"(.*)\";$/] /^\"(?.*)\" = \"/i =~ string - if (!extra_keys.include?(string_key)) - extra_strings << string + unless extra_keys.include?(string_key) + extra_strings << string extra_keys << string_key end end @@ -39,8 +39,8 @@ def self.merge_folder(strings_folder) File.delete(join_strings) end - File.open(main_file, "w") do | f | - File.open(tmp_main_file).each do | line | + File.open(main_file, 'w') do |f| + File.open(tmp_main_file).each do |line| f.puts(check_line(line, extra_keys)) end f.puts(extra_strings) @@ -50,20 +50,20 @@ def self.merge_folder(strings_folder) end def self.check_line(line, extra_keys) - return line unless (line[/^\"(.*)\" = \"(.*)\";$/]) - + return line unless line[/^\"(.*)\" = \"(.*)\";$/] + /^\"(?.*)\" = \"/i =~ line - return "" if (extra_keys.include?(line_key)) + return '' if extra_keys.include?(line_key) return line end def self.description - "Merge strings for translators" + 'Merge strings for translators' end def self.authors - ["Lorenzo Mattei"] + ['Lorenzo Mattei'] end def self.return_value @@ -72,15 +72,15 @@ def self.return_value def self.details # Optional: - "Merges waiting and fuzzy strings into the main file for translators" + 'Merges waiting and fuzzy strings into the main file for translators' end def self.available_options [ FastlaneCore::ConfigItem.new(key: :strings_folder, - env_name: "IMTS_STRING_FOLDER", - description: "The folder that contains all the translations", - optional: false, + env_name: 'IMTS_STRING_FOLDER', + description: 'The folder that contains all the translations', + optional: false, type: String), ] end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb index 6f2b243a5..988cce570 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_tag_build.rb @@ -4,43 +4,41 @@ class IosTagBuildAction < Action def self.run(params) require_relative '../../helper/ios/ios_version_helper.rb' require_relative '../../helper/ios/ios_git_helper.rb' - - itc_ver = Fastlane::Helpers::IosVersionHelper.get_build_version() - int_ver = Fastlane::Helpers::IosVersionHelper.get_internal_version() unless ENV["INTERNAL_CONFIG_FILE"].nil? - Fastlane::Helpers::IosGitHelper.tag_build(itc_ver, int_ver) + + itc_ver = Fastlane::Helper::Ios::VersionHelper.get_build_version() + int_ver = Fastlane::Helper::Ios::VersionHelper.get_internal_version() unless ENV['INTERNAL_CONFIG_FILE'].nil? + Fastlane::Helper::GitHelper.create_tag(itc_ver) + Fastlane::Helper::GitHelper.create_tag(int_ver) unless int_ver.nil? end - + ##################################################### # @!group Documentation ##################################################### - + def self.description - "Tags the current build" + 'Tags the current build' end - + def self.details - "Tags the current build" + 'Tags the current build' end - + def self.available_options - end - + def self.output - end - + def self.return_value - end - + def self.authors - ["loremattei"] + ['loremattei'] end - + def self.is_supported?(platform) platform == :ios end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb index 55b3bc8d0..89876b569 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata.rb @@ -4,7 +4,7 @@ class IosUpdateMetadataAction < Action def self.run(params) require_relative '../../helper/ios/ios_git_helper.rb' - Fastlane::Helpers::IosGitHelper.update_metadata() + Fastlane::Helper::Ios::GitHelper.update_metadata() end ##################################################### @@ -12,27 +12,24 @@ def self.run(params) ##################################################### def self.description - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.details - "Downloads translated metadata from the translation system" + 'Downloads translated metadata from the translation system' end def self.available_options - end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -40,4 +37,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb index 1dfb0d4b8..950ee3e71 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_metadata_source.rb @@ -6,19 +6,19 @@ def self.run(params) other_action.ensure_git_status_clean() other_action.gp_update_metadata_source(po_file_path: params[:po_file_path], - source_files: params[:source_files], - release_version: params[:release_version]) + source_files: params[:source_files], + release_version: params[:release_version]) Action.sh("git add #{params[:po_file_path]}") - params[:source_files].each do | key, file | + params[:source_files].each do |_key, file| Action.sh("git add #{file}") end - repo_status = Actions.sh("git status --porcelain") + repo_status = Actions.sh('git status --porcelain') repo_clean = repo_status.empty? - if (!repo_clean) then - Action.sh("git commit -m \"Update metadata strings\"") - Action.sh("git push") + unless repo_clean + Action.sh('git commit -m "Update metadata strings"') + Action.sh('git push') end end @@ -27,52 +27,50 @@ def self.run(params) ##################################################### def self.description - "Updates the AppStoreStrings.po file with the data from text source files" + 'Updates the AppStoreStrings.po file with the data from text source files' end def self.details - "Updates the AppStoreStrings.po file with the data from text source files" + 'Updates the AppStoreStrings.po file with the data from text source files' end def self.available_options - # Define all options your action supports. - + # Define all options your action supports. + # Below a few examples [ FastlaneCore::ConfigItem.new(key: :po_file_path, - env_name: "FL_IOS_UPDATE_METADATA_SOURCE_PO_FILE_PATH", - description: "The path of the .po file to update", - is_string: true, - verify_block: proc do |value| - UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless (value and not value.empty?) - UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) - end), + env_name: 'FL_IOS_UPDATE_METADATA_SOURCE_PO_FILE_PATH', + description: 'The path of the .po file to update', + is_string: true, + verify_block: proc do |value| + UI.user_error!("No .po file path for UpdateMetadataSourceAction given, pass using `po_file_path: 'file path'`") unless value && (!value.empty?) + UI.user_error!("Couldn't find file at path '#{value}'") unless File.exist?(value) + end), FastlaneCore::ConfigItem.new(key: :release_version, - env_name: "FL_IOS_UPDATE_METADATA_SOURCE_RELEASE_VERSION", - description: "The release version of the app (to use to mark the release notes)", - verify_block: proc do |value| - UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless (value and not value.empty?) - end), + env_name: 'FL_IOS_UPDATE_METADATA_SOURCE_RELEASE_VERSION', + description: 'The release version of the app (to use to mark the release notes)', + verify_block: proc do |value| + UI.user_error!("No relase version for UpdateMetadataSourceAction given, pass using `release_version: 'version'`") unless value && (!value.empty?) + end), FastlaneCore::ConfigItem.new(key: :source_files, - env_name: "FL_IOS_UPDATE_METADATA_SOURCE_SOURCE_FILES", - description: "The hash with the path to the source files and the key to use to include their content", - is_string: false, - verify_block: proc do |value| - UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless (value and not value.empty?) - end) + env_name: 'FL_IOS_UPDATE_METADATA_SOURCE_SOURCE_FILES', + description: 'The hash with the path to the source files and the key to use to include their content', + is_string: false, + verify_block: proc do |value| + UI.user_error!("No source file hash for UpdateMetadataSourceAction given, pass using `source_files: 'source file hash'`") unless value && (!value.empty?) + end), ] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb index 4ee173f75..562a4c5ac 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_update_release_notes.rb @@ -1,58 +1,56 @@ module Fastlane - module Actions + module Actions class IosUpdateReleaseNotesAction < Action def self.run(params) - UI.message "Updating the release notes..." + UI.message 'Updating the release notes...' require_relative '../../helper/ios/ios_version_helper.rb' require_relative '../../helper/release_notes_helper.rb' require_relative '../../helper/git_helper.rb' - path = File.join(ENV["PROJECT_ROOT_FOLDER"] || '.', 'RELEASE-NOTES.txt') - next_version = Fastlane::Helpers::IosVersionHelper.calc_next_release_version(params[:new_version]) + path = File.join(ENV['PROJECT_ROOT_FOLDER'] || '.', 'RELEASE-NOTES.txt') + next_version = Fastlane::Helper::Ios::VersionHelper.calc_next_release_version(params[:new_version]) Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: path, section_title: next_version) Fastlane::Helper::GitHelper.commit(message: "Release Notes: add new section for next version (#{next_version})", files: path, push: true) - - UI.message "Done." + + UI.message 'Done.' end - + ##################################################### # @!group Documentation ##################################################### - + def self.description - "Updates the release notes file for the next app version" + 'Updates the release notes file for the next app version' end - + def self.details - "Updates the release notes file for the next app version" + 'Updates the release notes file for the next app version' end - + def self.available_options - [ - FastlaneCore::ConfigItem.new(key: :new_version, - env_name: "FL_IOS_UPDATE_RELEASE_NOTES_VERSION", - description: "The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes", - is_string: true) - ] + [ + FastlaneCore::ConfigItem.new(key: :new_version, + env_name: 'FL_IOS_UPDATE_RELEASE_NOTES_VERSION', + description: 'The version we are currently freezing; An empty entry for the _next_ version after this one will be added to the release notes', + is_string: true), + ] end def self.output - end - + def self.return_value - end - + def self.authors - ["loremattei"] + ['loremattei'] end - + def self.is_supported?(platform) platform == :ios end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb index 074917d2c..453a12d14 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/actions/ios/ios_validate_ci_build.rb @@ -5,10 +5,11 @@ def self.run(params) require_relative '../../helper/ios/ios_git_helper.rb' require_relative '../../helper/ios/ios_version_helper.rb' - version = Fastlane::Helpers::IosVersionHelper::get_public_version() - UI.user_error!("HEAD is not on tag. Aborting!") unless Fastlane::Helpers::IosGitHelper::is_head_on_tag() + version = Fastlane::Helper::Ios::VersionHelper.get_public_version() + head_tags = Fastlane::Helper::GitHelper.list_tags_on_current_commit() + UI.user_error!('HEAD is not on tag. Aborting!') if head_tags.empty? - return Fastlane::Helpers::IosGitHelper::has_final_tag_for(version) + return head_tags.include?(version) # Current commit is tagged with "version" tag end ##################################################### @@ -16,29 +17,25 @@ def self.run(params) ##################################################### def self.description - "Validate the build on CI environment" + 'Validate the build on CI environment' end def self.details - "Validate the build on CI environment" + 'Validate the build on CI environment' end def self.available_options - [ - - ] + [] end def self.output - end def self.return_value - end def self.authors - ["loremattei"] + ['loremattei'] end def self.is_supported?(platform) @@ -46,4 +43,4 @@ def self.is_supported?(platform) end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb index be625250d..e06114f35 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/an_metadata_update_helper.rb @@ -1,6 +1,5 @@ module Fastlane module Helper - # Basic line handler class MetadataBlock attr_reader :block_key @@ -18,15 +17,15 @@ def is_handler_for(key) end end - class UnknownMetadataBlock < MetadataBlock + class UnknownMetadataBlock < MetadataBlock attr_reader :content_file_path - def initialize() + def initialize super(nil) end end - class StandardMetadataBlock < MetadataBlock + class StandardMetadataBlock < MetadataBlock attr_reader :content_file_path def initialize(block_key, content_file_path) @@ -39,43 +38,41 @@ def is_handler_for(key) end def handle_line(fw, line) - # put the new content on block start + # put the new content on block start # and skip all the other content - if line.start_with?('msgctxt') - generate_block(fw) - end + generate_block(fw) if line.start_with?('msgctxt') end def generate_block(fw) # init fw.puts("msgctxt \"#{@block_key}\"") - line_count = File.foreach(@content_file_path).inject(0) {|c, line| c+1} + line_count = File.foreach(@content_file_path).inject(0) { |c, _line| c + 1 } - if (line_count <= 1) + if line_count <= 1 # Single line output - fw.puts("msgid \"#{File.open(@content_file_path, "r").read}\"") + fw.puts("msgid \"#{File.open(@content_file_path, 'r').read}\"") else # Multiple line output - fw.puts("msgid \"\"") + fw.puts('msgid ""') # insert content - File.open(@content_file_path, "r").each do | line | + File.open(@content_file_path, 'r').each do |line| fw.puts("\"#{line.strip}\\n\"") end end # close - fw.puts("msgstr \"\"") - fw.puts("") + fw.puts('msgstr ""') + fw.puts('') end end - class ReleaseNoteMetadataBlock < StandardMetadataBlock + class ReleaseNoteMetadataBlock < StandardMetadataBlock attr_reader :new_key, :keep_key, :rel_note_key, :release_version def initialize(block_key, content_file_path, release_version) super(block_key, content_file_path) - @rel_note_key = "release_note" + @rel_note_key = 'release_note' @release_version = release_version generate_keys(release_version) end @@ -94,7 +91,7 @@ def generate_keys(release_version) def is_handler_for(key) values = key.split('_') - key.start_with?(@rel_note_key) && values.length == 3 && (Integer(values[2].sub(/^[0]*/, "")) != nil rescue false) + key.start_with?(@rel_note_key) && values.length == 3 && is_int?(values[2].sub(/^[0]*/, '')) end def handle_line(fw, line) @@ -103,30 +100,26 @@ def handle_line(fw, line) if line.start_with?('msgctxt') key = extract_key(line) @is_copying = (key == @keep_key) - if (@is_copying) - generate_block(fw) - end - end - - if (@is_copying) - fw.puts(line) + generate_block(fw) if @is_copying end + + fw.puts(line) if @is_copying end def generate_block(fw) # init fw.puts("msgctxt \"#{@new_key}\"") - fw.puts("msgid \"\"") + fw.puts('msgid ""') fw.puts("\"#{@release_version}:\\n\"") # insert content - File.open(@content_file_path, "r").each do | line | + File.open(@content_file_path, 'r').each do |line| fw.puts("\"#{line.strip}\\n\"") end # close - fw.puts("msgstr \"\"") - fw.puts("") + fw.puts('msgstr ""') + fw.puts('') end def extract_key(line) @@ -134,24 +127,26 @@ def extract_key(line) end end - class ReleaseNoteShortMetadataBlock < ReleaseNoteMetadataBlock - + class ReleaseNoteShortMetadataBlock < ReleaseNoteMetadataBlock def initialize(block_key, content_file_path, release_version) super(block_key, content_file_path, release_version) - @rel_note_key = "release_note_short" + @rel_note_key = 'release_note_short' @release_version = release_version generate_keys(release_version) end - + def is_handler_for(key) values = key.split('_') - key.start_with?(@rel_note_key) && values.length == 4 && (Integer(values[3].sub(/^[0]*/, "")) != nil rescue false) + key.start_with?(@rel_note_key) && values.length == 4 && is_int?(values[3].sub(/^[0]*/, '')) end def generate_block(fw) super(fw) unless File.zero?(@content_file_path) end + + def is_int?(value) + true if Integer(string) rescue false + end end end end - diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb index 7b6cfd825..4a06b03a4 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_git_helper.rb @@ -1,95 +1,43 @@ module Fastlane - module Helpers - module AndroidGitHelper - - def self.git_checkout_and_pull(branch) - Action.sh("git checkout #{branch}") - Action.sh("git pull") - end - - def self.git_checkout_and_pull_release_branch_for(version) - branch_name = "release/#{version}" - Action.sh("git pull") - begin - Action.sh("git checkout #{branch_name}") - Action.sh("git pull origin #{branch_name}") - return true - rescue - return false + module Helper + module Android + # Helper methods to execute git-related operations that are specific to Android projects + # + module GitHelper + # Commit and push the files that are modified when we bump version numbers on an iOS project + # + # This typically commits and pushes the `build.gradle` file inside the project subfolder. + # + # @env PROJECT_ROOT_FOLDER The path to the git root of the project + # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file) + # + def self.commit_version_bump + Fastlane::Helper::GitHelper.commit( + message: 'Bump version number', + files: File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'build.gradle'), + push: true + ) end - end - def self.do_release_branch(branch_name) - if (check_branch_exists(branch_name) == true) then - UI.message("Branch #{branch_name} already exists. Skipping creation.") - Action.sh("git checkout #{branch_name}") - Action.sh("git pull origin #{branch_name}") - else - Action.sh("git checkout -b #{branch_name}") - - # Push to origin - Action.sh("git push -u origin #{branch_name}") + # Calls the `tools/update-translations.sh` script from the project repo, then lint them using the provided gradle task + # + # @env PROJECT_ROOT_FOLDER The path to the git root of the project + # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file) + # + # @param [String] validate_translation_command The name of the gradle task to run to validate the translations + # + # @todo Migrate the scripts, currently in each host repo and called by this method, to be helpers and actions + # in the release-toolkit instead, and move this code away from `ios_git_helper`. + # + def self.update_metadata(validate_translation_command) + Action.sh('./tools/update-translations.sh') + Action.sh('git', 'submodule', 'update', '--init', '--recursive') + Action.sh('./gradlew', validate_translation_command) + + res_dir = File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'src', 'main', 'res') + Fastlane::Helper::GitHelper.commit(message: 'Update translations', files: res_dir, push: true) end end - - def self.check_branch_exists(branch_name) - !Action.sh("git branch --list #{branch_name}").empty? - end - - def self.update_metadata(validate_translation_command) - Action.sh("./tools/update-translations.sh") - Action.sh("git submodule update --init --recursive") - Action.sh("./gradlew #{validate_translation_command}") - Action.sh("git add #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]}/src/main/res") - Action.sh("git diff-index --quiet HEAD || git commit -m \"Updates translations\"") - - Action.sh("git push origin HEAD") - end - - def self.bump_version_release() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]} && git add ./build.gradle") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.bump_version_beta() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]} && git add ./build.gradle") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.bump_version_hotfix(version) - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]} && git add ./build.gradle") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.bump_version_final() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]} && git add ./build.gradle") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.tag_build(release_version, alpha_version) - tag_and_push(release_version) - tag_and_push(alpha_version) unless alpha_version.nil? - end - - def self.check_on_branch(branch_name) - current_branch_name=Action.sh("git symbolic-ref -q HEAD") - UI.user_error!("This command works only on #{branch_name} branch") unless current_branch_name.include?(branch_name) - end - - def self.branch_for_hotfix(tag_version, new_version) - Action.sh("git checkout #{tag_version}") - Action.sh("git checkout -b release/#{new_version}") - Action.sh("git push --set-upstream origin release/#{new_version}") - end - - private - def self.tag_and_push(version) - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && git tag #{version} && git push origin #{version}") - end end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb new file mode 100644 index 000000000..735542ef8 --- /dev/null +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_localize_helper.rb @@ -0,0 +1,215 @@ +require 'fastlane_core/ui/ui' +require 'fileutils' +require 'nokogiri' + +module Fastlane + UI = FastlaneCore::UI unless Fastlane.const_defined?('UI') + + module Helper + module Android + module LocalizeHelper + # Checks if string_line has the content_override flag set + def self.skip_string_by_tag(string_line) + skip = string_line.attr('content_override') == 'true' unless string_line.attr('content_override').nil? + if skip + puts " - Skipping #{string_line.attr('name')} string" + return true + end + + return false + end + + # Checks if string_name is in the excluesion list + def self.skip_string_by_exclusion_list(library, string_name) + return false unless library.key?(:exclusions) + + skip = library[:exclusions].include?(string_name) + if skip + puts " - Skipping #{string_name} string" + return true + end + end + + # Merge string_line into main_string + def self.merge_string(main_strings, library, string_line) + string_name = string_line.attr('name') + string_content = string_line.content + + # Skip strings in the exclusions list + return :skipped if skip_string_by_exclusion_list(library, string_name) + + # Search for the string in the main file + result = :added + main_strings.xpath('//string').each do |this_string| + if this_string.attr('name') == string_name + # Skip if the string has the content_override tag + return :skipped if skip_string_by_tag(this_string) + + # If nodes are equivalent, skip + return :found if string_line =~ this_string + + # The string needs an update + result = :updated + if this_string.attr('tools:ignore').nil? + # It can be updated, so remove the current one and move ahead + this_string.remove + break + else + # It has the tools:ignore flag, so update the content without touching the other attributes + this_string.content = string_content + return result + end + end + end + + # String not found, or removed because needing update and not in the exclusion list: add to the main file + main_strings.xpath('//string').last().add_next_sibling("\n#{' ' * 4}#{string_line.to_xml().strip}") + return result + end + + # Verify a string + def self.verify_string(main_strings, library, string_line) + string_name = string_line.attr('name') + string_content = string_line.content + + # Skip strings in the exclusions list + return if skip_string_by_exclusion_list(library, string_name) + + # Search for the string in the main file + main_strings.xpath('//string').each do |this_string| + if this_string.attr('name') == string_name + # Skip if the string has the content_override tag + return if skip_string_by_tag(this_string) + + # Update if needed + UI.user_error!("String #{string_name} [#{string_content}] has been updated in the main file but not in the library #{library[:library]}.") if this_string.content != string_content + return + end + end + + # String not found and not in the exclusion list: + UI.user_error!("String #{string_name} [#{string_content}] was found in library #{library[:library]} but not in the main file.") + end + + def self.merge_lib(main, library) + UI.message("Merging #{library[:library]} strings into #{main}") + main_strings = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } + lib_strings = File.open(library[:strings_path]) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } + + updated_count = 0 + untouched_count = 0 + added_count = 0 + skipped_count = 0 + lib_strings.xpath('//string').each do |string_line| + res = merge_string(main_strings, library, string_line) + case res + when :updated + puts "#{string_line.attr('name')} updated." + updated_count = updated_count + 1 + when :found + untouched_count = untouched_count + 1 + when :added + puts "#{string_line.attr('name')} added." + added_count = added_count + 1 + when :skipped + skipped_count = skipped_count + 1 + else + UI.user_error!("Internal Error! #{res}") + end + end + + File.open(main, 'w:UTF-8') do |f| + f.write(main_strings.to_xml(indent: 4)) + end + + UI.message("Done (#{added_count} added, #{updated_count} updated, #{untouched_count} untouched, #{skipped_count} skipped).") + return (added_count + updated_count) != 0 + end + + def self.verify_diff(diff_string, main_strings, lib_strings, library) + if diff_string.start_with?('name=') + diff_string.slice!('name="') + + end_index = diff_string.index('"') + end_index ||= diff_string.length # Use the whole string if there's no '"' + + diff_string = diff_string.slice(0..(end_index - 1)) + + lib_strings.xpath('//string').each do |string_line| + res = verify_string(main_strings, library, string_line) if string_line.attr('name') == diff_string + end + end + end + + def self.verify_lib(main, library, source_diff) + UI.message("Checking #{library[:library]} strings vs #{main}") + main_strings = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } + lib_strings = File.open(library[:strings_path]) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } + + verify_local_diff(main, library, main_strings, lib_strings) + verify_pr_diff(main, library, main_strings, lib_strings, source_diff) unless source_diff.nil? + end + + def self.verify_local_diff(main, library, main_strings, lib_strings) + `git diff #{main}`.each_line do |line| + if line.start_with?('+ ') || line.start_with?('- ') + diffs = line.gsub(/\s+/m, ' ').strip.split(' ') + diffs.each do |diff| + verify_diff(diff, main_strings, lib_strings, library) + end + end + end + end + + def self.verify_pr_diff(main, library, main_strings, lib_strings, source_diff) + source_diff.each_line do |line| + if line.start_with?('+ ') || line.start_with?('- ') + diffs = line.gsub(/\s+/m, ' ').strip.split(' ') + diffs.each do |diff| + verify_diff(diff, main_strings, lib_strings, library) + end + end + end + end + end + end + end +end + +# Source: https://stackoverflow.com/questions/7825258/determine-if-two-nokogiri-nodes-are-equivalent?rq=1 +# There may be better solutions now that Ruby supports canonicalization. +module Nokogiri + module XML + class Node + # Return true if this node is content-equivalent to other, false otherwise + def =~(other) + return true if self == other + return false unless name == other.name + + stype = node_type + otype = other.node_type + return false unless stype == otype + + sa = attributes + oa = other.attributes + return false unless sa.length == oa.length + + sa = sa.sort.map { |n, a| [n, a.value, a.namespace && a.namespace.href] } + oa = oa.sort.map { |n, a| [n, a.value, a.namespace && a.namespace.href] } + return false unless sa == oa + + skids = children + okids = other.children + return false unless skids.length == okids.length + return false if stype == TEXT_NODE && (content != other.content) + + sns = namespace + ons = other.namespace + return false if !sns ^ !ons + return false if sns && (sns.href != ons.href) + + skids.to_enum.with_index.all? { |ski, i| ski =~ okids[i] } + end + end + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb index 4621949b5..ad96bf907 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android/android_version_helper.rb @@ -1,56 +1,123 @@ module Fastlane - module Helpers - module AndroidVersionHelper - VERSION_NAME = "name" - VERSION_CODE = "code" + module Helper + module Android + # A module containing helper methods to manipulate/extract/bump Android version strings in gradle files + # + module VersionHelper + # The key used in internal version Hash objects to hold the versionName value + VERSION_NAME = 'name' + # The key used in internal version Hash objects to hold the versionCode value + VERSION_CODE = 'code' + # The index for the major version number part MAJOR_NUMBER = 0 + # The index for the minor version number part MINOR_NUMBER = 1 + # The index for the hotfix version number part HOTFIX_NUMBER = 2 - ALPHA_PREFIX = "alpha-" - RC_SUFFIX = "-rc" - + # The prefix used in front of the versionName for alpha versions + ALPHA_PREFIX = 'alpha-' + # The suffix used in the versionName for RC (beta) versions + RC_SUFFIX = '-rc' + + # Returns the public-facing version string. + # + # @example + # "1.2" # Assuming build.gradle contains versionName "1.2" + # "1.2" # Assuming build.gradle contains versionName "1.2.0" + # "1.2.3" # Assuming build.gradle contains versionName "1.2.3" + # + # @return [String] The public-facing version number, extracted from the `versionName` of the `build.gradle` file. + # - If this version is a hotfix (more than 2 parts and 3rd part is non-zero), returns the "X.Y.Z" formatted string + # - Otherwise (not a hotfix / 3rd part of version is 0), returns "X.Y" formatted version number + # def self.get_public_version version = get_release_version vp = get_version_parts(version[VERSION_NAME]) - return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix(version) + return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix?(version) + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}" end + # Extract the version name and code from the `vanilla` flavor of the `$PROJECT_NAME/build.gradle file` + # or for the defaultConfig if `HAS_ALPHA_VERSION` is not defined. + # + # @env HAS_ALPHA_VERSION If set (with any value), indicates that the project uses `vanilla` flavor. + # + # @return [Hash] A hash with 2 keys "name" and "code" containing the extracted version name and code, respectively + # def self.get_release_version - section = ENV["HAS_ALPHA_VERSION"].nil? ? "defaultConfig" : "vanilla {" + section = ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {' gradle_path = self.gradle_path - name = get_version_name_from_file(gradle_path, section) - code = get_version_build_from_file(gradle_path, section) + name = get_version_name_from_gradle_file(gradle_path, section) + code = get_version_build_from_gradle_file(gradle_path, section) return { VERSION_NAME => name, VERSION_CODE => code } end + # Extract the version name and code from the `defaultConfig` of the `$PROJECT_NAME/build.gradle` file + # + # @return [Hash] A hash with 2 keys `"name"` and `"code"` containing the extracted version name and code, respectively, + # or `nil` if `$HAS_ALPHA_VERSION` is not defined. + # def self.get_alpha_version - if (ENV["HAS_ALPHA_VERSION"].nil?) - return nil - end + return nil if ENV['HAS_ALPHA_VERSION'].nil? - section = "defaultConfig" + section = 'defaultConfig' gradle_path = self.gradle_path - name = get_version_name_from_file(gradle_path, section) - code = get_version_build_from_file(gradle_path, section) + name = get_version_name_from_gradle_file(gradle_path, section) + code = get_version_build_from_gradle_file(gradle_path, section) return { VERSION_NAME => name, VERSION_CODE => code } end - - def self.is_alpha_version(version) + + # Determines if a version name corresponds to an alpha version (starts with `"alpha-"`` prefix) + # + # @param [String] version The version name to check + # + # @return [Bool] true if the version name starts with the `ALPHA_PREFIX`, false otherwise. + # + # @private + # + def self.is_alpha_version?(version) version[VERSION_NAME].start_with?(ALPHA_PREFIX) end - - def self.is_beta_version(version) + + # Check if this versionName corresponds to a beta, i.e. contains some `-rc` suffix + # + # @param [String] version The versionName string to check for + # + # @return [Bool] True if the version string contains `-rc`, indicating it is a beta version. + # + def self.is_beta_version?(version) version[VERSION_NAME].include?(RC_SUFFIX) end - + + # Returns the version name and code to use for the final release. + # + # - The final version name corresponds to the beta's versionName, without the `-rc` suffix + # - The final version code corresponds to the versionCode for the alpha (or for the beta if alpha_version is nil) incremented by one. + # + # @param [Hash] beta_version The version hash for the beta (vanilla flavor), containing values for keys "name" and "code" + # @param [Hash] alpha_version The version hash for the alpha (defaultConfig), containing values for keys "name" and "code", + # or `nil` if no alpha version to consider. + # + # @return [Hash] A version hash with keys "name" and "code", containing the version name and code to use for final release. + # def self.calc_final_release_version(beta_version, alpha_version) version_name = beta_version[VERSION_NAME].split('-')[0] - version_code = alpha_version.nil? ? beta_version[VERSION_CODE] + 1 : alpha_version[VERSION_CODE] + 1 + version_code = alpha_version.nil? ? beta_version[VERSION_CODE] + 1 : alpha_version[VERSION_CODE] + 1 { VERSION_NAME => version_name, VERSION_CODE => version_code } end + # Returns the version name and code to use for the next alpha. + # + # - The next version name corresponds to the `alpha_version`'s name incremented by one (alpha-42 => alpha-43) + # - The next version code corresponds to the `version`'s code incremented by one. + # + # @param [Hash] version The version hash for the current beta or release, containing values for keys "name" and "code" + # @param [Hash] alpha_version The version hash for the current alpha (defaultConfig), containing values for keys "name" and "code" + # + # @return [Hash] A version hash with keys "name" and "code", containing the version name and code to use for final release. + # def self.calc_next_alpha_version(version, alpha_version) # Bump alpha name alpha_number = alpha_version[VERSION_NAME].sub(ALPHA_PREFIX, '') @@ -61,10 +128,27 @@ def self.calc_next_alpha_version(version, alpha_version) { VERSION_NAME => alpha_name, VERSION_CODE => alpha_code } end - + + # Compute the version name and code to use for the next beta (`X.Y.Z-rc-N`). + # + # - The next version name corresponds to the `version`'s name with the value after the `-rc-` suffix incremented by one, + # or with `-rc-1` added if there was no previous rc suffix (if `version` was not a beta but a release) + # - The next version code corresponds to the `alpha_version`'s (or `version`'s if `alpha_version` is nil) code, incremented by one. + # + # @example + # calc_next_beta_version({"name": "1.2.3", "code": 456}) #=> {"name": "1.2.3-rc-1", "code": 457} + # calc_next_beta_version({"name": "1.2.3-rc-2", "code": 456}) #=> {"name": "1.2.3-rc-3", "code": 457} + # calc_next_beta_version({"name": "1.2.3", "code": 456}, {"name": "alpha-1.2.3", "code": 457}) #=> {"name": "1.2.3-rc-1", "code": 458} + # + # @param [Hash] version The version hash for the current beta or release, containing values for keys "name" and "code" + # @param [Hash] alpha_version The version hash for the alpha, containing values for keys "name" and "code", + # or `nil` if no alpha version to consider. + # + # @return [Hash] A hash with keys `"name"` and `"code"` containing the next beta version name and code. + # def self.calc_next_beta_version(version, alpha_version = nil) # Bump version name - beta_number = is_beta_version(version) ? version[VERSION_NAME].split('-')[2].to_i + 1 : 1 + beta_number = is_beta_version?(version) ? version[VERSION_NAME].split('-')[2].to_i + 1 : 1 version_name = "#{version[VERSION_NAME].split('-')[0]}#{RC_SUFFIX}-#{beta_number}" # Bump version code @@ -72,16 +156,31 @@ def self.calc_next_beta_version(version, alpha_version = nil) { VERSION_NAME => version_name, VERSION_CODE => version_code } end + # Compute the version name to use for the next release (`"X.Y"`). + # + # @param [String] version The version name (string) to increment + # + # @return [String] The version name for the next release + # def self.calc_next_release_short_version(version) - v = self.calc_next_release_base_version({ VERSION_NAME => version, VERSION_CODE => nil }) + v = self.calc_next_release_base_version(VERSION_NAME => version, VERSION_CODE => nil) return v[VERSION_NAME] end + # Compute the next release version name for the given version, without incrementing the version code + # + # - The version name sees its minor version part incremented by one (and carried to next major if it reaches 10) + # - The version code is unchanged. This method is intended to be called internally by other methods taking care of the version code bump. + # + # @param [Hash] version A version hash, with keys `"name"` and `"code"`, containing the version to increment + # + # @return [Hash] Hash containing the next release version name ("X.Y") and code. + # def self.calc_next_release_base_version(version) version_name = remove_beta_suffix(version[VERSION_NAME]) vp = get_version_parts(version_name) vp[MINOR_NUMBER] += 1 - if (vp[MINOR_NUMBER] == 10) + if vp[MINOR_NUMBER] == 10 vp[MAJOR_NUMBER] += 1 vp[MINOR_NUMBER] = 0 end @@ -89,119 +188,237 @@ def self.calc_next_release_base_version(version) { VERSION_NAME => "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}", VERSION_CODE => version[VERSION_CODE] } end + # Compute the name of the next version to use after code freeze, by incrementing the current version name and making it a `-rc-1` + # + # @example + # calc_next_release_version({"name": "1.2", "code": 456}) #=> {"name":"1.3-rc-1", "code": 457} + # calc_next_release_version({"name": "1.2.3", "code": 456}) #=> {"name":"1.3-rc-1", "code": 457} + # calc_next_release_version({"name": "1.2", "code": 456}, {"name":"alpha-1.2", "code": 457}) #=> {"name":"1.3-rc-1", "code": 458} + # + # @param [Hash] version The current version hash, with keys `"name"` and `"code"` + # @param [Hash] alpha_version The current alpha version hash, with keys `"name"` and `"code"`, or nil if no alpha version + # + # @return [Hash] The hash containing the version name and code to use after release cut + # def self.calc_next_release_version(version, alpha_version = nil) - nv = calc_next_release_base_version({ VERSION_NAME => version[VERSION_NAME], VERSION_CODE => alpha_version.nil? ? version[VERSION_CODE] : [version[VERSION_CODE], alpha_version[VERSION_CODE]].max}) + nv = calc_next_release_base_version(VERSION_NAME => version[VERSION_NAME], VERSION_CODE => alpha_version.nil? ? version[VERSION_CODE] : [version[VERSION_CODE], alpha_version[VERSION_CODE]].max) calc_next_beta_version(nv) end + # Compute the name and code of the next hotfix version. + # + # @param [String] hotfix_version_name The next version name we want for the hotfix + # @param [String] hotfix_version_code The next version code we want for the hotfix + # + # @return [Hash] The predicted next hotfix version, as a Hash containing the keys `"name"` and `"code"` + # def self.calc_next_hotfix_version(hotfix_version_name, hotfix_version_code) - { VERSION_NAME => hotfix_version_name, VERSION_CODE => hotfix_version_code} + { VERSION_NAME => hotfix_version_name, VERSION_CODE => hotfix_version_code } end + # Compute the name of the previous release version, by decrementing the minor version number + # + # @example + # calc_prev_release_version("1.2") => "1.1" + # calc_prev_release_version("1.2.3") => "1.1" + # calc_prev_release_version("3.0") => "2.9" + # + # @param [String] version The version string to decrement + # + # @return [String] A 2-parts version string "X.Y" corresponding to the guessed previous release version. + # def self.calc_prev_release_version(version) vp = get_version_parts(version) - if (vp[MINOR_NUMBER] == 0) + if vp[MINOR_NUMBER] == 0 vp[MAJOR_NUMBER] -= 1 vp[MINOR_NUMBER] = 9 else vp[MINOR_NUMBER] -= 1 end - - "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" + + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end - - def self.is_hotfix(version) - return false if is_alpha_version(version) + + # Determines if a version name corresponds to a hotfix + # + # @param [String] version The version number to test + # + # @return [Bool] True if the version number has a non-zero 3rd component, meaning that it is a hotfix version. + # + def self.is_hotfix?(version) + return false if is_alpha_version?(version) + vp = get_version_parts(version[VERSION_NAME]) return (vp.length > 2) && (vp[HOTFIX_NUMBER] != 0) end - + + # Prints the current and next release version names to stdout, then returns the next release version + # + # @return [String] The next release version name to use after bumping the currently used release version. + # def self.bump_version_release # Bump release - current_version=get_release_version() + current_version = get_release_version() UI.message("Current version: #{current_version[VERSION_NAME]}") - new_version=calc_next_release_base_version(current_version) + new_version = calc_next_release_base_version(current_version) UI.message("New version: #{new_version[VERSION_NAME]}") - verified_version=verify_version(new_version[VERSION_NAME]) + verified_version = verify_version(new_version[VERSION_NAME]) return verified_version end + # Update the `build.gradle` file with new `versionName` and `versionCode` values, both or the `defaultConfig` and `vanilla` flavors + # + # @param [Hash] new_version_beta The version hash for the beta (vanilla flavor), containing values for keys "name" and "code" + # @param [Hash] new_version_alpha The version hash for the alpha (defaultConfig), containing values for keys "name" and "code" + # @env HAS_ALPHA_VERSION If set (with any value), indicates that the project uses `vanilla` flavor. + # def self.update_versions(new_version_beta, new_version_alpha) - self.update_version(new_version_beta, ENV["HAS_ALPHA_VERSION"].nil? ? "defaultConfig" : "vanilla {") - self.update_version(new_version_alpha, "defaultConfig") unless new_version_alpha.nil? + self.update_version(new_version_beta, ENV['HAS_ALPHA_VERSION'].nil? ? 'defaultConfig' : 'vanilla {') + self.update_version(new_version_alpha, 'defaultConfig') unless new_version_alpha.nil? end + # Compute the name of the previous hotfix version. + # + # @param [String] version_name The current version name we want to decrement + # + # @return [String] The predicted previous hotfix version, in the form of "X.Y.Z", or "X.Y" if Z is 0. + # Corresponds to decrementing the 3rd component Z of the version, stripping it if it ends up being zero. + # def self.calc_prev_hotfix_version_name(version_name) vp = get_version_parts(version_name) vp[HOTFIX_NUMBER] -= 1 unless vp[HOTFIX_NUMBER] == 0 return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}" unless vp[HOTFIX_NUMBER] == 0 + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end - # private + #---------------------------------------- + private + + # Remove the beta suffix (part after the `-`) from a version string + # + # @param [String] version The version string to remove the suffix from + # + # @return [String] The part of the version string without the beta suffix, i.e. the part before the first dash. + # + # @example remove_beta_suffix("1.2.3-rc.4") => "1.2.3" + # def self.remove_beta_suffix(version) version.split('-')[0] end + # Split a version string into its individual integer parts + # + # @param [String] version The version string to split, e.g. "1.2.3.4" + # + # @return [Array] An array of integers containing the individual integer parts of the version. + # Always contains 3 items at minimum (0 are added to the end if the original string contains less than 3 parts) + # def self.get_version_parts(version) - version.split(".").fill("0", version.length...3).map{|chr| chr.to_i} + parts = version.split('.').map(&:to_i) + parts.fill(0, parts.length...3) # add 0 if needed to ensure array has at least 3 components + return parts end - - def self.get_version_name_from_file(file_path, section) - res = get_data_from_file(file_path, section, "versionName") - res = res.split(' ')[1].tr('\"', '') unless res.nil? + + # Extract the versionName from a build.gradle file + # + # @param [String] file_path The path to the `.gradle` file + # @param [String] section The name of the section we expect the keyword to be in, e.g. "defaultConfig" or "vanilla" + # + # @return [String] The value of the versionName attribute as found in the build.gradle file and for this section. + # + def self.get_version_name_from_gradle_file(file_path, section) + res = get_keyword_from_gradle_file(file_path, section, 'versionName') + res = res.tr('\"', '') unless res.nil? return res end - - def self.get_version_build_from_file(file_path, section) - res = get_data_from_file(file_path, section, "versionCode") - res = res.split(' ')[1].to_i - return res + + # Extract the versionCode rom a build.gradle file + # + # @param [String] file_path The path to the `.gradle` file + # @param [String] section The name of the section we expect the keyword to be in, e.g. "defaultConfig" or "vanilla" + # + # @return [String] The value of the versionCode attribute as found in the build.gradle file and for this section. + # + def self.get_version_build_from_gradle_file(file_path, section) + res = get_keyword_from_gradle_file(file_path, section, 'versionCode') + return res.to_i end - # FIXME: This implementation is very fragile. This should be done parsing the file in a proper way. - # Leveraging gradle itself is probably the easiest way. - def self.get_data_from_file(file_path, section, keyword) + # Extract the value for a specific keyword in a specific section of a `.gradle` file + # + # @todo: This implementation is very fragile. This should be done parsing the file in a proper way. + # Leveraging gradle itself is probably the easiest way. + # + # @param [String] file_path The path of the `.gradle` file to extract the value from + # @param [String] section The name of the section from which we want to extract this keyword from. For example `defaultConfig` or `myFlavor` + # @param [String] keyword The keyword (key name) we want the value for + # + # @return [String] Returns the value for that keyword in the section of the `.gradle` file, or nil if not found. + # + def self.get_keyword_from_gradle_file(file_path, section, keyword) found_section = false File.open(file_path, 'r') do |file| file.each_line do |line| if !found_section - if (line.include? section) - found_section = true - end + found_section = true if line.include?(section) else - if (line.include? keyword) - return line unless line.include?("\"#{keyword}\"") or line.include?("P#{keyword}") - end + return line.split(' ')[1] if line.include?(keyword) && !line.include?("\"#{keyword}\"") && !line.include?("P#{keyword}") end end end return nil end + # Ensure that a version string is correctly formatted (that is, each of its parts is a number) and returns the 2-parts version number + # + # @param [String] version The version string to verify + # + # @return [String] The "major.minor" version string, only with the first 2 components + # @raise [UserError] If any of the parts of the version string is not a number + # def self.verify_version(version) v_parts = get_version_parts(version) - - v_parts.each do | part | - if (!is_number?(part)) then - UI.user_error!("Version value can only contains numbers.") - end + + v_parts.each do |part| + UI.user_error!('Version value can only contains numbers.') unless is_int?(part) end "#{v_parts[MAJOR_NUMBER]}.#{v_parts[MINOR_NUMBER]}" end - def self.is_number? string - true if Float(string) rescue false + # Check if a string is an integer. + # + # @param [String] string The string to test + # + # @return [Bool] true if the string is representing an integer value, false if not + # + def self.is_int? string + true if Integer(string) rescue false end - def self.gradle_path - "#{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]}/build.gradle" + # The path to the build.gradle file for the project. + # + # @env PROJECT_ROOT_FOLDER The path to the root of the project (the folder containing the `.git` directory). + # @env PROJECT_NAME The name of the project, i.e. the name of the subdirectory containing the project's `build.gradle` file. + # + # @return [String] The path of the `build.gradle` file inside the project subfolder in the project's repo + # + def self.gradle_path + UI.user_error!("You need to set the \`PROJECT_ROOT_FOLDER\` environment variable to the path to the project's root") if ENV['PROJECT_ROOT_FOLDER'].nil? + UI.user_error!("You need to set the \`PROJECT_NAME\` environment variable to the relative path to the project subfolder name") if ENV['PROJECT_NAME'].nil? + File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'build.gradle') end - # FIXME: This implementation is very fragile. This should be done parsing the file in a proper way. - # Leveraging gradle itself is probably the easiest way. + # Update both the versionName and versionCode of the build.gradle file to the specified version. + # + # @param [Hash] version The version hash, containing values for keys "name" and "code" + # @param [String] section The name of the section to update in the build.gradle file, e.g. "defaultConfig" or "vanilla" + # + # @todo This implementation is very fragile. This should be done parsing the file in a proper way. + # Leveraging gradle itself is probably the easiest way. + # def self.update_version(version, section) gradle_path = self.gradle_path temp_file = Tempfile.new('fastlaneIncrementVersion') @@ -211,20 +428,18 @@ def self.update_version(version, section) file.each_line do |line| if !found_section temp_file.puts line - if (line.include? section) - found_section = true - end + found_section = true if line.include? section else - if (version_updated < 2) - if (line.include? "versionName") and (!line.include? "\"versionName\"") and (!line.include?"PversionName") + if version_updated < 2 + if line.include?('versionName') && !line.include?('"versionName"') && !line.include?('PversionName') version_name = line.split(' ')[1].tr('\"', '') - line.replace line.sub(version_name, version[VERSION_NAME].to_s) + line.sub!(version_name, version[VERSION_NAME].to_s) version_updated = version_updated + 1 end - if (line.include? "versionCode") + if line.include? 'versionCode' version_code = line.split(' ')[1] - line.replace line.sub(version_code, version[VERSION_CODE].to_s) + line.sub!(version_code, version[VERSION_CODE].to_s) version_updated = version_updated + 1 end end @@ -240,4 +455,5 @@ def self.update_version(version, section) end end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android_localize_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/android_localize_helper.rb deleted file mode 100644 index b7ccc4dc4..000000000 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/android_localize_helper.rb +++ /dev/null @@ -1,205 +0,0 @@ -require 'fastlane_core/ui/ui' -require 'fileutils' -require 'nokogiri' - -module Fastlane - UI = FastlaneCore::UI unless Fastlane.const_defined?("UI") - - module Helper - class AndroidLocalizeHelper - - # Checks if string_line has the content_override flag set - def self.skip_string_by_tag(string_line) - skip = string_line.attr("content_override") == "true" unless string_line.attr("content_override").nil? - if (skip) - puts " - Skipping #{string_line.attr("name")} string" - return true - end - - return false - end - - # Checks if string_name is in the excluesion list - def self.skip_string_by_exclusion_list(library, string_name) - if (!library.key?(:exclusions)) - return false - end - - skip = library[:exclusions].include?(string_name) - if (skip) - puts " - Skipping #{string_name} string" - return true - end - end - - # Merge string_line into main_string - def self.merge_string(main_strings, library, string_line) - string_name = string_line.attr("name") - string_content = string_line.content - - # Skip strings in the exclusions list - return :skipped if skip_string_by_exclusion_list(library, string_name) - - # Search for the string in the main file - result = :added - main_strings.xpath('//string').each do | this_string | - if (this_string.attr("name") == string_name) then - # Skip if the string has the content_override tag - return :skipped if skip_string_by_tag(this_string) - - # If nodes are equivalent, skip - return :found if (string_line =~ this_string) - - # The string needs an update - result = :updated - if (this_string.attr("tools:ignore").nil?) - # It can be updated, so remove the current one and move ahead - this_string.remove - break - else - # It has the tools:ignore flag, so update the content without touching the other attributes - this_string.content = string_content - return result - end - end - end - - # String not found, or removed because needing update and not in the exclusion list: add to the main file - main_strings.xpath('//string').last().add_next_sibling("\n#{" " * 4}#{string_line.to_xml().strip}") - return result - end - - # Verify a string - def self.verifystring(main_strings, library, string_line) - string_name = string_line.attr("name") - string_content = string_line.content - - # Skip strings in the exclusions list - return if skip_string_by_exclusion_list(library, string_name) - - # Search for the string in the main file - main_strings.xpath('//string').each do | this_string | - if (this_string.attr("name") == string_name) then - # Skip if the string has the content_override tag - return if skip_string_by_tag(this_string) - - # Update if needed - UI.user_error!("String #{string_name} [#{string_content}] has been updated in the main file but not in the library #{library[:library]}.") if (this_string.content != string_content) - return - end - end - - # String not found and not in the exclusion list: - UI.user_error!("String #{string_name} [#{string_content}] was found in library #{library[:library]} but not in the main file.") - end - - def self.merge_lib(main, library) - UI.message("Merging #{library[:library]} strings into #{main}") - main_strings = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } - lib_strings = File.open(library[:strings_path]) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } - - updated_count = 0 - untouched_count = 0 - added_count = 0 - skipped_count = 0 - lib_strings.xpath('//string').each do |string_line| - res = merge_string(main_strings, library, string_line) - case res - when :updated - puts "#{string_line.attr("name")} updated." - updated_count = updated_count + 1 - when :found - untouched_count = untouched_count + 1 - when :added - puts "#{string_line.attr("name")} added." - added_count = added_count + 1 - when :skipped - skipped_count = skipped_count + 1 - else - UI.user_error!("Internal Error! #{res}") - end - end - - File.open(main, "w:UTF-8") do | f | - f.write(main_strings.to_xml(:indent => 4)) - end - - UI.message("Done (#{added_count} added, #{updated_count} updated, #{untouched_count} untouched, #{skipped_count} skipped).") - return (added_count + updated_count) != 0 - end - - def self.verify_diff(diff_string, main_strings, lib_strings, library) - if diff_string.start_with?("name=") then - diff_string.slice!('name="') - - end_index = diff_string.index('"') - end_index ||= diff_string.length # Use the whole string if there's no '"' - - diff_string=diff_string.slice(0..(end_index - 1)) - - lib_strings.xpath('//string').each do |string_line| - if (string_line.attr("name") == diff_string) then - res = verifystring(main_strings, library, string_line) - end - end - end - end - - def self.verify_lib(main, library, source_diff) - UI.message("Checking #{library[:library]} strings vs #{main}") - main_strings = File.open(main) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } - lib_strings = File.open(library[:strings_path]) { |f| Nokogiri::XML(f, nil, Encoding::UTF_8.to_s) } - - verify_local_diff(main, library, main_strings, lib_strings) - verify_pr_diff(main, library, main_strings, lib_strings, source_diff) unless source_diff.nil? - - end - - def self.verify_local_diff(main, library, main_strings, lib_strings) - `git diff #{main}`.each_line do | line | - if (line.start_with?("+ ") or line.start_with?("- ")) then - diffs = line.gsub(/\s+/m, ' ').strip.split(" ") - diffs.each do | diff | - verify_diff(diff, main_strings, lib_strings, library) - end - end - end - end - - def self.verify_pr_diff(main, library, main_strings, lib_strings, source_diff) - source_diff.each_line do | line | - if (line.start_with?("+ ") or line.start_with?("- ")) then - diffs = line.gsub(/\s+/m, ' ').strip.split(" ") - diffs.each do | diff | - verify_diff(diff, main_strings, lib_strings, library) - end - end - end - end - end - end -end - -# Source: https://stackoverflow.com/questions/7825258/determine-if-two-nokogiri-nodes-are-equivalent?rq=1 -# There may be better solutions now that Ruby supports canonicalization. -class Nokogiri::XML::Node - # Return true if this node is content-equivalent to other, false otherwise - def =~(other) - return true if self == other - return false unless name == other.name - stype = node_type; otype = other.node_type - return false unless stype == otype - sa = attributes; oa = other.attributes - return false unless sa.length == oa.length - sa = sa.sort.map{ |n,a| [n,a.value,a.namespace && a.namespace.href] } - oa = oa.sort.map{ |n,a| [n,a.value,a.namespace && a.namespace.href] } - return false unless sa == oa - skids = children; okids = other.children - return false unless skids.length == okids.length - return false if stype == TEXT_NODE && (content != other.content) - sns = namespace; ons = other.namespace - return false if !sns ^ !ons - return false if sns && (sns.href != ons.href) - skids.to_enum.with_index.all?{ |ski,i| ski =~ okids[i] } - end -end \ No newline at end of file diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ci_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ci_helper.rb index ef00982ac..02a4f096f 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ci_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ci_helper.rb @@ -10,7 +10,7 @@ module CIHelper # @param [Parameters] CI provider specific parameters # def trigger_job(branch:, parameters: nil) - raise "Not implemented" + raise 'Not implemented' end # Login @@ -18,7 +18,7 @@ def trigger_job(branch:, parameters: nil) # @return [String] The CI login credentials # def login - raise "Not implemented" + raise 'Not implemented' end # Organization @@ -26,36 +26,36 @@ def login # @return [String] The organization the repository belongs to # def organization - raise "Not implemented" + raise 'Not implemented' end # Repository # # @return [String] The repository name # - def repository - raise "Not implemented" + def repository + raise 'Not implemented' end end module Fastlane module Helper - class CircleCIHelper + class CircleCIHelper include CIHelper attr_accessor :login, :organization, :repository - + # Initializes CircleCI helper. # # @param [String] login The CI login credentials. Usually a personal token on CircleCI # @param [String] repository The repository name # @param [String] organization The organization the repository belongs to # - def initialize(login:, repository:, organization: "wordpress-mobile") + def initialize(login:, repository:, organization: 'wordpress-mobile') @login = login @organization = organization @repository = repository - end + end # Command URI # diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb index be962face..63d612da0 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/configure_helper.rb @@ -4,17 +4,16 @@ require_relative '../models/configuration' module Fastlane - UI = FastlaneCore::UI unless Fastlane.const_defined?("UI") + UI = FastlaneCore::UI unless Fastlane.const_defined?('UI') module Helper class ConfigureHelper - ### Returns the contents of the project's `.configure` file. ### If the file doesn't exist, it'll return an empty Configuration ### that can later be saved to `.configure`. def self.configuration if self.configuration_path_exists - Configuration.from_file(FilesystemHelper::configure_file) + Configuration.from_file(FilesystemHelper.configure_file) else Configuration.new end @@ -22,12 +21,12 @@ def self.configuration ### Returns whether or not the `.configure` file exists in the project. def self.configuration_path_exists - File.file?(FilesystemHelper::configure_file) + File.file?(FilesystemHelper.configure_file) end ### A global helper to save the current configuration to `.configure`. def self.update_configuration(config) - config.save_to_file(FilesystemHelper::configure_file) + config.save_to_file(FilesystemHelper.configure_file) end ### @@ -73,7 +72,7 @@ def self.update_configure_file_commit_hash(new_hash) ### NB: Returns nil if the repo is in a detached HEAD state. def self.repo_branch_name result = `cd #{repository_path} && git rev-parse --abbrev-ref HEAD`.strip - (result == "HEAD") ? nil : result + (result == 'HEAD') ? nil : result end ### Returns the most recent commit hash in the `~/.mobile-secrets` repository. @@ -96,28 +95,26 @@ def self.repo_has_changes ### Returns whether or not the `.configure` file has a pinned hash that's older than the most recent ### ~/.mobile-secrets` commit hash. def self.configure_file_is_behind_local - configure_file_commits_behind_repo > 0 + configure_file_commits_behind_repo > 0 end def self.configure_file_commits_behind_repo - # Get a sily number of revisions to ensure we don't miss any - result = `cd #{repository_path} && git --no-pager log -10000 --pretty=format:"%H" && echo` - hashes = result.each_line.map{ |s| s.strip }.reverse + # Get a sily number of revisions to ensure we don't miss any + result = `cd #{repository_path} && git --no-pager log -10000 --pretty=format:"%H" && echo` + hashes = result.each_line.map { |s| s.strip }.reverse - index_of_configure_hash = hashes.find_index(configure_file_commit_hash) - index_of_repo_commit_hash = hashes.find_index(repo_commit_hash) + index_of_configure_hash = hashes.find_index(configure_file_commit_hash) + index_of_repo_commit_hash = hashes.find_index(repo_commit_hash) - if index_of_configure_hash >= index_of_repo_commit_hash - return 0 - end + return 0 if index_of_configure_hash >= index_of_repo_commit_hash - index_of_repo_commit_hash - index_of_configure_hash + index_of_repo_commit_hash - index_of_configure_hash end ### Get a list of files changed in the secrets repo between to commits def self.files_changed_between(commit_hash_1, commit_hash_2) result = `cd #{repository_path} && git diff --name-only #{commit_hash_1}...#{commit_hash_2}` - result.each_line.map{ |s| s.strip } + result.each_line.map { |s| s.strip } end ### Determine whether ~/.mobile-secrets` repository is behind its remote counterpart. @@ -130,9 +127,7 @@ def self.repo_is_behind_remote def self.repo_commits_behind_remote matches = repo_status.match(/behind \d+/) - if matches == nil - return 0 - end + return 0 if matches.nil? parse_distance(matches[0]) end @@ -147,9 +142,7 @@ def self.repo_is_ahead_of_remote def self.repo_commits_ahead_of_remote matches = repo_status.match(/ahead \d+/) - if matches == nil - return 0 - end + return 0 if matches.nil? parse_distance(matches[0]) end @@ -159,9 +152,7 @@ def self.repo_commits_ahead_of_remote def self.parse_distance(match) distance = match.to_s.scan(/\d+/).first - if distance == nil - return 0 - end + return 0 if distance.nil? distance.to_i end @@ -191,18 +182,17 @@ def self.file_dependencies file_dependencies ||= [] # Allows support for specifying directories – they'll be expanded recursively - expanded_file_dependencies = file_dependencies.map { |path| + expanded_file_dependencies = file_dependencies.map do |path| + abs_path = self.mobile_secrets_path(path) - abs_path = self.mobile_secrets_path(path) - - if File.directory?(abs_path) - Dir.glob("#{abs_path}**/*").map{ |path| - path.gsub(repository_path + "/", "") - } - else - return path + if File.directory?(abs_path) + Dir.glob("#{abs_path}**/*").map do |sub_path| + sub_path.gsub(repository_path + '/', '') end - } + else + return path + end + end self.files_to_copy.map { |o| o.file } + expanded_file_dependencies end @@ -213,18 +203,16 @@ def self.new_files_in(files) file_dependencies = self.configuration.file_dependencies file_dependencies ||= [] - directory_dependencies = file_dependencies.select { |path| - File.directory?(self.mobile_secrets_path(path)) - } + directory_dependencies = file_dependencies.select do |path| + File.directory?(self.mobile_secrets_path(path)) + end new_files = [] files.each do |path| - directory_dependencies.each do |directory_name| - if path.start_with?(directory_name) - new_files << path - end - end + directory_dependencies.each do |directory_name| + new_files << path if path.start_with?(directory_name) + end end new_files @@ -233,14 +221,9 @@ def self.new_files_in(files) # Adds a file to the `.configure` file's `files_to_copy` hash. # The hash for this method must contain the `source` and `destination` keys def self.add_file(params) + UI.user_error!('You must pass a `source` to `add_file`') unless params[:source] - unless(params[:source]) - UI.user_error!("You must pass a `source` to `add_file`") - end - - unless(params[:destination]) - UI.user_error!("You must pass a `destination` to `add_file`") - end + UI.user_error!('You must pass a `destination` to `add_file`') unless params[:destination] new_config = self.configuration new_config.add_file_to_copy(params[:source], params[:destination], params[:encrypt]) @@ -255,6 +238,7 @@ def self.mobile_secrets_path(path) ## Contents of ~/.mobile-secrets/keys.json as a hash def self.mobile_secrets_keys_json return {} unless File.file?(Fastlane::Helper::FilesystemHelper.secret_store_keys_path) + JSON.parse(File.read(Fastlane::Helper::FilesystemHelper.secret_store_keys_path)) end @@ -262,6 +246,7 @@ def self.mobile_secrets_keys_json ## Uses the project encryption key or the CONFIGURE_ENCRYPTION_KEY env variable, if present def self.encryption_key return Base64.decode64(ENV['CONFIGURE_ENCRYPTION_KEY']) if ENV.key?('CONFIGURE_ENCRYPTION_KEY') + project_encryption_key end @@ -269,6 +254,7 @@ def self.encryption_key def self.project_encryption_key keys_json = mobile_secrets_keys_json return nil unless keys_json.key?(configuration.project_name) + base64_key = keys_json[configuration.project_name] Base64.decode64(base64_key) end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/encryption_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/encryption_helper.rb index 1e0d835e6..1067e5216 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/encryption_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/encryption_helper.rb @@ -2,7 +2,7 @@ module Fastlane module Helper - class EncryptionHelper + class EncryptionHelper module OperationType ENCRYPT = 1 DECRYPT = 2 @@ -48,4 +48,4 @@ def self.generate_key end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/filesystem_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/filesystem_helper.rb index 00cfb2d25..970d629cd 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/filesystem_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/filesystem_helper.rb @@ -3,101 +3,91 @@ require 'digest' module Fastlane - UI = FastlaneCore::UI unless Fastlane.const_defined?("UI") + UI = FastlaneCore::UI unless Fastlane.const_defined?('UI') module Helper class FilesystemHelper - - ### Traverse the file system to find the root project directory. - ### For the purposes of this function, we're assuming the root project - ### directory is the one with the `.git` file in it. - def self.project_path - - continue = true - dir = Pathname.new(Dir.pwd) - - while continue - child_filenames = dir.children.map!{ |x| File.basename(x) } - - if child_filenames.include? ".git" - continue = false - else - dir = dir.parent - end - - if dir.root? - UI.user_error!("Unable to determine the project root directory – #{Dir.pwd} doesn't appear to reside within a git repository.") - end - end - - dir - end - - def self.plugin_root - - continue = true - dir = Pathname.new(__FILE__).dirname - - while continue - child_filenames = dir.children.map! { |x| File.basename(x) } - - if child_filenames.include? "fastlane-plugin-wpmreleasetoolkit.gemspec" - continue = false - else - dir = dir.parent - end - - if dir.root? - UI.user_error!("Unable to determine the plugin root directory.") - end - end - - dir - end - - ### Returns the path to the project's `.configure` file. - def self.configure_file - Pathname.new(project_path) + ".configure" + ### Traverse the file system to find the root project directory. + ### For the purposes of this function, we're assuming the root project + ### directory is the one with the `.git` file in it. + def self.project_path + continue = true + dir = Pathname.new(Dir.pwd) + + while continue + child_filenames = dir.children.map! { |x| File.basename(x) } + + if child_filenames.include? '.git' + continue = false + else + dir = dir.parent + end + + UI.user_error!("Unable to determine the project root directory – #{Dir.pwd} doesn't appear to reside within a git repository.") if dir.root? end - ### Returns the path to the project's `.configure-files` directory. - def self.configure_files_dir - Pathname.new(project_path) + ".configure-files" - end - - def self.encrypted_file_path(file) - File.join(configure_files_dir, "#{File.basename(file)}.enc") - end + dir + end - ### Returns the path to the `~/.mobile-secrets` directory. - def self.secret_store_dir - return "#{Dir.home}/.mobile-secrets" - end + def self.plugin_root + continue = true + dir = Pathname.new(__FILE__).dirname - ### Transforms a relative path within the secret store to an absolute path on disk. - def self.absolute_secret_store_path(relative_path) - File.join(secret_store_dir, relative_path) - end + while continue + child_filenames = dir.children.map! { |x| File.basename(x) } - ### Path to keys.json in the secrets repository - def self.secret_store_keys_path - File.join(secret_store_dir, 'keys.json') - end + if child_filenames.include? 'fastlane-plugin-wpmreleasetoolkit.gemspec' + continue = false + else + dir = dir.parent + end - ### Transforms a relative path within the project to an absolute path on disk. - def self.absolute_project_path(relative_path) - File.join(project_path, relative_path) + UI.user_error!('Unable to determine the plugin root directory.') if dir.root? end - ### Returns the `sha1` hash of a file, given the absolute path. - def self.file_hash(absolute_path) - - unless File.file?(absolute_path) - UI.user_error!("Unable to hash #{absolute_path} – the file does not exist") - end - - Digest::SHA1.file absolute_path - end + dir + end + + ### Returns the path to the project's `.configure` file. + def self.configure_file + Pathname.new(project_path) + '.configure' + end + + ### Returns the path to the project's `.configure-files` directory. + def self.configure_files_dir + Pathname.new(project_path) + '.configure-files' + end + + def self.encrypted_file_path(file) + File.join(configure_files_dir, "#{File.basename(file)}.enc") + end + + ### Returns the path to the `~/.mobile-secrets` directory. + def self.secret_store_dir + return "#{Dir.home}/.mobile-secrets" + end + + ### Transforms a relative path within the secret store to an absolute path on disk. + def self.absolute_secret_store_path(relative_path) + File.join(secret_store_dir, relative_path) + end + + ### Path to keys.json in the secrets repository + def self.secret_store_keys_path + File.join(secret_store_dir, 'keys.json') + end + + ### Transforms a relative path within the project to an absolute path on disk. + def self.absolute_project_path(relative_path) + File.join(project_path, relative_path) + end + + ### Returns the `sha1` hash of a file, given the absolute path. + def self.file_hash(absolute_path) + UI.user_error!("Unable to hash #{absolute_path} – the file does not exist") unless File.file?(absolute_path) + + Digest::SHA1.file absolute_path + end end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ghhelper_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ghhelper_helper.rb deleted file mode 100644 index b626d2b7f..000000000 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ghhelper_helper.rb +++ /dev/null @@ -1,83 +0,0 @@ -require 'fastlane_core/ui/ui' -require 'octokit' - -module Fastlane - UI = FastlaneCore::UI unless Fastlane.const_defined?("UI") - - module Helper - class GhhelperHelper - def self.GHClient() - client = Octokit::Client.new(:access_token => ENV["GHHELPER_ACCESS"]) - - # Fetch the current user - user = client.user - UI.message("Logged in as: #{user.name}") - - client - end - - def self.get_milestone(repository, release) - miles = GHClient().list_milestones(repository) - mile = nil - - miles&.each do |mm| - if mm[:title].start_with?(release) - mile = mm - end - end - - return mile - end - - def self.get_last_milestone(repository) - options = {} - options[:state]="open" - - milestones = GHClient().list_milestones(repository, options) - if (milestones.nil?) - return nil - end - - last_stone = nil - milestones.each do | mile | - if (last_stone.nil?) - last_stone = mile unless mile[:title].split(' ')[0].split('.').length < 2 - else - begin - if (mile[:title].split(' ')[0].split('.')[0] > last_stone[:title].split(' ')[0].split('.')[0]) - last_stone = mile - else - if (mile[:title].split(' ')[0].split('.')[1] > last_stone[:title].split(' ')[0].split('.')[1]) - last_stone = mile - end - end - rescue - puts "Found invalid milestone" - end - end - end - - last_stone - end - - def self.create_milestone(repository, newmilestone_number, newmilestone_duedate, need_submission) - submission_date = need_submission ? newmilestone_duedate.to_datetime.next_day(11) : newmilestone_duedate.to_datetime.next_day(14) - release_date = newmilestone_duedate.to_datetime.next_day(14) - comment = "Code freeze: #{newmilestone_duedate.to_datetime.strftime("%B %d, %Y")} App Store submission: #{submission_date.strftime("%B %d, %Y")} Release: #{release_date.strftime("%B %d, %Y")}" - - options = {} - options[:due_on] = newmilestone_duedate - options[:description] = comment - GHClient().create_milestone(repository, newmilestone_number, options) - end - - def self.create_release(repository, version, release_notes, assets, prerelease) - release = GHClient().create_release(repository, version, { name: version, draft: true, prerelease: prerelease, body: release_notes }) - assets.each do | file_path | - GHClient().upload_asset(release[:url], file_path, { content_type: "application/octet-stream"}) - end - end - - end - end -end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb index ebb543457..232e62775 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/git_helper.rb @@ -2,17 +2,65 @@ module Fastlane module Helper + # Helper methods to execute git-related operations + # module GitHelper - - def self.is_git_repo - system "git rev-parse --git-dir 1> /dev/null 2>/dev/null" + # Checks if the current directory is (inside) a git repo + # + # @return [Bool] True if the current directory is the root of a git repo (i.e. a local working copy) or a subdirectory of one. + # + def self.is_git_repo? + system 'git rev-parse --git-dir 1> /dev/null 2>/dev/null' end - def self.has_git_lfs - return false unless is_git_repo + # Check if the current directory has git-lfs enabled + # + # @return [Bool] True if the current directory is a git working copy and has git-lfs enabled. + # + def self.has_git_lfs? + return false unless is_git_repo? + `git config --get-regex lfs`.length > 0 end + # Switch to the given branch and pull its latest commits. + # + # @param [String,Hash] branch Name of the branch to pull. + # If you provide a Hash with a single key=>value pair, it will build the branch name as `"#{key}/#{value}"`, + # i.e. `checkout_and_pull(release: version)` is equivalent to `checkout_and_pull("release/#{version}")`. + # + # @return [Bool] True if it succeeded switching and pulling, false if there was an error during the switch or pull. + # + def self.checkout_and_pull(branch) + branch = branch.first.join('/') if branch.is_a?(Hash) + Action.sh('git', 'checkout', branch) + Action.sh('git', 'pull') + return true + rescue + return false + end + + # Create a new branch named `branch_name`, cutting it from branch/commit/tag `from`, and push it + # + # If the branch with that name already exists, it will instead switch to it and pull new commits. + # + # @param [String] branch_name The full name of the new branch to create, e.g "release/1.2" + # @param [String?] from The branch or tag from which to cut the branch from. + # If `nil`, will cut the new branch from the current commit. Otherwise, will checkout that commit/branch/tag before cutting the branch. + # @param [Bool] push If true, will also push the branch to `origin`, tracking the upstream branch with the local one. + # + def self.create_branch(branch_name, from: nil, push: true) + if branch_exists?(branch_name) + UI.message("Branch #{branch_name} already exists. Skipping creation.") + Action.sh('git', 'checkout', branch_name) + Action.sh('git', 'pull', 'origin', branch_name) + else + Action.sh('git', 'checkout', from) unless from.nil? + Action.sh('git', 'checkout', '-b', branch_name) + Action.sh('git', 'push', '-u', 'origin', branch_name) if push + end + end + # `git add` the specified files (if any provided) then commit them using the provided message. # Optionally, push the commit to the remote too. # @@ -22,16 +70,92 @@ def self.has_git_lfs # Also accepts the special symbol `:all` to add all the files (`git commit -a -m …`). # @param [Bool] push If true, will `git push` to `origin` after the commit has been created. Defaults to `false`. # + # @return [Bool] True if commit and push were successful, false if there was an issue during commit & push (most likely being "nothing to commit"). + # def self.commit(message:, files: nil, push: false) files = [files] if files.is_a?(String) args = [] - if files == :all + if files == :all args = ['-a'] elsif !files.nil? && !files.empty? - Action.sh("git", "add", *files) + Action.sh('git', 'add', *files) + end + begin + Action.sh('git', 'commit', *args, '-m', message) + Action.sh('git', 'push', 'origin', 'HEAD') if push + return true + rescue + return false + end + end + + # Creates a tag for the given version, and optionally push it to the remote. + # + # @param [String] version The name of the tag to push, e.g. "1.2" + # @param [Bool] push If true (the default), the tag will also be pushed to `origin` + # + def self.create_tag(version, push: true) + Action.sh('git', 'tag', version) + Action.sh('git', 'push', 'origin', version) if push + end + + # Returns the list of tags that are pointing to the current commit (HEAD) + # + # @return [Array] List of tags associated with the HEAD commit + # + def self.list_tags_on_current_commit + Action.sh('git', 'tag', '--points-at', 'HEAD').split("\n") + end + + # List all the tags in the local working copy, optionally filtering the list using a pattern + # + # @param [String] matching The pattern of the tag(s) to match and filter on; use "*" for wildcards. + # For example, `"1.2.*"` will match every tag starting with `"1.2."`. Defaults to '*' which lists all tags. + # + # @return [Array] The list of local tags matching the pattern + # + def self.list_local_tags(matching: '*') + Action.sh('git', 'tag', '--list', matching).split("\n") + end + + # Delete the mentioned local tags in the local working copy, and optionally delete them on the remote too. + # + # @param [Array] tag_names The list of tags to delete + # @param [Bool] delete_on_remote If true, will also delete the tag from the remote. Otherwise, it will only be deleted locally. + # + def self.delete_tags(tag_names, delete_on_remote: false) + Action.sh('git', 'tag', '-d', *tag_names) + if delete_on_remote + remote_refs = tag_names.map { |tag| ":refs/tags/#{tag}" } + Action.sh('git', 'push', 'origin', *remote_refs) end - Action.sh("git", "commit", *args, "-m", message) - Action.sh("git", "push", "origin", "HEAD") if push + end + + # Fetch all the tags from the remote. + # + def self.fetch_all_tags + Action.sh('git', 'fetch', '--tags') + end + + # Checks if a branch exists locally. + # + # @param [String] branch_name The name of the branch to check for + # + # @return [Bool] True if the branch exists in the local working copy, false otherwise. + # + def self.branch_exists?(branch_name) + !Action.sh('git', 'branch', '--list', branch_name).empty? + end + + # Ensure that we are on the expected branch, and abort if not. + # + # @param [String] branch_name The name of the branch we expect to be on + # + # @raise [UserError] Raises a user_error! and interrupts the lane if we are not on the expected branch. + # + def self.ensure_on_branch!(branch_name) + current_branch_name = Action.sh('git', 'symbolic-ref', '-q', 'HEAD') + UI.user_error!("This command works only on #{branch_name} branch") unless current_branch_name.include?(branch_name) end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb new file mode 100644 index 000000000..2e8f5bcb3 --- /dev/null +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/github_helper.rb @@ -0,0 +1,76 @@ +require 'fastlane_core/ui/ui' +require 'octokit' + +module Fastlane + UI = FastlaneCore::UI unless Fastlane.const_defined?('UI') + + module Helper + class GithubHelper + def self.github_client + client = Octokit::Client.new(access_token: ENV['GHHELPER_ACCESS']) + + # Fetch the current user + user = client.user + UI.message("Logged in as: #{user.name}") + + client + end + + def self.get_milestone(repository, release) + miles = github_client().list_milestones(repository) + mile = nil + + miles&.each do |mm| + mile = mm if mm[:title].start_with?(release) + end + + return mile + end + + def self.get_last_milestone(repository) + options = {} + options[:state] = 'open' + + milestones = github_client().list_milestones(repository, options) + return nil if milestones.nil? + + last_stone = nil + milestones.each do |mile| + if last_stone.nil? + last_stone = mile unless mile[:title].split(' ')[0].split('.').length < 2 + else + begin + if mile[:title].split(' ')[0].split('.')[0] > last_stone[:title].split(' ')[0].split('.')[0] + last_stone = mile + elsif mile[:title].split(' ')[0].split('.')[1] > last_stone[:title].split(' ')[0].split('.')[1] + last_stone = mile + end + rescue StandardError + puts 'Found invalid milestone' + end + end + end + + last_stone + end + + def self.create_milestone(repository, newmilestone_number, newmilestone_duedate, need_submission) + submission_date = need_submission ? newmilestone_duedate.to_datetime.next_day(11) : newmilestone_duedate.to_datetime.next_day(14) + release_date = newmilestone_duedate.to_datetime.next_day(14) + comment = "Code freeze: #{newmilestone_duedate.to_datetime.strftime('%B %d, %Y')} App Store submission: #{submission_date.strftime('%B %d, %Y')} Release: #{release_date.strftime('%B %d, %Y')}" + + options = {} + options[:due_on] = newmilestone_duedate + options[:description] = comment + github_client().create_milestone(repository, newmilestone_number, options) + end + + def self.create_release(repository, version, release_notes, assets, prerelease) + release = github_client().create_release(repository, version, name: version, draft: true, prerelease: prerelease, body: release_notes) + assets.each do |file_path| + github_client().upload_asset(release[:url], file_path, content_type: 'application/octet-stream') + end + end + end + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb index 6c98fe30b..0b470867a 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_adc_app_sizes_helper.rb @@ -1,47 +1,46 @@ require 'spaceship' module Fastlane - module Helpers - module IosADCAppSizesHelper - DEFAULT_DEVICES = ["Universal", "iPhone 8", "iPhone X"] + module Helper + module Ios + module ADCAppSizesHelper + DEFAULT_DEVICES = ['Universal', 'iPhone 8', 'iPhone X'] # Fetch the App Sizes stats from ADC # # @return [Array] app build details, one entry per app version found # Each entry is a hash with keys `cfBundleVersion` and `sizesInBytes`. # Value for key `sizeInBytes` is itself a Hash with one entry per device name (including special name "Universal") - # whose value is a Hash with keys {'compressed', 'uncompressed'} + # whose value is a Hash with keys `compressed` and `uncompressed` # def self.get_adc_sizes(adc_user:, adc_team: 'Automattic, Inc.', bundle_id:, only_version: nil, limit: 10) - UI.message "Connecting to ADC..." + UI.message 'Connecting to ADC...' Spaceship::ConnectAPI.login(adc_user, team_name: adc_team) app = Spaceship::ConnectAPI::App.find(bundle_id) - UI.message "Fetching the list of versions..." + UI.message 'Fetching the list of versions...' versions = app.app_store_versions.select { |v| v.version_string == only_version && !v.build.nil? } - if versions.empty? - versions = app.get_app_store_versions.reject { |v| v.build.nil? } - end - UI.message "Found #{versions.count} versions." + (limit == 0 ? "" : " Limiting to last #{limit}") + versions = app.get_app_store_versions.reject { |v| v.build.nil? } if versions.empty? + UI.message "Found #{versions.count} versions." + (limit == 0 ? '' : " Limiting to last #{limit}") versions = versions.first(limit) unless limit == 0 - UI.message "Fetching App Sizes..." + UI.message 'Fetching App Sizes...' builds_details = versions.each_with_index.map do |v, idx| print "Fetching info for: #{v.version_string.rjust(8)} (#{v.build.version.rjust(11)}) [#{idx.to_s.rjust(3)}/#{versions.count}]\r" Spaceship::Tunes.client.build_details(app_id: app.id, train: v.version_string, build_number: v.build.version, platform: 'ios') rescue nil end.compact.reverse - print(" " * 55 + "\n") + print(' ' * 55 + "\n") builds_details end def self.sz(bytes) - (bytes.to_f / (1024*1024)).round(1) + (bytes.to_f / (1024 * 1024)).round(1) end def self.sz_mb(bytes) - sz(bytes).to_s.rjust(5) + " MB" + sz(bytes).to_s.rjust(5) + ' MB' end def self.format_csv(app_sizes, devices: nil) @@ -61,14 +60,15 @@ def self.format_markdown(app_sizes, devices: nil) build_number = details['cfBundleVersion'] sizes = details['sizesInBytes'].select { |name, _| devices.include?(name) } col_size = devices.map(&:length).max - table = "| #{build_number.ljust(col_size)} | Download | Install |\n" + table = "| #{build_number.ljust(col_size)} | Download | Install |\n" table += "|:#{'-' * col_size}-|---------:|---------:|\n" - sizes.each do |(device_name, sizes)| - table += "| #{device_name.ljust(col_size)} | #{sz_mb(sizes['compressed'])} | #{sz_mb(sizes['uncompressed'])} |\n" + sizes.each do |(device_name, size_info)| + table += "| #{device_name.ljust(col_size)} | #{sz_mb(size_info['compressed'])} | #{sz_mb(size_info['uncompressed'])} |\n" end table end end end end + end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb index aaf024941..759951c3d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_git_helper.rb @@ -1,140 +1,73 @@ module Fastlane - module Helpers - module IosGitHelper - - def self.git_checkout_and_pull(branch) - Action.sh("git checkout #{branch}") - Action.sh("git pull") - end + module Helper + module Ios + # Helper methods to execute git-related operations that are specific to iOS projects + # + module GitHelper + # Commit and push the files that are modified when we bump version numbers on an iOS project + # + # This typically commits and pushes: + # - The files in `./config/*` – especially `Version.*.xcconfig` files + # - The `fastlane/Deliverfile` file (which contains the `app_version` line) + # - The `//Resources/AppStoreStrings.pot` file, containing a key for that version's release notes + # + # @env PROJECT_ROOT_FOLDER The path to the git root of the project + # @env PROJECT_NAME The name of the directory containing the project code (especially containing the Resources/ subfolder) + # + # @param [Bool] include_deliverfile If true (the default), includes the `fastlane/Deliverfile` in files being commited + # @param [Bool] include_metadata If true (the default), includes the `fastlane/download_metadata.swift` file and the `.pot` file (which typically contains an entry or release notes for the new version) + # + def self.commit_version_bump(include_deliverfile: true, include_metadata: true) + files_list = [File.join(ENV['PROJECT_ROOT_FOLDER'], 'config', '.')] + files_list.append File.join('fastlane', 'Deliverfile') if include_deliverfile + if include_metadata + files_list.append File.join('fastlane', 'download_metadata.swift') + files_list.append File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'], 'Resources', ENV['APP_STORE_STRINGS_FILE_NAME']) + end - def self.git_checkout_and_pull_release_branch_for(version) - branch_name = "release/#{version}" - Action.sh("git pull") - begin - Action.sh("git checkout #{branch_name}") - Action.sh("git pull origin #{branch_name}") - return true - rescue - return false + Fastlane::Helper::GitHelper.commit(message: 'Bump version number', files: files_list, push: true) end - end - - def self.branch_for_hotfix(tag_version, new_version) - Action.sh("git checkout #{tag_version}") - Action.sh("git checkout -b release/#{new_version}") - Action.sh("git push --set-upstream origin release/#{new_version}") - end - - def self.bump_version_release(skip_deliver=false, skip_metadata=false) - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && git add ./config/.") - Action.sh("git add fastlane/Deliverfile") unless skip_deliver - Action.sh("git add fastlane/download_metadata.swift") unless skip_metadata - Action.sh("git add #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]}/Resources/#{ENV["APP_STORE_STRINGS_FILE_NAME"]}") unless skip_metadata - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.bump_version_hotfix(version) - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && git add ./config/.") - Action.sh("git add fastlane/Deliverfile") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - - def self.bump_version_beta() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && git add ./config/.") - Action.sh("git commit -m \"Bump version number\"") - Action.sh("git push origin HEAD") - end - def self.delete_tags(version) - Action.sh("git tag | xargs git tag -d; git fetch --tags") - tags = Action.sh("git tag") - tags.split("\n").each do | tag | - if (tag.split(".").length == 4) then - if tag.start_with?(version) then - UI.message("Removing: #{tag}") - Action.sh("git tag -d #{tag}") - Action.sh("git push origin :refs/tags/#{tag}") - end + # Calls the `Scripts/localize.py` script in the project root folder and push the `*.strings` files + # + # That script updates the `.strings` files with translations from GlotPress. + # + # @env PROJECT_ROOT_FOLDER The path to the git root of the project + # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file) + # + # @todo Migrate the scripts, currently in each host repo and called by this method, to be helpers and actions + # in the release-toolkit instead, and move this code away from `ios_git_helper`. + # + def self.localize_project + Action.sh("cd #{ENV['PROJECT_ROOT_FOLDER']} && ./Scripts/localize.py") + + strings_files = Dir.chdir(File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'])) do + Dir.glob('*.lproj/*.strings') end + Fastlane::Helper::GitHelper.commit(message: 'Update strings for localization', files: strings_files, push: true) || UI.message('No new strings, skipping commit') end - end - - def self.final_tag(version) - Action.sh("git tag #{version}") - Action.sh("git push origin #{version}") - end - - def self.localize_project() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && ./Scripts/localize.py") - Action.sh("git add #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]}*.lproj/*.strings") - is_repo_clean = `git status --porcelain`.empty? - if is_repo_clean then - UI.message("No new strings, skipping commit") - else - Action.sh("git commit -m \"Updates strings for localization\"") - Action.sh("git push origin HEAD") - end - end - def self.tag_build(itc_version, internal_version) - tag_and_push(itc_version) - tag_and_push(internal_version) unless internal_version.nil? - end - - def self.update_metadata() - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && ./Scripts/update-translations.rb") - Action.sh("git add #{ENV["PROJECT_ROOT_FOLDER"]}#{ENV["PROJECT_NAME"]}/*.lproj/*.strings") - Action.sh("git diff-index --quiet HEAD || git commit -m \"Updates translation\"") - - Action.sh("cd fastlane && ./download_metadata.swift") - Action.sh("git add ./fastlane/metadata/") - Action.sh("git diff-index --quiet HEAD || git commit -m \"Updates metadata translation\"") - - Action.sh("git push origin HEAD") - end + # Call the `Scripts/update-translations.rb` then the `fastlane/download_metadata` Scripts from the host project folder + # + # @env PROJECT_ROOT_FOLDER The path to the git root of the project + # @env PROJECT_NAME The name of the directory containing the project code (especially containing the `build.gradle` file) + # + # @todo Migrate the scripts, currently in each host repo and called by this method, to be helpers and actions + # in the release-toolkit instead, and move this code away from `ios_git_helper`. + # + def self.update_metadata + Action.sh("cd #{ENV['PROJECT_ROOT_FOLDER']} && ./Scripts/update-translations.rb") + + strings_files = Dir.chdir(File.join(ENV['PROJECT_ROOT_FOLDER'], ENV['PROJECT_NAME'])) do + Dir.glob('*.lproj/*.strings') + end + Fastlane::Helper::GitHelper.commit(message: 'Update translations', files: strings_files, push: false) - def self.do_release_branch(branch_name) - if (check_branch_exists(branch_name) == true) then - UI.message("Branch #{branch_name} already exists. Skipping creation.") - Action.sh("git checkout #{branch_name}") - Action.sh("git pull origin #{branch_name}") - else - Action.sh("git checkout -b #{branch_name}") + Action.sh('cd fastlane && ./download_metadata.swift') - # Push to origin - Action.sh("git push -u origin #{branch_name}") + Fastlane::Helper::GitHelper.commit(message: 'Update metadata translations', files: './fastlane/metadata/', push: true) end end - - def self.check_branch_exists(branch_name) - !Action.sh("git branch --list #{branch_name}").empty? - end - - def self.check_on_branch(branch_name) - current_branch_name=Action.sh("git symbolic-ref -q HEAD") - UI.user_error!("This command works only on #{branch_name} branch") unless current_branch_name.include?(branch_name) - end - - def self.is_head_on_tag() - !Action.sh("git tag --points-at HEAD").empty? - end - - def self.has_final_tag_for(version) - head_tags=Action.sh("git tag --points-at HEAD").split("\n") - head_tags.each { | vtag | - if (vtag == version) - return true - end - } - return false - end - - private - def self.tag_and_push(version) - Action.sh("cd #{ENV["PROJECT_ROOT_FOLDER"]} && git tag #{version} && git push origin #{version}") - end end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb index 987023a31..8b07ea87d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_l10n_helper.rb @@ -2,8 +2,9 @@ require 'tmpdir' module Fastlane - module Helpers - class IosL10nHelper + module Helper + module Ios + class L10nHelper SWIFTGEN_VERSION = '6.4.0' DEFAULT_BASE_LANG = 'en' CONFIG_FILE_NAME = 'swiftgen-stringtypes.yml' @@ -11,7 +12,7 @@ class IosL10nHelper attr_reader :install_path attr_reader :version - # @param [String] install_path The path to install SwiftGen to. Usually something like "#{PROJECT_DIR}/vendor/swiftgen/#{SWIFTGEN_VERSION}". + # @param [String] install_path The path to install SwiftGen to. Usually something like "$PROJECT_DIR/vendor/swiftgen/#{SWIFTGEN_VERSION}". # It's recommended to provide an absolute path here rather than a relative one, to ensure it's not dependant on where the action is run from. # @param [String] version The version of SwiftGen to use. This will be used both: # - to check if the current version located in `install_path`, if it already exists, is the expected one @@ -25,7 +26,8 @@ def initialize(install_path:, version: SWIFTGEN_VERSION) # Check if SwiftGen is installed in the provided `install_path` and if so if the installed version matches the expected `version` # def check_swiftgen_installed - return false unless File.exists?(swiftgen_bin) + return false unless File.exist?(swiftgen_bin) + vers_string = `#{swiftgen_bin} --version` # The SwiftGen version string has this format: # @@ -37,7 +39,7 @@ def check_swiftgen_installed # Download the ZIP of SwiftGen for the requested `version` and install it in the `install_path` # - # @warning This action nukes anything at `install_path` – if something already exists – prior to install SwiftGen there + # @note This action nukes anything at `install_path` – if something already exists – prior to install SwiftGen there # def install_swiftgen! UI.message "Installing SwiftGen #{version} into #{install_path}" @@ -47,7 +49,7 @@ def install_swiftgen! extracted_dir = File.join(tmpdir, "swiftgen-#{version}") Action.sh('unzip', zipfile, '-d', extracted_dir) - FileUtils.rm_rf(install_path) if File.exists?(install_path) + FileUtils.rm_rf(install_path) if File.exist?(install_path) FileUtils.mkdir_p(install_path) FileUtils.cp_r("#{extracted_dir}/.", install_path) end @@ -68,7 +70,7 @@ def run(input_dir:, base_lang: DEFAULT_BASE_LANG, only_langs: nil) ################## private - + # Path to the swiftgen binary installed at install_path def swiftgen_bin "#{install_path}/bin/swiftgen" @@ -78,24 +80,24 @@ def swiftgen_bin def output_filename(lang) "L10nParamsList.#{lang}.txt" end - + # The Stencil template that we want SwiftGen to use to generate the output. # It iterates on every "table" (`.strings` file, in most cases there's only one, `Localizable.strings`), # and for each, iterates on every entry found to print the key and the corresponding types parsed by SwiftGen from the placeholders found in that translation def template_content <<~TEMPLATE - {% macro recursiveBlock table item %} - {% for string in item.strings %} - "{{string.key}}" => [{{string.types|join:","}}] - {% endfor %} - {% for child in item.children %} - {% call recursiveBlock table child %} + {% macro recursiveBlock table item %} + {% for string in item.strings %} + "{{string.key}}" => [{{string.types|join:","}}] + {% endfor %} + {% for child in item.children %} + {% call recursiveBlock table child %} + {% endfor %} + {% endmacro %} + + {% for table in tables %} + {% call recursiveBlock table.name table.levels %} {% endfor %} - {% endmacro %} - - {% for table in tables %} - {% call recursiveBlock table.name table.levels %} - {% endfor %} TEMPLATE end @@ -110,31 +112,31 @@ def generate_swiftgen_config!(input_dir, output_dir, only_langs: nil) # Dynamically create a SwiftGen config which will cover all supported languages langs = Dir.chdir(input_dir) do - Dir.glob('*.lproj/Localizable.strings').map { |loc_file| File.basename(File.dirname(loc_file), '.lproj') } + Dir.glob('*.lproj/Localizable.strings').map { |loc_file| File.basename(File.dirname(loc_file), '.lproj') } end.sort langs.select! { |lang| only_langs.include?(lang) } unless only_langs.nil? - + config = { 'input_dir' => input_dir, 'output_dir' => output_dir, 'strings' => langs.map do |lang| { - 'inputs' => ["#{lang}.lproj/Localizable.strings"], - # Choose an unlikely separator (instead of the default '.') to avoid creating needlessly complex Stencil Context nested - # structure just because we have '.' in the English sentences we use (instead of structured reverse-dns notation) for the keys - 'options' => { 'separator' => "____" }, - 'outputs' => [{ - 'templatePath' => template_path, - 'output' => output_filename(lang) - }] + 'inputs' => ["#{lang}.lproj/Localizable.strings"], + # Choose an unlikely separator (instead of the default '.') to avoid creating needlessly complex Stencil Context nested + # structure just because we have '.' in the English sentences we use (instead of structured reverse-dns notation) for the keys + 'options' => { 'separator' => '____' }, + 'outputs' => [{ + 'templatePath' => template_path, + 'output' => output_filename(lang) + }] } end } - + # Write SwiftGen config file config_file = File.join(output_dir, CONFIG_FILE_NAME) File.write(config_file, config.to_yaml) - + return [config_file, langs] end @@ -147,7 +149,8 @@ def generate_swiftgen_config!(input_dir, output_dir, only_langs: nil) # def sort_file_lines!(dir, lang) file = File.join(dir, output_filename(lang)) - return nil unless File.exists?(file) + return nil unless File.exist?(file) + sorted_lines = File.readlines(file).sort File.write(file, sorted_lines.join) return file @@ -164,11 +167,11 @@ def sort_file_lines!(dir, lang) # def find_diffs(input_dir:, base_lang:, only_langs: nil) Dir.mktmpdir('a8c-lint-translations-') do |tmpdir| - # Run SwiftGen + # Run SwiftGen langs = only_langs.nil? ? nil : (only_langs + [base_lang]).uniq (config_file, langs) = generate_swiftgen_config!(input_dir, tmpdir, only_langs: langs) Action.sh(swiftgen_bin, 'config', 'run', '--config', config_file) - + # Run diffs base_file = sort_file_lines!(tmpdir, base_lang) langs.delete(base_lang) @@ -176,6 +179,7 @@ def find_diffs(input_dir:, base_lang:, only_langs: nil) file = sort_file_lines!(tmpdir, lang) # If the lang ends up not having any translation at all (e.g. a `.lproj` without any `.strings` file in it but maybe just a storyboard or assets catalog), ignore it next nil if file.nil? || only_empty_lines?(file) + # Compute the diff diff = `diff -U0 "#{base_file}" "#{file}"` # Remove the lines starting with `---`/`+++` which contains the file names (which are temp files we don't want to expose in the final diff to users) @@ -191,13 +195,14 @@ def find_diffs(input_dir:, base_lang:, only_langs: nil) # Returns true if the file only contains empty lines, i.e. lines that only contains whitespace (space, tab, CR, LF) def only_empty_lines?(file) - File.open(file) do |f| - while line = f.gets - return false if not line.strip.empty? - end - end + File.open(file) do |f| + while (line = f.gets) + return false unless line.strip.empty? + end + end return true end end end + end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb index 0d4a11a26..16059c4b4 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/ios/ios_version_helper.rb @@ -1,128 +1,244 @@ module Fastlane - module Helpers - module IosVersionHelper + module Helper + module Ios + # A module containing helper methods to manipulate/extract/bump iOS version strings in xcconfig files + # + module VersionHelper + # The index for the major version number part MAJOR_NUMBER = 0 + # The index for the minor version number part MINOR_NUMBER = 1 + # The index for the hotfix version number part HOTFIX_NUMBER = 2 + # The index for the build version number part BUILD_NUMBER = 3 - + + # Returns the public-facing version string. + # + # @return [String] The public-facing version number, extracted from the VERSION_LONG entry of the xcconfig file. + # - If this version is a hotfix (more than 2 parts and 3rd part is non-zero), returns the "X.Y.Z" formatted string + # - Otherwise (not a hotfix / 3rd part of version is 0), returns "X.Y" formatted version number + # def self.get_public_version version = get_build_version vp = get_version_parts(version) - return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix(version) + return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" unless is_hotfix?(version) + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}" end - + + # Compute the name of the next release version. + # + # @param [String] version The current version that we want to increment + # + # @return [String] The predicted next version, in the form of "X.Y". + # Corresponds to incrementing the minor part, except if it reached 10 + # (in that case we go to the next major version, as decided in our versioning conventions) + # def self.calc_next_release_version(version) vp = get_version_parts(version) vp[MINOR_NUMBER] += 1 - if (vp[MINOR_NUMBER] == 10) + if vp[MINOR_NUMBER] == 10 vp[MAJOR_NUMBER] += 1 vp[MINOR_NUMBER] = 0 end - + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end - + + # Return the short version string "X.Y" from the full version. + # + # @param [String] version The version to convert to a short version + # + # @return [String] A version string consisting of only the first 2 parts "X.Y" + # def self.get_short_version_string(version) vp = get_version_parts(version) "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end + # Compute the name of the previous release version. + # + # @param [String] version The current version we want to decrement + # + # @return [String] The predicted previous version, in the form of "X.Y". + # Corresponds to decrementing the minor part, or decrement the major and set minor to 9 if minor was 0. + # def self.calc_prev_release_version(version) vp = get_version_parts(version) - if (vp[MINOR_NUMBER] == 0) + if vp[MINOR_NUMBER] == 0 vp[MAJOR_NUMBER] -= 1 vp[MINOR_NUMBER] = 9 else vp[MINOR_NUMBER] -= 1 end - + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end - + + # Compute the name of the next build version. + # + # @param [String] version The current version we want to increment + # + # @return [String] The predicted next build version, in the form of "X.Y.Z.N". + # Corresponds to incrementing the last (4th) component N of the version. + # def self.calc_next_build_version(version) vp = get_version_parts(version) vp[BUILD_NUMBER] += 1 "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}.#{vp[BUILD_NUMBER]}" end - + + # Compute the name of the next hotfix version. + # + # @param [String] version The current version we want to increment + # + # @return [String] The predicted next hotfix version, in the form of "X.Y.Z". + # Corresponds to incrementing the 3rd component of the version. + # def self.calc_next_hotfix_version(version) vp = get_version_parts(version) vp[HOTFIX_NUMBER] += 1 "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}" end - + + # Compute the name of the previous build version. + # + # @param [String] version The current version we want to decrement + # + # @return [String] The predicted previous build version, in the form of "X.Y.Z.N". + # Corresponds to decrementing the last (4th) component N of the version. + # def self.calc_prev_build_version(version) vp = get_version_parts(version) vp[BUILD_NUMBER] -= 1 unless vp[BUILD_NUMBER] == 0 "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}.#{vp[BUILD_NUMBER]}" end - + + # Compute the name of the previous hotfix version. + # + # @param [String] version The current version we want to decrement + # + # @return [String] The predicted previous hotfix version, in the form of "X.Y.Z", or "X.Y" if Z is 0. + # Corresponds to decrementing the 3rd component Z of the version, striping it if it ends up being zero. + # def self.calc_prev_hotfix_version(version) vp = get_version_parts(version) vp[HOTFIX_NUMBER] -= 1 unless vp[HOTFIX_NUMBER] == 0 return "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}" unless vp[HOTFIX_NUMBER] == 0 + "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}" end + # Create an internal version number, for which the build number is based on today's date. + # + # @param [String] version The current version to create an internal version name for. + # + # @return [String] The internal version, in the form of "X.Y.Z.YYYYMMDD". + # def self.create_internal_version(version) vp = get_version_parts(version) d = DateTime.now - todayDate = d.strftime("%Y%m%d") + todayDate = d.strftime('%Y%m%d') "#{vp[MAJOR_NUMBER]}.#{vp[MINOR_NUMBER]}.#{vp[HOTFIX_NUMBER]}.#{todayDate}" end - + + # Return the build number value incremented by one. + # + # @param [String|Int|nil] build_number The build number to increment + # + # @return [Int] The incremented build number, or 0 if it was `nil`. + # def self.bump_build_number(build_number) build_number.nil? ? 0 : build_number.to_i + 1 end - def self.is_hotfix(version) + # Determines if a version number corresponds to a hotfix + # + # @param [String] version The version number to test + # + # @return [Bool] True if the version number has a non-zero 3rd component, meaning that it is a hotfix version. + # + def self.is_hotfix?(version) vp = get_version_parts(version) return (vp.length > 2) && (vp[HOTFIX_NUMBER] != 0) end - + + # Returns the current value of the `VERSION_LONG` key from the public xcconfig file + # + # @return [String] The current version according to the public xcconfig file. + # def self.get_build_version versions = get_version_strings()[0] end - + + # Returns the current value of the `VERSION_LONG` key from the internal xcconfig file + # + # @return [String] The current version according to the internal xcconfig file. + # def self.get_internal_version get_version_strings()[1] end - + + # Prints the current and next release version numbers to stdout, then return the next release version + # + # @return [String] The next release version to use after bumping the currently used public version. + # def self.bump_version_release # Bump release - current_version=get_public_version() + current_version = get_public_version() UI.message("Current version: #{current_version}") - new_version=calc_next_release_version(current_version) + new_version = calc_next_release_version(current_version) UI.message("New version: #{new_version}") - verified_version=verify_version(new_version) + verified_version = verify_version(new_version) return verified_version end + # Updates the `app_version` entry in the `Deliverfile` + # + # @param [String] new_version The new value to set the `app_version` entry to. + # @raise [UserError] If the Deliverfile was not found. + # def self.update_fastlane_deliver(new_version) - fd_file = "./fastlane/Deliverfile" - if (File.exist?(fd_file)) then + fd_file = './fastlane/Deliverfile' + if File.exist?(fd_file) Action.sh("sed -i '' \"s/app_version.*/app_version \\\"#{new_version}\\\"/\" #{fd_file}") else UI.user_error!("Can't find #{fd_file}.") end end + # Update the `.xcconfig` files (the public one, and the internal one if it exists) with the new version strings. + # + # @env PUBLIC_CONFIG_FILE The path to the xcconfig file containing the public version numbers. + # @env INTERNAL_CONFIG_FILE The path to the xcconfig file containing the internal version numbers. Can be nil. + # + # @param [String] new_version The new version number to use as `VERSION_LONG` for the public xcconfig file + # @param [String] new_version_short The new version number to use for `VERSION_SHORT` (for both public and internal xcconfig files) + # @param [String] internal_version The new version number to use as `VERSION_LONG` for the interrnal xcconfig file, if it exists + # def self.update_xc_configs(new_version, new_version_short, internal_version) - update_xc_config(ENV["PUBLIC_CONFIG_FILE"], new_version, new_version_short) - update_xc_config(ENV["INTERNAL_CONFIG_FILE"], internal_version, new_version_short) unless ENV["INTERNAL_CONFIG_FILE"].nil? + update_xc_config(ENV['PUBLIC_CONFIG_FILE'], new_version, new_version_short) + update_xc_config(ENV['INTERNAL_CONFIG_FILE'], internal_version, new_version_short) unless ENV['INTERNAL_CONFIG_FILE'].nil? end + # Updates an xcconfig file with new values for VERSION_SHORT and VERSION_LONG entries. + # Also bumps the BUILD_NUMBER value from that config file if there is one present. + # + # @param [String] file_path The path to the xcconfig file + # @param [String] new_version The new version number to use for VERSION_LONG + # @param [String] new_version_short The new version number to use for VERSION_SHORT + # @raise [UserError] If the xcconfig file was not found + # def self.update_xc_config(file_path, new_version, new_version_short) - if File.exist?(file_path) then + if File.exist?(file_path) UI.message("Updating #{file_path} to version #{new_version_short}/#{new_version}") - Action.sh("sed -i '' \"$(awk '/^VERSION_SHORT/{ print NR; exit }' \"#{file_path}\")s/=.*/=#{new_version_short}/\" \"#{file_path}\"") + Action.sh("sed -i '' \"$(awk '/^VERSION_SHORT/{ print NR; exit }' \"#{file_path}\")s/=.*/=#{new_version_short}/\" \"#{file_path}\"") Action.sh("sed -i '' \"$(awk '/^VERSION_LONG/{ print NR; exit }' \"#{file_path}\")s/=.*/=#{new_version}/\" \"#{file_path}\"") build_number = read_build_number_from_config_file(file_path) - unless (build_number.nil?) + unless build_number.nil? new_build_number = bump_build_number(build_number) Action.sh("sed -i '' \"$(awk '/^BUILD_NUMBER/{ print NR; exit }' \"#{file_path}\")s/=.*/=#{new_build_number}/\" \"#{file_path}\"") end @@ -131,62 +247,102 @@ def self.update_xc_config(file_path, new_version, new_version_short) end end - private - + #---------------------------------------- + private + + # Split a version string into its 4 parts, ensuring its parts count is valid + # + # @param [String] version The version string to split into parts + # @return [Array] An array of exactly 4 elements, containing each part of the version string. + # @note If the original version string contains less than 4 parts, the returned array is filled with zeros at the end to always contain 4 items. + # @raise [UserError] Interrupts the lane if the provided version contains _more_ than 4 parts + # def self.get_version_parts(version) - parts=version.split(".") - parts=parts.fill("0", parts.length...4).map{|chr| chr.to_i} - if (parts.length > 4) then - UI.user_error!("Bad version string: #{version}") - end + parts = version.split('.') + parts = parts.fill('0', parts.length...4).map { |chr| chr.to_i } + UI.user_error!("Bad version string: #{version}") if parts.length > 4 return parts end - + + # Extract the VERSION_LONG entry from an `xcconfig` file + # + # @param [String] filePath The path to the `.xcconfig` file to read the value from + # @return [String] The long version found in said xcconfig file, or nil if not found + # def self.read_long_version_from_config_file(filePath) - read_from_config_file("VERSION_LONG", filePath) + read_from_config_file('VERSION_LONG', filePath) end + # Extract the BUILD_NUMBER entry from an `xcconfig` file + # + # @param [String] filePath The path to the `.xcconfig` file to read the value from + # @return [String] The build number found in said xcconfig file, or nil if not found + # def self.read_build_number_from_config_file(filePath) - read_from_config_file("BUILD_NUMBER", filePath) + read_from_config_file('BUILD_NUMBER', filePath) end + # Read the value of a given key from an `.xcconfig` file. + # + # @param [String] key The xcconfig key to get the value for + # @param [String] filePath The path to the `.xcconfig` file to read the value from + # + # @return [String] The value for the given key, or `nil` if the key was not found. + # def self.read_from_config_file(key, filePath) - File.open(filePath, "r") do |f| + File.open(filePath, 'r') do |f| f.each_line do |line| line = line.strip() - if line.start_with?("#{key}=") then - return line.split("=")[1] - end - end + return line.split('=')[1] if line.start_with?("#{key}=") + end end return nil end + # Read the version numbers from the xcconfig file + # + # @env PUBLIC_CONFIG_FILE The path to the xcconfig file containing the public version numbers. + # @env INTERNAL_CONFIG_FILE The path to the xcconfig file containing the internal version numbers. Can be nil. + # + # @return [String] Array of long version strings found. + # The first element is always present and contains the version extracted from the public config file + # The second element is the version extracted from the internal config file, only present if one was provided. def self.get_version_strings - version_strings = Array.new - version_strings << read_long_version_from_config_file(ENV["PUBLIC_CONFIG_FILE"]) - version_strings << read_long_version_from_config_file(ENV["INTERNAL_CONFIG_FILE"]) unless ENV["INTERNAL_CONFIG_FILE"].nil? + version_strings = [] + version_strings << read_long_version_from_config_file(ENV['PUBLIC_CONFIG_FILE']) + version_strings << read_long_version_from_config_file(ENV['INTERNAL_CONFIG_FILE']) unless ENV['INTERNAL_CONFIG_FILE'].nil? return version_strings end + # Ensure that the version provided is only composed of number parts and return the validated string + # + # @param [String] version The version string to validate + # @return [String] The version string, re-validated as being a string of the form `X.Y.Z.T` + # @raise [UserError] Interrupts the lane with a user_error! if the version contains non-numberic parts + # def self.verify_version(version) v_parts = get_version_parts(version) - - v_parts.each do | part | - if (!is_number?(part)) then - UI.user_error!("Version value can only contains numbers.") - end + + v_parts.each do |part| + UI.user_error!('Version value can only contains numbers.') unless is_int?(part) end "#{v_parts[MAJOR_NUMBER]}.#{v_parts[MINOR_NUMBER]}.#{v_parts[HOTFIX_NUMBER]}.#{v_parts[BUILD_NUMBER]}" end - def self.is_number? string - true if Float(string) rescue false + # Check if a string is an integer + # + # @param [String] string The string to test + # + # @return [Bool] true if the string is representing an integer value, false if not + # + def self.is_int? string + true if Integer(string) rescue false end end end - end \ No newline at end of file + end +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb index 8b5d8ac4e..cce5b52d6 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_download_helper.rb @@ -3,7 +3,6 @@ module Fastlane module Helper - class MetadataDownloader attr_reader :target_folder, :target_files @@ -13,36 +12,34 @@ def initialize(target_folder, target_files) @alternates = {} end - # Downloads data from GlotPress, + # Downloads data from GlotPress, # in JSON format def download(target_locale, glotpress_url, is_source) uri = URI(glotpress_url) response = Net::HTTP.get_response(uri) - if response.code == "301" - response = Net::HTTP.get_response(URI.parse(response.header['location'])) - end + response = Net::HTTP.get_response(URI.parse(response.header['location'])) if response.code == '301' @alternates.clear loc_data = JSON.parse(response.body) rescue loc_data = nil - parse_data(target_locale, loc_data, is_source) - reparse_alternates(target_locale, loc_data, is_source) unless (@alternates.length == 0) + parse_data(target_locale, loc_data, is_source) + reparse_alternates(target_locale, loc_data, is_source) unless @alternates.length == 0 end # Parse JSON data and update the local files def parse_data(target_locale, loc_data, is_source) delete_existing_metadata(target_locale) - - if (loc_data == nil) + + if loc_data.nil? UI.message "No translation available for #{target_locale}" return end - - loc_data.each do | d | + + loc_data.each do |d| key = d[0].split(/\u0004/).first source = d[0].split(/\u0004/).last - target_files.each do | file | - if (file[0].to_s == key) + target_files.each do |file| + if file[0].to_s == key data = file[1] msg = is_source ? source : d[1] update_key(target_locale, key, file, data, msg) @@ -53,13 +50,13 @@ def parse_data(target_locale, loc_data, is_source) # Parse JSON data and update the local files def reparse_alternates(target_locale, loc_data, is_source) - loc_data.each do | d | + loc_data.each do |d| key = d[0].split(/\u0004/).first source = d[0].split(/\u0004/).last - @alternates.each do | file | - puts "Data: #{file[0].to_s} - key: #{key}" - if (file[0].to_s == key) + @alternates.each do |file| + puts "Data: #{file[0]} - key: #{key}" + if file[0].to_s == key puts "Alternate: #{key}" data = file[1] msg = is_source ? source : d[1] @@ -70,11 +67,11 @@ def reparse_alternates(target_locale, loc_data, is_source) end def update_key(target_locale, key, file, data, msg) - message_len = msg.to_s.length - 4 # Don't count JSON delimiters. - if (data.key?(:max_size)) && (data[:max_size] != 0) && ((message_len) > data[:max_size]) then - if (data.key?(:alternate_key)) then + message_len = msg.to_s.length - 4 # Don't count JSON delimiters. + if (data.key?(:max_size)) && (data[:max_size] != 0) && ((message_len) > data[:max_size]) + if data.key?(:alternate_key) UI.message("#{target_locale} translation for #{key} exceeds maximum length (#{message_len}). Switching to the alternate translation.") - @alternates[data[:alternate_key]] = {desc: data[:desc], max_size: 0 } + @alternates[data[:alternate_key]] = { desc: data[:desc], max_size: 0 } else UI.message("Rejecting #{target_locale} traslation for #{key}: translation length: #{message_len} - max allowed length: #{data[:max_size]}") end @@ -87,26 +84,24 @@ def update_key(target_locale, key, file, data, msg) # to the target file def save_metadata(locale, file_name, content) file_path = get_target_file_path(locale, file_name) - + dir_path = File.dirname(file_path) - FileUtils.mkdir_p(dir_path) unless File.exists?(dir_path) + FileUtils.mkdir_p(dir_path) unless File.exist?(dir_path) - File.open(file_path, "w") { |file| file.puts(content) } + File.open(file_path, 'w') { |file| file.puts(content) } end # Some small helpers def delete_existing_metadata(target_locale) - @target_files.each do | file | + @target_files.each do |file| file_path = get_target_file_path(target_locale, file[1][:desc]) - File.delete(file_path) if File.exists? file_path + File.delete(file_path) if File.exist? file_path end end - + def get_target_file_path(locale, file_name) "#{@target_folder}/#{locale}/#{file_name}" end end - - end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb index 0cb74bcac..2f0a14fc3 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/metadata_update_helper.rb @@ -1,6 +1,5 @@ module Fastlane module Helper - # Basic line handler class MetadataBlock attr_reader :block_key @@ -18,15 +17,15 @@ def is_handler_for(key) end end - class UnknownMetadataBlock < MetadataBlock + class UnknownMetadataBlock < MetadataBlock attr_reader :content_file_path - def initialize() + def initialize super(nil) end end - class StandardMetadataBlock < MetadataBlock + class StandardMetadataBlock < MetadataBlock attr_reader :content_file_path def initialize(block_key, content_file_path) @@ -39,47 +38,45 @@ def is_handler_for(key) end def handle_line(fw, line) - # put the new content on block start + # put the new content on block start # and skip all the other content - if line.start_with?('msgctxt') - generate_block(fw) - end + generate_block(fw) if line.start_with?('msgctxt') end def generate_block(fw) # init fw.puts("msgctxt \"#{@block_key}\"") - line_count = File.foreach(@content_file_path).inject(0) {|c, line| c+1} + line_count = File.foreach(@content_file_path).inject(0) { |c, _line| c + 1 } - if (line_count <= 1) + if line_count <= 1 # Single line output - fw.puts("msgid \"#{File.open(@content_file_path, "r").read}\"") + fw.puts("msgid \"#{File.open(@content_file_path, 'r').read}\"") else # Multiple line output - fw.puts("msgid \"\"") + fw.puts('msgid ""') # insert content - sf = File.open(@content_file_path, "r").to_a - sf.each do | line | - l = "\"#{line.strip}" - l << "\\n" unless line == sf.last - l << "\"" + sf = File.open(@content_file_path, 'r').to_a + sf.each do |line| + l = "\"#{line.strip}" + l << '\\n' unless line == sf.last + l << '"' fw.puts(l) end end # close - fw.puts("msgstr \"\"") - fw.puts("") + fw.puts('msgstr ""') + fw.puts('') end end - class ReleaseNoteMetadataBlock < StandardMetadataBlock + class ReleaseNoteMetadataBlock < StandardMetadataBlock attr_reader :new_key, :keep_key, :rel_note_key, :release_version def initialize(block_key, content_file_path, release_version) super(block_key, content_file_path) - @rel_note_key = "release_note" + @rel_note_key = 'release_note' @release_version = release_version generate_keys(release_version) end @@ -98,7 +95,7 @@ def generate_keys(release_version) def is_handler_for(key) values = key.split('_') - key.start_with?(@rel_note_key) && values.length == 3 && (Integer(values[2]) != nil rescue false) + key.start_with?(@rel_note_key) && values.length == 3 && (!Integer(values[2]).nil? rescue false) end def handle_line(fw, line) @@ -107,30 +104,26 @@ def handle_line(fw, line) if line.start_with?('msgctxt') key = extract_key(line) @is_copying = (key == @keep_key) - if (@is_copying) - generate_block(fw) - end - end - - if (@is_copying) - fw.puts(line) + generate_block(fw) if @is_copying end + + fw.puts(line) if @is_copying end def generate_block(fw) # init fw.puts("msgctxt \"#{@new_key}\"") - fw.puts("msgid \"\"") + fw.puts('msgid ""') fw.puts("\"#{@release_version}:\\n\"") # insert content - File.open(@content_file_path, "r").each do | line | + File.open(@content_file_path, 'r').each do |line| fw.puts("\"#{line.strip}\\n\"") end # close - fw.puts("msgstr \"\"") - fw.puts("") + fw.puts('msgstr ""') + fw.puts('') end def extract_key(line) @@ -138,12 +131,12 @@ def extract_key(line) end end - class WhatsNewMetadataBlock < StandardMetadataBlock + class WhatsNewMetadataBlock < StandardMetadataBlock attr_reader :new_key, :old_key, :rel_note_key, :release_version def initialize(block_key, content_file_path, release_version) super(block_key, content_file_path) - @rel_note_key = "whats_new" + @rel_note_key = 'whats_new' @release_version = release_version generate_keys(release_version) end @@ -161,32 +154,29 @@ def generate_keys(release_version) end def is_handler_for(key) - key.start_with?("v") && key.end_with?("-whats-new") + key.start_with?('v') && key.end_with?('-whats-new') end def handle_line(fw, line) # put content on block start or if copying the latest one # and skip all the other content - if line.start_with?('msgctxt') - generate_block(fw) - end + generate_block(fw) if line.start_with?('msgctxt') end def generate_block(fw) # init fw.puts("msgctxt \"#{@new_key}\"") - fw.puts("msgid \"\"") + fw.puts('msgid ""') # insert content - File.open(@content_file_path, "r").each do | line | + File.open(@content_file_path, 'r').each do |line| fw.puts("\"#{line.strip}\\n\"") end # close - fw.puts("msgstr \"\"") - fw.puts("") + fw.puts('msgstr ""') + fw.puts('') end end - end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb index 2dc43e3b1..d6e4fdeaa 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/promo_screenshots_helper.rb @@ -20,13 +20,12 @@ module Fastlane module Helper class PromoScreenshots - def initialize - if ($skip_magick) + if $skip_magick message = "PromoScreenshots feature is currently disabled.\n" message << "Please, install RMagick if you aim to generate the PromoScreenshots.\n" message << "\'bundle install --with screenshots\' should do it if your project is configured for PromoScreenshots.\n" - message << "Aborting." + message << 'Aborting.' UI.user_error!(message) end end @@ -37,31 +36,26 @@ def read_json(configFilePath) begin return JSON.parse(open(configFilePath).read) rescue - linter = JsonLint::Linter.new - linter.check(configFilePath) - linter.display_errors + linter = JsonLint::Linter.new + linter.check(configFilePath) + linter.display_errors - UI.user_error!("Invalid JSON configuration. See errors in log.") + UI.user_error!('Invalid JSON configuration. See errors in log.') end end - def draw_caption_to_canvas(entry, canvas, device, stylesheet_path = "") - + def draw_caption_to_canvas(entry, canvas, device, stylesheet_path = '') # If no caption is provided, it's ok to skip the body of this method - if entry["text"] == nil - return canvas - end + return canvas if entry['text'].nil? - text = entry["text"] - text_size = device["text_size"] - font_size = device["font_size"] - locale = entry["locale"] + text = entry['text'] + text_size = device['text_size'] + font_size = device['font_size'] + locale = entry['locale'] text = resolve_text_into_path(text, locale) - if can_resolve_path(stylesheet_path) - stylesheet_path = resolve_path(stylesheet_path) - end + stylesheet_path = resolve_path(stylesheet_path) if can_resolve_path(stylesheet_path) width = text_size[0] height = text_size[1] @@ -69,32 +63,30 @@ def draw_caption_to_canvas(entry, canvas, device, stylesheet_path = "") x_position = 0 y_position = 0 - if device["text_offset"] != nil - x_position = device["text_offset"][0] - y_position = device["text_offset"][1] + unless device['text_offset'].nil? + x_position = device['text_offset'][0] + y_position = device['text_offset'][1] end - draw_text_to_canvas( canvas, - text, - width, - height, - x_position, - y_position, - font_size, - stylesheet_path - ) + draw_text_to_canvas(canvas, + text, + width, + height, + x_position, + y_position, + font_size, + stylesheet_path) end def draw_background_to_canvas(canvas, entry) - - if entry["background"] != nil + unless entry['background'].nil? # If we're passed an image path, let's open it and paint it to the canvas - if can_resolve_path(entry["background"]) - background_image = open_image(entry["background"]) + if can_resolve_path(entry['background']) + background_image = open_image(entry['background']) return composite_image(canvas, background_image, 0, 0) - else # Otherwise, let's assume this is a colour code - background_image = create_image(canvas.columns, canvas.rows, entry["background"]) + else # Otherwise, let's assume this is a colour code + background_image = create_image(canvas.columns, canvas.rows, entry['background']) canvas = composite_image(canvas, background_image, 0, 0) end end @@ -103,173 +95,155 @@ def draw_background_to_canvas(canvas, entry) end def draw_device_frame_to_canvas(device, canvas) - # Apply the device frame to the canvas, but only if one is provided - unless device["device_frame_size"] != nil - return canvas - end + return canvas if device['device_frame_size'].nil? - w = device["device_frame_size"][0] - h = device["device_frame_size"][1] + w = device['device_frame_size'][0] + h = device['device_frame_size'][1] x = 0 y = 0 - if device["device_frame_size"] != nil - x = device["device_frame_offset"][0] - y = device["device_frame_offset"][1] + unless device['device_frame_size'].nil? + x = device['device_frame_offset'][0] + y = device['device_frame_offset'][1] end - device_frame = open_image(device["device_frame"]) + device_frame = open_image(device['device_frame']) device_frame = resize_image(device_frame, w, h) composite_image(canvas, device_frame, x, y) end def draw_screenshot_to_canvas(entry, canvas, device) - # Don't require a screenshot to be present – we can just skip # this function if one doesn't exist. - unless entry["screenshot"] != nil - return canvas - end + return canvas if entry['screenshot'].nil? - device_mask = device["screenshot_mask"] - screenshot_size = device["screenshot_size"] - screenshot_offset = device["screenshot_offset"] + device_mask = device['screenshot_mask'] + screenshot_size = device['screenshot_size'] + screenshot_offset = device['screenshot_offset'] - screenshot = entry["screenshot"] + screenshot = entry['screenshot'] screenshot = open_image(screenshot) - if device_mask != nil - screenshot = mask_image(screenshot, open_image(device_mask)) - end + screenshot = mask_image(screenshot, open_image(device_mask)) unless device_mask.nil? screenshot = resize_image(screenshot, screenshot_size[0], screenshot_size[1]) composite_image(canvas, screenshot, screenshot_offset[0], screenshot_offset[1]) end def draw_attachments_to_canvas(entry, canvas) - - entry["attachments"].each { |attachment| - if attachment["file"] != nil + entry['attachments'].each do |attachment| + if !attachment['file'].nil? canvas = draw_file_attachment_to_canvas(attachment, canvas, entry) - elsif attachment["text"] != nil - canvas = draw_text_attachment_to_canvas(attachment, canvas, entry["locale"]) + elsif !attachment['text'].nil? + canvas = draw_text_attachment_to_canvas(attachment, canvas, entry['locale']) end - } - + end + return canvas end def draw_file_attachment_to_canvas(attachment, canvas, entry) + file = resolve_path(attachment['file']) - file = resolve_path(attachment["file"]) - - image = open_image(file) + image = open_image(file) - if attachment.member?("operations") - - attachment["operations"].each { |operation| - image = apply_operation(image, operation, canvas) - } + if attachment.member?('operations') + attachment['operations'].each do |operation| + image = apply_operation(image, operation, canvas) end - size = attachment["size"] + end + + size = attachment['size'] - x_pos = attachment["position"][0] - y_pos = attachment["position"][1] + x_pos = attachment['position'][0] + y_pos = attachment['position'][1] - if attachment["offset"] != nil - x_pos += attachment["offset"][0] - y_pos += attachment["offset"][1] - end + unless attachment['offset'].nil? + x_pos += attachment['offset'][0] + y_pos += attachment['offset'][1] + end - image = resize_image(image, size[0], size[1]) - canvas = composite_image(canvas, image, x_pos, y_pos) + image = resize_image(image, size[0], size[1]) + canvas = composite_image(canvas, image, x_pos, y_pos) end def draw_text_attachment_to_canvas(attachment, canvas, locale) + text = resolve_text_into_path(attachment['text'], locale) + font_size = attachment['font-size'] ||= 12 - text = resolve_text_into_path(attachment["text"], locale) - font_size = attachment["font-size"] ||= 12 + width = attachment['size'][0] + height = attachment['size'][1] - width = attachment["size"][0] - height = attachment["size"][1] + x_position = attachment['position'][0] ||= 0 + y_position = attachment['position'][1] ||= 0 - x_position = attachment["position"][0] ||= 0 - y_position = attachment["position"][1] ||= 0 + stylesheet_path = attachment['stylesheet'] + stylesheet_path = resolve_path(stylesheet_path) if can_resolve_path(stylesheet_path) - stylesheet_path = attachment["stylesheet"] - if can_resolve_path(stylesheet_path) - stylesheet_path = resolve_path(stylesheet_path) - end + alignment = attachment['alignment'] ||= 'center' - alignment = attachment["alignment"] ||= 'center' - - draw_text_to_canvas( canvas, - text, - width, - height, - x_position, - y_position, - font_size, - stylesheet_path, - alignment - ) + draw_text_to_canvas(canvas, + text, + width, + height, + x_position, + y_position, + font_size, + stylesheet_path, + alignment) end def apply_operation(image, operation, canvas) - - return case operation["type"] - when "crop" - x_pos = operation["at"][0] - y_pos = operation["at"][1] - - width = operation["to"][0] - height = operation["to"][1] + case operation['type'] + when 'crop' + x_pos = operation['at'][0] + y_pos = operation['at'][1] - crop_image(image, x_pos, y_pos, width, height) + width = operation['to'][0] + height = operation['to'][1] - when "resize" - width = operation["to"][0] - height = operation["to"][1] + crop_image(image, x_pos, y_pos, width, height) - resize_image(image, width, height) + when 'resize' + width = operation['to'][0] + height = operation['to'][1] - when "composite" + resize_image(image, width, height) - x_pos = operation["at"][0] - y_pos = operation["at"][1] + when 'composite' - if operation.member?("offset") - x_pos += operation["offset"][0] - y_pos += operation["offset"][1] - end + x_pos = operation['at'][0] + y_pos = operation['at'][1] - composite_image(canvas, image, x_pos, y_pos) + if operation.member?('offset') + x_pos += operation['offset'][0] + y_pos += operation['offset'][1] end + + composite_image(canvas, image, x_pos, y_pos) + end end def draw_text_to_canvas(canvas, text, width, height, x_position, y_position, font_size, stylesheet_path, position = 'center') begin - tempTextFile = Tempfile.new() command = "bundle exec drawText html=\"#{text}\" maxWidth=#{width} maxHeight=#{height} output=#{tempTextFile.path} fontSize=#{font_size} stylesheet=\"#{stylesheet_path}\" alignment=\"#{position}\"" - unless system(command) - UI.crash!("Unable to draw text") - end + UI.crash!('Unable to draw text') unless system(command) text_content = open_image(tempTextFile.path).trim text_frame = create_image(width, height) text_frame = case position - when 'left' then composite_image_left(text_frame, text_content, 0, 0) - when 'center' then composite_image_center(text_frame, text_content, 0, 0) - when 'top' then composite_image_top(text_frame, text_content, 0, 0) - end + when 'left' then composite_image_left(text_frame, text_content, 0, 0) + when 'center' then composite_image_center(text_frame, text_content, 0, 0) + when 'top' then composite_image_top(text_frame, text_content, 0, 0) + end ensure tempTextFile.close tempTextFile.unlink @@ -282,8 +256,8 @@ def draw_text_to_canvas(canvas, text, width, height, x_position, y_position, fon # # @example # - #. image = open_image("image-path") - #. mask = open_image("mask-path") + # image = open_image("image-path") + # mask = open_image("mask-path") # # mask_image(image, mask) # @@ -292,14 +266,14 @@ def draw_text_to_canvas(canvas, text, width, height, x_position, y_position, fon # # @return [Magick::Image] The masked image def mask_image(image, mask, offset_x = 0, offset_y = 0) - image.composite(mask, offset_x, offset_y, CopyAlphaCompositeOp) + image.composite(mask, offset_x, offset_y, CopyAlphaCompositeOp) end # resize_image # # @example # - #. image = open_image("image-path") + # image = open_image("image-path") # resize_image(image, 640, 480) # # @param [Magick::Image] original An ImageMagick object containing the image to be masked. @@ -308,10 +282,7 @@ def mask_image(image, mask, offset_x = 0, offset_y = 0) # # @return [Magick::Image] The resized image def resize_image(original, width, height) - - if !original.is_a?(Magick::Image) - UI.user_error!("You must pass an image object to `resize_image`.") - end + UI.user_error!('You must pass an image object to `resize_image`.') unless original.is_a?(Magick::Image) original.adaptive_resize(width, height) end @@ -320,25 +291,20 @@ def resize_image(original, width, height) # # @example # - #. image = open_image("image-path") - #. other = open_image("other-path") + # image = open_image("image-path") + # other = open_image("other-path") # composite_image(image, other, 0, 0) # - # @param [Magick::Image] image The original image. - # @param [Magick::Image] image The image that will be placed onto the original image. + # @param [Magick::Image] original The original image. + # @param [Magick::Image] child The image that will be placed onto the original image. # @param [Integer] x_position The horizontal position for the image to be placed. # @param [Integer] y_position The vertical position for the image to be placed. # # @return [Magick::Image] The resized image def composite_image(original, child, x_position, y_position, starting_position = NorthWestGravity) + UI.user_error!('You must pass an image object as the first argument to `composite_image`.') unless original.is_a?(Magick::Image) - if !original.is_a?(Magick::Image) - UI.user_error!("You must pass an image object as the first argument to `composite_image`.") - end - - if !child.is_a?(Magick::Image) - UI.user_error!("You must pass an image object as the second argument to `composite_image`.") - end + UI.user_error!('You must pass an image object as the second argument to `composite_image`.') unless child.is_a?(Magick::Image) original.composite(child, starting_position, x_position, y_position, Magick::OverCompositeOp) end @@ -359,7 +325,7 @@ def composite_image_center(original, child, x_position, y_position) # # @example # - #. image = open_image("image-path") + # image = open_image("image-path") # crop_image(image, other, 0, 0) # # @param [Magick::Image] original The original image. @@ -370,29 +336,25 @@ def composite_image_center(original, child, x_position, y_position) # # @return [Magick::Image] The resized image def crop_image(original, x_position, y_position, width, height) - - if !original.is_a?(Magick::Image) - UI.user_error!("You must pass an image object to `crop_image`.") - end + UI.user_error!('You must pass an image object to `crop_image`.') unless original.is_a?(Magick::Image) original.crop(x_position, y_position, width, height) end def open_image(path) - path = resolve_path(path) + path = resolve_path(path) - Magick::Image.read(path) { - self.background_color = 'transparent' - }.first + Magick::Image.read(path) do + self.background_color = 'transparent' + end.first end def create_image(width, height, background = 'transparent') - background_color = background.paint.to_hex - Image.new(width, height) { + Image.new(width, height) do self.background_color = background - } + end end def can_resolve_path(path) @@ -405,39 +367,32 @@ def can_resolve_path(path) end def resolve_path(path) - - if path == nil - UI.crash!("Path not provided – you must provide one to continue") - end + UI.crash!('Path not provided – you must provide one to continue') if path.nil? [ Pathname.new(path), # Absolute Path Pathname.new(FastlaneCore::FastlaneFolder.fastfile_path).dirname + path, # Path Relative to the fastfile Fastlane::Helper::FilesystemHelper.plugin_root + path, # Path Relative to the plugin - Fastlane::Helper::FilesystemHelper.plugin_root + "spec/test-data/" + path, # Path Relative to the test data + Fastlane::Helper::FilesystemHelper.plugin_root + 'spec/test-data/' + path, # Path Relative to the test data ] - .each { |resolved_path| - - if resolved_path != nil && resolved_path.exist? - return resolved_path - end - } + .each do |resolved_path| + return resolved_path if !resolved_path.nil? && resolved_path.exist? + end message = "Unable to locate #{path}" UI.crash!(message) end def resolve_text_into_path(text, locale) - - localizedFile = sprintf(text, locale) - - if File.exist?(localizedFile) - text = localizedFile - elsif can_resolve_path(localizedFile) - text = resolve_path(localizedFile).realpath.to_s - else - text = sprintf(text, "source") - end + localizedFile = format(text, locale) + + text = if File.exist?(localizedFile) + localizedFile + elsif can_resolve_path(localizedFile) + resolve_path(localizedFile).realpath.to_s + else + format(text, 'source') + end end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/helper/release_notes_helper.rb b/lib/fastlane/plugin/wpmreleasetoolkit/helper/release_notes_helper.rb index 05a5f59ed..710d3d1a8 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/helper/release_notes_helper.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/helper/release_notes_helper.rb @@ -1,12 +1,11 @@ module Fastlane module Helper module ReleaseNotesHelper - # Update the release notes file (typycally RELEASE-NOTES.txt) to add a new entry. # # @param [String] path The path to the release notes text file. # @param [String] section_title The title of the new section (typically the new version number) to add. - # + # def self.add_new_section(path:, section_title:) lines = File.readlines(path) @@ -17,7 +16,6 @@ def self.add_new_section(path:, section_title:) File.write(path, new_lines.join) end - end end end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb index f428a15e0..ad707393d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/configuration.rb @@ -1,4 +1,3 @@ - require 'json' require_relative 'file_reference.rb' @@ -8,14 +7,14 @@ class Configuration def initialize(params = {}) self.project_name = params[:project_name] || Fastlane::Helper::FilesystemHelper.project_path.basename.to_s - self.branch = params[:branch] || "" - self.pinned_hash = params[:pinned_hash] || "" + self.branch = params[:branch] || '' + self.pinned_hash = params[:pinned_hash] || '' self.files_to_copy = (params[:files_to_copy] || []).map { |f| FileReference.new(f) } self.file_dependencies = params[:file_dependencies] || [] end def self.from_file(path) - json = JSON.parse(File.read(path), { symbolize_names: true }) + json = JSON.parse(File.read(path), symbolize_names: true) self.new(json) end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb b/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb index 75a11b6a7..21508e8bd 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/models/file_reference.rb @@ -2,35 +2,38 @@ module Fastlane class Configuration class FileReference attr_accessor :file, :destination, :encrypt - + def initialize(params = {}) - self.file = params[:file] || "" - self.destination = params[:destination] || "" + self.file = params[:file] || '' + self.destination = params[:destination] || '' self.encrypt = params[:encrypt] || false end - + def source_contents # TODO: This works only on CircleCI. I chose this variable because it's the one checked by Fastlane::is_ci. # Fastlane::is_ci doesn't work here, so reimplementing the code has been necessary. # (This should be updated if we change CI or if fastlane is updated.) - return File.read(secrets_repository_file_path) unless (self.encrypt || ENV.key?('CIRCLECI')) + return File.read(secrets_repository_file_path) unless self.encrypt || ENV.key?('CIRCLECI') return nil unless File.file?(encrypted_file_path) + encrypted = File.read(encrypted_file_path) Fastlane::Helper::EncryptionHelper.decrypt(encrypted, encryption_key) end - + def destination_contents return nil unless File.file?(destination_file_path) + File.read(destination_file_path) end - + def needs_apply? destination = destination_contents destination.nil? || source_contents != destination end - + def update return unless self.encrypt + # Create the destination directory if it doesn't exist FileUtils.mkdir_p(Pathname.new(encrypted_file_path).dirname) # Encrypt the file @@ -38,34 +41,35 @@ def update encrypted = Fastlane::Helper::EncryptionHelper.encrypt(file_contents, encryption_key) File.write(encrypted_file_path, encrypted) end - + def apply # Create the destination directory if it doesn't exist FileUtils.mkdir_p(Pathname.new(destination_file_path).dirname) # Copy/decrypt the file File.write(destination_file_path, source_contents) end - + def secrets_repository_file_path File.join(Fastlane::Helper::FilesystemHelper.secret_store_dir, self.file) end - + def encrypted_file_path Fastlane::Helper::FilesystemHelper.encrypted_file_path(self.file) end - + def destination_file_path return File.expand_path(self.destination) if self.destination.start_with?('~') + File.join(Fastlane::Helper::FilesystemHelper.project_path, self.destination) end - + def encryption_key Fastlane::Helper::ConfigureHelper.encryption_key end - + def to_hash { file: self.file, destination: self.destination, encrypt: self.encrypt } end end end -end \ No newline at end of file +end diff --git a/lib/fastlane/plugin/wpmreleasetoolkit/version.rb b/lib/fastlane/plugin/wpmreleasetoolkit/version.rb index 3ea8cd549..a299bdb3d 100644 --- a/lib/fastlane/plugin/wpmreleasetoolkit/version.rb +++ b/lib/fastlane/plugin/wpmreleasetoolkit/version.rb @@ -1,5 +1,5 @@ module Fastlane module Wpmreleasetoolkit - VERSION = "0.14.0" + VERSION = '0.14.0' end end diff --git a/spec/android_merge_translators_strings_spec.rb b/spec/android_merge_translators_strings_spec.rb index b4a68695b..7a64a9b40 100644 --- a/spec/android_merge_translators_strings_spec.rb +++ b/spec/android_merge_translators_strings_spec.rb @@ -1,89 +1,85 @@ require 'spec_helper.rb' require 'tmpdir' - describe Fastlane::Actions::AndroidMergeTranslatorsStringsAction do - before do - @amtsTestUtils = AMTSTestUtils.new - @amtsTestUtils.create_test_folder - end - - it 'checks no merge' do - amts_run_test("test-merge-android-nomerge.json") - end - - it 'checks merge simple' do - amts_run_test("test-merge-android-merge-simple.json") - end - - it 'checks merge overwrite' do - amts_run_test("test-merge-android-merge-overwrite.json") - end - - it 'checks merge overwrite with double key in pending file' do - amts_run_test("test-merge-android-merge-overwrite-double.json") - end - - it 'checks merge overwrite with fuzzy strings' do - amts_run_test("test-merge-android-merge-overwrite-fuzzy.json") - end - - after do - @amtsTestUtils.delete_test_folder - end + before do + @amtsTestUtils = AMTSTestUtils.new + @amtsTestUtils.create_test_folder + end + + it 'checks no merge' do + amts_run_test('test-merge-android-nomerge.json') + end + + it 'checks merge simple' do + amts_run_test('test-merge-android-merge-simple.json') + end + + it 'checks merge overwrite' do + amts_run_test('test-merge-android-merge-overwrite.json') + end + + it 'checks merge overwrite with double key in pending file' do + amts_run_test('test-merge-android-merge-overwrite-double.json') + end + + it 'checks merge overwrite with fuzzy strings' do + amts_run_test('test-merge-android-merge-overwrite-fuzzy.json') + end + + after do + @amtsTestUtils.delete_test_folder + end end def amts_run_test(script) - test_script = @amtsTestUtils.get_test_from_file(script) - @amtsTestUtils.create_test_data(test_script) - Fastlane::Actions::AndroidMergeTranslatorsStringsAction.run({strings_folder: @amtsTestUtils.test_folder_path}) - expect(@amtsTestUtils.read_result_data(test_script)).to eq(test_script["result"]["content"]) + test_script = @amtsTestUtils.get_test_from_file(script) + @amtsTestUtils.create_test_data(test_script) + Fastlane::Actions::AndroidMergeTranslatorsStringsAction.run(strings_folder: @amtsTestUtils.test_folder_path) + expect(@amtsTestUtils.read_result_data(test_script)).to eq(test_script['result']['content']) end class AMTSTestUtils - attr_accessor :test_folder_path + attr_accessor :test_folder_path - def initialize() - @test_folder_path = File.join(Dir.tmpdir(), "amts_tests") - end + def initialize + @test_folder_path = File.join(Dir.tmpdir(), 'amts_tests') + end - def create_test_folder - FileUtils.mkdir_p(@test_folder_path) - end + def create_test_folder + FileUtils.mkdir_p(@test_folder_path) + end - def delete_test_folder - FileUtils.rm_rf(@test_folder_path) - end + def delete_test_folder + FileUtils.rm_rf(@test_folder_path) + end - def get_test_from_file(filename) - filename = self.test_data_path_for("translations/#{filename}") - return JSON.parse(open(filename).read) - end + def get_test_from_file(filename) + filename = self.test_data_path_for("translations/#{filename}") + return JSON.parse(open(filename).read) + end - def test_data_path_for(filename) - File.expand_path(File.join(File.dirname(__FILE__), "test-data", filename)) - end + def test_data_path_for(filename) + File.expand_path(File.join(File.dirname(__FILE__), 'test-data', filename)) + end - def create_test_data(test_script) - test_script["test_data"].each do | test_file | - self.generate_test_file(test_file["file"], test_file["content"]) - end + def create_test_data(test_script) + test_script['test_data'].each do |test_file| + self.generate_test_file(test_file['file'], test_file['content']) end + end - def generate_test_file(filename, content) - file_path = File.join(@test_folder_path, filename) - - dir = File.dirname(file_path) - unless File.directory?(dir) - FileUtils.mkdir_p(dir) - end + def generate_test_file(filename, content) + file_path = File.join(@test_folder_path, filename) - File.open(file_path, 'w') {|f| f.write(content) } - end + dir = File.dirname(file_path) + FileUtils.mkdir_p(dir) unless File.directory?(dir) - def read_result_data(test_script) - file_path = File.join(@test_folder_path, test_script["result"]["file"]) - return File.read(file_path) - end -end + File.open(file_path, 'w') { |f| f.write(content) } + end + def read_result_data(test_script) + file_path = File.join(@test_folder_path, test_script['result']['file']) + return File.read(file_path) + end +end diff --git a/spec/ci_helper_spec.rb b/spec/ci_helper_spec.rb index 36e238816..8ca76dff4 100644 --- a/spec/ci_helper_spec.rb +++ b/spec/ci_helper_spec.rb @@ -1,36 +1,40 @@ require 'spec_helper.rb' require 'webmock/rspec' -shared_examples "a CI provider" do - subject { model } - it { is_expected.to respond_to(:login) } - it { is_expected.to respond_to(:organization) } - it { is_expected.to respond_to(:repository) } - it { is_expected.to respond_to(:trigger_job) } +shared_examples 'a CI provider' do + subject { model } + + it { is_expected.to respond_to(:login) } + it { is_expected.to respond_to(:organization) } + it { is_expected.to respond_to(:repository) } + it { is_expected.to respond_to(:trigger_job) } end describe Fastlane::Helper::CircleCIHelper do - it_behaves_like "a CI provider" do - let(:model) { Fastlane::Helper::CircleCIHelper.new(login: "my_circleci_token", repository: "test_repo") } - end + it_behaves_like 'a CI provider' do + let(:model) { Fastlane::Helper::CircleCIHelper.new(login: 'my_circleci_token', repository: 'test_repo') } + end - context "initialization" do - describe Fastlane::Helper::CircleCIHelper.new(login: "my_circleci_token", repository: "test_repo") do - it { is_expected.to have_attributes(:organization => "wordpress-mobile", "repository" => "test_repo", "command_uri" => URI.parse("https://circleci.com/api/v2/project/github/wordpress-mobile/test_repo/pipeline"))} - end + context 'initialization' do + describe Fastlane::Helper::CircleCIHelper.new(login: 'my_circleci_token', repository: 'test_repo') do + it { is_expected.to have_attributes(:organization => 'wordpress-mobile', 'repository' => 'test_repo', 'command_uri' => URI.parse('https://circleci.com/api/v2/project/github/wordpress-mobile/test_repo/pipeline')) } + end - describe Fastlane::Helper::CircleCIHelper.new(login: "my_circleci_token", repository: "test_repo", organization: "my_org") do - it { is_expected.to have_attributes(:organization => "my_org", "repository" => "test_repo", "command_uri" => URI.parse("https://circleci.com/api/v2/project/github/my_org/test_repo/pipeline"))} - end + describe Fastlane::Helper::CircleCIHelper.new(login: 'my_circleci_token', repository: 'test_repo', organization: 'my_org') do + it { is_expected.to have_attributes(:organization => 'my_org', 'repository' => 'test_repo', 'command_uri' => URI.parse('https://circleci.com/api/v2/project/github/my_org/test_repo/pipeline')) } end + end - context "Main Commands" do - describe Fastlane::Helper::CircleCIHelper.new(login: "my_circleci_token", repository: "test_repo") do - it "triggers a job" do - stub = stub_request(:post, "https://circleci.com/api/v2/project/github/wordpress-mobile/test_repo/pipeline").with(:body => {"branch":"develop","parameters":nil}, :headers => {'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Circle-Token' => 'my_circleci_token'}).to_return(:body => "efg") - subject.trigger_job(branch: "develop") - expect(stub).to have_been_made.once - end - end + context 'Main Commands' do + describe Fastlane::Helper::CircleCIHelper.new(login: 'my_circleci_token', repository: 'test_repo') do + it 'triggers a job' do + stub = stub_request(:post, 'https://circleci.com/api/v2/project/github/wordpress-mobile/test_repo/pipeline').with( + body: { "branch": 'develop', "parameters": nil }, + headers: { 'Content-Type' => 'application/json', 'Accept' => 'application/json', 'Circle-Token' => 'my_circleci_token' } + ).to_return(body: 'efg') + subject.trigger_job(branch: 'develop') + expect(stub).to have_been_made.once + end end + end end diff --git a/spec/configuration_spec.rb b/spec/configuration_spec.rb index 1ac64035f..0fcfae9af 100644 --- a/spec/configuration_spec.rb +++ b/spec/configuration_spec.rb @@ -4,8 +4,8 @@ describe 'initialization' do it 'creates an empty config' do expect(subject.project_name).to eq(Fastlane::Helper::FilesystemHelper.project_path.basename.to_s) - expect(subject.branch).to eq("") - expect(subject.pinned_hash).to eq("") + expect(subject.branch).to eq('') + expect(subject.pinned_hash).to eq('') expect(subject.files_to_copy).to eq([]) expect(subject.file_dependencies).to eq([]) end @@ -16,11 +16,11 @@ let(:configure_json) do { - project_name: "MyProject", - branch: "a_branch", + project_name: 'MyProject', + branch: 'a_branch', pinned_hash: 'a_hash', - files_to_copy: [ { file: 'a_file_to_copy', destination: 'a_destination', encrypt: true } ], - file_dependencies: [ 'a_file_dependencies' ], + files_to_copy: [{ file: 'a_file_to_copy', destination: 'a_destination', encrypt: true }], + file_dependencies: ['a_file_dependencies'] } end let(:configure_json_string) { JSON.pretty_generate(configure_json) } diff --git a/spec/file_reference_spec.rb b/spec/file_reference_spec.rb index 977388069..c2bd97324 100644 --- a/spec/file_reference_spec.rb +++ b/spec/file_reference_spec.rb @@ -41,8 +41,8 @@ describe Fastlane::Configuration::FileReference do describe 'initialization' do it 'creates an empty file reference' do - expect(subject.file).to eq("") - expect(subject.destination).to eq("") + expect(subject.file).to eq('') + expect(subject.destination).to eq('') expect(subject.encrypt).to eq(false) end end @@ -94,7 +94,7 @@ expect(Fastlane::Helper::EncryptionHelper).to receive(:decrypt).with('encrypted contents', 'key').and_return('decrypted contents') expect(subject.source_contents).to eq('decrypted contents') end - + it 'gives nil if the encrypted does not exist' do allow(File).to receive(:file?).with(subject.encrypted_file_path).and_return(false) expect(subject.source_contents).to eq(nil) diff --git a/spec/git_helper_spec.rb b/spec/git_helper_spec.rb index 9eba034ce..198b5c17f 100644 --- a/spec/git_helper_spec.rb +++ b/spec/git_helper_spec.rb @@ -14,33 +14,33 @@ end it 'can detect a missing git repository' do - expect(Fastlane::Helper::GitHelper.is_git_repo).to be false + expect(Fastlane::Helper::GitHelper.is_git_repo?).to be false end it 'can detect a valid git repository' do `git init` - expect(Fastlane::Helper::GitHelper.is_git_repo).to be true + expect(Fastlane::Helper::GitHelper.is_git_repo?).to be true end it 'can detect a repository with Git-lfs enabled' do `git init` `git lfs install` - expect(Fastlane::Helper::GitHelper.has_git_lfs).to be true + expect(Fastlane::Helper::GitHelper.has_git_lfs?).to be true end it 'can detect a repository without Git-lfs enabled' do `git init` `git lfs uninstall &>/dev/null` - expect(Fastlane::Helper::GitHelper.is_git_repo).to be true - expect(Fastlane::Helper::GitHelper.has_git_lfs).to be false + expect(Fastlane::Helper::GitHelper.is_git_repo?).to be true + expect(Fastlane::Helper::GitHelper.has_git_lfs?).to be false end context('commit(message:, files:, push:)') do before(:each) do allow_fastlane_action_sh() - @message = "Some commit message with spaces" + @message = 'Some commit message with spaces' end - + it 'commits without adding any file if none are provided' do expect_shell_command('git', 'add', any_args).never expect_shell_command('git', 'commit', '-m', @message) diff --git a/spec/ios_lint_localizations_spec.rb b/spec/ios_lint_localizations_spec.rb index 0eadb4998..8ddbbbcdb 100644 --- a/spec/ios_lint_localizations_spec.rb +++ b/spec/ios_lint_localizations_spec.rb @@ -18,10 +18,10 @@ # First run: expect curl, unzip and cp_r to be called to install SwiftGen before running the action # See spec_helper.rb for documentation about `expect_shell_command`. - expect_shell_command("curl", any_args, /\/.*swiftgen-#{Fastlane::Helpers::IosL10nHelper::SWIFTGEN_VERSION}.zip/) - expect_shell_command("unzip", any_args) + expect_shell_command('curl', any_args, %r{/.*swiftgen-#{Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION}.zip}) + expect_shell_command('unzip', any_args) expect(FileUtils).to receive(:cp_r) - expect_shell_command("#{install_dir}/bin/swiftgen", "config", "run", "--config", anything) + expect_shell_command("#{install_dir}/bin/swiftgen", 'config', 'run', '--config', anything) Fastlane::Actions::IosLintLocalizationsAction.run( install_path: install_dir, @@ -33,14 +33,15 @@ script = <<~SCRIPT #!/bin/sh if [[ "$1" == "--version" ]]; then - echo "SwiftGen v#{Fastlane::Helpers::IosL10nHelper::SWIFTGEN_VERSION} (Fake binstub)" + echo "SwiftGen v#{Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION} (Fake binstub)" fi SCRIPT FileUtils.mkdir_p File.join(install_dir, 'bin') - File.write(File.join(install_dir, 'bin/swiftgen'), script, perm: 0766) + # note: `0o` is octal notation, used to specify chmod-like flags + File.write(File.join(install_dir, 'bin/swiftgen'), script, perm: 0o766) # Second run: ensure we only run SwiftGen directly, without a call to curl nor unzip beforehand - expect_shell_command("#{install_dir}/bin/swiftgen", "config", "run", "--config", anything) + expect_shell_command("#{install_dir}/bin/swiftgen", 'config', 'run', '--config', anything) Fastlane::Actions::IosLintLocalizationsAction.run( install_path: install_dir, @@ -101,13 +102,13 @@ def run_l10n_linter_test(data_file) # Note: We will install SwiftGen in vendor/swiftgen if it's not already installed yet, and intentionally won't # remove this after the test ends, so that further executions of the test run faster. # Only the first execution of the tests might take longer if it needs to install SwiftGen first to be able to run the tests. - install_dir = "vendor/swiftgen/#{Fastlane::Helpers::IosL10nHelper::SWIFTGEN_VERSION}" + install_dir = "vendor/swiftgen/#{Fastlane::Helper::Ios::L10nHelper::SWIFTGEN_VERSION}" result = Fastlane::Actions::IosLintLocalizationsAction.run( install_path: install_dir, input_dir: @test_data_dir, base_lang: 'en' ) - + # Assert - expect(result).to eq(yml["result"]) + expect(result).to eq(yml['result']) end diff --git a/spec/ios_merge_translators_strings_spec.rb b/spec/ios_merge_translators_strings_spec.rb index 55adc066d..f42760115 100644 --- a/spec/ios_merge_translators_strings_spec.rb +++ b/spec/ios_merge_translators_strings_spec.rb @@ -1,90 +1,85 @@ require 'spec_helper.rb' require 'tmpdir' - describe Fastlane::Actions::IosMergeTranslatorsStringsAction do - before do - @imtsTestUtils = IMTSTestUtils.new - @imtsTestUtils.create_test_folder - end - - it 'checks no merge' do - imts_run_test("test-merge-ios-nomerge.json") - end - - it 'checks merge simple' do - imts_run_test("test-merge-ios-merge-simple.json") - end - - it 'checks merge overwrite' do - imts_run_test("test-merge-ios-merge-overwrite.json") - end - - it 'checks merge overwrite with double key in pending file' do - imts_run_test("test-merge-ios-merge-overwrite-double.json") - end - - it 'checks merge overwrite with fuzzy strings' do - imts_run_test("test-merge-ios-merge-overwrite-fuzzy.json") - end - - after do - @imtsTestUtils.delete_test_folder - end + before do + @imtsTestUtils = IMTSTestUtils.new + @imtsTestUtils.create_test_folder + end + + it 'checks no merge' do + imts_run_test('test-merge-ios-nomerge.json') + end + + it 'checks merge simple' do + imts_run_test('test-merge-ios-merge-simple.json') + end + + it 'checks merge overwrite' do + imts_run_test('test-merge-ios-merge-overwrite.json') + end + + it 'checks merge overwrite with double key in pending file' do + imts_run_test('test-merge-ios-merge-overwrite-double.json') + end + + it 'checks merge overwrite with fuzzy strings' do + imts_run_test('test-merge-ios-merge-overwrite-fuzzy.json') + end + + after do + @imtsTestUtils.delete_test_folder + end end def imts_run_test(script) - test_script = @imtsTestUtils.get_test_from_file(script) - @imtsTestUtils.create_test_data(test_script) - Fastlane::Actions::IosMergeTranslatorsStringsAction.run({strings_folder: @imtsTestUtils.test_folder_path}) - expect(@imtsTestUtils.read_result_data(test_script)).to eq(test_script["result"]["content"]) + test_script = @imtsTestUtils.get_test_from_file(script) + @imtsTestUtils.create_test_data(test_script) + Fastlane::Actions::IosMergeTranslatorsStringsAction.run(strings_folder: @imtsTestUtils.test_folder_path) + expect(@imtsTestUtils.read_result_data(test_script)).to eq(test_script['result']['content']) end class IMTSTestUtils - attr_accessor :test_folder_path + attr_accessor :test_folder_path - def initialize() - @test_folder_path = File.join(Dir.tmpdir(), "imts_tests") - end + def initialize + @test_folder_path = File.join(Dir.tmpdir(), 'imts_tests') + end - def create_test_folder - FileUtils.mkdir_p(@test_folder_path) - end + def create_test_folder + FileUtils.mkdir_p(@test_folder_path) + end - def delete_test_folder - FileUtils.rm_rf(@test_folder_path) - end + def delete_test_folder + FileUtils.rm_rf(@test_folder_path) + end - def get_test_from_file(filename) - filename = self.test_data_path_for("translations/#{filename}") - return JSON.parse(open(filename).read) - end + def get_test_from_file(filename) + filename = self.test_data_path_for("translations/#{filename}") + return JSON.parse(open(filename).read) + end - def test_data_path_for(filename) - File.expand_path(File.join(File.dirname(__FILE__), "test-data", filename)) - end + def test_data_path_for(filename) + File.expand_path(File.join(File.dirname(__FILE__), 'test-data', filename)) + end - def create_test_data(test_script) - test_script["test_data"].each do | test_file | - self.generate_test_file(test_file["file"], test_file["content"]) - end + def create_test_data(test_script) + test_script['test_data'].each do |test_file| + self.generate_test_file(test_file['file'], test_file['content']) end + end - def generate_test_file(filename, content) - file_path = File.join(@test_folder_path, filename) - - dir = File.dirname(file_path) - unless File.directory?(dir) - FileUtils.mkdir_p(dir) - end - - File.open(file_path, 'w') {|f| f.write(content) } - end + def generate_test_file(filename, content) + file_path = File.join(@test_folder_path, filename) - def read_result_data(test_script) - file_path = File.join(@test_folder_path, test_script["result"]["file"]) - return File.read(file_path) - end -end + dir = File.dirname(file_path) + FileUtils.mkdir_p(dir) unless File.directory?(dir) + File.open(file_path, 'w') { |f| f.write(content) } + end + def read_result_data(test_script) + file_path = File.join(@test_folder_path, test_script['result']['file']) + return File.read(file_path) + end +end diff --git a/spec/promo_screenshots_helper_spec.rb b/spec/promo_screenshots_helper_spec.rb index 29da1d833..c1f6fec09 100644 --- a/spec/promo_screenshots_helper_spec.rb +++ b/spec/promo_screenshots_helper_spec.rb @@ -1,7 +1,7 @@ -#require 'shellwords' -#require_relative './spec_helper' +# require 'shellwords' +# require_relative './spec_helper' # -#describe Fastlane::Helper::PromoScreenshots do +# describe Fastlane::Helper::PromoScreenshots do # # context "initialization" do # @@ -231,34 +231,34 @@ # expect(images_are_identical(output, "text-test-2.png")).to eq(true) # end # end -#end +# end # -#def helper() +# def helper() # Fastlane::Helper::PromoScreenshots.new -#end +# end # -#def source_image(filename) +# def source_image(filename) # helper.open_image(test_data_path_for("images/source/#{filename}")) -#end +# end # -#def sample_image(filename) +# def sample_image(filename) # helper.open_image(test_data_path_for("images/output/#{filename}")) -#end +# end # -#def sample_script(filename) +# def sample_script(filename) # filename = test_data_path_for("scripts/#{filename}") # return JSON.parse(open(filename).read) -#end +# end # -#def sample_stylesheet(filename) +# def sample_stylesheet(filename) # test_data_path_for("scripts/#{filename}") -#end +# end # -#def test_data_path_for(filename) +# def test_data_path_for(filename) # File.expand_path(File.join(File.dirname(__FILE__), 'test-data', filename)) -#end +# end # -#def write_test_data(output, filename = "") +# def write_test_data(output, filename = "") # # if filename.empty? # filename = Tempfile.new(output.signature).path @@ -269,26 +269,26 @@ # output.write(filename) # # output -#end +# end # -#def images_are_identical(image1, sample_image) +# def images_are_identical(image1, sample_image) # # if sample_image.is_a? String # sample_image = sample_image(sample_image) # end # # image1.compare_channel(sample_image, Magick::MeanAbsoluteErrorMetric)[1] == 0 -#end +# end # -#$original_stderr = $stderr -#$original_stdout = $stdout +# $original_stderr = $stderr +# $original_stdout = $stdout # -#def silence_output +# def silence_output # $stderr = File.open(File::NULL, "w") # $stdout = File.open(File::NULL, "w") -#end +# end # -#def unsilence_output +# def unsilence_output # $stderr = $original_stderr # $stdout = $original_stdout -#end +# end diff --git a/spec/release_notes_helper_spec.rb b/spec/release_notes_helper_spec.rb index a0b719fcf..c74b4323f 100644 --- a/spec/release_notes_helper_spec.rb +++ b/spec/release_notes_helper_spec.rb @@ -18,7 +18,7 @@ run_release_notes_test <<~HEADER *** This is a header *** that we want to keep pinned on top. - + HEADER end @@ -38,7 +38,7 @@ // It also contains some empty lines we want to count as part of the pinned lines. - + HEADER end @@ -65,7 +65,7 @@ - Item 1 for v1.2.3 - Item 2 for v1.2.3 - // Comment in the middle + // Comment in the middle 1.2.2 ----- @@ -85,7 +85,7 @@ def run_release_notes_test(header, post_header_content = FAKE_CONTENT) tmp_file = File.join(dir, 'TEST-REL-NOTES.txt') File.write(tmp_file, header + post_header_content) - Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: tmp_file, section_title: "New Section") + Fastlane::Helper::ReleaseNotesHelper.add_new_section(path: tmp_file, section_title: 'New Section') new_content = File.read(tmp_file) expect(new_content).to eq(header + NEW_SECTION + post_header_content) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2f599dc81..8211d18b9 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,4 @@ -$LOAD_PATH.unshift(File.expand_path('../../lib', __FILE__)) +$LOAD_PATH.unshift(File.expand_path('../lib', __dir__)) require 'simplecov' require 'codecov' @@ -9,9 +9,7 @@ code_coverage_token = ENV['CODECOV_TOKEN'] || false # If the environment variable is present, format for Codecov -if code_coverage_token - SimpleCov.formatter = SimpleCov::Formatter::Codecov -end +SimpleCov.formatter = SimpleCov::Formatter::Codecov if code_coverage_token # This module is only used to check the environment is currently a testing env module SpecHelper @@ -29,15 +27,15 @@ module SpecHelper def set_circle_env(define_ci) is_ci = ENV.key?('CIRCLECI') orig_circle_ci = ENV['CIRCLECI'] - if (define_ci) - ENV['CIRCLECI'] = "true" + if define_ci + ENV['CIRCLECI'] = 'true' else ENV.delete 'CIRCLECI' - end + end yield ensure - if (is_ci) + if is_ci ENV['CIRCLECI'] = orig_circle_ci else ENV.delete 'CIRCLECI' @@ -59,7 +57,7 @@ def allow_fastlane_action_sh # @param [String] output The output string to expect as a result of running the command. Defaults to "". # @return [MessageExpectation] self, to support further chaining. # -def expect_shell_command(*command, exitstatus: 0, output: "") +def expect_shell_command(*command, exitstatus: 0, output: '') mock_input = double(:input) mock_output = StringIO.new(output) mock_status = double(:status, exitstatus: exitstatus)