ics-builder 4.4.9 → 4.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.prettierignore +1 -0
- package/.prettierrc +7 -0
- package/.vscode/launch.json +15 -0
- package/.vscode/settings.json +6 -0
- package/Dockerfile +32 -0
- package/build/modules.yaml +7 -0
- package/build.template.yml +51 -0
- package/dist/jest.config.js +4 -0
- package/dist/package.json +76 -0
- package/{src → dist/src}/builder/ui/webpackUiBuilder.js +5 -2
- package/{src → dist/src}/index.js +0 -0
- package/dist/src/services/source/assets/hostList.yml +12 -0
- package/dist/src/services/source/assets/sourceList.yml +50 -0
- package/package.json +1 -1
- package/src/app.ts +64 -0
- package/src/builder/api/csprojFile.ts +15 -0
- package/src/builder/api/dotnetApiBuilder.ts +145 -0
- package/src/builder/api/net5Builder.ts +181 -0
- package/src/builder/api/webConfigFile.ts +11 -0
- package/src/builder/api/xmlFile.ts +24 -0
- package/src/builder/baseBuilder.ts +71 -0
- package/src/builder/data/dataBuilder.ts +28 -0
- package/src/builder/db/dbBuilder.ts +167 -0
- package/src/builder/e2e/e2eBuilder.ts +23 -0
- package/src/builder/schema/schemaBuilder.ts +156 -0
- package/src/builder/ui/customUiBuilder.ts +50 -0
- package/src/builder/ui/webpackUiBuilder.ts +497 -0
- package/src/builder/uiDependency/dependencyBuilder.ts +38 -0
- package/src/builder/winservice/winserviceBuilder.ts +11 -0
- package/src/dotnetUtils.ts +41 -0
- package/src/exceptions/BuilderException.ts +7 -0
- package/src/index.ts +34 -0
- package/src/services/buildManager.ts +151 -0
- package/src/services/commandManager.ts +78 -0
- package/src/services/configManager.ts +82 -0
- package/src/services/packageManager.ts +180 -0
- package/src/services/packageStructure/legacyPackageStructureManager.ts +34 -0
- package/src/services/packageStructure/packageStructureManager.ts +75 -0
- package/src/services/packageStructure/structureUtils.ts +66 -0
- package/src/services/source/loadPackages.ts +18 -0
- package/src/services/source/loaders/baseLoader.ts +28 -0
- package/src/services/source/loaders/gitScmProvider.ts +73 -0
- package/src/services/source/loaders/hgScmProvider.ts +63 -0
- package/src/services/source/sourceManager.ts +95 -0
- package/src/services/testManager.ts +27 -0
- package/src/testRunners/apiTestRunner.ts +68 -0
- package/src/testRunners/baseTestRunner.ts +19 -0
- package/src/testRunners/uiTestRunner.ts +8 -0
- package/src/utils.ts +228 -0
- package/test/sourceManager.test.ts +17 -0
- package/tsconfig.json +18 -0
- package/wallaby.js +14 -0
- /package/{src → dist/src}/app.js +0 -0
- /package/{src → dist/src}/builder/api/csprojFile.js +0 -0
- /package/{src → dist/src}/builder/api/dotnetApiBuilder.js +0 -0
- /package/{src → dist/src}/builder/api/net5Builder.js +0 -0
- /package/{src → dist/src}/builder/api/webConfigFile.js +0 -0
- /package/{src → dist/src}/builder/api/xmlFile.js +0 -0
- /package/{src → dist/src}/builder/baseBuilder.js +0 -0
- /package/{src → dist/src}/builder/data/dataBuilder.js +0 -0
- /package/{src → dist/src}/builder/db/dbBuilder.js +0 -0
- /package/{src → dist/src}/builder/e2e/e2eBuilder.js +0 -0
- /package/{src → dist/src}/builder/schema/schemaBuilder.js +0 -0
- /package/{src → dist/src}/builder/ui/customUiBuilder.js +0 -0
- /package/{src → dist/src}/builder/uiDependency/dependencyBuilder.js +0 -0
- /package/{src → dist/src}/builder/winservice/winserviceBuilder.js +0 -0
- /package/{src → dist/src}/dotnetUtils.js +0 -0
- /package/{src → dist/src}/exceptions/BuilderException.js +0 -0
- /package/{src → dist/src}/services/buildManager.js +0 -0
- /package/{src → dist/src}/services/commandManager.js +0 -0
- /package/{src → dist/src}/services/configManager.js +0 -0
- /package/{src → dist/src}/services/packageManager.js +0 -0
- /package/{src → dist/src}/services/packageStructure/legacyPackageStructureManager.js +0 -0
- /package/{src → dist/src}/services/packageStructure/packageStructureManager.js +0 -0
- /package/{src → dist/src}/services/packageStructure/structureUtils.js +0 -0
- /package/{src → dist/src}/services/source/loadPackages.js +0 -0
- /package/{src → dist/src}/services/source/loaders/baseLoader.js +0 -0
- /package/{src → dist/src}/services/source/loaders/gitScmProvider.js +0 -0
- /package/{src → dist/src}/services/source/loaders/hgScmProvider.js +0 -0
- /package/{src → dist/src}/services/source/sourceManager.js +0 -0
- /package/{src → dist/src}/services/testManager.js +0 -0
- /package/{src → dist/src}/testRunners/apiTestRunner.js +0 -0
- /package/{src → dist/src}/testRunners/baseTestRunner.js +0 -0
- /package/{src → dist/src}/testRunners/uiTestRunner.js +0 -0
- /package/{src → dist/src}/utils.js +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SourceConfig, PackageVersion } from "../sourceManager";
|
|
2
|
+
import * as shell from "shelljs";
|
|
3
|
+
import * as yaml from "yamljs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
|
|
6
|
+
export type ScmProviderOptions = {
|
|
7
|
+
url: string;
|
|
8
|
+
group: string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface ScmProvider {
|
|
12
|
+
exec(cmd: string, targetDir?: string): shell.ShellString;
|
|
13
|
+
clone(config: SourceConfig): shell.ShellString;
|
|
14
|
+
pull(config: SourceConfig): shell.ShellString;
|
|
15
|
+
update(config: SourceConfig, version: PackageVersion): shell.ShellString;
|
|
16
|
+
getBranches(config: SourceConfig): shell.ShellString;
|
|
17
|
+
getTags(config: SourceConfig): shell.ShellString;
|
|
18
|
+
getVersion(config: SourceConfig): PackageVersion;
|
|
19
|
+
clean(config: SourceConfig): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ScmType = "git" | "hg";
|
|
23
|
+
|
|
24
|
+
export interface ScmHosts {
|
|
25
|
+
[hostName: string]: { defaultType: ScmType; url: string; defaultGroup?: string };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const sources: ScmHosts = <ScmHosts>yaml.load(path.join(__dirname, "../assets/hostList.yml"));
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { SourceConfig, PackageVersion } from "../sourceManager";
|
|
2
|
+
import { ScmProvider, ScmProviderOptions } from "./baseLoader";
|
|
3
|
+
import { Logger, Utils } from "../../../utils";
|
|
4
|
+
import * as shell from "shelljs";
|
|
5
|
+
|
|
6
|
+
export class GitScmProvider implements ScmProvider {
|
|
7
|
+
constructor(protected options: ScmProviderOptions) {}
|
|
8
|
+
|
|
9
|
+
exec(cmd: string, targetDir?: string, skipError?: boolean) {
|
|
10
|
+
return Utils.exec("git " + cmd, { silent: true, cwd: targetDir || "", skipError: skipError } );
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
clone(config: SourceConfig) {
|
|
14
|
+
Logger.info(`Cloning repository ${config.package.name} in ${config.paths.source}, please wait...`);
|
|
15
|
+
return this.exec(
|
|
16
|
+
`clone --no-checkout ${this._getGitUrl(config)} ${config.paths.source}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pull(config: SourceConfig) {
|
|
21
|
+
Logger.info(
|
|
22
|
+
`Pulling from repository ${config.package.name} (${this._getGitUrl(config)}) ...`
|
|
23
|
+
);
|
|
24
|
+
return this.exec(`fetch --all --tags -f`, config.paths.source);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
update(config: SourceConfig, version: PackageVersion) {
|
|
28
|
+
let update = this.exec(`checkout ${version.branch} --force`, config.paths.source);
|
|
29
|
+
if (!version.isTag) {
|
|
30
|
+
let result = this.exec("merge", config.paths.source, true);
|
|
31
|
+
if (result.code !== 0)
|
|
32
|
+
throw result.stderr || result.stdout;
|
|
33
|
+
}
|
|
34
|
+
Logger.info(`${config.package.name} updated to ${version.branch} (rev. ${version.revision})`);
|
|
35
|
+
return update;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getBranches(config: SourceConfig) {
|
|
39
|
+
return this.exec(`for-each-ref --format="%(refname) %(objectname:short=8)" refs/remotes refs/tags`, config.paths.source);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
getTags(config: SourceConfig) {
|
|
43
|
+
return this.exec(`tag --list`, config.paths.source);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
getVersion(config: SourceConfig) {
|
|
47
|
+
let parse = (response: shell.ShellString): PackageVersion =>
|
|
48
|
+
response
|
|
49
|
+
.split("\n")
|
|
50
|
+
.filter(v => v)
|
|
51
|
+
.map(line => line.split(/\s+/))
|
|
52
|
+
.map(arr => ({ branch: arr[0].replace(/tags\/|origin\/|heads\/|remotes\/|refs\//gi, ""), revision: arr[1], isTag: arr[0].includes("tags") }))
|
|
53
|
+
.filter(version => version.branch == config.package.version)[0];
|
|
54
|
+
|
|
55
|
+
let version = parse(this.getBranches(config));
|
|
56
|
+
|
|
57
|
+
if (!version) Logger.error(`Cannot find version ${config.package.version} of module ${config.package.name}`);
|
|
58
|
+
|
|
59
|
+
return version;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
clean(config: SourceConfig) {
|
|
63
|
+
this.exec(`clean -fdx '*/package-lock.json'`, config.paths.source);
|
|
64
|
+
this.exec(`clean -fdx 'api/*/bin/*'`, config.paths.source);
|
|
65
|
+
this.exec(`clean -fdx '*/api/*/bin/*'`, config.paths.source);
|
|
66
|
+
this.exec(`clean -fdx 'api/*/obj/*'`, config.paths.source);
|
|
67
|
+
this.exec(`clean -fdx '*/api/*/obj/*'`, config.paths.source);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
private _getGitUrl(config: SourceConfig): string {
|
|
71
|
+
return config.package.url ?? `${this.options.url + this.options.group}/${config.package.name}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { SourceConfig, PackageVersion } from "../sourceManager";
|
|
2
|
+
import * as shell from "shelljs";
|
|
3
|
+
import { Logger, Utils } from "../../../utils";
|
|
4
|
+
import { ScmProviderOptions, ScmProvider } from "./baseLoader";
|
|
5
|
+
|
|
6
|
+
export class HgScmProvider implements ScmProvider {
|
|
7
|
+
constructor(protected options: ScmProviderOptions) {}
|
|
8
|
+
|
|
9
|
+
exec(cmd: string, targetDir?: string) {
|
|
10
|
+
return Utils.exec("hg " + cmd + (targetDir ? ` -R ${targetDir}` : ""), { silent: true });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
clone(config: SourceConfig) {
|
|
14
|
+
Logger.info(`Cloning repository ${config.package.name} in ${config.paths.source}, please wait...`);
|
|
15
|
+
return this.exec(
|
|
16
|
+
`clone -U ${this.options.url + this.options.group}/${config.package.name} ${config.paths.source}`
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
pull(config: SourceConfig) {
|
|
21
|
+
Logger.info(
|
|
22
|
+
`Pulling from repository ${config.package.name} (${this.options.url + this.options.group}/${
|
|
23
|
+
config.package.name
|
|
24
|
+
}) ...`
|
|
25
|
+
);
|
|
26
|
+
return this.exec(`pull`, config.paths.source);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
update(config: SourceConfig, version: PackageVersion) {
|
|
30
|
+
let update = this.exec(`update ${version.revision} --clean`, config.paths.source);
|
|
31
|
+
Logger.info(`${config.package.name} updated to ${version.branch} (rev. ${version.revision})`);
|
|
32
|
+
return update;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getBranches(config: SourceConfig) {
|
|
36
|
+
return this.exec(`branches`, config.paths.source);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
getTags(config: SourceConfig) {
|
|
40
|
+
return this.exec(`tags`, config.paths.source);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getVersion(config: SourceConfig): PackageVersion {
|
|
44
|
+
let parse = (response: shell.ShellString): PackageVersion =>
|
|
45
|
+
response
|
|
46
|
+
.split("\n")
|
|
47
|
+
.filter(value => value)
|
|
48
|
+
.map(line => line.split(/\s+/))
|
|
49
|
+
.map(arr => {
|
|
50
|
+
return { branch: arr[0], revision: arr[1].split(":")[0] };
|
|
51
|
+
})
|
|
52
|
+
.filter(version => version.branch == config.package.version)[0];
|
|
53
|
+
|
|
54
|
+
let version = parse(this.getBranches(config)) || parse(this.getTags(config));
|
|
55
|
+
|
|
56
|
+
if (!version) Logger.error(`Cannot find version ${config.package.version} of module ${config.package.name}`);
|
|
57
|
+
|
|
58
|
+
return version;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
clean(config: SourceConfig) {
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import * as shell from "shelljs";
|
|
2
|
+
import * as yaml from "yamljs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
|
|
5
|
+
import { Config, Package } from "../configManager";
|
|
6
|
+
import { Utils, Logger } from "../../utils";
|
|
7
|
+
import { ScmProvider, ScmType, ScmHosts, sources } from "./loaders/baseLoader";
|
|
8
|
+
import { loadPackages } from "./loadPackages";
|
|
9
|
+
import { GitScmProvider } from "./loaders/gitScmProvider";
|
|
10
|
+
import { HgScmProvider } from "./loaders/hgScmProvider";
|
|
11
|
+
|
|
12
|
+
export interface PackageVersion {
|
|
13
|
+
branch: string;
|
|
14
|
+
revision: string;
|
|
15
|
+
isTag?: boolean;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface SourceConfig {
|
|
19
|
+
paths: { source: string; build: string };
|
|
20
|
+
package: Package;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface Packages {
|
|
24
|
+
[packageName: string]: { host: string; type?: ScmType; group?: string };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const defaultPackage: Packages[keyof Packages] = { host: "gitlab" };
|
|
28
|
+
|
|
29
|
+
const packages: Packages = loadPackages(path.join(__dirname, "./assets/sourceList.yml"));
|
|
30
|
+
|
|
31
|
+
export class SourceManager {
|
|
32
|
+
private config: Config;
|
|
33
|
+
|
|
34
|
+
constructor(config: Config) {
|
|
35
|
+
this.config = config;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public loadSource(pkg: Package, skipLoad?: boolean): PackageVersion {
|
|
39
|
+
let sourceConfig: SourceConfig = {
|
|
40
|
+
package: pkg,
|
|
41
|
+
paths: {
|
|
42
|
+
source: path.join(this.config.paths.source, pkg.name),
|
|
43
|
+
build: path.join(this.config.paths.build, pkg.name)
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
let packageSource = packages[pkg.name] ?? defaultPackage;
|
|
48
|
+
let sourceType = packageSource.type ?? sources[packageSource.host].defaultType;
|
|
49
|
+
let packageGroup = packageSource.group ?? sources[packageSource.host].defaultGroup;
|
|
50
|
+
|
|
51
|
+
let scmOptions = { url: sources[packageSource.host].url, group: packageGroup };
|
|
52
|
+
let scmProvider = sourceType === "git" ? new GitScmProvider(scmOptions) : new HgScmProvider(scmOptions);
|
|
53
|
+
|
|
54
|
+
let version: PackageVersion;
|
|
55
|
+
if (!skipLoad) {
|
|
56
|
+
try {
|
|
57
|
+
if (Utils.ensurePath(path.join(sourceConfig.paths.source, `.${sourceType.toLowerCase()}`))) {
|
|
58
|
+
scmProvider.clean(sourceConfig);
|
|
59
|
+
scmProvider.pull(sourceConfig);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
scmProvider.clone(sourceConfig);
|
|
63
|
+
}
|
|
64
|
+
version = this.update(scmProvider, sourceConfig, true);
|
|
65
|
+
}
|
|
66
|
+
catch (e) {
|
|
67
|
+
if (e.includes("Merge conflict")) {
|
|
68
|
+
Logger.warn("Merge conflict, retrying");
|
|
69
|
+
Utils.prepareDir(sourceConfig.paths.source);
|
|
70
|
+
scmProvider.clone(sourceConfig);
|
|
71
|
+
version = this.update(scmProvider, sourceConfig, false);
|
|
72
|
+
}
|
|
73
|
+
else throw e;
|
|
74
|
+
}
|
|
75
|
+
} else version = scmProvider.getVersion(sourceConfig);
|
|
76
|
+
|
|
77
|
+
return version;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private update(scmProvider: ScmProvider, sourceConfig: SourceConfig, throwError: boolean): PackageVersion
|
|
81
|
+
{
|
|
82
|
+
try
|
|
83
|
+
{
|
|
84
|
+
let version = scmProvider.getVersion(sourceConfig);
|
|
85
|
+
scmProvider.update(sourceConfig, version);
|
|
86
|
+
return version
|
|
87
|
+
}
|
|
88
|
+
catch (e)
|
|
89
|
+
{
|
|
90
|
+
if (throwError)
|
|
91
|
+
throw e;
|
|
92
|
+
Logger.error(e);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ApiTestRunner } from "../testRunners/apiTestRunner";
|
|
2
|
+
import { UiTestRunner } from "../testRunners/uiTestRunner";
|
|
3
|
+
import { BaseTestRunner, TestRunnerConfig } from "../testRunners/baseTestRunner";
|
|
4
|
+
|
|
5
|
+
interface TestRunnerConstructor {
|
|
6
|
+
new (config: TestRunnerConfig): BaseTestRunner;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class TestManager {
|
|
10
|
+
private config: TestRunnerConfig;
|
|
11
|
+
private layerTestRunner: Map<string, TestRunnerConstructor>;
|
|
12
|
+
|
|
13
|
+
constructor(config: TestRunnerConfig) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.layerTestRunner = new Map<string, TestRunnerConstructor>();
|
|
16
|
+
this.layerTestRunner.set("api", ApiTestRunner);
|
|
17
|
+
this.layerTestRunner.set("ui", UiTestRunner);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
testApi(): BaseTestRunner {
|
|
21
|
+
return new (this.layerTestRunner.get("api"))(this.config);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
testUi(): BaseTestRunner {
|
|
25
|
+
return new (this.layerTestRunner.get("ui"))(this.config);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
|
|
4
|
+
import { DotnetUtils } from "../dotnetUtils";
|
|
5
|
+
import { Utils } from "../utils";
|
|
6
|
+
import { BaseTestRunner, TestRunnerConfig } from "./baseTestRunner";
|
|
7
|
+
|
|
8
|
+
export class ApiTestRunner extends BaseTestRunner {
|
|
9
|
+
private path: string;
|
|
10
|
+
private projects = new Array<string>();
|
|
11
|
+
|
|
12
|
+
constructor(config: TestRunnerConfig) {
|
|
13
|
+
super(config);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
run(): void | Promise<void> {
|
|
17
|
+
this.path = fs.lstatSync(this.config.basePath).isDirectory()
|
|
18
|
+
? this.config.basePath
|
|
19
|
+
: path.dirname(this.config.basePath);
|
|
20
|
+
|
|
21
|
+
this.projects = this.findProjects();
|
|
22
|
+
|
|
23
|
+
this.runTests();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private runSeparately() {
|
|
27
|
+
this.projects.forEach(p => {
|
|
28
|
+
var name = path.basename(p, ".csproj");
|
|
29
|
+
var logPath = path.join(this.config.resultPath, name + ".trx");
|
|
30
|
+
Utils.exec(
|
|
31
|
+
`dotnet test ${p} -p:DefineConstants=TEST --logger:"trx;LogFileName=${this.config.resultPath}"`,
|
|
32
|
+
{
|
|
33
|
+
silent: false
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private findProjects(): Array<string> {
|
|
40
|
+
return Utils.findFilesInDirRecursively(this.path, "[A-Za-z0-9\\.]*.csproj$");
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private runEntirely() {
|
|
44
|
+
var testSlnFileName = "Temp";
|
|
45
|
+
let projects = this.findProjects();
|
|
46
|
+
DotnetUtils.createTempSln(this.path, testSlnFileName);
|
|
47
|
+
DotnetUtils.addProjectsToSln(`${this.getSlnFullPath(testSlnFileName)}`, projects, true);
|
|
48
|
+
DotnetUtils.restoreNugetPackages(this.getSlnFullPath(testSlnFileName));
|
|
49
|
+
Utils.exec(
|
|
50
|
+
`dotnet test ${this.getSlnFullPath(testSlnFileName)} --no-restore -p:DefineConstants=TEST --logger:"trx;LogFileName=${this.config.resultPath}"`,
|
|
51
|
+
{ onProcessExit: () => this.dropTestSln("Test") }
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
this.dropTestSln(testSlnFileName);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
private getSlnFullPath(name: string): string {
|
|
58
|
+
return `${path.join(this.path, name + ".sln")}`;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
private dropTestSln(name: string): void {
|
|
62
|
+
Utils.deleteFiles("", [this.getSlnFullPath(name)]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private runTests(): void {
|
|
66
|
+
this.runEntirely();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Run } from "../services/commandManager";
|
|
2
|
+
import { Logger } from "../utils";
|
|
3
|
+
|
|
4
|
+
export interface TestRunnerConfig {
|
|
5
|
+
resultPath?: string;
|
|
6
|
+
basePath?: string;
|
|
7
|
+
watch?: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export abstract class BaseTestRunner implements Run {
|
|
11
|
+
protected config: TestRunnerConfig;
|
|
12
|
+
|
|
13
|
+
abstract run(): void | Promise<void>;
|
|
14
|
+
|
|
15
|
+
constructor(config: TestRunnerConfig) {
|
|
16
|
+
this.config = config;
|
|
17
|
+
Logger.info(`using ${this.constructor.name}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { BaseTestRunner } from "./baseTestRunner";
|
|
2
|
+
import { run } from "jest-cli";
|
|
3
|
+
|
|
4
|
+
export class UiTestRunner extends BaseTestRunner {
|
|
5
|
+
run(): void | Promise<void> {
|
|
6
|
+
run(["--ci", "--reporters=default", "--reporters=jest-junit", `--roots=${this.config.basePath}`], __dirname);
|
|
7
|
+
}
|
|
8
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { logger } from "just-task/lib/index";
|
|
2
|
+
import * as shell from "shelljs";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import * as glob from "glob";
|
|
6
|
+
import stripBomBuffer = require("strip-bom-buf");
|
|
7
|
+
import * as child_process from "child_process";
|
|
8
|
+
|
|
9
|
+
export interface ExecOptions extends shell.ExecOptions {
|
|
10
|
+
skipError?: boolean;
|
|
11
|
+
logCmd?: boolean;
|
|
12
|
+
onProcessExit?: { (): void };
|
|
13
|
+
async?: false;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class Utils {
|
|
17
|
+
static exec(cmd: string, options?: ExecOptions) {
|
|
18
|
+
const { skipError, logCmd = true, ...cmdOptions } = { ...options };
|
|
19
|
+
logCmd && Logger.info(cmd);
|
|
20
|
+
try {
|
|
21
|
+
const result = shell.exec(cmd, { ...cmdOptions });
|
|
22
|
+
if (result.code !== 0 && !skipError) {
|
|
23
|
+
if (options?.onProcessExit) options.onProcessExit();
|
|
24
|
+
Logger.error(result.stderr || result.stdout || `Command execution ended with code ${result.code}`);
|
|
25
|
+
}
|
|
26
|
+
return result;
|
|
27
|
+
} catch (e) {
|
|
28
|
+
if (e?.code === "ENOENT") {
|
|
29
|
+
Logger.error(`Path: ${options?.cwd} does not exsit`);
|
|
30
|
+
} else throw e;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static execModule(path: string, args: string[], options: child_process.ForkOptions) {
|
|
35
|
+
const proc = child_process.fork(path, args, options);
|
|
36
|
+
|
|
37
|
+
process.on("SIGTERM", () => proc.kill("SIGTERM"));
|
|
38
|
+
process.on("SIGINT", () => proc.kill("SIGINT"));
|
|
39
|
+
process.on("SIGBREAK", () => proc.kill("SIGBREAK"));
|
|
40
|
+
process.on("SIGHUP", () => proc.kill("SIGHUP"));
|
|
41
|
+
proc.on("exit", (code, signal) => {
|
|
42
|
+
let exitCode = code;
|
|
43
|
+
if (exitCode === null) {
|
|
44
|
+
exitCode = signal === "SIGINT" ? 0 : 1;
|
|
45
|
+
}
|
|
46
|
+
process.exit(exitCode);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return proc;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static ensurePath(path: string): boolean {
|
|
53
|
+
return fs.existsSync(path);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
static ensureFolder(path: string): void {
|
|
57
|
+
if (!Utils.ensurePath(path)) shell.mkdir("-p", path);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
static copyAllFilesByPattern(sourcePath: string, destinationPath: string, pattern: string) {
|
|
61
|
+
glob.sync(pattern, { cwd: sourcePath }).forEach(file => {
|
|
62
|
+
this.copyFile(path.join(sourcePath, file), path.join(destinationPath, file));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static copyAllFolders(sourcePath: string, destinationPath: string) {
|
|
67
|
+
glob.sync("**/", { cwd: sourcePath }).forEach(folder => {
|
|
68
|
+
this.copyFolder(path.join(sourcePath, folder), path.join(destinationPath, folder));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
static copyFile(from: string, to: string): void {
|
|
73
|
+
if (Utils.ensurePath(from)) {
|
|
74
|
+
Utils.ensureFolder(path.dirname(to));
|
|
75
|
+
fs.writeFileSync(to, stripBomBuffer(fs.readFileSync(from)));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static copyFolder(from: string, to: string, skip?: Array<string>): void {
|
|
80
|
+
if (!fs.existsSync(from) || fs.lstatSync(from).isSymbolicLink())
|
|
81
|
+
// ссылки пропускаем
|
|
82
|
+
return;
|
|
83
|
+
let files = fs.readdirSync(from);
|
|
84
|
+
Utils.ensureFolder(to);
|
|
85
|
+
|
|
86
|
+
files.forEach((file, index) => {
|
|
87
|
+
let currentFrom = path.join(from, file);
|
|
88
|
+
let currentTo = path.join(to, file);
|
|
89
|
+
|
|
90
|
+
if (skip && skip.length > 0) {
|
|
91
|
+
let found = false;
|
|
92
|
+
skip.forEach(item => {
|
|
93
|
+
if (item.toLowerCase() == currentFrom.toLowerCase()) {
|
|
94
|
+
found = true;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
if (found) return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
let stats = fs.statSync(currentFrom);
|
|
102
|
+
if (stats.isFile()) {
|
|
103
|
+
Utils.copyFile(currentFrom, currentTo);
|
|
104
|
+
} else if (stats.isDirectory()) {
|
|
105
|
+
Utils.copyFolder(currentFrom, currentTo, skip);
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static clearFolder(dir: string): void {
|
|
111
|
+
if (fs.existsSync(dir)) {
|
|
112
|
+
fs.readdirSync(dir).forEach(function (file, index) {
|
|
113
|
+
var curPath = path.join(dir, file);
|
|
114
|
+
if (fs.lstatSync(curPath).isDirectory()) {
|
|
115
|
+
Utils.clearFolder(curPath);
|
|
116
|
+
} else {
|
|
117
|
+
// delete file
|
|
118
|
+
Utils.safeInvoke(() => {
|
|
119
|
+
fs.unlinkSync(curPath);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
Utils.safeInvoke(() => {
|
|
124
|
+
fs.rmdirSync(dir);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
static safeInvoke(func: Function): void {
|
|
130
|
+
try {
|
|
131
|
+
func();
|
|
132
|
+
} catch (ex) {
|
|
133
|
+
// do nothing
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
static deleteFiles(dir: string, files: Array<string>) {
|
|
138
|
+
for (var i = 0; i < files.length; i++) {
|
|
139
|
+
var file = path.join(dir, files[i]);
|
|
140
|
+
this.deleteFile(file);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static deleteFile(path: string) {
|
|
145
|
+
if (fs.existsSync(path)) fs.unlinkSync(path);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
static prepareDir(dir: string): void {
|
|
149
|
+
Utils.clearFolder(dir);
|
|
150
|
+
Utils.ensureFolder(dir);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
static removeEmptyFolders(dir: string) {
|
|
154
|
+
try {
|
|
155
|
+
if (fs.existsSync(dir)) {
|
|
156
|
+
fs.readdirSync(dir).forEach(file => {
|
|
157
|
+
let curPath = path.join(dir, file);
|
|
158
|
+
if (fs.lstatSync(curPath).isDirectory()) {
|
|
159
|
+
Utils.removeEmptyFolders(curPath);
|
|
160
|
+
}
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
if (fs.readdirSync(dir).length == 0)
|
|
164
|
+
Utils.safeInvoke(() => {
|
|
165
|
+
fs.rmdirSync(dir);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
} catch (ex) {}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
static findFilesInDirRecursively(dir: string, fileNamePattern: string): Array<string> {
|
|
172
|
+
let res = Array<string>();
|
|
173
|
+
let regex = RegExp(fileNamePattern);
|
|
174
|
+
|
|
175
|
+
let findFilesRecursively = (files: fs.Dirent[], baseDirPath: string) => {
|
|
176
|
+
files.forEach(f => {
|
|
177
|
+
let dirFullPath = path.join(baseDirPath, f.name);
|
|
178
|
+
if (f.isDirectory()) {
|
|
179
|
+
findFilesRecursively(fs.readdirSync(dirFullPath, { withFileTypes: true }), dirFullPath);
|
|
180
|
+
} else if (f.isFile()) {
|
|
181
|
+
if (regex.test(f.name)) res.push(dirFullPath);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
let startFile = fs.lstatSync(dir);
|
|
187
|
+
|
|
188
|
+
if (startFile.isDirectory()) {
|
|
189
|
+
findFilesRecursively(fs.readdirSync(dir, { withFileTypes: true }), dir);
|
|
190
|
+
} else if (startFile.isFile() && regex.test(path.basename(dir))) {
|
|
191
|
+
res.push(dir);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return res;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
static deleteAllFoldersRecursively(cwd: string, folderName: string): void {
|
|
198
|
+
let files = fs.readdirSync(cwd, { withFileTypes: true });
|
|
199
|
+
files.forEach(f => {
|
|
200
|
+
if (!f.isDirectory()) return;
|
|
201
|
+
let dirFullPath = path.join(cwd, f.name);
|
|
202
|
+
if (f.name == folderName) {
|
|
203
|
+
Utils.clearFolder(dirFullPath);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
this.deleteAllFoldersRecursively(dirFullPath, folderName);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
static getFileName(path: string) {
|
|
211
|
+
return path.match(/([^\\/]+?)(\.[^.\\/]+)?$/)?.[1] ?? "";
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
export class Logger {
|
|
216
|
+
static info(...args: any): void {
|
|
217
|
+
logger.info(...args);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
static warn(...args: any): void {
|
|
221
|
+
logger.warn(...args);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
static error(...args: any): void {
|
|
225
|
+
logger.error(...args);
|
|
226
|
+
process.exit(1);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { mapPackages } from "../src/services/source/loadPackages";
|
|
2
|
+
|
|
3
|
+
test("Packages config is loaded correctly", () => {
|
|
4
|
+
const groups = {
|
|
5
|
+
icsit: {
|
|
6
|
+
mdt: { host: "bitbucket" },
|
|
7
|
+
ics: { host: "bitbucket", type: "git" }
|
|
8
|
+
},
|
|
9
|
+
alfa: { mdm: { host: "gitlab" } }
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const packages = mapPackages(groups);
|
|
13
|
+
|
|
14
|
+
expect(packages).not.toBe(null);
|
|
15
|
+
expect(Object.keys(packages).length).toBe(3);
|
|
16
|
+
expect(packages["mdt"]).toEqual({ host: "bitbucket", group: "icsit" });
|
|
17
|
+
});
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"sourceMap": false,
|
|
4
|
+
"target": "es5",
|
|
5
|
+
"baseUrl": "./",
|
|
6
|
+
"moduleResolution": "node",
|
|
7
|
+
"outDir": "./dist/src",
|
|
8
|
+
"skipLibCheck": true
|
|
9
|
+
},
|
|
10
|
+
"exclude": [
|
|
11
|
+
"node_modules",
|
|
12
|
+
"**/*.test.ts"
|
|
13
|
+
],
|
|
14
|
+
"include": [
|
|
15
|
+
"src"
|
|
16
|
+
],
|
|
17
|
+
"compileOnSave": false
|
|
18
|
+
}
|
package/wallaby.js
ADDED
/package/{src → dist/src}/app.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|