mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 14:56:07 +08:00
完善拉取私有仓库
This commit is contained in:
parent
1695b8c0fe
commit
7caabe9063
|
@ -28,17 +28,16 @@ export default (app: Router) => {
|
||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
type: Joi.string().required(),
|
type: Joi.string().required(),
|
||||||
schedule: Joi.string().optional(),
|
schedule: Joi.string().optional().allow('').allow(null),
|
||||||
interval_schedule: Joi.object().optional(),
|
interval_schedule: Joi.object().optional().allow('').allow(null),
|
||||||
name: Joi.string().optional(),
|
name: Joi.string().optional().allow('').allow(null),
|
||||||
url: Joi.string().required(),
|
url: Joi.string().required(),
|
||||||
whitelist: Joi.string().optional(),
|
whitelist: Joi.string().optional().allow('').allow(null),
|
||||||
blacklist: Joi.string().optional(),
|
blacklist: Joi.string().optional().allow('').allow(null),
|
||||||
branch: Joi.string().optional(),
|
branch: Joi.string().optional().allow('').allow(null),
|
||||||
dependences: Joi.string().optional(),
|
dependences: Joi.string().optional().allow('').allow(null),
|
||||||
status: Joi.number().optional(),
|
pull_type: Joi.string().optional().allow('').allow(null),
|
||||||
pull_type: Joi.string().optional(),
|
pull_option: Joi.object().optional().allow('').allow(null),
|
||||||
pull_option: Joi.object().optional(),
|
|
||||||
schedule_type: Joi.string().required(),
|
schedule_type: Joi.string().required(),
|
||||||
alias: Joi.string().required(),
|
alias: Joi.string().required(),
|
||||||
}),
|
}),
|
||||||
|
@ -157,18 +156,17 @@ export default (app: Router) => {
|
||||||
celebrate({
|
celebrate({
|
||||||
body: Joi.object({
|
body: Joi.object({
|
||||||
type: Joi.string().required(),
|
type: Joi.string().required(),
|
||||||
schedule: Joi.string().optional(),
|
schedule: Joi.string().optional().allow('').allow(null),
|
||||||
interval_schedule: Joi.object().optional(),
|
interval_schedule: Joi.object().optional().allow('').allow(null),
|
||||||
name: Joi.string().optional(),
|
name: Joi.string().optional().allow('').allow(null),
|
||||||
url: Joi.string().required(),
|
url: Joi.string().required(),
|
||||||
whitelist: Joi.string().optional(),
|
whitelist: Joi.string().optional().allow('').allow(null),
|
||||||
blacklist: Joi.string().optional(),
|
blacklist: Joi.string().optional().allow('').allow(null),
|
||||||
branch: Joi.string().optional(),
|
branch: Joi.string().optional().allow('').allow(null),
|
||||||
dependences: Joi.string().optional(),
|
dependences: Joi.string().optional().allow('').allow(null),
|
||||||
status: Joi.number().optional(),
|
pull_type: Joi.string().optional().allow('').allow(null),
|
||||||
pull_type: Joi.string().optional(),
|
pull_option: Joi.object().optional().allow('').allow(null),
|
||||||
pull_option: Joi.object().optional(),
|
schedule_type: Joi.string().optional().allow('').allow(null),
|
||||||
schedule_type: Joi.string().optional(),
|
|
||||||
alias: Joi.string().required(),
|
alias: Joi.string().required(),
|
||||||
id: Joi.number().required(),
|
id: Joi.number().required(),
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -13,6 +13,7 @@ import UserService from '../services/user';
|
||||||
import handler from 'serve-handler';
|
import handler from 'serve-handler';
|
||||||
import * as Sentry from '@sentry/node';
|
import * as Sentry from '@sentry/node';
|
||||||
import { EnvModel } from '../data/env';
|
import { EnvModel } from '../data/env';
|
||||||
|
import { errors } from 'celebrate';
|
||||||
|
|
||||||
export default ({ app }: { app: Application }) => {
|
export default ({ app }: { app: Application }) => {
|
||||||
app.enable('trust proxy');
|
app.enable('trust proxy');
|
||||||
|
@ -134,6 +135,7 @@ export default ({ app }: { app: Application }) => {
|
||||||
next(err);
|
next(err);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.use(errors());
|
||||||
app.use(Sentry.Handlers.errorHandler());
|
app.use(Sentry.Handlers.errorHandler());
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import os from 'os';
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
import Logger from './logger';
|
import Logger from './logger';
|
||||||
import { fileExist } from '../config/util';
|
import { fileExist } from '../config/util';
|
||||||
|
@ -15,6 +16,8 @@ const confFile = path.join(configPath, 'config.sh');
|
||||||
const authConfigFile = path.join(configPath, 'auth.json');
|
const authConfigFile = path.join(configPath, 'auth.json');
|
||||||
const sampleConfigFile = path.join(samplePath, 'config.sample.sh');
|
const sampleConfigFile = path.join(samplePath, 'config.sample.sh');
|
||||||
const sampleAuthFile = path.join(samplePath, 'auth.sample.json');
|
const sampleAuthFile = path.join(samplePath, 'auth.sample.json');
|
||||||
|
const homedir = os.homedir();
|
||||||
|
const sshPath = path.resolve(homedir, '.ssh');
|
||||||
|
|
||||||
export default async () => {
|
export default async () => {
|
||||||
const authFileExist = await fileExist(authConfigFile);
|
const authFileExist = await fileExist(authConfigFile);
|
||||||
|
@ -23,6 +26,7 @@ export default async () => {
|
||||||
const logDirExist = await fileExist(logPath);
|
const logDirExist = await fileExist(logPath);
|
||||||
const configDirExist = await fileExist(configPath);
|
const configDirExist = await fileExist(configPath);
|
||||||
const uploadDirExist = await fileExist(uploadPath);
|
const uploadDirExist = await fileExist(uploadPath);
|
||||||
|
const sshDirExist = await fileExist(sshPath);
|
||||||
|
|
||||||
if (!configDirExist) {
|
if (!configDirExist) {
|
||||||
fs.mkdirSync(configPath);
|
fs.mkdirSync(configPath);
|
||||||
|
@ -48,6 +52,10 @@ export default async () => {
|
||||||
fs.mkdirSync(uploadPath);
|
fs.mkdirSync(uploadPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!sshDirExist) {
|
||||||
|
fs.mkdirSync(sshPath);
|
||||||
|
}
|
||||||
|
|
||||||
dotenv.config({ path: confFile });
|
dotenv.config({ path: confFile });
|
||||||
|
|
||||||
Logger.info('✌️ Init file down');
|
Logger.info('✌️ Init file down');
|
||||||
|
|
|
@ -27,6 +27,7 @@ import path from 'path';
|
||||||
import ScheduleService, { TaskCallbacks } from './schedule';
|
import ScheduleService, { TaskCallbacks } from './schedule';
|
||||||
import { SimpleIntervalSchedule } from 'toad-scheduler';
|
import { SimpleIntervalSchedule } from 'toad-scheduler';
|
||||||
import SockService from './sock';
|
import SockService from './sock';
|
||||||
|
import SshKeyService from './sshKey';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class SubscriptionService {
|
export default class SubscriptionService {
|
||||||
|
@ -34,6 +35,7 @@ export default class SubscriptionService {
|
||||||
@Inject('logger') private logger: winston.Logger,
|
@Inject('logger') private logger: winston.Logger,
|
||||||
private scheduleService: ScheduleService,
|
private scheduleService: ScheduleService,
|
||||||
private sockService: SockService,
|
private sockService: SockService,
|
||||||
|
private sshKeyService: SshKeyService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public async list(searchText?: string): Promise<Subscription[]> {
|
public async list(searchText?: string): Promise<Subscription[]> {
|
||||||
|
@ -92,21 +94,44 @@ export default class SubscriptionService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private formatCommand(doc: Subscription) {
|
private formatCommand(doc: Subscription, url?: string) {
|
||||||
let command = 'ql ';
|
let command = 'ql ';
|
||||||
const { type, url, whitelist, blacklist, dependences, branch } = doc;
|
let _url = url || doc.url;
|
||||||
|
const { type, whitelist, blacklist, dependences, branch } = 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 || ''}"`;
|
||||||
}
|
}
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleTask(doc: Subscription, needCreate = true) {
|
private handleTask(doc: Subscription, needCreate = true, needAddKey = true) {
|
||||||
doc.command = this.formatCommand(doc);
|
let url = doc.url;
|
||||||
|
if (doc.type === 'private-repo') {
|
||||||
|
if (doc.pull_type === 'ssh-key') {
|
||||||
|
const host = doc.url!.replace(/.*\@([^\:]+)\:.*/, '$1');
|
||||||
|
url = doc.url!.replace(host, doc.alias);
|
||||||
|
if (needAddKey) {
|
||||||
|
this.sshKeyService.addSSHKey(
|
||||||
|
(doc.pull_option as any).private_key,
|
||||||
|
doc.alias,
|
||||||
|
host,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.sshKeyService.removeSSHKey(doc.alias, host);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const host = doc.url!.replace(/.*\:\/\/([^\/]+)\/.*/, '$1');
|
||||||
|
const { username, password } = doc.pull_option as any;
|
||||||
|
url = doc.url!.replace(host, `${username}:${password}@${host}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.command = this.formatCommand(doc, url as string);
|
||||||
|
|
||||||
if (doc.schedule_type === 'crontab') {
|
if (doc.schedule_type === 'crontab') {
|
||||||
this.scheduleService.cancelCronTask(doc as any);
|
this.scheduleService.cancelCronTask(doc as any);
|
||||||
needCreate &&
|
needCreate &&
|
||||||
|
@ -191,7 +216,6 @@ export default class SubscriptionService {
|
||||||
|
|
||||||
public async create(payload: Subscription): Promise<Subscription> {
|
public async create(payload: Subscription): Promise<Subscription> {
|
||||||
const tab = new Subscription(payload);
|
const tab = new Subscription(payload);
|
||||||
console.log(tab);
|
|
||||||
const doc = await this.insert(tab);
|
const doc = await this.insert(tab);
|
||||||
this.handleTask(doc);
|
this.handleTask(doc);
|
||||||
return doc;
|
return doc;
|
||||||
|
@ -246,7 +270,7 @@ export default class SubscriptionService {
|
||||||
public async remove(ids: number[]) {
|
public async remove(ids: number[]) {
|
||||||
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
const docs = await SubscriptionModel.findAll({ where: { id: ids } });
|
||||||
for (const doc of docs) {
|
for (const doc of docs) {
|
||||||
this.handleTask(doc, false);
|
this.handleTask(doc, false, false);
|
||||||
}
|
}
|
||||||
await SubscriptionModel.destroy({ where: { id: ids } });
|
await SubscriptionModel.destroy({ where: { id: ids } });
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,12 @@ export enum IntervalSchedule {
|
||||||
'seconds' = '秒',
|
'seconds' = '秒',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum SubscriptionType {
|
||||||
|
'private-repo' = '私有仓库',
|
||||||
|
'public-repo' = '公开仓库',
|
||||||
|
'file' = '单文件',
|
||||||
|
}
|
||||||
|
|
||||||
const Subscription = ({ headerStyle, isPhone, socketMessage }: any) => {
|
const Subscription = ({ headerStyle, isPhone, socketMessage }: any) => {
|
||||||
const columns: any = [
|
const columns: any = [
|
||||||
{
|
{
|
||||||
|
@ -88,6 +94,16 @@ const Subscription = ({ headerStyle, isPhone, socketMessage }: any) => {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
width: 130,
|
||||||
|
align: 'center' as const,
|
||||||
|
render: (text: string, record: any) => {
|
||||||
|
return (SubscriptionType as any)[record.type];
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: '分支',
|
title: '分支',
|
||||||
dataIndex: 'branch',
|
dataIndex: 'branch',
|
||||||
|
|
|
@ -56,7 +56,9 @@ const SubscriptionModal = ({
|
||||||
form.setFieldsValue({
|
form.setFieldsValue({
|
||||||
alias: formatAlias(_url, _branch, e.target.value),
|
alias: formatAlias(_url, _branch, e.target.value),
|
||||||
});
|
});
|
||||||
form.validateFields(['url']);
|
if (_url) {
|
||||||
|
form.validateFields(['url']);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const scheduleTypeChange = (e) => {
|
const scheduleTypeChange = (e) => {
|
||||||
|
@ -149,16 +151,28 @@ const SubscriptionModal = ({
|
||||||
onChange?: (param: any) => void;
|
onChange?: (param: any) => void;
|
||||||
}) => {
|
}) => {
|
||||||
return type === 'ssh-key' ? (
|
return type === 'ssh-key' ? (
|
||||||
<Form.Item name="private_key" label="私钥" rules={[{ required: true }]}>
|
<Form.Item
|
||||||
<Input.TextArea rows={4} autoSize={true} placeholder="请输入私钥" />
|
name={['pull_option', 'private_key']}
|
||||||
|
label="私钥"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={4}
|
||||||
|
autoSize={{ minRows: 1, maxRows: 6 }}
|
||||||
|
placeholder="请输入私钥"
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Form.Item name="username" label="用户名" rules={[{ required: true }]}>
|
<Form.Item
|
||||||
|
name={['pull_option', 'username']}
|
||||||
|
label="用户名"
|
||||||
|
rules={[{ required: true }]}
|
||||||
|
>
|
||||||
<Input placeholder="请输入认证用户名" />
|
<Input placeholder="请输入认证用户名" />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
<Form.Item
|
||||||
name="password"
|
name={['pull_option', 'password']}
|
||||||
tooltip="Github已不支持密码认证,请使用Token方式"
|
tooltip="Github已不支持密码认证,请使用Token方式"
|
||||||
label="密码/Token"
|
label="密码/Token"
|
||||||
rules={[{ required: true }]}
|
rules={[{ required: true }]}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user