CI(持续集成)指开发人员一天内进行多次合并和提交代码操作,并通过自动化测试,完成构建
CD(持续部署)指每次代码更改都会自动部署到对应环境
CI/CD 结合在一起,可以加快开发团队交付成果的效率,减少时间成本
gitlab-ci 是 gitlab8.0 之后自带的一个持续集成系统,中心思想是每一次 push 到 gitlab 就会触发一次脚本执行,脚本内容包括测试、编译、部署等一系列内容
gitlab-ci 的脚本需要 gitlab-runner 来执行,代码 push 之后,webhook 检查到代码变化,就会触发 gitlab-ci,分配到各个 Runner 来运行相应的脚本
gitlab 有 ce 和 ee 两个版本,ce 是社区版,开源免费,ee 是企业版,需要付费
下面以 Ubuntu18.04.6 为例,安装 gitlab-ce
安装依赖软件
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates tzdata perl
添加 gitlab 软件源镜像
curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
安装 gitlab-ce
sudo apt-get install gitlab-ce
如果命令行能看到 Gitlab 的 Logo 打印,就说明安装成功了
打开 gitlab 配置文件
vim /etc/gitlab/gitlab.rb
为了能在浏览器访问 gitlab,还需要配置 gitlab 的访问地址和端口
# ip:port 改成自己的,也可以用域名
external_url 'http://192.168.66.100:82'
重载配置并重启
gitlab-ctl recofigure
gitlab-ctl restart
在浏览器输入 http://192.168.66.100:82 即可访问 gitlab,当然了,前提是你的端口要放开

初始用户名为 root,初始密码记录在 /etc/gitlab/initial_root_password 文件,密码有效期为 24 小时,建议登录后尽快修改密码
登录以后,就可以创建项目了,其余的基本的 git 操作这里就不赘述了
gitlab-ctl recofigure 过程,有可能出现卡在 ruby_block[wait for logrotate service socket] action run 的情况,解决办法如下:
ctrl + c 强行结束
运行 systemctl restart gitlab-runsvdir
再次运行 gitlab-ctl recofigure
安装结束以后,访问 web 端报 502,最可能的原因是端口被占用了,需要修改端口
vim /etc/gitlab/gitlab.rb
# 修改为没有被使用的端口即可
puma['port'] = 9091
下面以 Ubuntu18.04.6 为例,安装 gitlab-runner
添加 gitlab 软件源镜像
curl https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
安装 gitlab-runner
sudo apt-get install gitlab-runner
首先获取 gitlab-ci 的 token:项目主页->Setting->CI/CD->Runners Expand

使用命令注册 gitlab-runner
gitlab-runner register
按照步骤输入:
完成以后,刷新页面,即可在 Runners Expand 看到新增了一个 Runner

下面我们简单测试一下 Runner 是否能正常运行,随意新建一个 SpringBoot 项目

在根目录下创建一个 .gitlab-ci.yml 文件,这里只是简单输出一段语句
stages:
- deploy
deploy-job:
tags:
- prod
stage: deploy
script:
- echo "hello world!!!"
push 到 gitlab 后,会发现脚本已经自动执行了,绿勾代表执行成功

点击绿勾,在下方 Pipeline 点击 deploy-job 可以查看执行过程


.gitlab-ci.yml 文件中可以定义一个或多个作业(job),每个作业独立执行,必须有唯一的名称(不能使用关键字)以及包含一个 script,这里定义了三个作业 build、test、deploy,script 可以是 shell 命令
build:
script:
- echo "build"
test:
script:
- echo "test"
deploy:
script:
- echo "deploy"
- echo "finish"
before_script 用于定义一个命令,在每个作业运行之前运行,before_script 失败将导致整个作业失败,其他作业不再执行,如果在作业中定义了 before_script,则该作业不会运行全局的 before_script
after_script 用于定义一个命令,在每个作业运行之后运行,作业失败不影响 after_script 的运行,如果在作业中定义了 after_script,则该作业不会运行全局的 after_script
before_script:
- echo "before script"
build:
before_script:
- echo "before script in buildjob"
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
script:
- echo "test"
deploy:
script:
- echo "deploy"
- echo "finish"
after_script:
- echo "after script"
用于定义作业可以使用的阶段,并且是全局定义的,同一阶段的作业并行运行,不同阶段按顺序执行
before_script:
- echo "before script"
stages:
- build
- test
- deploy
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
.pre 始终是整个 pipeline 的第一个运行阶段,.post 始终是整个 pipeline 的最后一个运行阶段,无法修改,用户自定义的 stage 则在这两者之间,如果一个 pipeline 仅包含 .pre 和 .post,则不会创建 pipeline
before_script:
- echo "before script"
stages:
- build
- test
- deploy
codescan:
stage: .pre
script:
- echo "codescan"
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
定义变量,可以定义 pipeline 变量、job 变量,job 变量优先级最高
before_script:
- echo "before script"
variables:
DOMAIN: example.com
stages:
- build
- test
- deploy
codescan:
stage: .pre
script:
- echo "codescan"
build:
before_script:
- echo "before script in buildjob"
stage: build
script:
- echo "build"
- echo "$DOMAIN"
after_script:
- echo "before script in buildjob"
test:
stage: test
script:
- echo "test"
deploy:
stage: deploy
script:
- echo "deploy"
- sleep 5
after_script:
- echo "after script"
用于指定特定的 job 在特定的 runner 运行,如果 job 不指定 tags,则默认在共享的 runner 运行
windows_job:
stages:
- build
tags:
-windows
script:
- echo "windows job"
linux_job:
stages:
- build
tags:
-linux
script:
- echo "linux job"
allow_failure 表示是否允许作业失败,默认值 false 不允许失败,改为 true 后,如果该作业失败也不会被阻塞
job1:
stage: test
script:
- "..."
allow_failure: true
when 用于控制作业运行:
job1:
stage: test
script:
- "..."
when: delayed # 表示延迟30s执行
start_in: "30"
配置作业失败后重试作业的次数
job1:
stage: test
script:
- "..."
retry: 2
也可以精确匹配到某一错误,即出现某一错误时才重试
job1:
stage: test
script:
- "..."
retry:
max: 2
when:
- script_failure # 脚本失败时重试
作业级别的超时可以超过项目级别的超时,但不能超过 Runner 特定的超时
job1:
stage: test
script:
- "..."
timeout: 3h
配置要并行运行的作业的实例数,此值必须大于等于 2 并小于等于 50,这将创建 N 个并行运行的同一作业实例
job1:
stage: test
script:
- "..."
parallel: 5
rules 允许按顺序评估单个规则,直到匹配为止:
if:如果条件匹配,多条件匹配可以使用 && ||
variables:
DOMAIN: example.com
job1:
stage: test
script:
- "..."
rules: # DOMAIN值匹配,则手动运行,否则
- if: '$DOMAIN == "example.com"'
when: manual
- if: '$DOMAIN == "example2.com"'
when: delayed
start_in: '5'
- when: on_success
changes:指定文件发生变化
job1:
stage: test
script:
- "..."
rules:
- changes:
- fimeName # 文件名
when: manual
- when: on_success
exists:指定文件存在
job1:
stage: test
script:
- "..."
rules:
- exists:
- fimeName # 文件名
when: manual
- when: on_success
workfolw 关键字适用于整个管道,并确定是否创建管道
variables:
DOMAIN: example.com
workflow:
rules:
- if: '$DOMAIN == "example.com"'
when: always # 默认always,可以设置never
- when: never
存储编译项目时所需的运行时依赖项,指定项目工作空间中需要在 job 之间缓存的文件或目录
全局 cache 定义在 job 之外,针对所有 job 生效,job 中的 cache 优于全局
cache:
paths: # 在全局定义缓存
- my/files
job:
script: "..."
cache:
key: job # 为缓存设置唯一key,会为该job分配一个独立的cache
paths: # 在job中定义缓存,缓存target目录下的所有.jar文件,该缓存将覆盖全局缓存
- target/*.jar
# policy: pull # pull:不下载缓存,push不上传缓存,默认会在job执行之前下载缓存,并在结束之后上传缓存
用于指定作业成功或失败时应附加到作业的文件或目录的列表,可在 Gitlab UI 中下载
build:
script:
- mvn package
artifacts:
name: "$ARTIFACTS_NAME" # 指定所创建的制品名称,默认为artifacts,下载为artifacts.zip
paths:
- target/*.jar
when: always # 制品创建条件,on_success:作业成功时创造制品,on_failure:作业失败时创建制品,always:总是创建制品
expire_in: 1 week # 制品有效期,从存储到gitlab开始算起,默认30天
获取当前阶段之前的制品
build:
stage: build
script:
- mvn package
artifacts:
name "$ARTIFACTS_NAME"
paths:
- target/*.jar
deploy:
dependencies:
- build
stage: deploy
script:
- ... # 部署制品
可以让作业无需按照阶段顺序运行,下述的例子表示:deploy-a 在 build-a 完成之后就可以执行,deploy-b 在 build-b 完成之后就可以执行
stages:
- build
- deploy
build-a:
stage: build
script:
- ...
build-b:
stage: build
script:
- ...
deploy-a:
stage: deploy
script:
- ...
needs: ["build-a"]
deploy-b:
stage: deploy
script:
- ...
needs: ["build-b"]
可以引入外部 yaml 文件,使用合并功能可以自定义和覆盖本地定义的 CI/CD 配置
local
引入同一存储库的文件,使用相对于根目录的完整路径进行引用,必须保证走到同一分支
假设有 ci/localci.yml 文件
stages:
- deploy
deploy-job:
stage: deploy
script: ...
在 .gitlab-ci.yml 引入 ci/localci.yml 文件,如果存在相同名称的作业,它们的配置会进行合并,并且原文件 .gitlab-ci.yml 的配置优先生效
include:
local: "ci/localci.yaml"
stages:
- build
- test
- deploy
build-job:
stage: build
script: ...
test-job:
stage: test
script: ...
file
引入其他项目的 yaml 配置
include:
project: demo/demo-java-service
ref: master
file: .gitlab-ci.yml
template
引入官方提供的模板,可以访问 https://gitlab.com/gitlab-org/gitlab/tree/master/lib/gitlab/ci/templates 查看有哪些模板
include:
template: Auto-DevOps.gitlab-ci.yml
remote
引入远程文件
include:
remote: "https://gitlab.com/awesome-project/raw/master/.gitlab-ci-template.yml"
继承作业配置,相同配置覆盖,不同则继承
.tests:
script: mvn test
stage: test
only:
refs:
- tags
test-job:
extends: .tests
script: mvn clean test
only:
variables:
- $RSPEC
最终得到的作业配置如下
test-job:
stage: test
script: mvn clean test
only:
variables:
- $RSPEC
refs:
- tags
当 gitlab 从 trigger 定义创建的作业启动时,将创建一个下游管道,允许创建多项目管道和子管道:
多项目管道:跨多个项目设置流水线,以便一个项目的管道可以触发另一个项目的管道
stagging:
variables:
ENVIROMENT: stagging # 该变量会传递给下游管道,如果上下游定义了相同名称的变量,上游变量将优先
stage: deploy
trigger:
project: demo/demo-java-service # 指定下游项目的完整路径
branch: master # 指定项目的分支名称
strategy: depend # 将自身状态从触发的管道合并到源作业
父子管道:同一项目的管道可以触发一组同时运行的子管道
子管道 ci/child.yml
stages:
- build
child-build-job:
stage: build
script: ...
父管道
stages:
- deploy
stagging:
stage: deploy
trigger:
include: ci/child.yml
strategy: depend21
首先注册一个工作类型为 docker 的 runner,只要使用该类型的 runner,所有运行操作都会在容器中运行
gitlab-runner register \
--non-interactive \
--executor "docker" \
--docker-image alpine:latest \ # 默认使用该镜像
--url "http://192.168.1.200:30088/" \
--registration-token "JRzzw2j1Ji6aBjwvkxAv" \
--description "docker-runner" \
--tag-list "docker" \
--run-untagged="true" \
--locked="false" \
--access-level="not_protected"
默认注册 runner 会指定一个基础镜像,如果全局指定 image 则所有作业使用该镜像创建容器并运行,如果全局未指定 image,则查看 job 中是否有指定,有则按照 job 指定的镜像创建容器并运行,否则使用默认镜像
image: maven:3.6.3-jdk-8 # 全局定义
...
deploy-job:
stage: deploy
tags:
- docker
script: ...
image: maven:3.6.3-jdk-8 # 局部定义
工作期间运行的另一个 Docker 服务镜像,将其 link 到 image 定义的 Docker 镜像,这样可以在构建期间访问该服务镜像
...
services:
- name: mysql:latest
alias: mysql
build-job:
stage: build
tags:
- docker
script: ...
image: maven:3.6.3-jdk-8 # 局部定义
可用于在 gitlab ui 追踪作业运行情况,
deploy-job:
stage: deploy
tags:
- docker
script: ...
environment:
name: production # 应用名称
url: http://www.baidu.com # 应用地址
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
我完全不是程序员,正在学习使用Ruby和Rails框架进行编程。我目前正在使用Ruby1.8.7和Rails3.0.3,但我想知道我是否应该升级到Ruby1.9,因为我真的没有任何升级的“遗留”成本。缺点是什么?我是否会遇到与普通gem的兼容性问题,或者甚至其他我不太了解甚至无法预料的问题? 最佳答案 你应该升级。不要坚持从1.8.7开始。如果您发现不支持1.9.2的gem,请避免使用它们(因为它们很可能不被维护)。如果您对gem是否兼容1.9.2有任何疑问,您可以在以下位置查看:http://www.railsplugins.or
如何学习ruby的正则表达式?(对于假人) 最佳答案 http://www.rubular.com/在Ruby中使用正则表达式时是一个很棒的工具,因为它可以立即将结果可视化。 关于ruby-我如何学习ruby的正则表达式?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1881231/
深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG
文章目录1、自相关函数ACF2、偏自相关函数PACF3、ARIMA(p,d,q)的阶数判断4、代码实现1、引入所需依赖2、数据读取与处理3、一阶差分与绘图4、ACF5、PACF1、自相关函数ACF自相关函数反映了同一序列在不同时序的取值之间的相关性。公式:ACF(k)=ρk=Cov(yt,yt−k)Var(yt)ACF(k)=\rho_{k}=\frac{Cov(y_{t},y_{t-k})}{Var(y_{t})}ACF(k)=ρk=Var(yt)Cov(yt,yt−k)其中分子用于求协方差矩阵,分母用于计算样本方差。求出的ACF值为[-1,1]。但对于一个平稳的AR模型,求出其滞
写在之前Shader变体、Shader属性定义技巧、自定义材质面板,这三个知识点任何一个单拿出来都是一套知识体系,不能一概而论,本文章目的在于将学习和实际工作中遇见的问题进行总结,类似于网络笔记之用,方便后续回顾查看,如有以偏概全、不祥不尽之处,还望海涵。1、Shader变体先看一段代码......Properties{ [KeywordEnum(on,off)]USL_USE_COL("IsUseColorMixTex?",int)=0 [Toggle(IS_RED_ON)]_IsRed("IsRed?",int)=0}......//中间省略,后续会有完整代码 #pragmamulti_c
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它