95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
import { Pipeline } from './../pipelines/pipeline.entity';
|
|
import { PipelineTask } from './../pipeline-tasks/pipeline-task.entity';
|
|
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { F_OK } from 'constants';
|
|
import { access, mkdir } from 'fs/promises';
|
|
import { join } from 'path';
|
|
import { gitP } from 'simple-git';
|
|
import { Repository } from 'typeorm';
|
|
import { Project } from '../projects/project.entity';
|
|
import { ListBranchesArgs } from './dtos/list-branches.args';
|
|
import { ListLogsArgs } from './dtos/list-logs.args';
|
|
import { ConfigService } from '@nestjs/config';
|
|
|
|
const DEFAULT_REMOTE_NAME = 'origin';
|
|
const INFO_PATH = '@info';
|
|
@Injectable()
|
|
export class ReposService {
|
|
constructor(
|
|
@InjectRepository(Project)
|
|
private readonly projectRepository: Repository<Project>,
|
|
private readonly configService: ConfigService,
|
|
) {}
|
|
|
|
getWorkspaceRoot(project: Project): string {
|
|
return join(
|
|
this.configService.get<string>('workspaces.root'),
|
|
encodeURIComponent(project.name),
|
|
INFO_PATH,
|
|
);
|
|
}
|
|
|
|
async getGit(project: Project, workspaceRoot?: string) {
|
|
if (!workspaceRoot) {
|
|
workspaceRoot = this.getWorkspaceRoot(project);
|
|
}
|
|
|
|
await access(workspaceRoot, F_OK).catch(async () => {
|
|
await mkdir(workspaceRoot, { recursive: true });
|
|
});
|
|
const git = gitP(workspaceRoot);
|
|
if (!(await git.checkIsRepo())) {
|
|
await git.init();
|
|
await git.addRemote(DEFAULT_REMOTE_NAME, project.sshUrl);
|
|
}
|
|
await git.fetch();
|
|
return git;
|
|
}
|
|
|
|
async listLogs(dto: ListLogsArgs) {
|
|
const project = await this.projectRepository.findOneOrFail({
|
|
id: dto.projectId,
|
|
});
|
|
const git = await this.getGit(project);
|
|
return await git.log(
|
|
dto.branch ? ['--branches', dto.branch, '--'] : ['--all'],
|
|
);
|
|
}
|
|
|
|
async listBranches(dto: ListBranchesArgs) {
|
|
const project = await this.projectRepository.findOneOrFail({
|
|
id: dto.projectId,
|
|
});
|
|
const git = await this.getGit(project);
|
|
return git.branch();
|
|
}
|
|
|
|
async checkout(task: PipelineTask, workspaceRoot: string) {
|
|
const git = await this.getGit(task.pipeline.project, workspaceRoot);
|
|
try {
|
|
await git.fetch(DEFAULT_REMOTE_NAME);
|
|
} catch (err) {
|
|
if (err.message.includes("couldn't find remote ref nonexistent")) {
|
|
throw new NotFoundException(err.message);
|
|
}
|
|
throw err;
|
|
}
|
|
await git.checkout([task.commit]);
|
|
}
|
|
|
|
/**
|
|
* get workspace root absolute path
|
|
*
|
|
* ! example: `/var/tmp/fennec-workspaces-root/project/pipeline_name-commit_hash`
|
|
* @param task {PipelineTask} task (with pipeline and project info)
|
|
*/
|
|
getWorkspaceRootByTask(task: PipelineTask) {
|
|
return join(
|
|
this.configService.get<string>('workspaces.root'),
|
|
encodeURIComponent(task.pipeline.project.name),
|
|
encodeURIComponent(`${task.pipeline.name}-${task.commit}`),
|
|
);
|
|
}
|
|
}
|