mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 14:56:07 +08:00
订阅增加before/after
This commit is contained in:
parent
bdecdce118
commit
189826c5db
|
@ -38,6 +38,9 @@ export default (app: Router) => {
|
||||||
dependences: Joi.string().optional().allow('').allow(null),
|
dependences: Joi.string().optional().allow('').allow(null),
|
||||||
pull_type: Joi.string().optional().allow('').allow(null),
|
pull_type: Joi.string().optional().allow('').allow(null),
|
||||||
pull_option: Joi.object().optional().allow('').allow(null),
|
pull_option: Joi.object().optional().allow('').allow(null),
|
||||||
|
extensions: Joi.string().optional().allow('').allow(null),
|
||||||
|
sub_before: Joi.string().optional().allow('').allow(null),
|
||||||
|
sub_after: Joi.string().optional().allow('').allow(null),
|
||||||
schedule_type: Joi.string().required(),
|
schedule_type: Joi.string().required(),
|
||||||
alias: Joi.string().required(),
|
alias: Joi.string().required(),
|
||||||
}),
|
}),
|
||||||
|
@ -167,6 +170,9 @@ export default (app: Router) => {
|
||||||
pull_type: Joi.string().optional().allow('').allow(null),
|
pull_type: Joi.string().optional().allow('').allow(null),
|
||||||
pull_option: Joi.object().optional().allow('').allow(null),
|
pull_option: Joi.object().optional().allow('').allow(null),
|
||||||
schedule_type: Joi.string().optional().allow('').allow(null),
|
schedule_type: Joi.string().optional().allow('').allow(null),
|
||||||
|
extensions: Joi.string().optional().allow('').allow(null),
|
||||||
|
sub_before: Joi.string().optional().allow('').allow(null),
|
||||||
|
sub_after: Joi.string().optional().allow('').allow(null),
|
||||||
alias: Joi.string().required(),
|
alias: Joi.string().required(),
|
||||||
id: Joi.number().required(),
|
id: Joi.number().required(),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -25,6 +25,9 @@ export class Subscription {
|
||||||
log_path?: string;
|
log_path?: string;
|
||||||
alias: string;
|
alias: string;
|
||||||
command?: string;
|
command?: string;
|
||||||
|
extensions?: string;
|
||||||
|
sub_before?: string;
|
||||||
|
sub_after?: string;
|
||||||
|
|
||||||
constructor(options: Subscription) {
|
constructor(options: Subscription) {
|
||||||
this.id = options.id;
|
this.id = options.id;
|
||||||
|
@ -48,6 +51,9 @@ export class Subscription {
|
||||||
this.schedule_type = options.schedule_type;
|
this.schedule_type = options.schedule_type;
|
||||||
this.alias = options.alias;
|
this.alias = options.alias;
|
||||||
this.interval_schedule = options.interval_schedule;
|
this.interval_schedule = options.interval_schedule;
|
||||||
|
this.extensions = options.extensions;
|
||||||
|
this.sub_before = options.sub_before;
|
||||||
|
this.sub_after = options.sub_after;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +91,9 @@ export const SubscriptionModel = sequelize.define<SubscriptionInstance>(
|
||||||
blacklist: DataTypes.STRING,
|
blacklist: DataTypes.STRING,
|
||||||
status: DataTypes.NUMBER,
|
status: DataTypes.NUMBER,
|
||||||
dependences: DataTypes.STRING,
|
dependences: DataTypes.STRING,
|
||||||
|
extensions: DataTypes.STRING,
|
||||||
|
sub_before: DataTypes.STRING,
|
||||||
|
sub_after: DataTypes.STRING,
|
||||||
branch: DataTypes.STRING,
|
branch: DataTypes.STRING,
|
||||||
pull_type: DataTypes.STRING,
|
pull_type: DataTypes.STRING,
|
||||||
pull_option: DataTypes.JSON,
|
pull_option: DataTypes.JSON,
|
||||||
|
|
|
@ -21,14 +21,16 @@ export interface TaskCallbacks {
|
||||||
onStart?: (
|
onStart?: (
|
||||||
cp: ChildProcessWithoutNullStreams,
|
cp: ChildProcessWithoutNullStreams,
|
||||||
startTime: dayjs.Dayjs,
|
startTime: dayjs.Dayjs,
|
||||||
) => void;
|
) => Promise<void>;
|
||||||
onEnd?: (
|
onEnd?: (
|
||||||
cp: ChildProcessWithoutNullStreams,
|
cp: ChildProcessWithoutNullStreams,
|
||||||
endTime: dayjs.Dayjs,
|
endTime: dayjs.Dayjs,
|
||||||
diff: number,
|
diff: number,
|
||||||
) => void;
|
) => Promise<void>;
|
||||||
onLog?: (message: string) => void;
|
onLog?: (message: string) => Promise<void>;
|
||||||
onError?: (message: string) => void;
|
onError?: (message: string) => Promise<void>;
|
||||||
|
onBefore?: () => Promise<void>;
|
||||||
|
onAfter?: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
|
@ -44,33 +46,34 @@ export default class ScheduleService {
|
||||||
async runTask(command: string, callbacks: TaskCallbacks = {}) {
|
async runTask(command: string, callbacks: TaskCallbacks = {}) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
|
await callbacks.onBefore?.();
|
||||||
const startTime = dayjs();
|
const startTime = dayjs();
|
||||||
const cp = spawn(command, { shell: '/bin/bash' });
|
const cp = spawn(command, { shell: '/bin/bash' });
|
||||||
|
|
||||||
callbacks.onStart?.(cp, startTime);
|
await callbacks.onStart?.(cp, startTime);
|
||||||
|
|
||||||
cp.stdout.on('data', (data) => {
|
cp.stdout.on('data', async (data) => {
|
||||||
callbacks.onLog?.(data.toString());
|
await callbacks.onLog?.(data.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
cp.stderr.on('data', (data) => {
|
cp.stderr.on('data', async (data) => {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
'执行任务 %s 失败,时间:%s, 错误信息:%j',
|
'执行任务 %s 失败,时间:%s, 错误信息:%j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
new Date().toLocaleString(),
|
||||||
data.toString(),
|
data.toString(),
|
||||||
);
|
);
|
||||||
callbacks.onError?.(data.toString());
|
await callbacks.onError?.(data.toString());
|
||||||
});
|
});
|
||||||
|
|
||||||
cp.on('error', (err) => {
|
cp.on('error', async (err) => {
|
||||||
this.logger.error(
|
this.logger.error(
|
||||||
'创建任务 %s 失败,时间:%s, 错误信息:%j',
|
'创建任务 %s 失败,时间:%s, 错误信息:%j',
|
||||||
command,
|
command,
|
||||||
new Date().toLocaleString(),
|
new Date().toLocaleString(),
|
||||||
err,
|
err,
|
||||||
);
|
);
|
||||||
callbacks.onError?.(JSON.stringify(err));
|
await callbacks.onError?.(JSON.stringify(err));
|
||||||
});
|
});
|
||||||
|
|
||||||
cp.on('exit', async (code, signal) => {
|
cp.on('exit', async (code, signal) => {
|
||||||
|
@ -82,7 +85,12 @@ export default class ScheduleService {
|
||||||
cp.on('close', async (code) => {
|
cp.on('close', async (code) => {
|
||||||
const endTime = dayjs();
|
const endTime = dayjs();
|
||||||
this.logger.info(`${command} pid: ${cp.pid} closed ${code}`);
|
this.logger.info(`${command} pid: ${cp.pid} closed ${code}`);
|
||||||
callbacks.onEnd?.(cp, endTime, endTime.diff(startTime, 'seconds'));
|
await callbacks.onEnd?.(
|
||||||
|
cp,
|
||||||
|
endTime,
|
||||||
|
endTime.diff(startTime, 'seconds'),
|
||||||
|
);
|
||||||
|
await callbacks.onAfter?.();
|
||||||
resolve(null);
|
resolve(null);
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -92,7 +100,7 @@ export default class ScheduleService {
|
||||||
new Date().toLocaleString(),
|
new Date().toLocaleString(),
|
||||||
error,
|
error,
|
||||||
);
|
);
|
||||||
callbacks.onError?.(JSON.stringify(error));
|
await callbacks.onError?.(JSON.stringify(error));
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -97,13 +97,13 @@ export default class SubscriptionService {
|
||||||
private formatCommand(doc: Subscription, url?: string) {
|
private formatCommand(doc: Subscription, url?: string) {
|
||||||
let command = 'ql ';
|
let command = 'ql ';
|
||||||
let _url = url || this.formatUrl(doc).url;
|
let _url = url || this.formatUrl(doc).url;
|
||||||
const { type, whitelist, blacklist, dependences, branch } = doc;
|
const { type, whitelist, blacklist, dependences, branch, extensions } = doc;
|
||||||
if (type === 'file') {
|
if (type === 'file') {
|
||||||
command += `raw "${_url}"`;
|
command += `raw "${_url}"`;
|
||||||
} else {
|
} else {
|
||||||
command += `repo "${_url}" "${whitelist || ''}" "${blacklist || ''}" "${
|
command += `repo "${_url}" "${whitelist || ''}" "${blacklist || ''}" "${
|
||||||
dependences || ''
|
dependences || ''
|
||||||
}" "${branch || ''}"`;
|
}" "${branch || ''}" "${extensions || ''}"`;
|
||||||
}
|
}
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
@ -219,6 +219,40 @@ export default class SubscriptionService {
|
||||||
const absolutePath = await this.handleLogPath(sub.log_path as string);
|
const absolutePath = await this.handleLogPath(sub.log_path as string);
|
||||||
fs.appendFileSync(absolutePath, `\n${message}`);
|
fs.appendFileSync(absolutePath, `\n${message}`);
|
||||||
},
|
},
|
||||||
|
onBefore: async () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (doc.sub_before) {
|
||||||
|
exec(doc.sub_before, async (err, stdout, stderr) => {
|
||||||
|
const absolutePath = await this.handleLogPath(
|
||||||
|
doc.log_path as string,
|
||||||
|
);
|
||||||
|
fs.appendFileSync(
|
||||||
|
absolutePath,
|
||||||
|
stdout || stderr || `${JSON.stringify(err || {})}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onAfter: async () => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (doc.sub_after) {
|
||||||
|
exec(doc.sub_after, async (err, stdout, stderr) => {
|
||||||
|
const absolutePath = await this.handleLogPath(
|
||||||
|
doc.log_path as string,
|
||||||
|
);
|
||||||
|
fs.appendFileSync(
|
||||||
|
absolutePath,
|
||||||
|
stdout || stderr || `${JSON.stringify(err || {})}`,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,7 @@ update_repo() {
|
||||||
local blackword="$3"
|
local blackword="$3"
|
||||||
local dependence="$4"
|
local dependence="$4"
|
||||||
local branch="$5"
|
local branch="$5"
|
||||||
|
local extensions="$6"
|
||||||
local tmp="${url%/*}"
|
local tmp="${url%/*}"
|
||||||
local authorTmp1="${tmp##*/}"
|
local authorTmp1="${tmp##*/}"
|
||||||
local authorTmp2="${authorTmp1##*:}"
|
local authorTmp2="${authorTmp1##*:}"
|
||||||
|
@ -159,7 +160,7 @@ update_repo() {
|
||||||
fi
|
fi
|
||||||
if [[ $exit_status -eq 0 ]]; then
|
if [[ $exit_status -eq 0 ]]; then
|
||||||
echo -e "\n更新${repo_path}成功...\n"
|
echo -e "\n更新${repo_path}成功...\n"
|
||||||
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence"
|
diff_scripts "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions"
|
||||||
else
|
else
|
||||||
echo -e "\n更新${repo_path}失败,请检查网络...\n"
|
echo -e "\n更新${repo_path}失败,请检查网络...\n"
|
||||||
fi
|
fi
|
||||||
|
@ -341,8 +342,9 @@ diff_scripts() {
|
||||||
local path="$3"
|
local path="$3"
|
||||||
local blackword="$4"
|
local blackword="$4"
|
||||||
local dependence="$5"
|
local dependence="$5"
|
||||||
|
local extensions="$6"
|
||||||
|
|
||||||
gen_list_repo "$repo_path" "$author" "$path" "$blackword" "$dependence"
|
gen_list_repo "$repo_path" "$author" "$path" "$blackword" "$dependence" "$extensions"
|
||||||
|
|
||||||
local list_add="$dir_list_tmp/${uniq_path}_add.list"
|
local list_add="$dir_list_tmp/${uniq_path}_add.list"
|
||||||
local list_drop="$dir_list_tmp/${uniq_path}_drop.list"
|
local list_drop="$dir_list_tmp/${uniq_path}_drop.list"
|
||||||
|
@ -378,6 +380,9 @@ gen_list_repo() {
|
||||||
|
|
||||||
local cmd="find ."
|
local cmd="find ."
|
||||||
local index=0
|
local index=0
|
||||||
|
if [[ $6 ]]; then
|
||||||
|
file_extensions="$6"
|
||||||
|
fi
|
||||||
for extension in $file_extensions; do
|
for extension in $file_extensions; do
|
||||||
if [[ $index -eq 0 ]]; then
|
if [[ $index -eq 0 ]]; then
|
||||||
cmd="${cmd} -name \"*.${extension}\""
|
cmd="${cmd} -name \"*.${extension}\""
|
||||||
|
@ -458,6 +463,7 @@ main() {
|
||||||
local p4=$4
|
local p4=$4
|
||||||
local p5=$5
|
local p5=$5
|
||||||
local p6=$6
|
local p6=$6
|
||||||
|
local p7=$7
|
||||||
local log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
local log_time=$(date "+%Y-%m-%d-%H-%M-%S")
|
||||||
local log_path="$dir_log/update/${log_time}_$p1.log"
|
local log_path="$dir_log/update/${log_time}_$p1.log"
|
||||||
local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
|
local begin_time=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
@ -479,7 +485,7 @@ main() {
|
||||||
get_user_info
|
get_user_info
|
||||||
get_uniq_path "$p2" "$p6"
|
get_uniq_path "$p2" "$p6"
|
||||||
if [[ -n $p2 ]]; then
|
if [[ -n $p2 ]]; then
|
||||||
update_repo "$p2" "$p3" "$p4" "$p5" "$p6"
|
update_repo "$p2" "$p3" "$p4" "$p5" "$p6" "$p7"
|
||||||
else
|
else
|
||||||
echo -e "命令输入错误...\n"
|
echo -e "命令输入错误...\n"
|
||||||
usage
|
usage
|
||||||
|
|
|
@ -357,6 +357,37 @@ const SubscriptionModal = ({
|
||||||
placeholder="请输入脚本依赖文件关键词,多个关键词竖线分割"
|
placeholder="请输入脚本依赖文件关键词,多个关键词竖线分割"
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="extensions"
|
||||||
|
label="文件后缀"
|
||||||
|
normalize={(value) => value.trim()}
|
||||||
|
tooltip="仓库需要拉取的文件后缀,多个后缀空格分隔"
|
||||||
|
>
|
||||||
|
<Input placeholder="请输入文件后缀" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="sub_before"
|
||||||
|
label="sub_before"
|
||||||
|
normalize={(value) => value.trim()}
|
||||||
|
tooltip="仓库需要拉取的文件后缀,多个后缀空格分隔"
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={4}
|
||||||
|
autoSize={true}
|
||||||
|
placeholder="请输入拉取仓库前要执行的命令"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
name="sub_after"
|
||||||
|
label="sub_after"
|
||||||
|
normalize={(value) => value.trim()}
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={4}
|
||||||
|
autoSize={true}
|
||||||
|
placeholder="请输入拉取仓库后要执行的命令"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Form>
|
</Form>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user