说明

这里先介绍下两个东西 CI/CDGitLab 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 changesF5 刷新页面即可。

查看设置中文教程

设置好后我们可能更方便的操作 gitlab 了,接着我们需要创建一个项目,这里将使用一个 DotNET Core 项目为例。创建好项目后我们需要将它先 clone 到本地。

下载 Gitlab Runner

在我们定义 任务作业 之前我们需要在我们的服务器或者是电脑上安装好 Gitlab Runner

官网下载地址:https://docs.gitlab.com/runner/install/

下面是我整理好的下载地址,本次使用的是 Windows amd64

Windows: 下载x86下载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 的真正配置处。

  1. stage 对应 stages 中的项,如果一个 job 没有指定 stage,那么这个任务会分配到test stage。

  2. script 就是执行的脚本,构建自动化的核心也就是在此处。作为简单的演示,我就还原了包和生成项目。

  3. only 是值该 job 会在被哪些分支 push 触发。

  4. 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_scriptscript 中的命令在一条条的执行,当然如果你的脚本出现了错误,状态会是 失败,你需要检查你的脚本是否有误。如果你的状态一直处于 等待中 那么需要检查你的 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 也就是编写的脚本发生了变化。

再开干之前我们需要把我们的思路捋一捋,核心在于怎么通过命令的形式发布一个站点。

  1. 首先需要编译项目,确保代码没有问题
  2. 使用 dotnet publish -c release -r win81-x64 获取我们需要发布站点的部署文件
  3. IIS 停止运行需要发布的站点
  4. IIS 停止该站点的进程池
  5. 备份原有项目(不是必须,但是最好不要省去该步骤)
  6. 删除 IIS 上需要发布的站点的原有文件
  7. 复制我们准备好发布的文件(也就是 publish 文件夹)到 IIS 站点下
  8. IIS 启动进程池
  9. IIS 启动该站点

下面一步一步已脚本的形式来说明:

  1. 首先确定整体的东西,这里我准备构建两个 job testdeploy,第一个 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
  1. 在进行编写剩下的脚本之前需要定义几个变量:

    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

使用 Gitlab CI/CD 实现自动化发布站点到 IIS的更多相关文章

  1. .Net Core自动化部署系列(三):使用GitLab CI/CD 自动部署Api到Docker

    之前写过使用Jenkins实现自动化部署,最近正好没事研究了下GitLab的自动化部署,顺便记录一下. 使用GitLab部署我们需要准备两件事,第一个起码你得有个GitLab,自己搭建或者使用官方的都 ...

  2. GitLab CI/CD 自动化部署入门

    前言:因为找了B站内推,测试开发,正好知道内部使用GitLab做自动化测试,所以简单学了一下,有错误的地方请指正. 入门 初始化 cp: 无法获取'/root/node-v12.9.0-linux-x ...

  3. 使用Docker方式部署Gitlab,Gitlab-Runner并使用Gitlab提供的CI/CD功能自动化构建SpringBoot项目

    1.Docker安装Gitlab,地址:https://www.cnblogs.com/sanduzxcvbnm/p/13814730.html 2.Docker安装Gitlab-runner,地址: ...

  4. GitLab CI/CD的官译【原】

    CI / CD方法简介 软件开发的持续集成基于自动执行脚本,以最大限度地减少在开发应用程序时引入错误的可能性.从新代码的开发到部署,它们需要较少的人为干预甚至根本不需要干预. 它涉及在每次小迭代中不断 ...

  5. .NetCore 配合 Gitlab CI&CD 实践 - 单体项目

    前言 上一篇博文 .NetCore 配合 Gitlab CI&CD 实践 - 开篇,主要简单的介绍了一下 GitLab CI 的持续集成以及持续部署,这篇将通过 GitLab CI 发布一个 ...

  6. 前端初探 Gitlab CI/CD

    前言 纵观人类历史的发展以及三次工业革命,你会发现利用机器来替代部分人力劳动,将重复的工作自动化从而解放生产力都是发展的必然趋势,在软件工程领域也不例外,其中 CI/CD 就是其中一项,那么什么是 C ...

  7. Gitlab CI/CD

    Gitlab CI/CD 前言 纵观人类历史的发展以及三次工业革命,你会发现利用机器来替代部分人力劳动,将重复的工作自动化从而解放生产力都是发展的必然趋势,在软件工程领域也不例外,其中 CI/CD 就 ...

  8. .NetCore 配合 Gitlab CI&CD 实践 - 开篇

    引言 这是一个系列的文章,讲述的是一个中小型开发团队如何从零开始使用搭建基建 GitLab 代码托管平台,以及使用 GitLab Runner 实现 CI/CD 的故事.本系列通过部署一个完整的 .n ...

  9. 官网GitLab CI/CD英文文档翻译

    在查阅GitLab官网的CI/CD功能说明时,全是英文看起来不方便,通过翻译软件自动翻译后"内容失真",看起来很变扭.查阅了百度上的资料发现很多翻译很老旧,有些甚至是挂羊头卖狗肉. ...

随机推荐

  1. QT之二级菜单(二级菜单的箭头可以使用QSS设置图片)

    QT之二级菜单 QT之二级菜单 开场白 效果图 上代码 可参考文章 下代码 结尾 开场白 今天我们一起来了解下,在我们QT中,二级菜单是如何实现的,在上篇我们学习了QT之系统托盘,QT之自定义菜单,  ...

  2. Qt自定义弹窗屏蔽父窗口(QWidget设置setWindowModality(Qt::ApplicationModal);以后再show)

    写Qt程序时遇到一个问题: Qt自带的弹窗功能单一,所以须要自己用ui设计弹窗的内容,这样弹窗就和普通窗口一样了,但问题是这个弹窗显示后父窗口还是活动的.网上找了很久找到了解决办法: Qt::Wind ...

  3. 张正友相机标定Opencv实现以及标定流程&&标定结果评价&&图像矫正流程解析(附标定程序和棋盘图)

    使用Opencv实现张正友法相机标定之前,有几个问题事先要确认一下,那就是相机为什么需要标定,标定需要的输入和输出分别是哪些? 相机标定的目的:获取摄像机的内参和外参矩阵(同时也会得到每一幅标定图像的 ...

  4. NAT对于网络上的其它人都不可见(但可以转发端口),Bridged和网络里的其它物理机没区别,Internal只能在虚拟机之间可见,Host-only只对主机可见(最符合我的服务器需求),最多可设置8块网卡实现混杂

    VirtualBox 可以为每一个虚拟机分配8个网卡.每一个网卡的连接方式可以选为下列之一: Not attached Network Address Translation (NAT) Bridge ...

  5. C#中的String.Format介绍

    关键字:C# string.format作者:txw1958原文:http://www.cnblogs.com/txw1958/archive/2012/11/15/csharp-string_for ...

  6. Qt编程中QDiaog的ESC键(按下Esc键会默认调用reject()方法)

    最近使用QDialog时,按了下Esc键,导致QDialog被关闭,而后续的数据处理出现了问题.原来在QDialog中按下Esc键会默认调用reject()方法而不是closeEvent(QClose ...

  7. FFmpeg来源简单分析:结构会员管理系统-AVClass

    ===================================================== FFmpeg章列表: [架构图] FFmpeg源码结构图 - 解码 FFmpeg源码结构图 ...

  8. libuv和libev 异步I/O库的比较

    libuv 和 libev ,两个名字相当相近的 I/O Library,最近有幸用两个 Library 都写了一些东西,下面就来说一说我本人对两者共同与不同点的主观表述. 高性能网络编程这个话题已经 ...

  9. XF 绝对布局

    using System; using Xamarin.Forms; using Xamarin.Forms.Xaml; [assembly: XamlCompilation (XamlCompila ...

  10. Web service的学习资源

    看了半天的Web service,总算是对它有了一点眉目,不枉此行:)那就整理一下吧,来日还需要用到呢! 1.什么是Web service(请看这儿). 2.Web service的开发        ...