pod庫自動化部署腳本

前言

咱們平時在作開發的時候,多少會接觸到組件化的思想。iOS的組件化通常是經過使用 cocoapods 製成pod庫的形式完成的。pod庫又分爲公開庫和私有庫兩種。好比咱們上傳到 github 的就屬於公開庫,提供別人下載使用。而部署在公司內部的則屬於私有庫,別人訪問不了,使用不到。html

概念

本文主要是講如何實現自動部署pod腳本的,所以關於pod庫相關的概念只會作個簡單的介紹,不會作過多的講解。若是想要有更深刻的瞭解,能夠查閱官方文檔git

1. repo

一個 repo 就是至關於一個放置相關 pod 庫的索引的倉庫。怎麼理解?好比咱們在github上製做的公開庫,它的 repo 叫什麼?叫 trunk,地址是 https://cdn.cocoapods.org/ 。咱們能夠直接在本機執行命令: pod repo,將會看到圖示。github

截屏2021-08-13 下午2.06.44.png

這個倉庫就是存放咱們部署上去的 podspec 文件的。ruby

2. podspec

而一個 podspec 則是用於描述一個pod庫,如庫結構,版本,源代碼地址等。markdown


瞭解了這兩個,那麼咱們就能夠製做本身的pod庫了。less

製做pod庫

以製做公開庫,提交到 github 爲例。提交到trunk的官方文檔點我ide

首先你須要現有一個源代碼倉庫,oop

1. 建立podspec文件

pod spec create yourSpecName.podspec
複製代碼

2. 編輯podspec文件

例如podspec文件內容以下,編輯裏面的source、source_files等。組件化

Pod::Spec.new do |spec|
  spec.name             = 'Reachability'
  spec.version          = '3.1.0'
  spec.license          = { :type => 'BSD' }
  spec.homepage         = 'https://github.com/tonymillion/Reachability'
  spec.authors          = { 'Tony Million' => 'tonymillion@gmail.com' }
  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.h,m'
  spec.framework        = 'SystemConfiguration'
  spec.requires_arc     = true
end
複製代碼

3. 提交咱們的源代碼

git commit -am 'submit'
git push origin
複製代碼

4. 給咱們的pod打tag

注意到podspec是有版本號的概念的,它須要和你pod庫,也就是源代碼庫的tag值是一致的。這樣,咱們的cocoapods才能在解析podspec以後,下載到正確版本對應的源代碼。ui

git tag 0.0.2

#推送指定tag到遠端
git push origin 0.0.2

# 或者推送本地全部tag到遠端
# git push origin --tags
複製代碼

5. 驗證咱們的podspec文件格式是否正確

本地驗證:

pod lib lint yourSpecName.podspec --allow-warnings
複製代碼

遠程驗證:

pod spec line yourSpecName.podspec --allow-warnings
複製代碼

6. 發佈咱們的podspec

pod trunk push yourSpecName.podspec --allow-warnings
複製代碼

更新pod庫

此時咱們的庫中應該已經有一個podspec文件了的,咱們須要作的就是更新它的版本號,若是文件結構有變更,就須要改動 source_files,有添加新的依賴庫,那麼須要修改 dependency

1. 更新podspec的版本號

打開podspec文件,編輯更新version字段就好,通常採用遞增的方式。

1. 爲咱們新版本的代碼打tag

# 須要先提交代碼
git commit -am 'update'
git push origin
git tag 0.0.2
git push origin 0.0.2
# 或 git push origin --tags
複製代碼

2. 本地驗證新修改的podspec文件是否有問題

這一步在這裏騎士能夠跳過,通常第一次上傳沒問題,後面也不會出現問題。

pod lib lint *.podspec
複製代碼

3. 部署新版本的podspec

pod trunk push *.podspec
複製代碼

腳本實現

腳本使用 ruby 實現的,源碼在這

實現的原理其實也是用了更新podspec的步驟,只不過是加了一些配置而已。

使用起來比較簡單,將腳本放在在當前的pod根目錄下,執行 ruby specpush.rb 便可一鍵發佈。

這裏直接貼代碼:

#! /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

# 拉取最新代碼
# 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 not File::exist?(cur_path + '/PodPushFile')
    system('touch PodPushFile')
    File.open(cur_path + '/PodPushFile', 'w+') do |f|
        f.write("#寫入*.podspec所在的相對目錄,不寫默認會在腳本執行的目錄下查找 PUSH_DIR_PATH= #是否容許用戶自定義版本號,不填或填true將容許用戶設置自定義的版本號,而不是自增版本號 USER_CUSTOM_VERSION=true #默認開啓驗證,能夠跳過驗證階段 VERIFY_PODSPEC_FORMAT=true #pod repo的名字,若是是私有庫就填私有庫的名字 POD_REPO_NAME=trunk #pod repo的源地址 POD_REPO_SOURCE=https://github.com/CocoaPods/Specs #若是這個庫是靜態庫,那麼須要設置爲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}"

# 搜索podspec路徑
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 not File::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

# 在當前podspec目錄下新建一個臨時 need_delete_temp.podspec 文件
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 = ''
# 讀取當前podspec文件的版本
File.open(podspec_absolute_path, 'r+') do |f|
    f.each_line do |line|
        # 查找.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)

# 容許自定義版本號
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

    # 判斷輸入的version是否>當前的版本號
    input_v_s = input_version.to_s.split('.')
    cur_v_s = cur_version.split('.')
    # 比較的位置,從最左邊開始
    v_index = 0
    # 輸入的version是否有效
    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
            # 說明用戶輸入的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|
            # # 查找.version
            # s.version = "0.0.2"
            # 須要注意的是,版本號能夠是'',也能夠是""
            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('.')
                    # 處理版本號 0.0.1
                    for i in 0...v_s.count do
                        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)

# 將新數據反寫回到原始podspec中
system("cp -f #{temp_podspec_path} #{podspec_path}")
system("rm -f #{temp_podspec_path}")


# 若是本地沒有這個repo,那麼添加
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

# 提交代碼到遠程倉庫
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

# 驗證podspec格式是否正確
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

# 提交pod spec到spec倉庫
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("Update success ☕️! Current version = #{new_version}", Color.green)
複製代碼

這裏提一下 PodPushFile 文件,這個是配置文件,裏面有這些配置項:

#寫入*.podspec所在的相對目錄,不寫默認會在腳本執行的目錄下查找,若是腳本執行的目錄和podspec文件不在同一目錄下,那麼須要配置下
PUSH_DIR_PATH=


#是否容許用戶自定義版本號,不填或填true將容許用戶設置自定義的版本號,而不是自增版本號 
USER_CUSTOM_VERSION=true


#默認開啓驗證,能夠跳過驗證階段
VERIFY_PODSPEC_FORMAT=true


#pod repo的名字,若是是私有庫就填私有庫的名字
POD_REPO_NAME=trunk


#pod repo的源地址,若是是私有倉庫,那麼填寫私有倉庫的地址,注意是存放podspec的倉庫的地址
POD_REPO_SOURCE=https://github.com/CocoaPods/Specs


#若是這個庫是靜態庫,那麼須要設置爲true
POD_IS_STATIC_LIBRARY=false
複製代碼

若是腳本有任何問題,請評論留言。rubyRepo 這是個人 ruby 倉庫地址,裏面會不時更新一些有用好玩的 ruby 腳本,喜歡的關注下。

相關文章
相關標籤/搜索