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:
parent
b098e04cdc
commit
c55c67e0a5
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -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'
|
||||||
|
@ -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()
|
||||||
|
@ -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
55
package-lock.json
generated
@ -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",
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user