refactor: 1

master
xiaojunnuo 2021-01-08 16:59:53 +08:00
parent 15467fc233
commit 137e043dfe
4 changed files with 44 additions and 27 deletions

View File

@ -11,7 +11,8 @@ function createDefaultOptions () {
args: { args: {
forceCert: false, forceCert: false,
forceDeploy: true, forceDeploy: true,
forceRedeploy: false forceRedeploy: false,
doNotThrowError: false // 部署流程执行有错误时,不抛异常,此时整个任务执行完毕后,可以返回结果,你可以在返回结果中处理
} }
} }
} }
@ -84,24 +85,23 @@ export class Executor {
context.certIsNew = !!cert.isNew context.certIsNew = !!cert.isNew
const trace = new Trace(context) const trace = new Trace(context)
const resultTrace = trace.getInstance({ type: 'result' })
// 运行部署任务 // 运行部署任务
try { try {
await this.runDeploys({ options, cert, context, trace }) await this.runDeploys({ options, cert, context, trace })
} finally { } finally {
await certd.certStore.setCurrentFile('context.json', JSON.stringify(context)) await certd.certStore.setCurrentFile('context.json', JSON.stringify(context))
} }
logger.info('任务完成') logger.info('任务完成')
trace.print() trace.print()
const result = trace.get({ }) const result = resultTrace.get({ })
const returnData = { const returnData = {
cert, cert,
context, context,
result result
} }
if (result.status === 'error') { if (result.status === 'error' && options.args.doNotThrowError === false) {
const err = new Error(result.remark) throw new Error(result.remark)
err.data = returnData
} }
return returnData return returnData
} }
@ -122,10 +122,12 @@ export class Executor {
for (const deploy of options.deploy) { for (const deploy of options.deploy) {
const deployName = deploy.deployName const deployName = deploy.deployName
logger.info(`------------【${deployName}】-----------`) logger.info(`------------【${deployName}】-----------`)
const deployTrace = trace.getInstance({ type: 'deploy', deployName })
if (deploy.disabled === true) { if (deploy.disabled === true) {
logger.info('此流程已被禁用,跳过') logger.info('此流程已被禁用,跳过')
logger.info('') logger.info('')
trace.set({ deployName, value: { current: 'skip', status: 'disabled', remark: '流程禁用' } }) deployTrace.set({ value: { current: 'skip', status: 'disabled', remark: '流程禁用' } })
continue continue
} }
try { try {
@ -134,13 +136,14 @@ export class Executor {
context[deployName] = {} context[deployName] = {}
} }
const taskContext = context[deployName] const taskContext = context[deployName]
// 开始执行任务列表
await this.runTask({ options, cert, task, context: taskContext, deploy, trace }) await this.runTask({ options, cert, task, context: taskContext, deploy, trace })
} }
trace.set({ deployName, value: { status: 'success', remark: '执行成功' } }) deployTrace.set({ value: { status: 'success', remark: '执行成功' } })
} catch (e) { } catch (e) {
trace.set({ deployName, value: { status: 'error', remark: '执行失败:' + e.message } }) deployTrace.set({ value: { status: 'error', remark: '执行失败:' + e.message } })
trace.set({ value: { status: 'error', remark: deployName + '执行失败:' + e.message } }) trace.set({ type: 'result', value: { status: 'error', remark: deployName + '执行失败:' + e.message } })
logger.error('流程执行失败', e) logger.error('流程执行失败', e)
} }
@ -161,18 +164,20 @@ export class Executor {
if (Plugin instanceof Function) { if (Plugin instanceof Function) {
instance = new Plugin({ accessProviders: options.accessProviders }) instance = new Plugin({ accessProviders: options.accessProviders })
} }
const traceStatus = trace.get({ deployName: deploy.deployName, taskName: taskName }) const taskTrace = trace.getInstance({ type: 'deploy', deployName, taskName })
const traceStatus = taskTrace.get({})
if (traceStatus?.status === 'success' && !options?.args?.forceRedeploy) { if (traceStatus?.status === 'success' && !options?.args?.forceRedeploy) {
logger.info(`----【${taskName}】已经执行完成,跳过此任务`) logger.info(`----【${taskName}】已经执行完成,跳过此任务`)
trace.set({ deployName, taskName, value: { current: 'skip', status: 'success', remark: '已执行成功过,本次跳过' } }) taskTrace.set({ value: { current: 'skip', status: 'success', remark: '已执行成功过,本次跳过' } })
return return
} }
logger.info(`----【${taskName}】开始执行`) logger.info(`----【${taskName}】开始执行`)
try { try {
// 执行任务
await instance.execute({ cert, props: task.props, context }) await instance.execute({ cert, props: task.props, context })
trace.set({ deployName, taskName, value: { current: 'success', status: 'success', remark: '执行成功', time: dayjs().format() } }) taskTrace.set({ value: { current: 'success', status: 'success', remark: '执行成功', time: dayjs().format() } })
} catch (e) { } catch (e) {
trace.set({ deployName, taskName, value: { current: 'error', status: 'error', remark: e.message, time: dayjs().format() } }) taskTrace.set({ value: { current: 'error', status: 'error', remark: e.message, time: dayjs().format() } })
throw e throw e
} }
logger.info(`----任务【${taskName}】执行完成`) logger.info(`----任务【${taskName}】执行完成`)

View File

@ -6,19 +6,30 @@ export class Trace {
this.context = context this.context = context
} }
set ({ deployName, taskName, prop, value }) { getInstance ({ type, deployName, taskName }) {
const key = this.buildTraceKey({ deployName, taskName, prop }) return {
get: ({ prop }) => {
return this.get({ type, deployName, taskName, prop })
},
set: ({ prop, value }) => {
this.set({ type, deployName, taskName, prop, value })
}
}
}
set ({ type, deployName, taskName, prop, value }) {
const key = this.buildTraceKey({ type, deployName, taskName, prop })
const oldValue = _.get(this.context, key) || {} const oldValue = _.get(this.context, key) || {}
_.merge(oldValue, value) _.merge(oldValue, value)
_.set(this.context, key, oldValue) _.set(this.context, key, oldValue)
} }
get ({ deployName, taskName, prop }) { get ({ type, deployName, taskName, prop }) {
return _.get(this.context, this.buildTraceKey({ deployName, taskName, prop })) return _.get(this.context, this.buildTraceKey({ type, deployName, taskName, prop }))
} }
buildTraceKey ({ deployName, taskName, prop }) { buildTraceKey ({ type = 'default', deployName, taskName, prop }) {
let key = '__trace__' let key = '__trace__.' + type
if (deployName) { if (deployName) {
key += '.' key += '.'
key += deployName.replace(/\./g, '_') key += deployName.replace(/\./g, '_')
@ -46,7 +57,7 @@ export class Trace {
} else { } else {
this.printTraceLine({ current: 'skip', remark: '还未到过期时间,跳过' }, '更新证书') this.printTraceLine({ current: 'skip', remark: '还未到过期时间,跳过' }, '更新证书')
} }
const trace = this.get({ }) const trace = this.get({ type: 'deploy' })
// logger.info('trace', trace) // logger.info('trace', trace)
for (const deployName in trace) { for (const deployName in trace) {
if (trace[deployName] == null) { if (trace[deployName] == null) {
@ -64,11 +75,12 @@ export class Trace {
} }
} }
} }
const result = this.get({ type: 'result' })
this.printTraceLine(result, 'result', '')
const mainContext = {} const mainContext = {}
_.merge(mainContext, context) _.merge(mainContext, context)
delete mainContext.__trace__ delete mainContext.__trace__
logger.info('context:', JSON.stringify(mainContext)) logger.info('【context】', JSON.stringify(mainContext))
} }
printTraceLine (traceStatus, name, prefix = '') { printTraceLine (traceStatus, name, prefix = '') {

View File

@ -5,7 +5,7 @@ const { expect } = pkg
describe('AutoDeploy', function () { describe('AutoDeploy', function () {
it('#run', async function () { it('#run', async function () {
this.timeout(20000) this.timeout(120000)
const options = createOptions() const options = createOptions()
const executor = new Executor() const executor = new Executor()
const ret = await executor.run(options) const ret = await executor.run(options)
@ -13,7 +13,7 @@ describe('AutoDeploy', function () {
expect(ret.cert).ok expect(ret.cert).ok
}) })
it('#forceCert', async function () { it('#forceCert', async function () {
this.timeout(20000) this.timeout(120000)
const executor = new Executor() const executor = new Executor()
const options = createOptions() const options = createOptions()
const ret = await executor.run(options, { forceCert: true, forceDeploy: false }) const ret = await executor.run(options, { forceCert: true, forceDeploy: false })
@ -21,7 +21,7 @@ describe('AutoDeploy', function () {
expect(ret.cert).ok expect(ret.cert).ok
}) })
it('#forceDeploy', async function () { it('#forceDeploy', async function () {
this.timeout(20000) this.timeout(120000)
const executor = new Executor() const executor = new Executor()
const options = createOptions() const options = createOptions()
const ret = await executor.run(options, { forceCert: false, forceDeploy: true, forceRedeploy: true }) const ret = await executor.run(options, { forceCert: false, forceDeploy: true, forceRedeploy: true })

View File

@ -4,7 +4,7 @@ const defaultOptions = {
args: { args: {
forceCert: false, // 强制更新证书 forceCert: false, // 强制更新证书
skipCert: false, // 是否跳过证书申请环节 skipCert: false, // 是否跳过证书申请环节
forceDeploy: false, forceDeploy: true,
test: true test: true
}, },
accessProviders: { accessProviders: {