# cicdTest
**Repository Path**: andy-code1/cicd-test
## Basic Information
- **Project Name**: cicdTest
- **Description**: cicd的示例和git hook的模板
实现github上面的流程,可以在push自动发短信。自定义eslint检验和audit扫描
和进行单元测试。hook实现husky和lint-staged还有version自动增加和commit提交文本的规范(这里用python的hook来做)
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2022-09-16
- **Last Updated**: 2022-09-16
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 1.cicd
github 上面上传就可以了。
详情看.github/workflows/main.yml
下面是一些示例图片
总结一下,还是github好用
CI(持续集成)CD(持续部署):当代码 push 到远程仓库后,借助 `WebHooks` 对当前代码在构建服务器(即 CI 服务器,也称作 Runner)中进行自动构建、测试及部署等
`CICD` 集成于 CICD 工具及代码托管服务。CICD 有时也可理解为进行 CICD 的构建服务器,而提供 CICD 的服务,如以下产品,将会提供构建服务与 github/gitlab 集成在一起。
cicd策略
1. 主分支禁止直接 PUSH 代码
2. 代码都必须通过 PR 才能合并到主分支
3. **分支必须 CI 成功才能合并到主分支**
4. 代码必须经过 Code Review (关于该 PR 下的所有 Review 必须解决)
5. 代码必须两个人同意才能合并到主分支
```
workflow (流程):持续集成一次运行的过程,就是一个 workflow。
job (任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。
step(步骤):每个 job 由多个 step 构成,一步步完成。
action (动作):每个 step 可以依次执行一个或多个命令(action)
```
## step1:开通和helloworld
https://gitee.com/features/gitee-go 中开通,或者具体的项目中开通gitee go
当我们选择用node.js的方式进行创建的时候会生成master-pipeline.yml
gitee
```yaml
version: '1.0'
name: master-pipeline
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install && rm -rf ./dist && npm run build
# 非必填字段,开启后表示将构建产物暂存,但不会上传到制品库中,7天后自动清除
artifacts:
# 构建产物名字,作为产物的唯一标识可向下传递,支持自定义,默认为BUILD_ARTIFACT。在下游可以通过${BUILD_ARTIFACT}方式引用来获取构建物地址
- name: BUILD_ARTIFACT
# 构建产物获取路径,是指代码编译完毕之后构建物的所在路径
path:
- ./dist
- step: publish@general_artifacts
name: publish_general_artifacts
displayName: 上传制品
# 上游构建任务定义的产物名,默认BUILD_ARTIFACT
dependArtifact: BUILD_ARTIFACT
# 上传到制品库时的制品命名,默认output
artifactName: output
dependsOn: build_nodejs
- stage:
name: release
displayName: 发布
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
# 上游上传制品任务的产出
dependArtifact: output
# 发布制品版本号
version: '1.0.0.0'
# 是否开启版本号自增,默认开启
autoIncrement: true
triggers: # 什么时候会触发,这里是在push代码的时候会触发
push:
branches:
include:
- master
```
github 点击actions,点击 set up a workflow yourself
```yaml
# 流程名字
name: CI
# 什么时候会触发
on:
#schedule: # 每天8:30做一些事情
#- cron: '30 8 * * *'
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
types:
- opened# 当新建了一个 PR 时
- synchronize# 当提交 PR 的分支,未合并前并拥有新的 Commit 时
workflow_dispatch:
# 具体做的事情
jobs:
# 命名这玩意叫做build
build:
# 表示在什么系统下面运行的
runs-on: ubuntu-latest
# 每一个- 代表一个步骤
steps:
# 把代码下载下来
- uses: actions/checkout@v3
# 运行一行脚本
- name: Run a one-line script
run: echo Hello, world!
# 运行两行脚本
- name: Run a multi-line script
run: |
echo Add other actions to build,
echo test, and deploy your project.
```
## step2:实战(github)
每一次提交之前我们通过 Lint4j、TSLint、ESLint 来进行代码检验
Test一般是指单元测试
```
1. 任务的并行与串行
在 CI 中,互不干扰的任务并行执行,可以节省很大时间。如 Lint 和 Test 无任何交集,就可以并行执行。
但是 Lint 和 Test 都需要依赖安装 (Install),在依赖安装结束后再执行,此时就是串行的。
「而进行串行时,如果前一个任务失败,则下一个任务也无法继续。即如果测试无法通过,则无法进行 Preview,更无法上线。」
```
node文件
```js
const axios = require('axios')
var nodemailer = require('nodemailer');
function getApi(address) {
return new Promise((resolve) => {
axios
.get('https://restapi.amap.com/v3/geocode/geo', {
params: {
key: '02173ea51a9245ef63966988c96a3a67',
address,
},
})
.then((resX) => {
axios
.get('https://restapi.amap.com/v3/weather/weatherInfo', {
params: {
key: '02173ea51a9245ef63966988c96a3a67',
city: +resX.data.geocodes[0].adcode,
},
})
.then((res) => {
resolve(res.data)
})
})
})
}
async function main() {
let params = "广东省广州市天河区";
let res = await getApi(params)
console.error("天气:", res.lives[0].temperature)
// 创建一个SMTP客户端配置
var config = {
host: 'smtp.qq.com',//网易163邮箱 smtp.163.com
port: 465,//网易邮箱端口 25
auth: {
user: '3451613934@qq.com', //邮箱账号
pass: 'exhpspuprkyecidd' //邮箱的授权码
}
};
// 创建一个SMTP客户端对象
var transporter = nodemailer.createTransport(config);
// 发送邮件
function send(mail) {
transporter.sendMail(mail, function (error, info) {
if (error) {
return console.log(error);
}
console.log('mail sent:', info.response);
});
};
// 创建一个邮件对象
var mail = {
// 发件人
from: '3451613934@qq.com',
// 主题
subject: "天气: "+res.lives[0].temperature,
// 收件人
to: '895361337@qq.com',
// 邮件内容,HTML格式
text: res.lives[0].temperature //可以是链接,也可以是验证码
};
send(mail);
}
main()
```
.github/workflows
```yaml
# 关于本次 workflow 的名字
name: CI
# 执行 CI 的时机: 当 git push 代码到 github 时
on:
# schedule: # 每天8:30做一些事情
# - cron: '30 8 * * *'
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
types:
# 当新建了一个 PR 时 # 当提交 PR 的分支,未合并前并拥有新的 Commit 时
- opened
- synchronize
# 执行所有的 jobs
jobs:
#命名成lint
lint:
runs-on: ubuntu-latest
steps:
# 切出代码,使用该 Action 将可以拉取最新代码
#- uses: actions/checkout@v2
# 配置 node.js 环境,此时使用的是 node14
# 注意此处 node.js 版本,与 Docker 中版本一致,与 package.json 中 engines.node 版本一致
# 如果需要测试不同 node.js 环境下的表现,可使用 matrix
# uses: actions/checkout@v2 这玩意可以在 ubuntu-20.04, ubuntu-18.04,上进行测试
- name: Setup Node
uses: actions/checkout@v2
with:
node-version: 14.x.
# 安装依赖
- name: Install Dependencies
run: npm install
# 在 cra 中,使用 npm run lint 来模拟 ESLint
- name: ESLint
run: npm run lint
# 测试这玩意
- name: node脚本获取天气
run: node test.js
# 在 npm audit --json
- name: audit依赖包扫描
run: npm audit --json
#运行一段脚本试试水
- name: Run a one-line script
run: echo Hello, world!
#命名成error
error:
runs-on: ubuntu-latest
steps:
# 运行bash试试水
- name: Run a multi-line script
shell: bash
run: |
sh pulish001.sh
```
## step3:实战(gitee) 不行放弃
```yaml
version: '1.0'
name: 测试
displayName: MasterPipeline
stages:
- stage:
name: compile
displayName: 编译
steps:
- step: build@nodejs
name: build_nodejs
displayName: Nodejs 构建
# 支持8.16.2、10.17.0、12.16.1、14.16.0、15.12.0五个版本
nodeVersion: 14.16.0
# 构建命令:安装依赖 -> 清除上次打包产物残留 -> 执行构建 【请根据项目实际产出进行填写】
commands:
- npm install
- stage:
name: release
displayName: lint测试
steps:
- step: publish@release_artifacts
name: publish_release_artifacts
displayName: '发布'
commands:
- npm run lint
triggers:
push:
branches:
include:
- master
```
## step4:高级CI检查
除了上面的lint和test 检查外
1.npm audit
可以分析不安全的依赖以及不是可能有问题的依赖
# 2.git hook
最终效果
## 2.1 git hook
### hook demo
为了代码的规范有必要进行 log 规范化检查。而检查的入口可以从 git hook 切入,而 git hook 却又有无限的遐想。
钩子都被存储在 Git 目录下的 hooks 子目录中。 也即绝大部分项目中的 `.git/hooks`,默认存在的都是示例,其名字都是以 `.sample` 结尾,如果你想启用它们,得先移除这个后缀。把一个正确命名且可执行的文件放入 Git 目录下的 hooks 子目录中,即可激活该钩子脚本。 这样一来,它就能被 Git 调用。
你可以用来检查消息、检查代码,可以用来触发任意流程,譬如自动规范检查等等
```
有两种类型的hook
一种是服务端的hook, receive之类的
一种是客户端的hook。precommiit之类的
有几种钩子的情况
msg(应用程序消息)
pre(应用前批处理)
post(应用程序批处理后)
hook,这其实是计算机领域中一个很常见的概念,hook 翻译过来的意思是钩子或者勾住,而在计算机领域中则要分为两种解释:
拦截消息,在消息到达目标前,提前对消息进行处理
对特定的事件进行监听,当某个事件或动作被触发时也会同时触发对应的 hook
也就是说 hook 本身也是一段程序,只是它会在特定的时机被触发。
```
在.git/hook/
```python
#!/usr/bin/env python
# coding=utf-8
#
# commit msg check
import sys
import re
import io
import os
if hasattr(sys.stdout, 'buffer'):
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
TIPS_INFO = '''
不符合commit规范,提交失败(当前状态等于没作刚刚的commit操做)!
commit规范:
类型 详细消息
规范样例:
git commit -m "xxxxx xxxxxxxxxxxxx"
!!!!提交失败!!!!
'''
def check_commit_line1_format(msg):
regOther = r'\S{5,} (.){10,100}'
matchObj = re.match(regOther, msg)
return matchObj
if __name__=="__main__":
print("进行lint扫描")
os.system("npm run lint")
print("进行audit扫描")
os.system("npm audit")
with open(sys.argv[1], 'r') as f:
for line in f:
if (check_commit_line1_format(line)):
sys.exit(0)
else:
print(TIPS_INFO)
sys.exit(1)
```
**一段好用的可以自动更新版本的工具js **package_version_auto_add.js
```js
const execSync = require('child_process').execSync
const path = require('path')
const fs = require('fs')
console.log('------------ 开发自动升级package.json版本号 ------------');
const projectPath = path.join(__dirname, './')
const packageJsonStr = fs.readFileSync('./package.json').toString()
try {
const packageJson = JSON.parse(packageJsonStr)
// 升级版本号
const arr = packageJson.version.split('.')
if (arr[2] < 9) {
arr[2] = +arr[2] + 1
} else if (arr[1] < 9) {
arr[1] = +arr[1] + 1
arr[2] = 0
} else {
arr[0] = +arr[0] + 1
arr[1] = 0
arr[2] = 0
}
const newVersion = arr.join('.')
packageJson.version = newVersion
// console.log(packageJson);
fs.writeFileSync('./package.json', JSON.stringify(packageJson, null, '\t'))
// add new package.json
execSync(`git add package.json`)
} catch (e) {
console.error('处理package.json失败,请重试', e.message);
process.exit(1)
}
```
package.json中
```js
"scripts": {
"serve": "cross-env NODE_ENV=production vue-cli-service serve",
"dev": "vue-cli-service serve --mode=development",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"analyz": "webpack-bundle-analyzer --port 8888 ./dist/stats.json",
"test": "node test.js",
"prepare": "husky install",
"package_version_auto_add": "node package_version_auto_add.js ",
"eslint:check": "eslint src/*.vue"
},
```
这里有一个问题,就是我们如果进行了git代码提交后,git上面的源码并不会得到保留
### **因此这里我们要用到husty**
husky的原理是在.git/config文件的[core]中添加 hooksPath = .husky就是原理了
官网:https://typicode.github.io/husky/#/?id=manual
step1:初始化
```js
命令行中
npm install husky@8 -D
package.json中添加
"scripts": {
"prepare": "husky install",
},
```
npm run prepare,构建一般目录
step2:添加钩子
然后如果是在powershell中我们构建,我们可以进行运行
```
npx husky add .husky/pre-commit "npm-run-lint"
```
如果在cmd中我们可以
```
npx husky add .husky/pre-commit "npm run lint"
```
我们还可以在husky文件夹下面新建precommit,我们写入
```sh
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
npm run lint
是一样的效果
```
校验名字-这玩意我写的贼牛皮-commit-msg
```python
#!/usr/bin/env python
# coding=utf-8
#
# commit msg check
import sys
import re
import io
import os
if hasattr(sys.stdout, 'buffer'):
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
TIPS_INFO = '''
不符合commit规范,提交失败(当前状态等于没作刚刚的commit操做)!
commit规范:
类型 详细消息
规范样例:
feat:类型是feat表示在代码库中新增了一个功能 git commit -m "feat: 增加了xxx功能"
fix:类型是fix表示在代码库中修复了了一个bug git commit -m "fix: 修复了xxx功能"
!!!!提交失败!!!!
'''
def check_commit_line1_format(msg):
print(msg)
# regOther = r'\S{5,} (.){10,100}' ^fix:|^feat: ((修复了)|(增加了))(.){2,100}功能
regOther = r'^fix:|^feat: ((修复了)|(增加了))(.){1,100}功能'
matchObj = re.match(regOther, msg)
return matchObj
if __name__=="__main__":
# print("进行lint扫描")
# os.system("npm run lint")
print("进行audit扫描")
os.system("npm audit")
# print(sys)
with open(sys.argv[1], 'r',encoding="utf-8") as f:
for line in f:
if (check_commit_line1_format(line)):
sys.exit(0)
else:
print(TIPS_INFO)
sys.exit(1)
```
## 2.2 npx 和 npm
区别1.一个永久存在,一个临时安装,用完后删除
区别2.npx 会帮你执行依赖包里的二进制文件。
区别3.npx可以执行文件,但是npm不可以
## 2.3 eslint 配置(格式化工具)
根目录下面新建.eslintrc.js
step1:eslint安装初始化
```
npm i eslint@7.32 -D
```
package.json中
```json
写入
"scripts": {
"eslint:check": "eslint src/*.vue"
"eslint:check": "eslint ./" //就是检查所有的东西 ,这一部分依赖于package.json同级目录下面的.eslintrc.js文件
},
```
step2:
.eslintrc.js中,我们在这里配置具体的规则
```js
module.exports = {
root: true,
env: {
browser: true,
node: true,
},
extends: [
// 额外添加的规则可查看 https://vuejs.github.io/eslint-plugin-vue/rules/
'plugin:vue/essential', //加了这个才能当作vue来进行解析,不然只会当成js来进行解析
],
//不加这个会报错Parsing error: The keyword 'import' is reserved
parserOptions: {
// 指定解析器 parser
"ecmaVersion": 7,
"sourceType": "module"
// parser: 'babel-eslint',
// sourceType: 'module',
// ecmaVersion: 12,
// allowImportExportEverywhere: true, // 不限制eslint对import使用位置
},
settings: {
},
// 取消没必要的校验 0 是 不报错 , 1是warn 2 是punishing
// "off"或者0 //关闭规则关闭
// "warn"或者1 //在打开的规则作为警告(不影响退出代码)
// "error"或者2 //把规则作为一个错误(退出代码触发时为1)
rules: {
// "camelcase": ["error", { "allow": ["aa_bb"] }], // 属性名
// "max-lines": ["error", {"max": 20, "skipComments": true}], // 每一个文件最多的行数
// "no-console": 2,//禁止使用console
// "no-mixed-spaces-and-tabs": [2, false],//禁止混用tab和空格
// "no-multiple-empty-lines": [1, {"max": 2}],//空行最多不能超过2行
// "no-multi-spaces": 1,//不能用多余的空格
// "indent": [1, 4],//缩进风格 缩进四个空格
"max-lines-per-function": [0, { "max": 2 }], // 指定每个function最多多少行
"no-unused-vars":1, //没被使用
'consistent-return': 0, // 有函数返回值
'no-underscore-dangle': 0, // 不允许有下划线
'no-plusplus': 1, // 不能用++
'no-eval': 0, // 不能用eval
'linebreak-style': [0, 'error', 'window'], // 换行风格
'camelcase': 'warn', //像是xx_xx这种会报错
},
};
```
package.json里面,这里是为了vue运行的时候在里面添加校验的东西------后来发现靠webpack检验不是很靠谱,会有延迟的现象。于是就在vs code下面下载eslint插件还更好用一点。eslint v2.2.2 插件
```json
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {
"max-lines-per-function": [0, { "max": 2 }],
"no-unused-vars":1,
"consistent-return": 0,
"no-underscore-dangle": 0,
"no-plusplus": 1,
"no-eval": 0,
"linebreak-style": [0, "error", "window"],
"camelcase": "warn"
}
},
```
step3:如果说是遇到了奇怪的eslint报错,可以新建.eslintignore文件把他忽略就行了
```js
*.js
```
## 2.4 prettier 安装
step1:安装prettier
```
npm i -D eslint-config-prettier@8.5 eslint-plugin-prettier@4.0 prettier@2.6.2 prettier-eslint-cli@5.0.1
```
安装了之后我们在vscode中下载prettic eslint 5.0.4
step2: 新建.prettierrc.js我们 ,如果要进行内容实时的更新。我们点击一下右下角的按钮就可以刷新
```js
module.exports = {
// 最大长度160个字符
printWidth: 120,
// 行末分号
semi: false,
// 单引号
singleQuote: false,
// JSX双引号
jsxSingleQuote: false,
// 尽可能使用尾随逗号(包括函数参数)
trailingComma: 'none',
// 在对象文字中打印括号之间的空格。
bracketSpacing: true,
// > 标签放在最后一行的末尾,而不是单独放在下一行
jsxBracketSameLine: false,
// 箭头圆括号
arrowParens: 'avoid',
// 在文件顶部插入一个特殊的 @format 标记,指定文件格式需要被格式化。
insertPragma: false,
// 缩进
tabWidth: 2,
// 使用tab还是空格
useTabs: false,
// 行尾换行格式
endOfLine: 'auto',
HTMLWhitespaceSensitivity: 'ignore'
}
```
## 2.5 lint-staged
在代码提交之前,进行代码规则检查能够确保进入git库的代码都是符合代码规则的。但是整个项目上运行lint速度会很慢,lint-staged能够让lint只检测暂存区的文件,所以速度很快。
step1:初始化
```
npm install lint-staged@11.1.2 -D
```
step2:package.json添加
```js
{
"name": "vue_helloworld",
"version": "0.1.3",
"scripts": {
"serve": "cross-env NODE_ENV=production vue-cli-service serve",
"dev": "vue-cli-service serve --mode=development",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint",
"analyz": "webpack-bundle-analyzer --port 8888 ./dist/stats.json",
"test": "node test.js",
"prepare": "husky install",
"lint-staged": "lint-staged",
"eslint:check": "eslint ./",
"package_version_auto_add": "node package_version_auto_add.js"
},
"dependencies": {
"@popperjs/core": "^2.11.6",
"@swc/core": "1.3",
"axios": "^0.27.2",
"babel-eslint": "^10.2.0",
"bootstrap": "^5.1.3",
"core-js": "^3.8.3",
"echarts": "^5.3.2",
"element-ui": "^2.15.8",
"frontutilpackage": "0.0.1",
"less": "^4.1.2",
"less-loader": "^12.0.0",
"nodemailer": "^6.7.8",
"qs": "^6.12.0",
"swc": "^2.0.11",
"swc-loader": "^0.1.16",
"vue": "^2.6.14",
"vue-router": "^3.1.3",
"vuex": "^3.6.2",
"webpack": "5.2"
},
"devDependencies": {
"@babel/core": "^7.12.16",
"@babel/eslint-parser": "^7.12.16",
"@vue/cli-plugin-babel": "~5.0.0",
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"cross-env": "^7.0.3",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3",
"husky": "^8.0.1",
"jquery": "^3.6.0",
"lint-staged": "^11.1.2",
"prettier": "^2.7.1",
"terser-webpack-plugin": "^5.3.6",
"thread-loader": "^3.0.4",
"vue-template-compiler": "^2.6.14",
"webpack-bundle-analyzer": "^4.6.1"
},
"husky": {
},
"lint-staged": {
"*.js": [
"npm run test",
"git add"
],
"*.vue": [
"npm run lint",
"git add"
]
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
```
step3:**创建 .lintstagedrc**
```js
{
"src/**/*.{js,ts,tsx,vue}": "npm run lint:eslint",
"src/**/*.{vue,css,scss}": "npm run lint:stylelint"
}
------------------------
{
"*.{js,ts,tsx,vue}": "npm run package_version_auto_add",
}
{
"./src/*.vue": "npm run eslint:check"
}
```
step4 :注意 eslint ecmaVersion不用8的话async await会报错
```js
// npm install babel-eslint --save
module.exports = {
root: true,
env: {
browser: true,
node: true,
},
extends: [
// 额外添加的规则可查看 https://vuejs.github.io/eslint-plugin-vue/rules/
'plugin:vue/essential', //加了这个才能当作vue来进行解析,不然只会当成js来进行解析
],
//不加这个会报错Parsing error: The keyword 'import' is reserved
parserOptions: {
// 指定解析器 parser
"ecmaVersion": 8,
"sourceType": "module",
// "parser": 'babel-eslint',
// sourceType: 'module',
// ecmaVersion: 12,
// allowImportExportEverywhere: true, // 不限制eslint对import使用位置
},
settings: {
},
// 取消没必要的校验 0 是 不报错 , 1是warn 2 是punishing
// "off"或者0 //关闭规则关闭
// "warn"或者1 //在打开的规则作为警告(不影响退出代码)
// "error"或者2 //把规则作为一个错误(退出代码触发时为1)
rules: {
// "camelcase": ["error", { "allow": ["aa_bb"] }], // 属性名
// "max-lines": ["error", {"max": 20, "skipComments": true}], // 每一个文件最多的行数
// "no-console": 2,//禁止使用console
// "no-mixed-spaces-and-tabs": [2, false],//禁止混用tab和空格
// "no-multiple-empty-lines": [1, {"max": 2}],//空行最多不能超过2行
// "no-multi-spaces": 1,//不能用多余的空格
// "indent": [1, 4],//缩进风格 缩进四个空格
// "max-lines-per-function": [0, { "max": 2 }], // 指定每个function最多多少行
"no-unused-vars":1, //没被使用
'consistent-return': 0, // 有函数返回值
'no-underscore-dangle': 0, // 不允许有下划线
'no-plusplus': 1, // 不能用++
'no-eval': 0, // 不能用eval
'linebreak-style': [0, 'error', 'window'], // 换行风格
'camelcase': 'warn', //像是xx_xx这种会报错
},
};
```
step5:husty/pre-commit 中写入
```sh
#!/usr/bin/env sh
# npm run lint
# npm run lint-staged
```