Skip to main content

4 posts tagged with "Practice"

View All Tags

· 7 min read
Panda

一、简介

Docusaurus 是一款静态网站生成器,可以帮助我们快速搭建一个优美的文档网站。

Docusaurus 的基本特性主要有:

  • 支持 Markdown
  • 支持侧边栏
  • 支持目录导航
  • 支持提示功能
  • 支持自定义样式
  • ……

此外,Docusaurus 还有一些高级特性:

  • 支持夜间模式
  • 支持站内搜索
  • 支持 SEO 优化
  • 支持插件扩展
  • 支持多语言
  • 支持多版本
  • ……

以下为 Docusaurus 的官网截图,我们可以先一睹为快:

二、核心组件

Docusaurus 的核心组件有:Docs、Blog、Pages。

2.1 Docs

Docs 为用户提供了按层级管理 Markdown 文档的功能,由官方插件 @docusaurus/plugin-content-docs 提供支持。

在 Docs 中,Markdown 文档具有清晰的层级关系,如下图所示:

2.2 Blog

Blog 即为我们熟知的博客。

该功能由官方插件 @docusaurus/plugin-content-blog 提供,可以帮助我们快速搭建博客页面。

下图为 Blog 示例:

2.3 Pages

Pages 指独立的页面,页面之间没有父子关系,由官方插件 @docusaurus/plugin-content-pages 提供支持。

在 Docusaurus 中,用户可以添加一个 React 页面,也可以添加一个 Markdown 页面。

下图为 Pages 示例:

三、使用指南

3.1 环境准备

Docusaurus 要求我们预先安装以下组件:

caution

yarn 指的是依赖管理工具,并不是 Hadoop 中的资源管理器 yarn。若本地安装了 Hadoop,注意在环境变量中去掉 yarn 脚本的地址,避免 yarn 命令冲突。

3.2 创建站点

在任意路径执行以下命令:

npx create-docusaurus@latest my-website classic

若创建成功,在当前路径下会出现 my-website 目录,且控制台输出如下信息:

3.3 配置说明

my-website 目录下包含多个配置文件,这些配置文件的具体作用可参考下表:

配置文件具体说明
docusaurus.config.js核心配置文件,包含基础信息配置、插件配置、主题配置等
src/css/custom.css自定义样式设置
src/pages/index.js主页标题栏配置
src/components/HomepageFeatures.js主页特性栏配置
info

具体配置项说明请参考官方文档:https://docusaurus.io/docs/api/docusaurus-config

3.4 快速启动

进入 my-website 目录,输入以下命令快速启动站点:

npx docusaurus start

若启动正常,则控制台会输出如下信息:

此时,我们便可以通过 http://localhost:3000/ 预览我们的本地站点。

3.5 语法高亮

默认情况下,Docusaurus 未开启 Java、Scala 等语言的语法高亮,需要我们在 docusaurus.config.js 增加如下配置:

module.exports = {
// ...
themeConfig: {
prism: {
additionalLanguages: ['powershell'],
},
// ...
},
};
info

Docusaurus 基于 Prism 实现语法高亮。

四、编辑器

4.1 编辑器选择

对于自建博客来说,找到合适的 MD 编辑器是非常重要的一件事,这将会影响到我们的文档编写体验与发布效率。

若条件允许,我们希望编辑器可以满足以下功能:

  • 功能一:支持与博客站点相同的文档层级结构
  • 功能二:支持自定义 CSS,以实现本地的实时预览
  • 功能三:支持与站点相同的提示功能与语法(Admonition),以实现本地的实时预览
  • 功能四:支持源文件快速同步

基于这些功能需求,笔者类比了几款知名 MD 编辑器,得出如下结论:

编辑器功能一功能二功能三功能四
Mark Text
Joplin
Obsidian
info

Typero 目前已收费,因此不列入比较清单。此外,Obsidian 实际上是支持功能四的,但是需要付费。

综合以上,笔者最终选择 Obsidian 作为本地的编辑器,其编辑界面如下图所示:

4.2 自定义设置

使用 Obsidian,我们有两个自定义项需要设置。

4.2.1 自定义 CSS

自定义 CSS 可以帮助我们复制博客站点的 CSS,使编辑器的预览样式与站点一致。为实现该功能,需要以下步骤:

  1. .obsidian/snippets 目录下创建 custom.css 文件,将博客站点的全部 CSS 复制到该文件中
  2. 通过路径 Settings → Appearance → CSS snippets 进入设置页面,点击按钮启用自定义样式

4.2.2 Admonition

默认情况下,Obsidian 不支持 Admonition。

为了使 Obsidian 支持 Admonition,我们需要下载 Admonition 插件,然后安装到目录 .obsidian/plugins

info

Admonition 的下载地址为:https://github.com/valentine195/obsidian-admonition

安装完成后,进入设置页面,并启用 Enable Non-codeblock Admonitions

插件支持的提示语法为 !!!???,与博客站点的 ::: 不同,因此我们还需要做一些修改。

打开目录 .obsidian/plugins/obsidian-admonition 下的 main.js 文件,找到其中的 enableMarkdownProcessor 方法,将 TYPE_REGEXEND_REGEX 修改为图中所示值:

重启 Obsidian,此时,我们便可以正常使用 Admonition 功能了。

五、部署

我们已经完成了 Docusaurus 的本地启动和编辑,现在,我们还需要将它发布到 GitHub Pages。

发布时,只需在 my-website 目录下输入以下命令:

set "GIT_USER=xxx" && set "GIT_PASS=xxx" && yarn deploy

其中,各参数的说明为:

  • GIT_USER:用户的 GitHub 账号
  • GIT_PASS:用户的 GitHub 私有凭证
caution

GIT_PASS 并非指密码,而是私有凭证,其生成方式请参考:https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token

· 5 min read
Panda

一、前言

与 Java 不同,Scala 比较小众,没有放之四海而皆准的规范。

为了使团队在 Scala 项目上的代码尽可能地保持一致,笔者在借鉴 官方文档开源项目 的基础上,整理了适用于自身团队的 Scala 代码规范。

二、项目创建规约

本规约展示了一个在 IDEA 上创建 Scala 项目的流程,以供参考。

2.1 依赖管理

Scala 支持通过 Maven 或 sbt 来管理项目。基于以下因素,我们选择 Maven:

  • Scala 开源项目大部分都是通过 Maven 进行管理
  • 团队成员对 Maven 比较熟悉,学习成本低
  • 主流持续集成产品对 Maven 支持度比较高

使用 Maven 创建 Scala 项目时,与 Java 无太大区别,可以通过 archetype 快速创建:

此时,项目仅能创建 Java 类,还无法创建 Scala 类。

2.2 Scala SDK

Scala SDK 是 Scala 项目中不可缺少的部分,我们可以在 Project Structure 完成 Scala SDK 的添加。

info

若本地没有 Scala SDK,可以点击 + 号,在弹出的对话框中选择对应的 Scala 版本进行下载。

2.3 框架支持

此时,距离完整创建 Scala 项目还差最后一步,即框架支持。

我们可以右键项目根目录,点击 Add Framework Support,然后会弹出如下对话框:

勾选 Scala,点击 OK。此时,Scala 项目创建完毕,可以在项目中新建 Scala 类并进行编码。

三、代码风格规约

Scala 官方提供了代码风格参考:

https://docs.scala-lang.org/style/index.html

但是,基于文档的规约常常是不安全的,团队中总会有“糊涂蛋”一不小心犯了“错”。为避免这个问题,我们可以引入 Scalafmt 插件,以强制的手段保证项目代码风格的一致性。

3.1 Scalafmt 安装

Scalafmt 可以直接在 IDEA 的插件商场中安装。

安装完成后,需重启 IDEA。

3.2 Scalafmt 配置

Scalafmt 基于 .scalafmt.conf 文件实现配置。

首先,打开 Settings,进入 Editor > Code Style > Scala 界面,将 Formatter 设置为 Scalafmt,如下图所示:

然后,在项目根目录下创建 .scalafmt.conf 文件,输入如下内容:

maxColumn = 150

若配置成功,可在 Editor > Code Style > Scala 界面看到如下结果:

3.3 变量类型补全

在 Scala 中,变量的实际类型可以是不显式指定的。例如,我们可以这样定义字符串类型的变量:

val value = "panda"

实际上,它的完整表达式是:

val value: String = "panda"

为了提高代码阅读性,使其他开发人员能快速知晓变量的实际类型,我们规定 变量类型要完全补全

在 Java 开发中,我们常常使用 .var 实现变量类型自动补全。但是,在 Scala 项目里,.var 补全的内容默认情况下是不显示实际类型的,如下图所示:

若想要显示实际类型,需要在 Type Annotations 选项卡中勾选 Local definition 选项,并取消勾选 Type is stable* 选项:

此时,再次使用 .var 进行补全时,会发现变量的实际类型已经自动补上了。

· 11 min read
Panda

一、为什么要用 Jenkins?

目前,我们在持续集成上使用的是 GitLab 自带的 gitlab-ci。它支持自动化完成代码编译、镜像构建与镜像推送,减少开发人员在项目构建上的时间开销。

但是,gitlab-ci 有一个明显的缺陷:在遇到多模块项目时(如基于 SpringBoot 搭建的微服务项目),它显得有些无力。具体表现为,gitlab-ci 不支持多管道,每当项目中某个模块的代码有新的提交,gitlab-ci 都会触发全项目的自动构建,而无法仅针对产生变动的子模块进行构建。当项目规模较大时,这种构建方式会导致自动构建的代价非常大。

而在这种场景下,Jenkins 可以很好地实现我们的需求。当代码提交触发构建事件时,Jenkins 可以筛选出产生变动的子模块,并对这些子模块进行构建与打包,使我们的自动化构建变得精准而优雅。

下图为 Jenkins 持续集成的工作流示意图:

二、Jenkins 安装与部署

本节将介绍 Jenkins 的安装与部署。若只想了解流水线的构建,可以直接跳过本节内容。

2.1 环境准备

我们将采用 Docker 的方式部署 Jenkins,因此,部署前需在宿主机完成 Docker 环境的搭建。

info

Docker 环境搭建不作为本文分享内容,请自行实现。

2.2 基础镜像

Jenkins 官方已提供现成的 Docker 镜像 jenkinsci/blueocean,该镜像内已包含以下组件:

  • Docker
  • Java
  • Git

但是我们不能直接使用它,因为它并未安装常用的构建工具(如 Maven、Gradle 等)。

为解决这个问题,我们可以参考以下 Dockerfile 文件,构建符合我们自身需求的 Jenkins 镜像:

FROM jenkinsci/blueocean:1.24.7
MAINTAINER pentaxie@qq.com

ARG BASE_DIR=/opt/maven

USER root
ADD apache-maven-3.6.3-bin.tar.gz ${BASE_DIR}
ADD settings.xml ${BASE_DIR}/apache-maven-3.6.3/conf
RUN ["cp","/usr/share/zoneinfo/Asia/Shanghai","/etc/localtime"]

ENV M2_HOME=${BASE_DIR}/apache-maven-3.6.3
ENV PATH=$PATH:$M2_HOME/bin
info

该镜像在官方镜像的基础上,安装了 Maven,并相应地修改了 Maven 配置文件。

2.3 启动 Jenkins

完成 Jenkins 基础镜像的构建后,我们可以直接使用 Docker 命令启动容器:

docker run \
-u root \
-d \
-p 38080:8080 \
-v /data/test/jenkins-data:/var/jenkins_home \
-v /var/run/docker.sock:/var/run/docker.sock \
hub.panda.com/dc-jenkins:2.289

其中,两个 -v 需要了解其作用:

  • 第一个 -v 表示将 Jenkins 的安装及数据存储目录挂载到宿主机,下次我们重启 Jenkins 的 Docker 容器时,Jenkins 中的数据才得以保留
  • 第二个 -v 表示支持容器内的 Docker 客户端直接使用宿主机的 Docker 服务,这样我们在容器内执行构建命令时,实际上是在宿主机构建镜像

2.4 插件安装

Jenkins 启动后,首先需要安装社区推荐的插件。

除此之外,我们还需要在 插件管理 界面自行安装以下插件:

  • GitLab
  • Maven Integration
  • Pathignore

上述插件的主要功能为:

插件名称主要功能
GitLab支持 GitLab Token 的配置
Maven IntegrationMaven 集成插件,支持在流水线中创建 Maven Project
Pathignore路径过滤插件,支持子模块过滤(实现多模块持续集成的关键)

2.5 必要配置

2.5.1 GitLab Token 设置

安装完 GitLab 插件后,需要在 系统管理 - 系统设置 页面添加 GitLab Token。

GitLab Token 是 GitLab 提供的身份验证的令牌,其生成方式可参考下图:

info

该 Token 尽可能赋予足够的权限,避免后续 Jenkins 集成出现权限不足的情况。

info

添加后,需点击图中的 Test Connection 按钮进行校验,确保 Token 可以正常运作。

2.5.2 Maven 设置

基础镜像部分介绍到,我们在官方 Jenkins 镜像的基础上安装了 Maven,并设置了环境变量与配置文件。

但这些还不够,使用 Jenkins 时,我们还需要在 系统管理 - 全局工具配置 页面中配置 Maven 的具体位置,使 Jenkins 能准确找到 Maven 的地址。

2.5.3 时区设置

在基础镜像部分,我们已经将镜像的时区设置为东八区。

但是在 Jenkins 的界面中,每个用户的初始时区都是伦敦时间,需要我们手动设置为东八区:

完成此步骤后,Jenkins 的整个初始化配置过程便完成了,接下来可开始创建流水线进行深入体验。

三、构建流水线

本节将以 多模块集成流水线 为例,展示具体的流水线构建流程。

3.1 创建任务

集成了 Maven Integration 插件后,我们就可以在 新建任务 界面中创建一个 Maven Project:

info

通过 Maven Project,我们可以很便捷地在 Jenkins 上实现代码的编译与打包。

3.2 配置流水线

流水线任务创建后,需要经过一系列配置。

3.2.1 代码源

Jenkins 支持从 GitLab 上拉取代码。

caution

仓库地址记得使用 HTTPS,如果要使用 SSH 方式,需在容器中创建私钥(本文不介绍此种方式)。

如果我们的 GitLab 项目是 Private 级别,那么我们还需要创建一个 GitLab 凭据(Username with password),该凭据需要填写具有项目对应权限的 GitLab 用户名与密码,如下所示:

3.2.2 构建器

构建器用于设置流水线任务触发的条件。

在本例中,我们勾选 Build when a change is pushed to GitLab

该选项实现了当 GitLab 上有代码提交等行为时,触发 Jenkins 作业。

需要注意的是,要实现 GitLab 主动向 Jenkins 推送触发事件,需在 GitLab 上配置 Webhooks:

Webhooks 中,有两个配置项需要格外注意:

  • URL 为 Jenkins 对应构建项目的地址,如本例为:http://192.168.5.98:38080/project/demo
  • Secret token 为 Jenkins 对应构建项目的令牌,通过点击 高级 按钮进行生成,具体示例可见下图

此外,图例中的 Allowed Branched 需要指定触发构建的分支。默认情况下,任意分支的提交都会触发构建任务。

info

在本例中,我们设置为只有 master 分支发生变更才会触发构建任务。

3.2.3 构建环境

构建环境设定了构建过程中的一些条件与行为。

由于本节主要介绍多模块的持续集成,因此关键点在于 Do not build if only specified paths have changed 选项。

info

该选项由 Pathignore 插件提供,可支持子模块的单独构建。

图例中的配置表示,只有子模块 dim-service 产生了变更项,才会触发构建任务。这是实现多模块持续集成的根基,在此基础上,我们可以很轻松地过滤掉其他子模块的构建流程。

3.2.4 Pre Steps

顾名思义,Pre Steps 可以完成构建前的一些准备工作。

例如,我们想要在构建时推送 Docker 镜像,那么就需要提前登录对应的 Docker 仓库:

3.2.5 Build

该步骤指明了我们整个流水线想要完成的构建指令。

在本例中,我们通过 -pl 参数指定构建的模块为 dim-service,配合上述 Pathignore 插件的过滤功能,我们可以实现当 dim-serivce 子模块发生变更项时自动触发该模块的 Docker 镜像创建与推送:

info

docker:builddocker:push 依赖 docker-maven-plugin 插件,可自行研究,或等待后续教程。

完成上述所有步骤后,点击 应用保存,便完成了流水线的配置。如果项目有多个模块,创建多个对应的流水线任务即可。

3.3 构建与验收

现在,我们可以提交一次代码,验证一下流水线任务执行情况。若无异常,在我们提交代码后,流水线会自动开启构建任务,完成我们预设的构建工作。

info

代码提交时,各子模块对应的流水线任务都会被触发,但是由于 Pathignore 插件的作用,流水线任务检测自身对应的子模块无变更项时,当前被触发的构建任务不会执行任何构建操作。

在构建任务明细中,可以通过点击 控制台输出 按钮,查看具体的构建日志:

如果一切顺利,即可在我们的 Docker 私仓里看到本次构建的镜像了!

· 16 min read
Panda

一、背景介绍

目前,成熟的代码检测工具有很多,如 SpotBugs(前身为 FindBugs)、PMD、Checkstyle 等,我们可以在本地开发环境,非常便捷地利用这些工具实现代码的扫描与检测。这看上去好像很不错,但实际上,采用这种代码检测方式,我们面临着两个问题:

  • 代码提交前需要手动运行检测工具
  • 检测结果仅对自己可见

那么,有没有什么方案可以规避这些问题呢?答案当然是有的。

我们可以基于 GitLab 和 SonarQube 搭建自动化代码检测平台,并通过该平台实现以下功能:

  • 每次提交时,自动触发 SonarQube 代码检测,产生检测报告(包含坏味道、BUG 数、覆盖率等)
  • 上述检测报告,若来源于主分支提交或合并,则发送至 SonarQube,若来源于其他分支提交,则以评论形式直接反馈至 GitLab
info

如果不知道 SonarQube 是什么,可以参考 SonarQube 官方网站

二、环境要求

本次搭建使用的操作系统为 CentOS 7,需要安装的组件如下表所示:

组件名版本号
SonarQube6.7
GitLab11.1.4
GitLab-Runner13.0.1
Maven3.6.3

实际版本号需严格遵循表格中的版本号,避免出现兼容性问题。目前,笔者已知的兼容性问题有以下几点:

  • SonarQube 在 7.6 版本后不支持插件 sonar-gitlab-plugin,若使用 7.6 之后的版本,将无法实现 SonarQube 与 GitLab 协作(除非使用付费版)
  • GitLab 与 GitLab-Runner 的版本要考虑兼容性,否则会出现 GitLab-Runner 无法连接至 GitLab 的问题

三、安装与配置

本节将描述上述组件安装与配置的详细步骤。其中,安装方式主要有本地安装和基于 Docker 安装,因此在安装前需确保宿主机已经具备 Docker 和 Docker Compose 的环境。

3.1 SonarQube

3.1.1 SonarQube 安装

使用 Docker Compose 安装 SonarQube 很简单,只需以下几个步骤:

  • 在任意位置创建安装目录 sonar,如 /usr/local/sonar
  • 在安装目录下创建 docker-compose.yml 文件,文件内容如下:
version: '2.1'

services:
# 使用 PostgreSQL 作为 SonarQube 的持久化方案
# 注:由于 SonarQube 7.9 及之后的版本不支持 MySQL,因此 MySQL 不作为考虑对象
postgres:
image: postgres:12
container_name: sonarqube_postgres
privileged: true
ports:
- "5432:5432"
networks:
- sonarnet
restart: always
# 将 PostgreSQL 数据文件存放至宿主机
volumes:
- ./postgres:/var/lib/postgresql/data
environment:
POSTGRES_DB: sonar
POSTGRES_USER: sonar
POSTGRES_PASSWORD: sonar

sonarqube:
image: sonarqube:6.7
container_name: sonarqube
privileged: true
ports:
- "9000:9000"
restart: always
networks:
- sonarnet
depends_on:
- postgres
# 将 SonarQube 日志文件、数据文件、配置文件、扩展插件存放至宿主机
volumes:
- ./data:/opt/sonarqube/data
- ./extensions:/opt/sonarqube/extensions
- ./logs:/opt/sonarqube/logs
- ./conf:/opt/sonarqube/conf
# 配置 SonarQube 的数据源,本例为 PostgreSQL
environment:
SONARQUBE_JDBC_USERNAME: sonar
SONARQUBE_JDBC_PASSWORD: sonar
SONARQUBE_JDBC_URL: jdbc:postgresql://postgres:5432/sonar?useUnicode=true&characterEncoding=utf8
# 由于 SonarQube 内部会启动 ElasticSearch,因此需要此配置
ulimits:
nproc: 65535
nofile:
soft: 65536
hard: 65536

networks:
sonarnet:
driver: bridge
  • 在安装目录下分别创建 dataextensionslogsconf 文件夹,并使用 chmod -R 777 <dir> 赋予所有权限,避免出现权限问题
  • 若宿主机有开启防护墙,需开放上述配置的端口:
firewall-cmd --add-port=5432/tcp --permanent
firewall-cmd --add-port=9000/tcp --permanent
firewall-cmd --reload
  • 在安装目录下,使用 docker-compose up -d 命令启动 SonarQube,若启动成功,控制台输出如下日志:
Creating network "sonar_sonarnet" with driver "bridge"
Creating sonarqube_postgres ... done
Creating sonarqube ... done
  • 打开浏览器,输入地址 http://sonar.example.com:9000 访问 SonarQube,若访问成功,则出现如下页面:

info

安装完成后,SonarQube 会自动生成管理员账号 admin:admin

3.1.2 SonarQube 插件

SonarQube 安装完成后,还需要安装部分插件以支持某些功能,具体插件清单如下:

插件名版本号插件用途
sonar-gitlab-plugin3.0.2为每个 GitLab 提交提供代码注释和评论的功能
sonar-l10n-zh-plugin1.19支持 SonarQube 汉化

插件安装非常简单,只需要将插件 jar 包放至扩展目录 ${sonarqube_home}/extensions/plugins 下,重启 SonarQube 即可。

关于 SonarQube 与 sonar-gitlab-plugin 的版本对照,可以参考:

https://github.com/gabrie-allaigre/sonar-gitlab-plugin

关于 SonarQube 与 sonar-l10n-zh-plugin 的版本对照,可以参考:

https://github.com/SonarQubeCommunity/sonar-l10n-zh%20

info

上述插件不支持在 SonarQube 的应用中心直接下载,因为官方已经不再提供这两款插件的在线安装了,我们可以直接在上述的 GitHub 地址中下载指定版本的 jar 包。

3.1.3 Sonar GitLab Plugin 配置

sonar-gitlab-plugin 成功安装,则在 SonarQube 的配置页面可以见到如下页面:

具体路径为:登录 admin 账号 -> 点击顶部导航栏【配置】按钮 -> 点击【通用设置】中的【GitLab】选项卡

在该页面中,需要修改以下参数的值:

参数名称参数标识目标值
GitLab urlsonar.gitlab.urlhttp://gitlab.example.com
GitLab User Tokensonar.gitlab.user_tokenGitLab 的用户令牌,获取方式参考 3.2.2
GitLab API versionsonar.gitlab.api_versionv4
info

上述参数中,GitLab User Token 是核心,设置错误的 token,将直接影响到 SonarQube 与 GitLab 的协作。特别要注意的是,生成该 token 的用户 一定要具备管理员权限,否则 SonarQube 无法对 GitLab 上的所有项目进行评论。

3.2 GitLab

3.2.1 GitLab 安装

与 SonarQube 相似,我们采用 Docker Compose 的方式安装 GitLab,具体步骤如下:

  • 在任意位置创建安装目录 gitlab,如 /usr/local/gitlab
  • 在安装目录下创建 docker-compose.yml 文件,文件内容如下:
version: '3'
services:
gitlab:
# 使用 gitlab 中文镜像,直接安装 gitlab 中文版
image: 'twang2218/gitlab-ce-zh:11.1.4'
restart: unless-stopped
# 若没有域名,建议直接写ip,否则页面上克隆的复制链接串将显示该值,无法直接使用
hostname: '192.168.117.128'
container_name: gitlab
environment:
# 设置时区
TZ: 'Asia/Shanghai'
GITLAB_OMNIBUS_CONFIG: |
external_url 'http://192.168.117.128'
gitlab_rails['time_zone'] = 'Asia/Shanghai'
ports:
- '80:80'
- '443:443'
- '22:22'
# 将 gitlab 日志文件、数据文件、配置文件存放至宿主机
volumes:
- config:/etc/gitlab
- data:/var/opt/gitlab
- logs:/var/log/gitlab
volumes:
config:
data:
logs:
  • 若宿主机 ssh 端口为默认值 22,则需要将其修改为其他值后,才能继续执行后续步骤,具体修改方式本文略
  • 若宿主机有开启防护墙,需开放上述配置的端口(22 端口默认开启,无需配置):
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=443/tcp --permanent
firewall-cmd --reload
  • 在安装目录下,使用 docker-compose up -d 命令启动 GitLab,若启动成功,控制台输出如下日志:
Creating network "gitlab_default" with the default driver
Creating gitlab ... done
  • 打开浏览器,输入地址 http://gitlab.example.com 访问 GitLab,若访问成功,则出现如下页面:

info

安装完成后,GitLab会自动生成管理员账号 root,首次登录前需要修改密码。

3.2.2 GitLab 用户令牌生成

GitLab 安装完成后,我们需要需要根据 3.1.3 中的要求,生成用户令牌。

具体步骤如下:

  • 登录具有管理员权限的账号(一定要是管理员身份)
  • 访问地址 http://gitlab.example.com/profile/personal_access_tokens 进入令牌生成页面
  • 输入令牌名称,勾选 apiread_usersudo 权限,点击【创建】按钮,即可生成用户令牌

生成的令牌需要马上保存,后续不再显示,具体令牌信息在如下位置:

3.3 GitLab Runner

3.3.1 GitLab Runner 安装

GitLab Runner 是一个处理构建的应用程序,我们需要通过它执行我们在 GitLab CI 中定义的 Job。

在本例中,由于后续编写的 Job 依赖于 Maven 环境,因此选择直接在宿主机上安装 GitLab Runner。

(当然,我们也可以自己构建包含 GitLab Runner 和 Maven 的镜像,然后使用 Docker 安装,具体实现方式本例略。)

在宿主机上安装 GitLab Runner 的步骤如下:

  • 下载 GitLab 官方源:
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
  • 使用 yum 下载 GitLab Runner:
yum install gitlab-runner

3.3.2 注册与启动 Runner

注册 Runner 前,我们需要先获取 GitLab 的注册令牌。

登录管理员账号,访问地址 http://gitlab.example.com/admin/runners,即可看到我们想要的注册令牌:

接下来,即可开始注册流程。

首先,执行注册命令:

gitlab-runner register

然后,根据控制台上的提示,我们需要依次输入以下信息:

  • GitLab 地址:http://gitlab.example.com
  • 注册令牌
  • Runner 描述,如 test
  • Runner 标签(与后续编写的 .gitlab-ci.yml 中的 tags 要一致,因此需要慎重填写,当然,写错了也无妨,后续在 UI 界面上可以修改)
  • 选择执行者(ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell)
  • 若执行者选择 shell,则注册流程结束,若执行者选择 docker,则需要选择默认的镜像,如 docker:stable

完成注册后,即可在刚刚的地址中看见该 Runner 的信息:

现在,我们可以使用命令 gitlab-ci-multi-runner run 启动所有 Runner。

3.4 Maven

Maven 用于执行 SonarQube 的代码检测命令(同样的工具有 Sonar Scanner、Gradle 等)。

由于没有找到已配置好阿里源的 Maven 镜像,所以我们也选择使用本地安装的方式安装 Maven,具体步骤如下:

  • 在任意目录下(如 /usr/local)下载 Maven 二进制包:
wget https://mirror.bit.edu.cn/apache/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
  • 解压压缩包,并将目录重命名为 maven
tar -xzvf apache-maven-3.6.3-bin.tar.gz
mv apache-maven-3.6.3/ maven
  • /etc/profile 文件追加以下内容:
export M2_HOME=/usr/local//maven
export PATH=$PATH:$M2_HOME/bin
  • 重置环境变量
source /etc/profile

至此,环境要求的所有组件已全部安装完毕。

四、结果验证

现在,我们通过一次完整的代码提交,来验证自动化代码检测平台是否生效,即:

  • 代码提交时,是否触发 SonarQube 检测作业
  • SonarQube 的检测结果,是否可以反馈至 GitLab

4.1 新建 Maven 工程

首先,我们创建满足要求的 Maven 工程。该工程的 pom.xml 文件要求具备以下内容:

  • 加入 sonar-maven-pluginjacoco-maven-plugin 插件:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.6.0.1398</version>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.4</version>
</plugin>
</plugins>
</pluginManagement>
</build>
  • 添加 jacoco-maven-plugin 插件的配置信息:
<profiles>
<profile>
<id>coverage</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<executions>
<execution>
<id>prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

可能有人会有疑问,为什么需要加入 jacoco-maven-plugin 插件呢?这是因为,SonarQube 本身并不支持覆盖率计算,我们需要借助 jacoco 来计算出项目单元测试的覆盖率。

4.2 集成 GitLab-CI

3.3.2 中,我们演示了如何创建 GitLab Runner。

在这里,我们首先创建执行者为 docker 的 Runner,并将其命名为 docker_runner

然后,我们编写如下 .gitlab-ci.yml 文件:

image: maven:3.6.3-jdk-8

variables:
SONAR_TOKEN: "${sonar_token}"
SONAR_HOST_URL: "http://sonar.example.com:9000"
GIT_DEPTH: 0

stages:
- build_push
- feedback_to_gitlab

# 执行 SonarQube 分析,并将检测结果推送至 SonarQube
sonarqube_analysis:
stage: build_push
only:
- merge_requests
- master
script:
- mvn --batch-mode verify sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_TOKEN
tags:
- docker_runner

# 执行 SonarQube 分析,并将检测结果反馈至 GitLab
sonarqube_gitlab_comment:
stage: feedback_to_gitlab
except:
- master
script:
- mvn --batch-mode verify sonar:sonar -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_TOKEN -Dsonar.analysis.mode=preview -Dsonar.gitlab.commit_sha=$CI_COMMIT_SHA -Dsonar.gitlab.ref_name=$CI_COMMIT_REF_NAME -Dsonar.gitlab.project_id=$CI_PROJECT_ID
tags:
- docker_runner

其中,参数 SONAR_TOKEN 为 SonarQube 的令牌,在 SonarQube 首次创建项目时即可创建。与 GitLab 的令牌一样,此 token 一旦创建,就需要马上保存,否则后续不再显示。

引入该 .gitlab-ci.yml 文件后,当我们提交代码时,上述 Runner 便会根据提交所来源的分支选择相应的执行脚本,具体描述如下:

  • 若提交为主分支提交(或合并至主分支),则执行器 docker_runner 会执行 SonarQube 的分析指令,并将分析结果报送至 SonarQube 平台
  • 若提交为非主分支提交,则执行器 docker_runner 会执行 SonarQube 的分析指令,并将分析结果反馈至 GitLab 中对应的分支下

4.3 提交验证

现在,我们分别在其他分支和主分支提交代码,查看提交结果。

在提交其他分支代码时,由于我们的代码中有严重 BUG,SonarQube 会在此分支下标记出 BUG 的具体信息,并标记该流水线的状态为失败,如下图所示:

在提交主分支代码时,我们发现执行器自动触发 SonarQube 分析作业,并将检测结果推送至 SonarQube 平台,如下图所示:

综上,我们发现结果符合预期,说明自动化代码检测平台搭建成功,enjoy it!