使用 Gitlab CI/CD 实现自动化发布站点到 IIS
说明
这里先介绍下两个东西 CI/CD
、GitLab Runner
,当然在此之前你需要对 git
有所了解,关于 git 这里不做说明,可以自行百度。
首先介绍 CI/CD :随着我们开发方式的转变,程序的发布变得非常频繁,而其这些发布操作都是重复的。CI/CD
就是为了使这些操作能变得自动化,那它是怎么实现自动化的呢?其实它做的就是当我们使用 git push
(推送)代码的时候会执行 任务
(task) 而这个 任务
里面其实又包含多个 作业
(job),如对代码进行单元测试、部署项目等等,这些 任务
和 作业
在 gitlab 中其实是以一个 .gitlab-ci.yml
文件存在的,这个文件后面会说明。好了我们知道了 CI/CD
是什么(心虚~,你们可以自行百度查看更详细的说明。),那么到底是谁在执行这些 任务
和 作业
的呢?这就是下面要介绍的 GitLab Runner
。
GitLab Runner:GitLab Runner
就是用来运行我们定义好的 任务
和 作业
也就是 .gitlab-ci.yml
文件。Runner 分为 Shared Runner
(共享型) 和 Specific Runner
(专有型),Shared Runner
是所有的项目都能用,但只能由管理员创建,而 Specific Runner
(专有型)只能为指定的项目服务。Shared Runner
一般是用在有多个项目的服务器上,Specific Runner
则是单个项目的服务器,或者是你自己的电脑上。
下面列出我本次使用的环境:
操作系统:Windows 10
项目版本:.NET Core 2.2
脚本执行环境:PowerShell 5.1.17763.316
Web服务器:IIS 10.0
Gitlab:使用 gitlab.com (*Gitlab 支持私有化部署 )
项目地址:https://gitlab.com/WigorRunnerTest
Gitlab CI/CD
首先你需要在 GitLab 上注册个账号,这里需要使用你懂的工具上网,因为它使用了谷歌的 reCAPTCHA
,如果你是自己部署的 gitlab 将没有这个问题。如果大家有需要请留下邮箱。
Gitlab 设置中文界面
Gitlab 默认的界面是英文的,只需要点击头像行的 Settings
,然后点击 左侧导航栏
的 Preferences
,之后在滑到最底部找到 Localization
旁边的 Language
选择 简体中文
,最后点击 Save changes
,F5
刷新页面即可。
设置好后我们可能更方便的操作 gitlab 了,接着我们需要创建一个项目,这里将使用一个 DotNET Core
项目为例。创建好项目后我们需要将它先 clone
到本地。
下载 Gitlab Runner
在我们定义 任务
和 作业
之前我们需要在我们的服务器或者是电脑上安装好 Gitlab Runner
。
官网下载地址:https://docs.gitlab.com/runner/install/
下面是我整理好的下载地址,本次使用的是 Windows amd64
:
下载好后,找到你下载的目录,将软件重命名为 gitlab-runner.exe
。只用使用 cmd 进入到该目录,需要注意的是你需要以 管理员
的方式运行 cmd,否者后面执行命令的时候会报错。
注册 Gitlab Runner
接着在命令行中输入:
gitlab-runner register
这时会出现提示:Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
它叫你输入协调器的地址,这个地址是在你 gitlab 项目的 左侧导航栏
,设置
下的 CI/CD
中,找到 Runner
点击展开,就会看到 专有Runner
和 共享Runner
,这里我们使用 专有Runner
做演示说明。红色框中的东西是我们后面需要用到的东西。
好了我们有了 coordinator URL 把它复制下了,粘贴到刚刚的命令中回车。
出现了另外一个提示:Please enter the gitlab-ci token for this runner:
,需要你输入 token ,这个 token 就是你刚刚复制 URL 下面的 注册令牌。接着它要你输入这个 Runner 的描述,这个根据自己的情况填。
之后又来一个提示:Please enter the gitlab-ci tags for this runner (comma separated):
,需要我们输入 Runner 的标签,这里我使用 deploy。
最后一个提示:Please enter the executor: docker, virtualbox, shell, ssh, docker+machine, docker-ssh+machine, kubernetes, docker-ssh, parallels:
,需要我们填入脚本的执行环境,这里先填 shell
,这时你的 gitlab-runner.exe 下会生成一个 config.toml
文件,里面保存着我们刚刚输入的信息。
需要注意的是这个标签就是我们后面编写
.gitlab-ci.yml
里的 job 会用到,它根据 tags 来指派哪些 Runner 会执行该任务
和作业
。
之后我们回到 gitlab 可以看到这里已经有个激活的运行器了,这里的图标也变成了绿色。如果你这里显示的不是绿色,那么你刷新下页面看看,还不行的话那么你需要运行 gitlab-runner restart
命令来重启 Runner,接着可以使用 gitlab-runner status
查看 Runner 的运行状态。出现 gitlab-runner: Service is running!
那么表示你的服务已经运行成功了。 再次强调你的命令需要使用 管理员
身份运行。
将 Shell 改成 PowerShell
上面选择脚本执行环境的时候我们选了 shell
,但是本次我是在 Windows 环境下运行,所以需要将它改为 PowerShell,打开 config.toml
文件,在 [[runners]]
下加入 shell = "powershell"
,然后保存文件即可。
.gitlab-ci.yml 简单说明
上面已经提过 .gitlab-ci.yml
使用来干什么的了,.gitlab-ci.yml
其实是本次自动化发布的核心,它是放在你 gitlab 上项目的根目录下。这里将对 .gitlab-ci.yml
该怎么配做一个简单说明,我只会介绍我用的东西更多的东西你可以查看我下面的「相关文档」。
首先在项目根目录下建立一个 .gitlab-ci.yml
文件,代码如下:
before_script:
- cd src
stages:
- test
# job
test:
stage: test
# 将会执行的脚本
script:
- dotnet restore
- dotnet build
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
我们来一个个说明这些东西的作用:
before_script
在整个项目 clone 到 Runner 所处的服务器时会先执行这个里面的脚本,这里我是进入到了 src 目录,你还可以在这里面做一些包还原的操作。
stages
里放的是将会执行的 job。
test
是做作业(job),这个命名你可以根据自己的情况来。test
就是上面 stages
会执行的 job 的真正配置处。
-
stage
对应stages
中的项,如果一个 job 没有指定 stage,那么这个任务会分配到test stage。 -
script
就是执行的脚本,构建自动化的核心也就是在此处。作为简单的演示,我就还原了包和生成项目。 -
only
是值该 job 会在被哪些分支 push 触发。 -
tags
上面在我们注册时有提到过,这个tags
对应的是我们注册gitlab runner
时所填的tages
,表示的是该 job 会触发哪些 Runner。
OK,我们此时已经将一个最简单的 .gitlab-ci.yml
构建好了,在项目根目录下执行 git commit -am "[init] .gitlab-ci.yml"
,git push
,将配置好的文件 push(推送)到远端。回到 gitlab 中,我们点击 CI/CD
可以看到有一个流水线在运行。
点进去可以看到运行的日志,可以看到我们 before_script
、script
中的命令在一条条的执行,当然如果你的脚本出现了错误,状态会是 失败
,你需要检查你的脚本是否有误。如果你的状态一直处于 等待中
那么需要检查你的 gitlab runner
是否允许正常,以及上面提到的 设置
中的 Runner
是否处于激活状态(绿色图标)。
输出乱码问题解决
你可能发现了这里怎么有一些奇怪的字符,这是因为我的操作系统是中文,乱码了解决办法是在 before_script
加入 - chcp 65001
脚本。
再次提交代码,ok 这次的中文信息显示正确了。
变量作用的说明
.gitlab-ci.yml
是存放在我们项目的根目录下的,如果我们项目使开源的,那么我们将会暴露一些私密信息如token,密钥,项目发布所处服务器的路径,这些信息公开可能会使我们的项目存在安全隐患。亦或者我们需要部署多个项目但是它们的 .gitlab-ci.yml
文件十分相似那么我们就可以通过变量控制哪些可变的因素。
那么到底怎么使用变量呢?第一步我们需要先声明变量,在 gitlab 的项目中找到 设置
下的 CI/CD
,可以看到 变量
然后展开,这里就是可以声明我们需要用到的变量。.gitlab-ci.yml
只需要在脚本需要用到变量的方法使用 $env:变量名
的形式使用即可,需要注意的是:不同的系统使用变量的方法也不一样,这里我使用是 PowerShell。
常用的变量使用方法:
Shell | 使用方法 |
---|---|
bash/sh | $variable |
windows batch | %variable% |
PowerShell | $env:variable |
关于变量的更多说明可以参考官方的文档:https://gitlab.com/help/ci/variables/README#variables
自动化部署到 IIS
前面已经介绍了构建一个自动化的流程,有了前面的基础其实自动化部署到 IIS 也就是编写的脚本发生了变化。
再开干之前我们需要把我们的思路捋一捋,核心在于怎么通过命令的形式发布一个站点。
- 首先需要编译项目,确保代码没有问题
- 使用
dotnet publish -c release -r win81-x64
获取我们需要发布站点的部署文件 - IIS 停止运行需要发布的站点
- IIS 停止该站点的进程池
- 备份原有项目(不是必须,但是最好不要省去该步骤)
- 删除 IIS 上需要发布的站点的原有文件
- 复制我们准备好发布的文件(也就是 publish 文件夹)到 IIS 站点下
- IIS 启动进程池
- IIS 启动该站点
下面一步一步已脚本的形式来说明:
- 首先确定整体的东西,这里我准备构建两个 job
test
和deploy
,第一个 job 用于校验我们的代码是否正确,第二个是部署的 job。第一个 job 只有两行命令,还原和编译。
before_script:
#中文乱码问题
- chcp 65001
- cd src
# 执行的 job
stages:
- test
- deploy
# 校验代码
test:
stage: test
# 将会执行的脚本
script:
- dotnet restore
- dotnet build
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
# 部署
deploy:
stage: deploy
# 将会执行的脚本
script:
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
- 在进行编写剩下的脚本之前需要定义几个变量:
ProjectName
:项目名称,用于 publish 用,如 VS 下一个解决方案可能存在多个项目,这时候就需要知道我们 publish 的项目使哪个。
WebSiteName
:站点名称,用户关闭 IIS 站点和 IIS 对应进程池的,如果你的进程池和站点的名称不一致请在声明一个变量。
WebSitePath
:站点的路径,用于备份、删除原有站点、新的项目复制到该路径下。
定义好这些变量后接着写我们 deploy
的脚本:
可以看到这里使用了:$env:ProjectName
、$env:WebSitePath
、$env:WebSiteName
变量。
# 部署
deploy:
stage: deploy
# 将会执行的脚本
script:
# 声明一个变量保存当前时间,用作备份数据文件夹名称
- $datetime=Get-Date -Format 'yyyy-MM-dd-HH-mm'
# 编译打包项目
- dotnet publish -c release -r win81-x64
# 进入编译好的项目目录
- cd $env:ProjectName\bin\Release\netcoreapp2.2\win81-x64\
# 停止 IIS 对应站点
- C:\Windows\System32\inetsrv\appcmd.exe stop site $env:WebSiteName
# 停止进程池
- C:\Windows\System32\inetsrv\appcmd.exe stop apppool /apppool.name:"$env:WebSiteName"
# 备份原有项目文件,项目名_当前时间
- cp "$env:WebSitePath" "$env:WebSitePath$datetime" -Recurse
# 删除原有站点
- del "$env:WebSitePath" -Recurse
#复制 publish 文件到站点
- cp "publish" "$env:WebSitePath" -Recurse
# 启动进程池
- C:\Windows\System32\inetsrv\appcmd.exe start apppool /apppool.name:"$env:WebSiteName"
# 启动 IIS 站点
- C:\Windows\System32\inetsrv\appcmd.exe start site $env:WebSiteName
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
到这一步整个自动化发布已经完成了,我们只要 push 代码到远端就会自动部署我们的项目到 IIS 中,需要注意的是你必须确保你的 IIS 中已经有这个站点了。
回到 gitlab 中查看 CI/CD
可以看到这次我们的阶段有两个,因为我配置了两个 作业(job),一个 test一个 deploy。
点击每个作业中看看执行的脚本是不是我们定义好的,需要提一下 powershell 脚本如果出错的话 gitlab-ci 返回的结果还是会显示成功,错误提示还是乱码的,坑啊。额~目前还找到解决的办法,如果是 docker 或者 linux 下应该没有这问题。
再看看 IIS 这边的效果,文件已经自动备份了,站点也正常运行了,一个自动化部署项目到 IIS 站点已经完成了。
模拟项目发布
下面修改代码然后 push 上去看看,看看我们的网站没有没有更新。
完整的 .gitlab-ci.yml
before_script:
#中文乱码问题
- chcp 65001
- cd src
# 执行的 job
stages:
- test
- deploy
# 校验代码
test:
stage: test
# 将会执行的脚本
script:
- dotnet restore
- dotnet build
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
# 部署
deploy:
stage: deploy
# 将会执行的脚本
script:
# 声明一个变量保存当前时间,用作备份数据文件夹名称
- $datetime=Get-Date -Format 'yyyy-MM-dd-HH-mm'
# 编译打包项目
- dotnet publish -c release -r win81-x64
# 进入编译好的项目目录
- cd $env:ProjectName\bin\Release\netcoreapp2.2\win81-x64\
# 停止 IIS 对应站点
- C:\Windows\System32\inetsrv\appcmd.exe stop site $env:WebSiteName
# 停止进程池
- C:\Windows\System32\inetsrv\appcmd.exe stop apppool /apppool.name:"$env:WebSiteName"
# 备份原有项目文件,项目名_当前时间
- cp "$env:WebSitePath" "$env:WebSitePath$datetime" -Recurse
# 删除原有站点
- del "$env:WebSitePath" -Recurse
- cp "publish" "$env:WebSitePath" -Recurse
# 启动进程池
- C:\Windows\System32\inetsrv\appcmd.exe start apppool /apppool.name:"$env:WebSiteName"
# 启动 IIS 站点
- C:\Windows\System32\inetsrv\appcmd.exe start site $env:WebSiteName
# 哪个分支会执行
only:
- master
#runner 注册时的 tag,这里指会触发的 runner
tags:
- deploy
小结
至此已经实现了 push 时项目自动发布到 IIS 。当然在这个过程中踩了 n 多的坑,总结要细心安装步骤一步一步认真的走。下一步准备对接钉钉的机器人。实现的效果是当我们项目发布时会自动通知,发布成功后也会自动通知。
相关文献
《什么是 CI/CD?》:https://linux.cn/article-9926-1.html
《GitLab-CI与GitLab-Runner》: http://www.cnblogs.com/cnundefined/p/7095368.html
《IIS 站点和进程池关闭》:https://www.cnblogs.com/jmaly/p/9860606.html
《Gitlab-CI job 配置文件 .gitlab-ci.yml 配置方式(翻译)》:https://blog.csdn.net/kunyus/article/details/81390330
powershell论坛:https://www.pstips.net
GitLab Runner 官方文档:https://docs.gitlab.com/ee/ci/runners/README.html