前言
我司之前使用的仓库工具是Gogs,并且很久都没有更新过,最近经过讨论之后决定迁移到gitlab。gitlab对很多同学来说应该是老朋友了,这里也不展开说两者的对比什么的。
老夫虽然纵横职场几年,但是这船只在水面上划动之理还是掌握的不好;这不,一百多个仓库的迁移任务交给了我,想想都知道这就是一个没有难度,只需做重复动作的任务。
话不多说,赶紧开始吧。
工作分析
一个仓库的迁移,我们前端只要关心以下步骤
- 在
gitlab中预先按照产品分好群组 - 新建仓库-从url中导入-填写各种基础信息
- 配置CI/CD
- 配置好仓库的分支(保护分支、删除无用分支等)主要是以前没有规范好
而上面的步骤,都是重复的操作,都在gitlab网页中操作。虽然我有想过用油猴做点什么,但最终还是没想什么可以做
而唯一有想法操作的,只有生成CI/CD配置文件的这个操作。配置过CI/CD的同学应该知道,每个项目得有一个对应的文件,而配置内容的骨架是一样的,不同的就是
- 打包命令
- 分支情况
- 服务器地址
- runner(配置文件中的tags)
先放上一个例子给大家看看
variables:
GIT_STRATEGY: clone
stages:
- deploy
deploy:
stage: deploy
tags:
- node-14
script:
- npm install --unsafe-perm=true --allow-root
- rm -rf ./dist
- >
if [ "$CI_BUILD_REF_NAME" == "test" ]; then
echo 'test branch'
yarn build:maintest
scp -r ./dist/* 测试环境服务器地址
elif [ "$CI_BUILD_REF_NAME" == "dev" ]; then
echo 'dev branch'
yarn build:test
scp -r ./dist/* 开发环境服务器地址
fi
except:
- master
只要配置好这些,那么我们push代码到仓库后就会自动构建流水。我们的服务端还实现了企微的群机器人通知,不过我个人觉得太烦了,就没有配置。
上面的这个配置文件,如果我们人工去做的话,我要搞一百多个文件,就算是粘贴复制也顶不住啊😫。所以呢,我想到了用nodejs生成
node生成yml配置文件
那又让我们分析一下用node怎么去做这个事情
- 写好生成代码的模板,找出变量
- 把上面的需要的变量用一个excel收集起来
- 把收集好的数据进行处理,生成文件
一看这么多活,我怎么可能低声忍气的一个人默默的完成呢,于是我找组长要人,把第二点这个只需要劳动力的活交给他😂估计这个同事心里一万句骂我的话。我这么帅,肯定是负责写node代码的呀😎。
我的收集表长这样
其中黄色的部分得叫运维的同事填写,因为我们前端仔是不知道这些的
这个枯燥的话就让他们先干着吧,我们来看看node的代码
吐槽
开始之前不得不吐槽一下这个shell语法和yaml语法,非常严格敏感,而且报错都是模棱两可的。当然,有我菜的原因
node代码
具体想体验的同学,点击上面的网址去玩玩吧
配置文件模板
function getContent(item) {
return `variables:
GIT_STRATEGY: clone
stages:
- deploy
deploy:
stage: deploy
tags:
- ${item.runner}
script:
- npm install --unsafe-perm=true --allow-root
- rm -rf ./dist
- >${item.测试服务器路径 ? `\n if [ "$CI_BUILD_REF_NAME" == "test" ]; then
echo 'test branch'
${item.测试环境自定义命令 || 'npm run build:test'}
scp -r ./dist/* ${item.测试服务器路径}${item.开发服务器路径 ? '' : '\n fi'}` : ''}${item.开发服务器路径 ? `${item.测试服务器路径 ? '\n elif' : '\n if'} [ "$CI_BUILD_REF_NAME" == "dev" ]; then
echo 'dev branch'
${item.开发环境自定义命令 || 'npm run build:dev'}
scp -r ./dist/* ${item.开发服务器路径}
fi` : ''}${item.机器人地址 ? `\n - curl ${item.机器人地址}` : ''}
except:
- master
`
}
是不是感觉一团乱,压根就不想看,没办法,还记得上面我吐槽yaml的语法吗,他对缩进非常严格;script中的shell代码也是如此,我也因此踩了很久的坑,因为配置有没有错误,跑流水才知道。
这个函数做的事情就是将传进来的数据对应的插入位置,并返回配置文件的内容
测试环境默认的打包命令是npm run build:test,开发环境默认的打包命令是npm run build:dev
关键代码
const fs = require("fs");
const data = require("./dataCI");
const child_process = require("child_process");
const json2xls = require("json2xls");
const newDirName = '生成好的配置文件';
const configList = []
// 删除文件夹
child_process.exec(`rm -rf ./${newDirName}`, () => {
fs.mkdir(`./${newDirName}`, () => {
const groups = [... new Set(data.map(item => item.群组名))]
// 按群组生成文件夹
groups.forEach(item => fs.mkdirSync(`./${newDirName}/${item}`))
data.forEach(item => {
const ymlPath = `./${newDirName}/${item.群组名}/.${item.项目名称}-gitlab-ci.yml`
const ymlName = `${item.群组名}/.${item.项目名称}-gitlab-ci.yml`
fs.writeFile(ymlPath, getContent(item), 'utf-8', (error) => {
if (error) console.log(error)
})
configList.push({
'项目名称': item.项目名称,
'配置文件地址': `http://192.168.2.123/-/raw/main/frontend/${ymlName}`
})
})
toExcel(configList)
});
});
// 生成对应配置文件网络路径的excel
function toExcel(data) {
const xls = json2xls(data);
fs.writeFileSync(`./CICD配置网址.xlsx`, xls, "binary");
}
我们要做的事情很简单
- 读取dataCI,也就是收集好的项目表数据
- 生成一个总的文件夹,我命名为
生成好的配置文件 - 群组数据去重后遍历生成以群组为名的空文件夹
- 接着就是遍历dataCI,创建好对应路径和名称的文件,写入对应的模板数据
- 收集好对应的网址,因为我们最后要在新仓库配置CICD,配置好这个网址就可以
新需求
当我迁移好仓库,准备继续探讨船只在水面上划动之理时,领导突然来了一句:整理一份迁移后的表给我,越详细越好。
TMD,刚建完一百多个仓库眼都花了,又搞这种东西;于是我背上电脑头也不回,明天再说😡
第二天早上我欣赏着搬好的gitlab仓库列表;看着看着,咦,gitlab的这个列表接口会不会携带着仓库的信息呢;F12一按,点开接口,我差点大喊一声

全体起立,看看接口的字段
还说啥呀兄弟们,nodejs开干啊
projectData具体看仓库哈,兄弟们,就是上面说的接口数据
const fs = require("fs");
const json2xls = require("json2xls");
const originData = require("./projectData");
function getTemplate(item) {
return {
'项目群组': item.group || '',
'项目名称': item.name,
'项目描述': item.description,
'代码仓库地址(内网)': `http://192.xxx.x.xxx${item.relative_path}`,
'代码仓库地址(外网)': `http://xxx.xxx.com${item.relative_path}`,
'搬迁时间': item.created_at.slice(0, 10),
}
}
const arr = originData.map((item, index) => {
const children = item.children;
// 分组
if(children) {
return children.map((child, index) => {
child.group = item.name
return getTemplate(child);
})
} else {
return getTemplate(item)
}
})
const excelData = arr.flat();
const xls = json2xls(excelData);
fs.writeFileSync(`./前端仓库迁移汇总.xlsx`, xls, "binary");
依然是这个套路,
- 先整理好表头的内容(模板),并定好取值
- 接着就是循环处理数据了,如果没有
children就代表改仓库没有分类。有就再循环一次,而这个循环就会加上群组的标识group - 二维数组拉个平,生成excel,大功告成!
最后
你们说船只要怎么划,才能水的时间更久呢🤔?
点个赞支持一下吧🙏🏻
blog:gauharchan.github.io/,这是我博客地址,让我们一起在前端道路上持续发胖吧,😁