forked from codeleague/codecoach
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 2444e99
Showing
78 changed files
with
7,277 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export interface Agent { | ||
buildAndGetLogFiles(): Promise<string[]>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { resolve } from 'path'; | ||
import { ChildProcess, spawn as baseSpawn } from 'child_process'; | ||
import { mocked } from 'ts-jest/utils'; | ||
|
||
import { AgentConfig } from '../Config/@types'; | ||
import { CSharpAgent, ErrorFile, WarningFile } from './CSharpAgent'; | ||
|
||
jest.mock('child_process'); | ||
|
||
const spawn = mocked(baseSpawn, true); | ||
|
||
describe('CSharpAgent', () => { | ||
const cwd = './tmp'; | ||
const agentLoader: AgentConfig = { | ||
execPath: 'test', | ||
target: 'test.sln', | ||
cwd, | ||
}; | ||
|
||
it('should create child process with arguments and return log files', async () => { | ||
const mockedResolveListener = jest.fn((e: string, cb: () => void) => { | ||
if (e === 'close') cb(); | ||
}); | ||
|
||
spawn.mockImplementation(() => { | ||
return ({ | ||
stdout: { once: jest.fn() }, | ||
on: mockedResolveListener, | ||
} as unknown) as ChildProcess; | ||
}); | ||
|
||
const agent = new CSharpAgent(agentLoader); | ||
|
||
const files = await agent.buildAndGetLogFiles(); | ||
|
||
const expectedWarningFile = resolve(cwd, WarningFile); | ||
const expectedErrorFile = resolve(cwd, ErrorFile); | ||
const expectedSolutionFile = resolve(cwd, agentLoader.target!); | ||
const expectedArgs = [ | ||
'build', | ||
'--nologo', | ||
'-p:ActiveRulesets="Coding Standards"', | ||
'-p:GenerateFullPaths=true', | ||
'--no-incremental', | ||
`-flp1:logfile=${expectedWarningFile};warningsonly;`, | ||
`-flp2:logfile=${expectedErrorFile};errorsonly;`, | ||
expectedSolutionFile, | ||
]; | ||
|
||
expect(files).toHaveLength(2); | ||
expect(spawn).toHaveBeenNthCalledWith(1, agentLoader.execPath, expectedArgs); | ||
}); | ||
|
||
it('should rejects with child process has error', async () => { | ||
const mockedRejectListener = jest.fn((e: string, cb: (err: string) => void) => { | ||
if (e === 'error') cb('Failed!'); | ||
}); | ||
|
||
spawn.mockImplementation(() => { | ||
return ({ | ||
stdout: { once: jest.fn() }, | ||
on: mockedRejectListener, | ||
} as unknown) as ChildProcess; | ||
}); | ||
|
||
const agent = new CSharpAgent(agentLoader); | ||
|
||
await expect(agent.buildAndGetLogFiles()).rejects.toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { spawn } from 'child_process'; | ||
import { resolve } from 'path'; | ||
|
||
import { AgentConfig } from '../Config/@types'; | ||
import { Agent } from './@interfaces/agent.interface'; | ||
|
||
export const WarningFile = 'dotnetbuild.wrn'; | ||
export const ErrorFile = 'dotnetbuild.err'; | ||
|
||
export class CSharpAgent implements Agent { | ||
private readonly execPath: string; | ||
private readonly target?: string; | ||
private readonly debug: boolean; | ||
private readonly cwd: string; | ||
private readonly warningOutFile: string; | ||
private readonly errorOutFile: string; | ||
|
||
constructor(loader: AgentConfig) { | ||
const { execPath, debug, target, cwd } = loader; | ||
this.execPath = execPath; | ||
this.target = target; | ||
this.debug = debug ?? false; | ||
this.cwd = cwd; | ||
this.errorOutFile = resolve(cwd, ErrorFile); | ||
this.warningOutFile = resolve(cwd, WarningFile); | ||
} | ||
|
||
private getBuildArgs(): string[] { | ||
const args: string[] = [ | ||
'build', | ||
'--nologo', | ||
'-p:ActiveRulesets="Coding Standards"', | ||
'-p:GenerateFullPaths=true', | ||
'--no-incremental', | ||
`-flp1:logfile=${this.warningOutFile};warningsonly;`, | ||
`-flp2:logfile=${this.errorOutFile};errorsonly;`, | ||
]; | ||
|
||
if (this.target) args.push(resolve(this.cwd, this.target)); | ||
|
||
return args; | ||
} | ||
|
||
async buildAndGetLogFiles(): Promise<string[]> { | ||
await new Promise((resolve, reject) => { | ||
const buildArgs = this.getBuildArgs(); | ||
const process = spawn(this.execPath, buildArgs); | ||
|
||
// **must add for consume stdout for get data, close events | ||
process.stdout.once('data', () => console.log('DotnetBuild...')); | ||
process.on('close', () => resolve()); | ||
process.on('error', (err) => reject(new Error('Agent error:' + err))); | ||
|
||
// debug log | ||
if (this.debug) { | ||
console.log('Task running...'); | ||
console.log(this.execPath); | ||
console.log('Agent param', buildArgs); | ||
process.stdout.on('data', (msg) => console.log('DotnetBuild: ', msg.toString())); | ||
} | ||
}); | ||
|
||
return [this.warningOutFile, this.errorOutFile]; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { AgentConfig } from '../Config'; | ||
import { Agent } from './@interfaces/agent.interface'; | ||
|
||
export class TSAgent implements Agent { | ||
constructor(loader: AgentConfig) { | ||
return; | ||
} | ||
|
||
buildAndGetLogFiles(): Promise<string[]> { | ||
throw new Error('Method not implemented.'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export type AgentConfig = { | ||
execPath: string; | ||
target?: string; | ||
debug?: boolean; | ||
cwd: string; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { CSharpAgent } from './CSharpAgent'; | ||
export { TSAgent } from './TSAgent'; | ||
export { Agent } from './@interfaces/agent.interface'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { existsSync } from 'fs'; | ||
import { mkdir, writeFile } from 'fs/promises'; | ||
import { resolve } from 'path'; | ||
import { REPO_DIR } from '../../src/app.constants'; | ||
import { Git } from './Git'; | ||
import { GitConfigType } from './git.config.type.ts.old'; | ||
|
||
describe('Git tests', () => { | ||
const cloneDest = './testdir'; | ||
const config: GitConfigType = { | ||
src: 'https://github.com/owner/repo', | ||
dest: cloneDest, | ||
prId: 5, | ||
}; | ||
const ROOT_PATH = resolve(cloneDest); | ||
const PROJECT_PATH = resolve(cloneDest, REPO_DIR); | ||
const git = new Git(config); | ||
|
||
it('Should execute git commands on correct path', () => { | ||
const cloneCommand = git.commands[0].cmd.join(' '); | ||
const cloneCwd = git.commands[0].cwd; | ||
const cloneTargetPath = resolve(cloneDest, REPO_DIR); | ||
|
||
const fetchCommand = git.commands[1].cmd.join(' '); | ||
const fetchCwd = git.commands[1].cwd; | ||
|
||
const checkoutCommand = git.commands[2].cmd.join(' '); | ||
const checkoutCwd = git.commands[2].cwd; | ||
|
||
expect(cloneCommand).toBe( | ||
'git clone https://github.com/owner/repo' + ' ' + cloneTargetPath, | ||
); | ||
expect(cloneCwd).toBe(ROOT_PATH); | ||
|
||
expect(fetchCommand).toBe('git fetch origin pull/5/head'); | ||
expect(fetchCwd).toBe(PROJECT_PATH); | ||
|
||
expect(checkoutCommand).toBe('git checkout -b pullrequest FETCH_HEAD'); | ||
expect(checkoutCwd).toBe(PROJECT_PATH); | ||
}); | ||
|
||
it('Should clear an old folder', async () => { | ||
await mkdir(PROJECT_PATH, { recursive: true }); | ||
await writeFile(PROJECT_PATH + '/test.txt', 'this is a test file'); | ||
await git.clearRepo(); | ||
const repoExist = existsSync(PROJECT_PATH); | ||
expect(repoExist).toBe(false); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import { exec } from 'child_process'; | ||
import { resolve } from 'path'; | ||
import rimraf from 'rimraf'; | ||
import { promisify } from 'util'; | ||
import { GitConfigType } from './git.config.type.ts.old'; | ||
import { REPO_DIR } from '../../app.constants'; | ||
import GitInterface, { CommandSequence } from './git.interface'; | ||
import { GIT_CHECKOUT, GIT_CLONE, GIT_EXEC, GIT_FETCH } from './git.constant'; | ||
|
||
const rimrafAsync = promisify(rimraf); | ||
|
||
const PULLS = (n: number) => `pull/${n}/head`; | ||
// todo: use cwd somehow ? | ||
export class Git implements GitInterface { | ||
commands: CommandSequence; | ||
rootPath: string; | ||
projectPath: string; | ||
|
||
constructor(config: GitConfigType) { | ||
this.rootPath = resolve(config.dest); | ||
this.projectPath = resolve(config.dest, REPO_DIR); | ||
|
||
this.commands = [ | ||
{ | ||
cmd: [GIT_EXEC, GIT_CLONE, config.src, this.projectPath], | ||
cwd: this.rootPath, | ||
}, | ||
{ | ||
cmd: [GIT_EXEC, GIT_FETCH, 'origin', PULLS(config.prId)], | ||
cwd: this.projectPath, | ||
}, | ||
{ | ||
cmd: [GIT_EXEC, GIT_CHECKOUT, '-b', 'pullrequest', 'FETCH_HEAD'], | ||
cwd: this.projectPath, | ||
}, | ||
]; | ||
} | ||
|
||
async clearRepo(): Promise<void> { | ||
await rimrafAsync(this.projectPath); | ||
} | ||
|
||
async clone(): Promise<void> { | ||
try { | ||
const commands = this.commands; | ||
await this.clearRepo(); | ||
|
||
for (const command of commands) { | ||
const process = promisify(exec); | ||
const git = await process(command.cmd.join(' '), { cwd: command.cwd }); | ||
if (git.stderr) console.log('std:', git.stderr); | ||
if (git.stdout) console.log('std:', git.stdout); | ||
} | ||
} catch (err) { | ||
throw new Error(err); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
export type GitConfigType = { | ||
src: string; | ||
dest: string; | ||
prId: number; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
export const GIT_EXEC = 'git'; | ||
export const GIT_CLONE = 'clone'; | ||
export const GIT_FETCH = 'fetch'; | ||
export const GIT_CHECKOUT = 'checkout'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
type Command = { cmd: string[]; cwd: string }; | ||
export type CommandSequence = Command[]; | ||
export default interface GitInterface { | ||
commands: CommandSequence; | ||
|
||
clone: () => Promise<void>; | ||
clearRepo: () => Promise<void>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
module.exports = { | ||
parser: '@typescript-eslint/parser', | ||
env: { | ||
es6: true, | ||
node: true, | ||
}, | ||
parserOptions: { | ||
ecmaVersion: 2020, | ||
sourceType: 'module', | ||
}, | ||
plugins: ['@typescript-eslint'], | ||
extends: [ | ||
'plugin:@typescript-eslint/recommended', | ||
'prettier/@typescript-eslint', | ||
'plugin:prettier/recommended', | ||
], | ||
rules: { | ||
'prettier/prettier': [ | ||
'warn', | ||
{ | ||
endOfLine: 'auto', | ||
}, | ||
], | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: CI | ||
|
||
on: | ||
pull_request: | ||
branches: | ||
- master | ||
|
||
jobs: | ||
build: | ||
name: Build | ||
runs-on: ubuntu-18.04 | ||
|
||
steps: | ||
- uses: actions/checkout@v1 | ||
- name: Use Node.js 14-latest | ||
uses: actions/setup-node@v1 | ||
with: | ||
node-version: '14.x' | ||
- name: Cache node_modules | ||
uses: actions/cache@v1 | ||
with: | ||
path: node_modules | ||
key: yarn-${{ hashFiles('yarn.lock') }} | ||
restore-keys: yarn- | ||
- run: yarn | ||
- run: yarn lint-ci | ||
- run: yarn test --ci | ||
- run: yarn build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
name: Publish to GitHub Packages | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- uses: actions/setup-node@v1 | ||
with: | ||
node-version: '14.x' | ||
registry-url: 'https://npm.pkg.github.com' | ||
- name: Cache node_modules | ||
uses: actions/cache@v1 | ||
with: | ||
path: node_modules | ||
key: yarn-${{ hashFiles('yarn.lock') }} | ||
restore-keys: yarn- | ||
- run: yarn | ||
- run: yarn publish --new-version 1.0.$GITHUB_RUN_NUMBER --no-git-tag-version | ||
env: | ||
NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |
Oops, something went wrong.