feat: 为 pipeline 添加运行环境,并用于配置文件的发布。
This commit is contained in:
parent
3ba8fc9759
commit
6b9f846154
1
.eslintcache
Normal file
1
.eslintcache
Normal file
File diff suppressed because one or more lines are too long
6
package-lock.json
generated
6
package-lock.json
generated
@ -76,7 +76,7 @@
|
||||
}
|
||||
},
|
||||
"../configuration": {
|
||||
"version": "1.0.0",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"debug": "^4.3.2",
|
||||
@ -90,7 +90,7 @@
|
||||
"@types/node": "^14.17.17",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.4.3"
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@angular-devkit/core": {
|
||||
@ -23187,7 +23187,7 @@
|
||||
"js-yaml": "^4.1.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"ts-node": "^10.2.1",
|
||||
"typescript": "^4.4.3"
|
||||
"typescript": "^4.4.4"
|
||||
}
|
||||
},
|
||||
"consola": {
|
||||
|
@ -65,7 +65,7 @@ import { ConfigurationsModule } from './configurations/configurations.module';
|
||||
playground: true,
|
||||
autoSchemaFile: true,
|
||||
installSubscriptionHandlers: true,
|
||||
context: ({ req, connection, ...args }) => {
|
||||
context: ({ req, connection }) => {
|
||||
return connection ? { req: connection.context } : { req };
|
||||
},
|
||||
subscriptions: {
|
||||
|
@ -13,9 +13,9 @@ export class ApplicationException extends Error {
|
||||
this.error = message.error;
|
||||
this.message = message.message as any;
|
||||
} else if (typeof message === 'string') {
|
||||
super((message as unknown) as any);
|
||||
super(message as unknown as any);
|
||||
} else {
|
||||
super((message as unknown) as any);
|
||||
super(message as unknown as any);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,12 +19,16 @@ export class HttpExceptionFilter implements ExceptionFilter {
|
||||
case 'graphql': {
|
||||
const errorName = exception.message;
|
||||
const extensions: Record<string, any> = {};
|
||||
const err = exception.getResponse();
|
||||
const err = exception.getResponse() as any;
|
||||
if (typeof err === 'string') {
|
||||
extensions.message = err;
|
||||
} else {
|
||||
Object.assign(extensions, (err as any).extension);
|
||||
extensions.message = (err as any).message;
|
||||
Object.assign(extensions, err.extension);
|
||||
if (typeof err.message === 'string') {
|
||||
extensions.message = err.message;
|
||||
} else {
|
||||
extensions.message = err.error;
|
||||
}
|
||||
}
|
||||
extensions.error = errorName;
|
||||
this.logger.error(extensions);
|
||||
|
@ -126,6 +126,7 @@ export class BaseDbService<Entity extends AppBaseEntity> extends TypeormHelper {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
async canYouRemoveWithIds(ids: string[]): Promise<void> {
|
||||
return;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { JwtService } from '@nestjs-lib/auth';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ConfigurationsResolver } from './configurations.resolver';
|
||||
import { ConfigurationsService } from './configurations.service';
|
||||
@ -8,10 +9,15 @@ describe('ConfigurationsResolver', () => {
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
ConfigurationsResolver,
|
||||
{
|
||||
provide: ConfigurationsService,
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: JwtService,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { ConfigurationsService } from './configurations.service';
|
||||
import { Configuration } from './entities/configuration.entity';
|
||||
import { IsNull } from 'typeorm';
|
||||
import { Etcd3 } from 'etcd3';
|
||||
|
||||
describe('ConfigurationsService', () => {
|
||||
let service: ConfigurationsService;
|
||||
@ -15,6 +16,10 @@ describe('ConfigurationsService', () => {
|
||||
provide: getRepositoryToken(Configuration),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: Etcd3,
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
}).compile();
|
||||
|
||||
@ -28,7 +33,7 @@ describe('ConfigurationsService', () => {
|
||||
describe('findOneByConditions', () => {
|
||||
it('should select by projectId only', async () => {
|
||||
const entity = new Configuration();
|
||||
const findOne = jest.fn((_) => Promise.resolve(entity));
|
||||
const findOne = jest.fn<any, [any]>(() => Promise.resolve(entity));
|
||||
service['repository'].findOne = findOne;
|
||||
|
||||
await expect(
|
||||
|
@ -26,7 +26,7 @@ export class ConfigurationsService extends BaseDbService<Configuration> {
|
||||
entity = this.repository.create(dto);
|
||||
}
|
||||
entity = await this.repository.save(entity);
|
||||
this.etcd.put(`share/config/${entity.id}`).value(entity.content);
|
||||
await this.syncToEtcd(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@ -36,4 +36,20 @@ export class ConfigurationsService extends BaseDbService<Configuration> {
|
||||
}
|
||||
return await this.repository.findOne(dto);
|
||||
}
|
||||
|
||||
async syncToEtcd({ pipelineId, id }: { pipelineId?: string; id?: string }) {
|
||||
const config = await this.repository.findOneOrFail({
|
||||
where: { pipelineId, id },
|
||||
relations: ['pipeline', 'project'],
|
||||
});
|
||||
|
||||
await this.etcd
|
||||
.put(`share/config/${config.id}`)
|
||||
.value(config.content)
|
||||
.exec();
|
||||
await this.etcd
|
||||
.put(`share/config/${config.pipeline.environment}/${config.project.name}`)
|
||||
.value(config.content)
|
||||
.exec();
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
import { InputType } from '@nestjs/graphql';
|
||||
import { PipelineUnits } from '../enums/pipeline-units.enum';
|
||||
|
||||
@InputType()
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Field, InputType, Int, ObjectType } from '@nestjs/graphql';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsInstance, isInstance, ValidateNested } from 'class-validator';
|
||||
import { IsInstance, ValidateNested } from 'class-validator';
|
||||
import { WorkUnit } from './work-unit.model';
|
||||
|
||||
@InputType('WorkUnitMetadataInput')
|
||||
|
@ -35,15 +35,6 @@ export class PipelineTasksResolver {
|
||||
);
|
||||
}
|
||||
|
||||
@Subscription(() => PipelineTask, {
|
||||
resolve: (value) => {
|
||||
return value;
|
||||
},
|
||||
})
|
||||
async pipelineTaskChanged(@Args('id') id: string) {
|
||||
// return await this.service.watchTaskUpdated(id);
|
||||
}
|
||||
|
||||
@Query(() => [PipelineTask])
|
||||
async listPipelineTaskByPipelineId(@Args('pipelineId') pipelineId: string) {
|
||||
return await this.service.listTasksByPipelineId(pipelineId);
|
||||
|
@ -12,7 +12,6 @@ describe('PipelineTasksService', () => {
|
||||
let service: PipelineTasksService;
|
||||
let module: TestingModule;
|
||||
let taskRepository: Repository<PipelineTask>;
|
||||
let pipelineRepository: Repository<Pipeline>;
|
||||
|
||||
beforeEach(async () => {
|
||||
module = await Test.createTestingModule({
|
||||
@ -43,7 +42,6 @@ describe('PipelineTasksService', () => {
|
||||
|
||||
service = module.get<PipelineTasksService>(PipelineTasksService);
|
||||
taskRepository = module.get(getRepositoryToken(PipelineTask));
|
||||
pipelineRepository = module.get(getRepositoryToken(Pipeline));
|
||||
jest
|
||||
.spyOn(taskRepository, 'save')
|
||||
.mockImplementation(async (data: any) => data);
|
||||
|
@ -4,7 +4,6 @@ import { PipelineTask } from './pipeline-task.entity';
|
||||
import { Repository } from 'typeorm';
|
||||
import { CreatePipelineTaskInput } from './dtos/create-pipeline-task.input';
|
||||
import { Pipeline } from '../pipelines/pipeline.entity';
|
||||
import debug from 'debug';
|
||||
import { AmqpConnection, RabbitRPC } from '@golevelup/nestjs-rabbitmq';
|
||||
import {
|
||||
EXCHANGE_PIPELINE_TASK_TOPIC,
|
||||
@ -19,8 +18,6 @@ import { InjectPinoLogger, PinoLogger } from 'nestjs-pino';
|
||||
import { getAppInstanceRouteKey } from '../commons/utils/rabbit-mq';
|
||||
import { ROUTE_PIPELINE_TASK_KILL } from './pipeline-tasks.constants';
|
||||
|
||||
const log = debug('fennec:pipeline-tasks:service');
|
||||
|
||||
@Injectable()
|
||||
export class PipelineTasksService {
|
||||
constructor(
|
||||
|
@ -28,4 +28,8 @@ export class CreatePipelineInput {
|
||||
@ValidateNested()
|
||||
@IsInstance(WorkUnitMetadata)
|
||||
workUnitMetadata: WorkUnitMetadata;
|
||||
|
||||
@IsString()
|
||||
@MaxLength(100)
|
||||
environment: string;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ export class Pipeline extends AppBaseEntity {
|
||||
@Column()
|
||||
projectId: string;
|
||||
|
||||
@Column({ comment: 'eg: remotes/origin/master' })
|
||||
@Column({ comment: 'E.g., remotes/origin/master' })
|
||||
branch: string;
|
||||
|
||||
@Column()
|
||||
@ -20,4 +20,7 @@ export class Pipeline extends AppBaseEntity {
|
||||
|
||||
@Column({ type: 'jsonb' })
|
||||
workUnitMetadata: WorkUnitMetadata;
|
||||
|
||||
@Column()
|
||||
environment: string;
|
||||
}
|
||||
|
@ -2,13 +2,11 @@ import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { PipelinesService } from './pipelines.service';
|
||||
import { Pipeline } from './pipeline.entity';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Project } from '../projects/project.entity';
|
||||
import { AmqpConnection } from '@golevelup/nestjs-rabbitmq';
|
||||
|
||||
describe('PipelinesService', () => {
|
||||
let service: PipelinesService;
|
||||
let repository: Repository<Pipeline>;
|
||||
let pipeline: Pipeline;
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -40,7 +38,6 @@ describe('PipelinesService', () => {
|
||||
}).compile();
|
||||
|
||||
service = module.get<PipelinesService>(PipelinesService);
|
||||
repository = module.get(getRepositoryToken(Pipeline));
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
|
@ -19,7 +19,9 @@ import { plainToClass } from 'class-transformer';
|
||||
|
||||
@Injectable()
|
||||
export class PipelinesService extends BaseDbService<Pipeline> {
|
||||
readonly uniqueFields: Array<Array<keyof Pipeline>> = [['projectId', 'name']];
|
||||
readonly uniqueFields: Array<Array<keyof Pipeline>> = [
|
||||
['projectId', 'name', 'environment'],
|
||||
];
|
||||
constructor(
|
||||
@InjectRepository(Pipeline)
|
||||
readonly repository: Repository<Pipeline>,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { ObjectType } from '@nestjs/graphql';
|
||||
import { Entity, Column, DeleteDateColumn } from 'typeorm';
|
||||
import { Entity, Column } from 'typeorm';
|
||||
import { AppBaseEntity } from '../commons/entities/app-base-entity';
|
||||
|
||||
@ObjectType()
|
||||
|
@ -1,10 +1,5 @@
|
||||
import { ObjectType, Field } from '@nestjs/graphql';
|
||||
import {
|
||||
LogResult,
|
||||
DefaultLogFields,
|
||||
BranchSummary,
|
||||
BranchSummaryBranch,
|
||||
} from 'simple-git';
|
||||
import { BranchSummaryBranch } from 'simple-git';
|
||||
|
||||
@ObjectType()
|
||||
export class Branch implements BranchSummaryBranch {
|
||||
|
@ -161,7 +161,7 @@ describe('ReposService', () => {
|
||||
const project = new Project();
|
||||
const pipeline = new Pipeline();
|
||||
pipeline.branch = 'test';
|
||||
const fetch = jest.fn((_: any) => Promise.resolve());
|
||||
const fetch = jest.fn<any, [any]>(() => Promise.resolve());
|
||||
pipeline.project = project;
|
||||
const getGit = jest.spyOn(service, 'getGit').mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
@ -182,7 +182,7 @@ describe('ReposService', () => {
|
||||
const project = new Project();
|
||||
const pipeline = new Pipeline();
|
||||
pipeline.branch = 'test';
|
||||
const fetch = jest.fn((_: any) => Promise.resolve());
|
||||
const fetch = jest.fn<any, [any]>(() => Promise.resolve());
|
||||
pipeline.project = project;
|
||||
const getGit = jest
|
||||
.spyOn(service, 'getGit')
|
||||
@ -196,7 +196,7 @@ describe('ReposService', () => {
|
||||
const project = new Project();
|
||||
const pipeline = new Pipeline();
|
||||
pipeline.branch = 'test';
|
||||
const fetch = jest.fn((_: any) => Promise.reject('error'));
|
||||
const fetch = jest.fn<any, [any]>(() => Promise.reject('error'));
|
||||
pipeline.project = project;
|
||||
const getGit = jest.spyOn(service, 'getGit').mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { MiddlewareConsumer, Module } from '@nestjs/common';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { PipelineTasksModule } from '../pipeline-tasks/pipeline-tasks.module';
|
||||
import { GiteaWebhooksController } from './gitea-webhooks.controller';
|
||||
@ -10,5 +10,4 @@ import { WebhooksService } from './webhooks.service';
|
||||
controllers: [GiteaWebhooksController],
|
||||
providers: [WebhooksService],
|
||||
})
|
||||
export class WebhooksModule {
|
||||
}
|
||||
export class WebhooksModule {}
|
||||
|
Loading…
Reference in New Issue
Block a user