Files
fennec-be/src/repos/repos.service.ts

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}`),
);
}
}