diff --git a/fastlane/Fastfile b/fastlane/Fastfile index acddfb4..7ab5873 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -4,10 +4,12 @@ lane :release do |options| # Checking that everything is alright check - podspec_names = Dir.glob('*.podspec', base: '..') + podspec_names = sorted_podspecs(podspecs:Dir.glob('*.podspec', base: '..')) # Bumping podspec version for podspec_name in podspec_names version = version_bump_podspec(path: podspec_name, bump_type: bump_type) + + bump_podspec_dependency(podspecs: podspec_names, name: podspec_name.delete_suffix('.podspec'), version: version) end add_files = extend_bump_version(version: version) diff --git a/fastlane/actions/bump_podspec_dependency.rb b/fastlane/actions/bump_podspec_dependency.rb new file mode 100644 index 0000000..d2c4e64 --- /dev/null +++ b/fastlane/actions/bump_podspec_dependency.rb @@ -0,0 +1,51 @@ +module Fastlane + module Actions + class BumpPodspecDependencyAction < Action + def self.run(params) + podspecs = params[:podspecs] + name = params[:name] + version = params[:version] + regexp = %r{(\.dependency\s+['"]#{Regexp.escape(name)}(?:/[^/'"]+)*['"]\s*,\s*['"])(?:[^'"]+)(['"])}m + affected_podspecs = [] + podspecs.each do |podspec| + UI.message("replacing #{regexp}") + content = File.read(podspec) + new_content = content.gsub(regexp, "\\1#{version}\\2") + if new_content != content + File.write(podspec, new_content) + affected_podspecs.append(podspec) + end + end + if affected_podspecs.empty? + UI.important("No affected podspecs for dependency '#{name}'") + else + UI.success("Update dependency '#{name}' to version #{version} in #{affected_podspecs.join(', ')}") + end + affected_podspecs + end + + def self.available_options + [ + FastlaneCore::ConfigItem.new( + key: :podspecs, + description: 'Podspec path list', + type: Array, + optional: false + ), + FastlaneCore::ConfigItem.new( + key: :name, + description: 'Dependency name (example: Alamofire)', + type: String, + optional: false + ), + FastlaneCore::ConfigItem.new( + key: :version, + description: 'Dependency version (example: \'~> 1.2.3\')', + type: String, + optional: false + ) + ] + end + end + end +end diff --git a/fastlane/actions/sorted_podspecs.rb b/fastlane/actions/sorted_podspecs.rb new file mode 100644 index 0000000..d12a5b2 --- /dev/null +++ b/fastlane/actions/sorted_podspecs.rb @@ -0,0 +1,86 @@ +require 'cocoapods' +require 'tsort' + +module Fastlane + module Actions + class SortedPodspecsAction < Action + def self.run(params) + @podspecs = params[:podspecs].map { |filename| Fastlane::Helper::Podspec.new(filename) } + + tsort.map(&:path) + end + + ##################################################### + # @!group Documentation + ##################################################### + + def self.description + 'Returns a list of podspecs sorted by dependency' + end + + def self.details + 'Parses podspec from a given list and topologically sorts them by dependency' + end + + def self.available_options + # Define all options your action supports. + + # Below a few examples + [ + FastlaneCore::ConfigItem.new( + key: :podspecs, + description: 'Podspec path list', + type: Array, + optional: false + ) + ] + end + + def self.return_value + 'An original list of podspec filenames sorted by dependency' + end + + def self.authors + ['adarovsky'] + end + + ##################################################### + # @!group Sorting + ##################################################### + + def self.tsort_each_node(&block) + @podspecs.each(&block) + end + + def self.tsort_each_child(node, &block) + node + .dependencies + .filter_map { |d| @podspecs.find { |e| e.name == d.name } } + .each(&block) + end + + extend TSort + end + end + + module Helper + class Podspec + + attr_reader :path + + # @param [String] path + def initialize(path) + @path = path + @spec = Pod::Spec.from_file(path) + end + + def dependencies + @spec.dependencies + end + + def name + @spec.name + end + end + end +end