背景

上次开发完那个DevOps的发布界面后,就开始正式使用了,首先我们需要把一个前端项目添加相关的部署步骤,完成一套CI/CD。接着就是抽离出一套标准化的部署流程,适用于所有的前端项目(理想)。

由于发布流程中需要接入一些代码质量把控的机制,所以用到了 Sonar、ESLint、Jest等等的工具。

于是,为了可以不依赖不稳定的镜像下载,自己搞一个。

创建 Dockerfile

1
2
3
4
5
6
FROM ubuntu

RUN apt-get update && apt-get install -y \
ca-certificates \
curl \
sudo

放入 Sonar Scanner

下载一个 SonarQube Scanner

放到根目录下的 /sonar-scanner 下

1
COPY ./sonar-scanner /root/.sonar/native-sonar-scanner/sonar-scanner-4.5.0.2216-linux/.

安装 Node

1
2
3
4
5
RUN curl https://nodejs.org/dist/v$NODE_VERSION/$NODE_PACKAGE.tar.gz | tar -xzC /opt/

# npm
RUN npm install -g yarn
RUN npm install -g sonarqube-scanner

完整版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
FROM ubuntu

RUN apt-get update && apt-get install -y \
ca-certificates \
curl \
sudo

ARG NODE_VERSION=14.16.0
ARG NODE_PACKAGE=node-v$NODE_VERSION-linux-x64
ARG NODE_HOME=/opt/$NODE_PACKAGE

ENV NODE_PATH $NODE_HOME/lib/node_modules
ENV PATH $NODE_HOME/bin:$PATH

COPY ./sonar-scanner /root/.sonar/native-sonar-scanner/sonar-scanner-4.5.0.2216-linux/.

RUN curl https://nodejs.org/dist/v$NODE_VERSION/$NODE_PACKAGE.tar.gz | tar -xzC /opt/

# npm
RUN npm install -g yarn
RUN npm install -g sonarqube-scanner
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.
├── Dockerfile
└── sonar-scanner
├── bin
│   ├── sonar-scanner
│   └── sonar-scanner-debug
├── conf
│   └── sonar-scanner.properties
├── jre
│   ├── bin
│   ├── conf
│   ├── legal
│   ├── lib
│   └── release
└── lib
└── sonar-scanner-cli-4.5.0.2216.jar

制作

1
docker build -t [namespace]/[image name] .

推送

1
2
docker login
docker push

使用该镜像部署一个React (CRA)项目

package.json

1
2
3
4
5
{
"sonar": "node tools/sonar-scan.js",
"test": "craco test --coverage --all -o",
"lint": "eslint --ext .ts --ext .tsx -f json -o reports/eslint.json src/",
}

tools/sonar-scan.js 中配置sonar

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const scanner = require('sonarqube-scanner');

scanner(
{
serverUrl : 'http://39.xxx.xxx.xxx',
// token : "xxx",
options: {
'sonar.projectKey': 'squat-fe',
'sonar.sources': './src',
'sonar.eslint.reportPaths': 'reports/eslint.json',
'sonar.typescript.tsconfigPath': 'tsconfig.json',
}
},
() => process.exit()
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
image: kianzyk/fe-build

variables:
REGISTRY_BASE: registry.gitlab.xxx.cn/crm/squat-fe
IMAGE_REF: $REGISTRY_BASE:$CI_PIPELINE_ID
DOCKER_IMAGE: docker:stable-git

stages:
- prepare
- reporting
- npm-build
- docker-build
- deploy

prepare:
stage: prepare
script:
- yarn lint
- yarn test
cache:
paths:
- node_modules/
artifacts:
paths:
- reports/
- coverage/

# 复制报告
reporting:
stage: reporting
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
script:
- sudo rm -fr /mnt/jest/$CI_PROJECT_NAME
- sudo mkdir -pv /mnt/jest/$CI_PROJECT_NAME
- if [ -d coverage/lcov-report/ ]; then sudo cp -a coverage/lcov-report/* /mnt/jest/$CI_PROJECT_NAME/; fi
- yarn sonar

npm-build:
stage: npm-build
script:
- yarn build:$CI_COMMIT_BRANCH # 最新CRA在build时也会跑一次eslint
cache:
paths:
- node_modules/
artifacts:
paths:
- build/

docker-build:
stage: docker-build
image: $DOCKER_IMAGE
script:
- docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.xxx.cn
- docker build -t $IMAGE_REF .
- docker push $IMAGE_REF
- docker rmi $IMAGE_REF

deploy:
...