Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"slash": "^3.0.0",
"winston": "^3.3.3",
"xml-js": "^1.6.11",
"yargs": "^16.2.0"
"yargs": "^16.2.0",
"zod": "^3.21.4"
}
}
5 changes: 5 additions & 0 deletions sample/config/dryrun.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module.exports = {
dryRun: true,
buildLogFile: ['dotnetbuild;./sample/dotnetbuild/build.content;/repo/src'],
output: './tmp/out.json',
};
5 changes: 0 additions & 5 deletions sample/config/dryrun.json

This file was deleted.

8 changes: 8 additions & 0 deletions sample/config/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
vcs: 'github',
githubRepoUrl: 'https://github.com/codeleague/codecoach.git',
githubPr: 42,
githubToken: 'mockGitHubToken',
buildLogFile: ['dotnetbuild;./sample/dotnetbuild/build.content;/repo/src'],
output: './tmp/out.json',
};
8 changes: 0 additions & 8 deletions sample/config/github.json

This file was deleted.

10 changes: 10 additions & 0 deletions sample/config/gitlab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
vcs: 'gitlab',
gitlabHost: 'https://gitlab.myawesomecompany.com',
gitlabProjectId: 1234,
gitlabMrIid: 69,
gitlabToken: 'mockGitLabToken',
buildLogFile: ['dotnetbuild;./sample/dotnetbuild/build.content;/repo/src'],
output: './tmp/out.json',
removeOldComment: true,
};
10 changes: 0 additions & 10 deletions sample/config/gitlab.json

This file was deleted.

19 changes: 3 additions & 16 deletions src/Config/@types/configArgument.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,4 @@
import { BuildLogFile } from './buildLogFile';
import { z } from 'zod';
import { configSchema } from '../Config';

export type ConfigArgument = {
vcs: 'gitlab' | 'github';
githubRepoUrl: string;
githubPr: number;
githubToken: string;
gitlabHost: string;
gitlabProjectId: number;
gitlabMrIid: number;
gitlabToken: string;
buildLogFile: BuildLogFile[];
output: string; // =logFilePath
removeOldComment: boolean;
failOnWarnings: boolean;
dryRun: boolean;
};
export type ConfigArgument = z.infer<typeof configSchema>;
20 changes: 10 additions & 10 deletions src/Config/Config.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BuildLogFile } from './@types';
import { BuildLogFile, ConfigArgument } from './@types';

const mockGitHubRepo = 'https://github.com/codeleague/codecoach.git';
const mockGitHubPr = 42;
Expand Down Expand Up @@ -27,7 +27,7 @@ const GITHUB_ENV_ARGS = [
`-o=${mockOutput}`,
];

const GITHUB_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/github.json'];
const GITHUB_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/github.js'];

const GITLAB_ENV_ARGS = [
'node',
Expand All @@ -42,7 +42,7 @@ const GITLAB_ENV_ARGS = [
'--failOnWarnings',
];

const GITLAB_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/gitlab.json'];
const GITLAB_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/gitlab.js'];

const DRYRUN_ENV_ARGS = [
'node',
Expand All @@ -52,7 +52,7 @@ const DRYRUN_ENV_ARGS = [
'--dryRun',
];

const DRYRUN_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/dryrun.json'];
const DRYRUN_FILE_ARGS = ['node', 'app.ts', '--config=sample/config/dryrun.js'];

describe('Config parsing Test', () => {
beforeEach(() => {
Expand All @@ -68,7 +68,7 @@ describe('Config parsing Test', () => {

it('should be able to parse GitHub config provided by environment variables', async () => {
process.argv = GITHUB_ENV_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.vcs).toBe('github');
expect(config.githubRepoUrl).toBe(mockGitHubRepo);
expect(config.githubPr).toBe(mockGitHubPr);
Expand All @@ -81,7 +81,7 @@ describe('Config parsing Test', () => {

it('should be able to parse GitHub config provided by file', async () => {
process.argv = GITHUB_FILE_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.vcs).toBe('github');
expect(config.githubRepoUrl).toBe(mockGitHubRepo);
expect(config.githubPr).toBe(mockGitHubPr);
Expand All @@ -94,7 +94,7 @@ describe('Config parsing Test', () => {

it('should be able to parse GitLab config provided by environment variables', async () => {
process.argv = GITLAB_ENV_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.vcs).toBe('gitlab');
expect(config.gitlabHost).toBe(mockGitLabHost);
expect(config.gitlabProjectId).toBe(mockGitLabProjectId);
Expand All @@ -108,7 +108,7 @@ describe('Config parsing Test', () => {

it('should be able to parse GitLab config provided by file', async () => {
process.argv = GITLAB_FILE_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.vcs).toBe('gitlab');
expect(config.gitlabHost).toBe(mockGitLabHost);
expect(config.gitlabProjectId).toBe(mockGitLabProjectId);
Expand All @@ -122,15 +122,15 @@ describe('Config parsing Test', () => {

it('should be able to parse dryRun config provided by environment variables', async () => {
process.argv = DRYRUN_ENV_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.dryRun).toBe(true);

validateBuildLog(config.buildLogFile);
});

it('should be able to parse dryRun config provided by file', async () => {
process.argv = DRYRUN_FILE_ARGS;
const config = (await import('./Config')).configs;
const config = (await import('./Config')).configs as ConfigArgument;
expect(config.dryRun).toBe(true);

validateBuildLog(config.buildLogFile);
Expand Down
118 changes: 76 additions & 42 deletions src/Config/Config.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,74 @@
import yargs from 'yargs';
import { ProjectType } from './@enums';
import { BuildLogFile, ConfigArgument } from './@types';
import { BuildLogFile } from './@types';
import { DEFAULT_OUTPUT_FILE } from './constants/defaults';
import { GITHUB_ARGS, GITLAB_ARGS } from './constants/required';
import fs from 'fs';
import { z } from 'zod';

const projectTypes = Object.keys(ProjectType);

const args = yargs
.config('config', (configPath) => JSON.parse(fs.readFileSync(configPath, 'utf-8')))
export const configSchema = z
.object({
vcs: z.enum(['github', 'gitlab']).optional().describe('VCS Type'),

githubRepoUrl: z.string().optional(),
githubPr: z.number().optional(),
githubToken: z.string().optional(),

gitlabHost: z.string().optional(),
gitlabProjectId: z.number().optional(),
gitlabMrIid: z.number().optional(),
gitlabToken: z.string().optional(),

buildLogFile: z.array(z.string()).transform((files) => {
return files
.map((opt) => {
const [type, path, cwd] = opt.split(';');
if (!projectTypes.includes(type) || !path) return null;
return { type, path, cwd: cwd ?? process.cwd() } as BuildLogFile;
})
.filter((file) => file !== null) as BuildLogFile[];
}),
output: z.string().default(DEFAULT_OUTPUT_FILE),
removeOldComment: z.boolean().default(false),
failOnWarnings: z.boolean().default(false),
dryRun: z.boolean().default(false),
})
.superRefine((options, ctx) => {
if (!options.vcs && !options.dryRun) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: 'VCS type is required',
});
}
})
.superRefine((options, ctx) => {
if (options.vcs === 'github' && GITHUB_ARGS.some((arg) => !options[arg])) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `GitHub requires [${GITHUB_ARGS.map((a) => `--${a}`).join(
', ',
)}] to be set`,
});
}

if (options.vcs === 'gitlab' && GITLAB_ARGS.some((arg) => !options[arg])) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: `GitLab requires [${GITLAB_ARGS.map((a) => `--${a}`).join(
', ',
)}] to be set`,
});
}
});

export const args = yargs
.config('config', (file) => {
console.log(`Loading config from ${file}`);
// eslint-disable-next-line @typescript-eslint/no-var-requires
const config = require(file);
return config;
})
.option('vcs', {
alias: 'g',
describe: 'VCS Type',
Expand Down Expand Up @@ -44,19 +104,6 @@ const args = yargs
describe: 'GitLab token',
type: 'string',
})
.group(['vcs', 'buildLogFile', 'output', 'removeOldComment'], 'Parsing options:')
.group(GITLAB_ARGS, 'GitLab options:')
.group(GITHUB_ARGS, 'GitHub options:')
.check((options) => {
// validate VCS configs
if (options.vcs === 'github' && GITHUB_ARGS.some((arg) => !options[arg]))
throw `GitHub requires [${GITHUB_ARGS.map((a) => `--${a}`).join(', ')}] to be set`;

if (options.vcs === 'gitlab' && GITLAB_ARGS.some((arg) => !options[arg]))
throw `GitLab requires [${GITLAB_ARGS.map((a) => `--${a}`).join(', ')}] to be set`;

return true;
})
.option('buildLogFile', {
alias: 'f',
describe: `Build log content files formatted in '<type>;<path>[;<cwd>]'
Expand All @@ -68,24 +115,6 @@ and <cwd> is build root directory (optional (Will use current context as cwd)).
string: true,
number: false,
})
.coerce('buildLogFile', (files: string[]) => {
return files.map((opt) => {
const [type, path, cwd] = opt.split(';');
if (!projectTypes.includes(type) || !path) return null;
return { type, path, cwd: cwd ?? process.cwd() } as BuildLogFile;
});
})
.check((options) => {
// check arguments parsing
const useConfigArgs = options.config !== undefined;
if (useConfigArgs) return true;

// if (!options.pr || Array.isArray(options.pr))
// throw '--pr config should be a single number';
if (!options.buildLogFile || options.buildLogFile.some((file) => file === null))
throw 'all of `--buildLogFile` options should have correct format';
return true;
})
.option('output', {
alias: 'o',
describe: 'Output parsed log file',
Expand All @@ -108,14 +137,19 @@ and <cwd> is build root directory (optional (Will use current context as cwd)).
type: 'boolean',
default: false,
})
.check((options) => {
if (options.dryRun) return true;
if (typeof options.vcs === 'undefined') throw 'VCS type is required';
return true;
})
.strict()
.help()
.wrap(120)
.parse(process.argv.slice(1)) as ConfigArgument;
.parse(process.argv.slice(1));

const getConfigs = () => {
const result = configSchema.safeParse(args);
if (!result.success) {
const firstIssue = result.error.issues[0];
console.log(`${firstIssue.message} ${firstIssue.path.join('.')}`);
process.exit(1);
}
return result.data;
};

export const configs = args;
export const configs = getConfigs();
13 changes: 5 additions & 8 deletions src/Provider/GitLab/GitLabMRService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,17 @@ import {
import * as Resource from '@gitbeaker/core/dist/types/resources';
import { Gitlab } from '@gitbeaker/node';

import { configs } from '../../Config';

export class GitLabMRService implements IGitLabMRService {
private readonly projectId: number;
private readonly mrIid: number;
private readonly api: Resource.Gitlab;

constructor() {
this.projectId = configs.gitlabProjectId;
this.mrIid = configs.gitlabMrIid;

constructor(token: string, host: string, projectId: number, mrIid: number) {
this.projectId = projectId;
this.mrIid = mrIid;
this.api = new Gitlab({
host: configs.gitlabHost,
token: configs.gitlabToken,
host: host,
token: token,
});
}

Expand Down
Loading