工作情况
随着业务发展,主项目工程中集合了各种各样的第三方库或者自研的库。比如:阿里系、打点、蓝牙、视频、RN、国内版、海外版、白标版
通过git创建各类分支管理相关的需要,分支的主要情况有:
- 公共分支common,用于处理国内与海外共同功能;
- 国际化分支language,专门处理国际化文件、国际化切换,国际化字段编译校验;
- 发版分支master
- 线上分支release
- 开发分支dev
仅仅是上面的情况,还能勉强整理处理,如果再加上...
- 公共分支需区分本月上线与下月上线的common1、common2
- 国际化分支需要裂变为国内国际化、海外国际化
- 开发分支以功能为最小单元,演化出本月功能,下月分支。因此会出现一个人负责一个分支,到了另外一个月后,需要记得切换到新分支去工作
最忙时,会在4、5个分支切来切去,经历过这种切来切切的场景,你会发现自己,再也记不住哪个功能具体在哪个分支上进行的开发了。每次开发新功能或者修复新问题,也要先问一圈,我在哪、我应该在哪?做...
准备之路
接收到老大需求,需要实现修改一个版本号就集成新功能到工程中。第一反应是需要建立公司自己的私有库,通过Pods管理不同的功能
需要怎么做呢?
以前做组件的过程都是一个组件一个仓库管理,这样做的优点:
- 完全独立,不担心产生耦合
- 使用方便,改为需要的版本后,直接pod install搞定
- 一般一个功能一个人开发就好,无过多的git提交冲突
缺点:
- 功能太过分散
- 如有code review功能,每次提交都要经过审核,效率降低
- 仓库过多,新人来,要运行主工程,需要给予他一群的仓库权限
开始之路
选择了创建两个仓库的模式进行组件开发,一个仓库管理所有的组件代码,一个管理所有的podspec。也不知道这个选择的路是对是错,后面的需求变动,也因为这个选择带来很多麻烦
需要使用的工具有
- Cocoapods依赖
- Gerrit代码审核
- Sourcetree处理git版本管理
- Xcode你懂得
- Shell
本地库怎么建,网上搜有一堆,或者看我的烂片,下面的脚本收好,不做pod lint检查的,修改里面两个地方后,就可以通过运行脚本的方式,快速提交到pod
#!/bin/bash
# 更新时间:2021-4-28
# 手动拷贝podspec到私有仓库更新
# 不通过lib lint检查
export LANG=en_US.UTF-8
tip="使用说明:直接git更新私有库推送spec,无lint验证操作,不符合正常流程规范,谨慎使用\n\
1.tag可先行推送,也可在此推送\n\
2.私有库路径有误时可手动设置localSpecGitDir\n\
3.最后spec确认推送前强行关闭或z取消,不会重置私有库修改,需手动删除\n\
4.最后spec确认不输入y会重置私有库修改,已推送tag需要手动处理"
echo -e "\033[34;1m$tip\033[0m"
spec_repo_name="看我,看我,改这里,自己的本地组件库名"
localSpecGitDir="看我,看我,改这里,索引仓库地址"
git reset --hard
echoError(){
echo -e "\033[31;1m$1\033[0m"
}
echoNormal(){
echo -e "\033[32;1m$1\033[0m"
}
spec_file=''
dir_file=$(dirname $0)
cd $dir_file
for file in `ls `
do
if [[ $file =~ \.podspec$ ]];then
spec_file=$file
break
fi
done
if [ "$spec_file" = "" ];then
echoError "error:未找到spec文件"
exit
fi
versionString=`grep -E 's.version.*=' $spec_file`
versionString=${versionString#*\'}
versionString=${versionString%*\'}
spec_filename=${spec_file%.*}
last_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
if [ $? != 0 ]; then
echoError "没有获取到tag"
fi
echoNormal "-------- 当前项目仓库最新 tag: ${last_tag} -----------------"
echoNormal "-------- 本地podspec tag: ${versionString} -----------------"
echoNormal "新tag:${versionString}(enter确认,手动输入其他终止)"
read newTag
if [ "" == "$newTag" ];then
newTag=${versionString}
fi
if [ "$versionString" != "$newTag" ];then
echoError "-----------------已手动终止-----------------"
exit
fi
if [ "$last_tag" != "$newTag" ];then
git tag ${newTag}
git push origin HEAD:refs/tags/${newTag}
# git push origin ${newTag}
if [ $? != 0 ]; then
echoError "-----------------推送tag失败,请检查网络环境-----------------"
exit 1
fi
fi
checkSpecGitDir(){
if [ -d $spec_git_dir ];then
echo
else
if [ "$1" = "" ]; then
echoError "未找到spec仓库地址"
exit 1
else
spec_git_dir=$1
fi
fi
}
#同级父目录下
spec_git_dir="$(dirname $(pwd))/${spec_repo_name}/"
#不存在可以手动设置
checkSpecGitDir ${localSpecGitDir}
#未找到再找找.cocoapods目录
checkSpecGitDir "${HOME}/.cocoapods/repos/${spec_repo_name}/"
#找不着
checkSpecGitDir ""
spec_content_dir=$spec_git_dir$spec_filename
target_dir=$spec_content_dir'/'$newTag
commitAction="Add"
if [ -d $spec_content_dir ];then
commitAction="Update"
else
mkdir $spec_content_dir
fi
if [ -d $target_dir ];then
rm -rf $target_dir
fi
mkdir $target_dir
target_file=$target_dir'/'$spec_file
cp $spec_file $target_file
resetSpec(){
git reset --hard
tag_dir="${spec_filename}/${newTag}/"
if [ -d $tag_dir ];then
rm -rf $tag_dir
fi
}
cd $spec_git_dir
git pull origin
if [ $? != 0 ]; then
echoError "-----------------pull spec 仓库失败,请检查网络环境-----------------"
resetSpec
exit 1
fi
message="[$commitAction] $spec_filename ($newTag)"
echoNormal "commit内容:$message"
echoNormal "----------------- 是否开始推送新的spec [输入'y'开始] -----------------------"
read answer
if [[ $answer != y ]]; then
resetSpec
exit 0
fi
git add -A
if [ $? != 0 ]; then
echoError "-----------------spec git add失败-----------------"
resetSpec
exit 1
fi
git commit -m "$message"
git push origin
if [ $? != 0 ]; then
echoError "-----------------push spec 仓库失败,请检查网络环境并重试-----------------"
exit 1
else
pod repo update ${spec_repo_name} --verbose
if [ $? != 0 ]; then
pod repo add ${spec_repo_name} ${localSpecGitDir}
echoError "-----------------push spec 仓库失败,重试-----------------"
exit 1
fi
echoNormal "-----------------push success-----------------"
fi
开发完毕
组件化完成后的结果如下,每一个目录是一个subspec,引入组件是,通过正常引入所有组件或者引入单个组件
pod 'IMILabKit'
//引入单个
pod 'IMILabKit/Log'
需求变动
组件开发到中后期时,说需要对外提供,因此就面临不能使用源码作为组件的问题。查找cocoapods二进制方案,大概有3类
- cocoapods-package命令打包生成二进制
- cocoapods-binary配置生成二进制
- 使用cocoapods管理framework
- ENV条件编译生成不同的包
其实cocoapods执行完毕后,在pod目录下有一个framework产生,没有去尝试这个framework是否能直接用于作为二进制方案(子组件化,这种机制不适合我们的场景,因此没有去做尝试)
- 转换为二进制最大的困难
共用同一套代码,cocoapods子组件形式在使用时其实还是在同一个module中,子组件变成一个个独立的framework就将现有现象变成在不同的module中,要解决一个个的兼容问题,模块引入在两种不同方式是不一样的,因为这点,需要处理比较多的细节