preface
When we do development, we come into contact with the idea of componentization. Componentization of iOS is generally done in the form of pod libraries made using Cocoapods. Pod libraries are divided into public libraries and private libraries. What we upload to Github, for example, is a public library for others to download and use. The ones that are deployed inside the company are private libraries that are inaccessible to others.
concept
This article will focus on how to automate the deployment of POD scripts, so the concepts related to the POD library will only be briefly introduced and will not be covered too much. For more insight, consult the official documentation.
1. repo
A REPo is the equivalent of a repository that holds an index of related POD libraries. How do you understand that? For example, what’s the repo of the public library we’re making on Github? Call trunk, the address is https://cdn.cocoapods.org/. We can run the command: pod repo directly on the machine and see the diagram.
This repository is where the podspec files we deployed are stored.
2. podspec
A PodSpec is used to describe a POD library, such as library structure, version, source code address, etc.
With these two in mind, we’re ready to make our own POD library.
Make pod library
Take the example of making a public library and submitting it to Github. To submit the official document to the Trunk click me
First you need an existing source code repository,
1. Create a Podspec file
pod spec create yourSpecName.podspec
Copy the code
2. Edit the Podspec file
For example, the contents of the Podspec file are as follows. Edit the source and source_files in the file.
Pod: : Spec. New do | Spec | Spec. The name = 'Reachability' Spec. Version = '3.1.0' Spec. The license = {: type = > 'BSD'} spec.homepage = 'https://github.com/tonymillion/Reachability' spec.authors = { 'Tony Million' => '[email protected]' } spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and macOS.' spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0'} spec.source_files = 'Reachability ',m' spec.framework = 'SystemConfiguration' spec.requires_arc = true endCopy the code
3. Submit our source code
git commit -am 'submit'
git push origin
Copy the code
4. Tag our POD
Note that podSpec has the concept of a version number, which needs to be consistent with the tag value of your Pod library, the source code library. This way, our Cocoapods can download the correct version of the source code after parsing the PodSpec.
Git tag 0.0.2 # push all tags to remote git push originCopy the code
5. Verify that our PodSpec file is formatted correctly
Local validation:
pod lib lint yourSpecName.podspec --allow-warnings
Copy the code
Remote verification:
pod spec line yourSpecName.podspec --allow-warnings
Copy the code
6. Publish our PodSpec
pod trunk push yourSpecName.podspec --allow-warnings
Copy the code
Update the pod library
We should have a podspec file in our library at this point. All we need to do is update the version number of the file, change the source_files if there is a change in the file structure, and change the dependency.
1. Update the version number of the PodSpec
Open the PodSpec file, edit and update the Version field, usually incrementing.
1. Tag our new version of the code
Git commit -am 'update' git push origin git tag 0.0.2 git push origin 0.0.2Copy the code
2. Verify that the newly modified Podspec file is correct
This step can be skipped by the knight here, usually the first upload is ok, and will not cause problems later.
pod lib lint *.podspec
Copy the code
3. Deploy a new version of PodSpec
pod trunk push *.podspec
Copy the code
Script implementation
The script is implemented in Ruby, and the source code is here.
The implementation is basically the same as updating PodSpec, but with some configuration.
It’s easy to use, put the script in the current pod root directory and execute Ruby specpush.rb for one-click publishing.
Here’s the code:
#! /usr/bin/ruby
class Color
def self.natural
0
end
def self.black
30
end
def self.red
31
end
def self.green
32
end
def self.yellow
33
end
def self.blue
34
end
def self.magenta
35
end
def self.cyan
36
end
def self.white
37
end
end
def color_text(text, color = Color.natural)
if color == 0
return text
end
return "\ [033#{color}m#{text}\033[0m"
end
def die_log(text)
puts color_text(text, Color.red)
end
# Pull the latest code
# if system('git pull --rebase origin') == false
# system('git rebase --abort')
# puts color_text("There is a conflict, please handle it and retry", Color.red)
# return
# end
cur_path = Dir.pwd
push_path = cur_path
relate_dir_path = ' '
user_custom_version = true
verify_podspec_format = true
pod_repo_name = 'trunk'
pod_repo_source =
is_static_lib = false
SpecPushFile: if SpecPushFile does not exist, create it
if notFile::exist? (cur_path +'/PodPushFile')
system('touch PodPushFile')
File.open(cur_path + '/PodPushFile'.'w+') do |f|
f.write(PUSH_DIR_PATH= # specifies whether to allow users to set their own version number. If this is not true or not, it will allow users to set their own version number. VERIFY_PODSPEC_FORMAT=true #pod repo name If it is the private library will fill in the name of the private libraries POD_REPO_NAME = trunk source address POD_REPO_SOURCE=https://github.com/CocoaPods/Specs # # pod repo if the library is static library, So you need to set it to true POD_IS_STATIC_LIBRARY=false")
end
puts color_text('Create PodPushFile', Color.green)
puts color_text("First you should modify 'PodPushFile' file and run the script again", Color.white)
system('open PodPushFile')
return
end
puts color_text('Parse PodPushFile... ', Color.white)
File.open(cur_path + '/PodPushFile') do |f|
f.each_line do |line|
key_value = line.split('=')
key = key_value.first.to_s.gsub("\n".' ').gsub(' '.' ').gsub("\t".' ')
value =
if key_value.count > 1
value = key_value.last.to_s.gsub("\n".' ').gsub(' '.' ').gsub("\t".' ')
end
# puts "key=#{key},value=#{value}"
if key.to_s == 'PUSH_DIR_PATH' and not value.nil?
relate_dir_path = value
push_path = cur_path + '/' + relate_dir_path
elsif key.to_s == 'USER_CUSTOM_VERSION' and not value.nil?
user_custom_version = value == 'true'
elsif key.to_s == 'VERIFY_PODSPEC_FORMAT' and not value.nil?
verify_podspec_format = value == 'true'
elsif key.to_s == 'POD_REPO_NAME' and not value.nil?
pod_repo_name = value.to_s
elsif key.to_s == 'POD_REPO_SOURCE' and not value.nil?
pod_repo_source = value
elsif key.to_s == 'POD_IS_STATIC_LIBRARY' and not value.nil?
is_static_lib = value == 'true'
end
end
end
# puts "Push path is: #{push_path}, relate dir path is: #{relate_dir_path}"
# Search the PodSpec path
podspec_path = ' '
find_podspec_reg = (relate_dir_path.length == 0 ? ' ' : (relate_dir_path + '/')) + '*.podspec'
# puts "Find podspec reg = #{find_podspec_reg}"
Dir::glob(find_podspec_reg) do |f|
podspec_path = f
end
if podspec_path.length == 0
puts "Find podspec in current dir"
else
puts "Find podspec in releate path=#{podspec_path}"
end
if notFile::exist? (podspec_path) die_log("Can't find any podspec file in path: #{podspec_path}, please modify PodPushFile' PUSH_DIR_PATH(key)")
return
else
puts "Find podspec named" + color_text("#{podspec_path}", Color.white)
end
Create a temporary need_delete_temp. Podspec file in the current podspec directory
podspec_dir = File.dirname podspec_path
podspec_absolute_path = cur_path + '/' + podspec_path
temp_podspec_path = podspec_dir + '/need_delete_temp.podspec'
temp_podspec_absolute_path = cur_path + '/' + temp_podspec_path
cur_version = ' '
Read the current version of the PodSpec file
File.open(podspec_absolute_path, 'r+') do |f|
f.each_line do |line|
# lookup. Version
version_desc = /.*\.version[\s]*=.*/.match line
if not version_desc.nil?
cur_version = version_desc.to_s.split('=').last.to_s.gsub("'".' ')
cur_version = cur_version.gsub(' '.' ')
break
end
end
end
puts color_text("Current version = ", Color.white) + color_text("#{cur_version}", Color.green)
# Allow custom version numbers
if user_custom_version == true
puts color_text "Please input pod lib's new version, if there is no input or less than or equal old version, it will be incremented:", Color.white
input_version = gets.chomp
# Check whether the input version is > the current version number
input_v_s = input_version.to_s.split('. ')
cur_v_s = cur_version.split('. ')
The position of comparison, starting from the far left
v_index = 0
Whether the version entered is valid
input_valid = false
while v_index < cur_v_s.count && v_index < input_v_s.count do
if input_v_s[v_index].to_i > cur_v_s[v_index].to_i
# Indicates that the version entered by the user is larger than the current version
input_valid = true
break
elsif input_v_s[v_index].to_i == cur_v_s[v_index].to_i
v_index += 1
else
break
end
end
if input_valid == false
puts color_text "Input invalid version = #{input_version}, will Auto +1 in last component", Color.natural
end
end
if not File.exist? temp_podspec_absolute_path
# system("cp -f #{podspec_path} #{temp_podspec_path}")
system("touch #{temp_podspec_path}")
end
new_version = ' '
git_source = ' '
File.open(temp_podspec_absolute_path, 'r+') do |t|
File.open(podspec_absolute_path) do |f|
f.each_line do |line|
# # Search for.version
# s.v ersion = "hundreds"
Note that the version number can be either '' or ''
write_line = line
version_desc = /.*\.version[\s]*=.*/.match line
if not version_desc.nil?
version_coms = version_desc.to_s.split('=')
if input_valid == true and user_custom_version == true
new_version = input_version.to_s
else
version_num = version_coms.last.to_s.gsub("'".' ').gsub("\" ".' ').gsub(' '.' ')
v_s = version_num.split('. ')
# Processing version number 0.0.1
for i in 0. v_s.countdo
if i == v_s.count - 1
new_version += (v_s[i].to_i + 1).to_s
else
new_version += (v_s[i].to_s + '. ')
end
end
end
puts color_text("New version = ",Color.white) + color_text("#{new_version}", Color.green)
write_line = version_coms.first.to_s + '=' + "'#{new_version}'" + "\n"
end
source_desc = /.*\.source[\s]*=.*/.match line
if not source_desc.nil?
source_desc = /:git.*,/.match source_desc.to_s
source_desc = / / '*'.match source_desc.to_s
git_source = source_desc.to_s.gsub("'".' ')
puts "git source is #{git_source}"
end
t.write write_line
end
end
end
puts color_text("Update version from ",Color.white) + color_text("#{cur_version}",Color.green) + color_text(" to ",Color.white) + color_text("#{new_version}", Color.green)
# Write the new data back to the original Podspec
system("cp -f #{temp_podspec_path} #{podspec_path}")
system("rm -f #{temp_podspec_path}")
If the repo is not locally available, add it
if system("pod repo | grep #{pod_repo_name}") = =false
puts color_text("Add pod repo named '#{pod_repo_name}' with source: #{pod_repo_source}", Color.white)
system("pod repo add #{pod_repo_name} #{pod_repo_source}")
end
# Commit code to remote repository
puts color_text('Start upload code to remote', Color.white)
system("git commit -am 'update version to #{new_version}'")
if system('git push origin') = =false
die_log('[!] git push code error')
end
system("git tag #{new_version}")
if system('git push origin --tags') = =false
die_log('[!] git push tags error')
return
end
Verify that the podSpec format is correct
if verify_podspec_format == true
puts color_text("Start verify podspec '#{podspec_path}'...", Color.white)
if system("pod lib lint #{podspec_path} --allow-warnings") = =false
die_log("[!] pod spec' format invalid")
return
end
end
# Submit a POD Spec to the Spec repository
puts color_text("Start push pod '#{podspec_path}' to remote repo '#{pod_repo_name}'", Color.white)
if pod_repo_name == 'trunk'
if (is_static_lib == true ? system("pod trunk push #{podspec_path} --allow-warnings --use-libraries") : system("pod trunk push #{podspec_path} --allow-warnings")) = =false
puts "If not timeout, you need to check your 'trunk' account like: 'pod trunk me', and register code is 'pod trunk register <your email> <your name>'"
return
end
else
if (is_static_lib == true ? system("pod repo push #{pod_repo_name} #{podspec_path} --allow-warnings --use-libraries") : system("pod repo push #{pod_repo_name} #{podspec_path} --allow-warnings")) = =false
return
end
end
puts color_text("The Update success ☕ ️! Current version =#{new_version}", Color.green)
Copy the code
Here’s the PodPushFile, this is the configuration file, and it has these configuration items:
If the script is not executed in the same directory as the podspec file, then you need to configure this directory
PUSH_DIR_PATH=
Whether to allow the user to customize the version number, not true will allow the user to set the custom version number, rather than increment the version number
USER_CUSTOM_VERSION=true
Authentication is enabled by default. You can skip the authentication phase
VERIFY_PODSPEC_FORMAT=true
The name of the #pod repo, or the private library name if it is a private library
POD_REPO_NAME=trunk
The source address of # Pod Repo. If it is a private repository, fill in the address of the private repository. Note that this is the address of the repository where the Podspec is stored
POD_REPO_SOURCE=https://github.com/CocoaPods/Specs
If the library is static, set this to true
POD_IS_STATIC_LIBRARY=false
Copy the code
If you have any questions about the script, please leave a comment. RubyRepo this is my Ruby repository address, which will be updated from time to time some useful and fun Ruby scripts, like to pay attention to.