1
1
mirror of https://github.com/theoludwig/programming-challenges.git synced 2024-12-08 00:45:29 +01:00

feat(cli): add --ci option to run test command

This commit is contained in:
Divlo 2021-06-25 12:46:01 +02:00
parent b098e04cdc
commit c55c67e0a5
No known key found for this signature in database
GPG Key ID: 185ED2F15F104E52
5 changed files with 69 additions and 62 deletions

View File

@ -108,4 +108,4 @@ jobs:
run: 'npm install --global' run: 'npm install --global'
- name: 'Test' - name: 'Test'
run: 'programming-challenges run test --affected' run: 'programming-challenges run test --affected --ci'

View File

@ -4,7 +4,7 @@ import * as typanion from 'typanion'
import chalk from 'chalk' import chalk from 'chalk'
import { Solution } from '../../services/Solution' import { Solution } from '../../services/Solution'
import { gitAffected } from '../../services/GitAffected' import { GitAffected } from '../../services/GitAffected'
const successMessage = `${chalk.bold.green('Success:')} Tests passed! 🎉` const successMessage = `${chalk.bold.green('Success:')} Tests passed! 🎉`
@ -35,10 +35,17 @@ export class RunTestCommand extends Command {
description: 'Only run the tests for the affected files in `git`.' description: 'Only run the tests for the affected files in `git`.'
}) })
public isContinuousIntegration = Option.Boolean('--ci', false, {
description: 'Run the tests for the Continuous Integration (CI).'
})
async execute (): Promise<number> { async execute (): Promise<number> {
console.log() console.log()
try { try {
if (this.affected) { if (this.affected) {
const gitAffected = new GitAffected({
isContinuousIntegration: this.isContinuousIntegration
})
const solutions = await gitAffected.getAffectedSolutions() const solutions = await gitAffected.getAffectedSolutions()
for (const solution of solutions) { for (const solution of solutions) {
await solution.test() await solution.test()

View File

@ -1,20 +1,66 @@
import simpleGit from 'simple-git' import execa from 'execa'
import { Challenge } from './Challenge' import { Challenge } from './Challenge'
import { Solution } from './Solution' import { Solution } from './Solution'
const git = simpleGit()
const solutionsRegex = new RegExp( const solutionsRegex = new RegExp(
/challenges\/[\s\S]*\/solutions\/(c|cpp|cs|dart|java|javascript|python|rust|typescript)\/[\s\S]*\/(solution|Solution).(c|cpp|cs|dart|java|js|py|rs|ts)/ /challenges\/[\s\S]*\/solutions\/(c|cpp|cs|dart|java|javascript|python|rust|typescript)\/[\s\S]*\/(solution|Solution).(c|cpp|cs|dart|java|js|py|rs|ts)/
) )
class GitAffected { export interface GitAffectedOptions {
isContinuousIntegration: boolean
}
export class GitAffected implements GitAffectedOptions {
public isContinuousIntegration: boolean
constructor (options: GitAffectedOptions) {
this.isContinuousIntegration = options.isContinuousIntegration
}
public parseGitOutput (output: string): string[] {
return output
.split('\n')
.map((line) => line.trim())
.filter((line) => line.length > 0)
}
public async getFilesUsingBaseAndHead (
base: string,
head: string
): Promise<string[]> {
const { stdout } = await execa.command(
`git diff --name-only --relative ${base} ${head}`
)
return this.parseGitOutput(stdout)
}
public async getUncommittedFiles (): Promise<string[]> {
return await this.getFilesUsingBaseAndHead('HEAD', '.')
}
public async getLatestPushedCommit (): Promise<string> {
const latestCommit = this.isContinuousIntegration ? '~1' : ''
const { stdout } = await execa.command(`git rev-parse origin/master${latestCommit}`)
return stdout
}
public async getUnpushedFiles (): Promise<string[]> {
return await this.getFilesUsingBaseAndHead(
await this.getLatestPushedCommit(),
'.'
)
}
public async getAffectedSolutions (): Promise<Solution[]> { public async getAffectedSolutions (): Promise<Solution[]> {
await git.add('.') const files = Array.from(
const diff = await git.diff(['--name-only', '--staged']) new Set([
const affectedSolutionsPaths = diff.split('\n').filter((currentDiff) => { ...(await this.getUnpushedFiles()),
return solutionsRegex.test(currentDiff) ...(await this.getUncommittedFiles())
])
)
const affectedSolutionsPaths = files.filter((filePath) => {
return solutionsRegex.test(filePath)
}) })
return affectedSolutionsPaths.map((solution) => { return affectedSolutionsPaths.map((solution) => {
const [, challengeName, , programmingLanguageName, solutionName] = const [, challengeName, , programmingLanguageName, solutionName] =
@ -29,5 +75,3 @@ class GitAffected {
}) })
} }
} }
export const gitAffected = new GitAffected()

55
package-lock.json generated
View File

@ -14,7 +14,6 @@
"execa": "5.1.1", "execa": "5.1.1",
"ora": "5.4.0", "ora": "5.4.0",
"replace-in-file": "6.2.0", "replace-in-file": "6.2.0",
"simple-git": "2.39.1",
"table": "6.7.1", "table": "6.7.1",
"typanion": "3.3.1", "typanion": "3.3.1",
"validate-npm-package-name": "3.0.0" "validate-npm-package-name": "3.0.0"
@ -1190,19 +1189,6 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
} }
}, },
"node_modules/@kwsites/file-exists": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
"dependencies": {
"debug": "^4.1.1"
}
},
"node_modules/@kwsites/promise-deferred": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -2445,6 +2431,7 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"dependencies": { "dependencies": {
"ms": "2.1.2" "ms": "2.1.2"
}, },
@ -6356,7 +6343,8 @@
"node_modules/ms": { "node_modules/ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}, },
"node_modules/natural-compare": { "node_modules/natural-compare": {
"version": "1.4.0", "version": "1.4.0",
@ -7527,16 +7515,6 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
}, },
"node_modules/simple-git": {
"version": "2.39.1",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.39.1.tgz",
"integrity": "sha512-+kEAkyQHsWejYxQNCzTrjvCxJOcijpB49RSs7HV+TK9B9prUq7YBNpFstQvjfGBn4Hecywp4tm+breGGGHlHwA==",
"dependencies": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
"debug": "^4.3.1"
}
},
"node_modules/sisteransi": { "node_modules/sisteransi": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
@ -9473,19 +9451,6 @@
"chalk": "^4.0.0" "chalk": "^4.0.0"
} }
}, },
"@kwsites/file-exists": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
"integrity": "sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==",
"requires": {
"debug": "^4.1.1"
}
},
"@kwsites/promise-deferred": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz",
"integrity": "sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw=="
},
"@nodelib/fs.scandir": { "@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@ -10420,6 +10385,7 @@
"version": "4.3.1", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
"integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==",
"dev": true,
"requires": { "requires": {
"ms": "2.1.2" "ms": "2.1.2"
} }
@ -13314,7 +13280,8 @@
"ms": { "ms": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
}, },
"natural-compare": { "natural-compare": {
"version": "1.4.0", "version": "1.4.0",
@ -14163,16 +14130,6 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
}, },
"simple-git": {
"version": "2.39.1",
"resolved": "https://registry.npmjs.org/simple-git/-/simple-git-2.39.1.tgz",
"integrity": "sha512-+kEAkyQHsWejYxQNCzTrjvCxJOcijpB49RSs7HV+TK9B9prUq7YBNpFstQvjfGBn4Hecywp4tm+breGGGHlHwA==",
"requires": {
"@kwsites/file-exists": "^1.1.1",
"@kwsites/promise-deferred": "^1.1.1",
"debug": "^4.3.1"
}
},
"sisteransi": { "sisteransi": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",

View File

@ -42,7 +42,6 @@
"execa": "5.1.1", "execa": "5.1.1",
"ora": "5.4.0", "ora": "5.4.0",
"replace-in-file": "6.2.0", "replace-in-file": "6.2.0",
"simple-git": "2.39.1",
"table": "6.7.1", "table": "6.7.1",
"typanion": "3.3.1", "typanion": "3.3.1",
"validate-npm-package-name": "3.0.0" "validate-npm-package-name": "3.0.0"