diff --git a/dist/mod_docker/index.d.ts b/dist/mod_docker/index.d.ts
index d7417f4..a5bf0f2 100644
--- a/dist/mod_docker/index.d.ts
+++ b/dist/mod_docker/index.d.ts
@@ -1,111 +1,20 @@
-///
+import * as helpers from './mod.helpers';
+import { Dockerfile } from './mod.classes.dockerfile';
+export { Dockerfile, helpers };
export declare let modArgvArg: any;
/**
* handle cli input
* @param argvArg
*/
export declare let handleCli: (argvArg: any) => Promise;
-/**
- * logs in docker
- */
-export declare let prepare: () => Promise;
/**
* builds a cwd of Dockerfiles by triggering a promisechain
*/
export declare let build: () => Promise;
-export declare let push: () => Promise;
-export declare let pull: () => Promise;
+/**
+ * logs in docker
+ */
+export declare let prepare: () => Promise;
+export declare let push: (argvArg: any) => Promise;
+export declare let pull: (argvArg: any) => Promise;
export declare let test: () => Promise;
-/**
- * creates instance of class Dockerfile for all Dockerfiles in cwd
- * @returns Promise
- */
-export declare let readDockerfiles: () => Promise;
-/**
- * sorts Dockerfiles into a dependency chain
- * @param sortableArrayArg an array of instances of class Dockerfile
- * @returns Promise
- */
-export declare let sortDockerfiles: (sortableArrayArg: Dockerfile[]) => Promise;
-/**
- * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
- */
-export declare let mapDockerfiles: (sortedArray: Dockerfile[]) => Promise;
-/**
- * builds the correspoding real docker image for each Dockerfile class instance
- */
-export declare let buildDockerfiles: (sortedArrayArg: Dockerfile[]) => Promise;
-/**
- * pushes the real Dockerfile images to a Docker registry
- */
-export declare let pushDockerfiles: (sortedArrayArg: Dockerfile[]) => Promise;
-/**
- * pulls corresponding real Docker images for instances of Dockerfile from a registry.
- * This is needed if building, testing, and publishing of Docker images is carried out in seperate CI stages.
- */
-export declare let pullDockerfileImages: (sortableArrayArg: Dockerfile[], registryArg?: string) => Promise;
-/**
- * tests all Dockerfiles in by calling class Dockerfile.test();
- * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
- */
-export declare let testDockerfiles: (sortedArrayArg: Dockerfile[]) => Promise;
-/**
- * class Dockerfile represents a Dockerfile on disk in npmci
- */
-export declare class Dockerfile {
- filePath: string;
- repo: string;
- version: string;
- cleanTag: string;
- buildTag: string;
- gitlabTestTag: string;
- gitlabReleaseTag: string;
- releaseTag: string;
- containerName: string;
- content: string;
- baseImage: string;
- localBaseImageDependent: boolean;
- localBaseDockerfile: Dockerfile;
- constructor(options: {
- filePath?: string;
- fileContents?: string | Buffer;
- read?: boolean;
- });
- /**
- * builds the Dockerfile
- */
- build(): Promise;
- /**
- * pushes the Dockerfile to a registry
- */
- push(stageArg: any): Promise;
- /**
- * pulls the Dockerfile from a registry
- */
- pull(registryArg: string): Promise;
- /**
- * tests the Dockerfile;
- */
- test(): Promise;
- /**
- * gets the id of a Dockerfile
- */
- getId(): Promise;
-}
-/**
- * returns a version for a docker file
- * @execution SYNC
- */
-export declare let dockerFileVersion: (dockerfileNameArg: string) => string;
-/**
- * returns the docker base image for a Dockerfile
- */
-export declare let dockerBaseImage: (dockerfileContentArg: string) => string;
-/**
- * returns the docker tag
- */
-export declare let getDockerTagString: (registryArg: string, repoArg: string, versionArg: string, suffixArg?: string) => string;
-/**
- *
- */
-export declare let cleanTagsArrayFunction: (dockerfileArrayArg: Dockerfile[], trackingArrayArg: Dockerfile[]) => string[];
diff --git a/dist/mod_docker/index.js b/dist/mod_docker/index.js
index 9dde4e1..9894c80 100644
--- a/dist/mod_docker/index.js
+++ b/dist/mod_docker/index.js
@@ -9,9 +9,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
};
Object.defineProperty(exports, "__esModule", { value: true });
const plugins = require("./mod.plugins");
-const paths = require("../npmci.paths");
const NpmciEnv = require("../npmci.env");
-const npmci_bash_1 = require("../npmci.bash");
+const helpers = require("./mod.helpers");
+exports.helpers = helpers;
+// classes
+const mod_classes_dockerfile_1 = require("./mod.classes.dockerfile");
+exports.Dockerfile = mod_classes_dockerfile_1.Dockerfile;
+const mod_classes_dockerregistry_1 = require("./mod.classes.dockerregistry");
+const mod_classes_registrystorage_1 = require("./mod.classes.registrystorage");
+// instances
+let npmciRegistryStorage = new mod_classes_registrystorage_1.RegistryStorage();
/**
* handle cli input
* @param argvArg
@@ -30,6 +37,12 @@ exports.handleCli = (argvArg) => __awaiter(this, void 0, void 0, function* () {
case 'test':
yield exports.test();
break;
+ case 'push':
+ yield exports.push(argvArg);
+ break;
+ case 'pull':
+ yield exports.pull(argvArg);
+ break;
default:
plugins.beautylog.error(`>>npmci node ...<< action >>${action}<< not supported`);
}
@@ -38,321 +51,68 @@ exports.handleCli = (argvArg) => __awaiter(this, void 0, void 0, function* () {
plugins.beautylog.log(`>>npmci node ...<< cli arguments invalid... Please read the documentation.`);
}
});
+/**
+ * builds a cwd of Dockerfiles by triggering a promisechain
+ */
+exports.build = () => __awaiter(this, void 0, void 0, function* () {
+ plugins.beautylog.log('now building Dockerfiles...');
+ yield helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles)
+ .then(helpers.buildDockerfiles);
+});
/**
* logs in docker
*/
exports.prepare = () => __awaiter(this, void 0, void 0, function* () {
NpmciEnv.setDockerRegistry('docker.io'); // TODO: checkup why we set this here
- // handle registries
- plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_LOGIN_DOCKER*', (envString) => __awaiter(this, void 0, void 0, function* () {
- let dockerRegexResultArray = envString.split('|');
- if (dockerRegexResultArray.length !== 3) {
- plugins.beautylog.error('malformed docker env var...');
- process.exit(1);
- return;
- }
- let registry = dockerRegexResultArray[0];
- let username = dockerRegexResultArray[1];
- let password = dockerRegexResultArray[2];
- if (registry === 'docker.io') {
- yield npmci_bash_1.bash(`docker login -u ${username} -p ${password}`);
- plugins.beautylog.info('Logged in to standard docker hub');
- }
- else {
- yield npmci_bash_1.bash(`docker login -u ${username} -p ${password} ${registry}`);
- }
- plugins.beautylog.success(`docker authenticated for ${registry}!`);
- }));
// Always login to GitLab Registry
if (!process.env.CI_BUILD_TOKEN || process.env.CI_BUILD_TOKEN === '') {
plugins.beautylog.error('No registry token specified by gitlab!');
return;
}
- yield npmci_bash_1.bash(`docker login -u gitlab-ci-token -p ${process.env.CI_BUILD_TOKEN} registry.gitlab.com`);
- plugins.beautylog.success(`docker authenticated for registry.gitlab.com!`);
+ npmciRegistryStorage.addRegistry(new mod_classes_dockerregistry_1.DockerRegistry({
+ registryUrl: 'registry.gitlab.com',
+ username: 'gitlab-ci-token',
+ password: process.env.CI_BUILD_TOKEN
+ }));
+ // handle registries
+ plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_LOGIN_DOCKER*', (envString) => __awaiter(this, void 0, void 0, function* () {
+ npmciRegistryStorage.addRegistry(mod_classes_dockerregistry_1.DockerRegistry.fromEnvString(envString));
+ yield npmciRegistryStorage.loginAll();
+ }));
return;
});
-/**
- * builds a cwd of Dockerfiles by triggering a promisechain
- */
-exports.build = () => __awaiter(this, void 0, void 0, function* () {
- plugins.beautylog.log('now building Dockerfiles...');
- yield exports.readDockerfiles()
- .then(exports.sortDockerfiles)
- .then(exports.mapDockerfiles)
- .then(exports.buildDockerfiles);
+exports.push = (argvArg) => __awaiter(this, void 0, void 0, function* () {
+ let registryUrlArg = argvArg._[2];
+ let suffix = null;
+ if (argvArg._.length >= 4) {
+ suffix = argvArg._[3];
+ }
+ let dockerfileArray = yield helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles);
+ let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
+ for (let dockerfile of dockerfileArray) {
+ dockerfile.push(localDockerRegistry, suffix);
+ }
});
-exports.push = () => __awaiter(this, void 0, void 0, function* () {
- yield exports.readDockerfiles()
- .then(exports.sortDockerfiles)
- .then(exports.mapDockerfiles)
- .then(exports.pushDockerfiles);
-});
-exports.pull = () => __awaiter(this, void 0, void 0, function* () {
- return yield exports.readDockerfiles()
- .then(exports.pullDockerfileImages);
+exports.pull = (argvArg) => __awaiter(this, void 0, void 0, function* () {
+ let registryUrlArg = argvArg._[2];
+ let suffix = null;
+ if (argvArg._.length >= 4) {
+ suffix = argvArg._[3];
+ }
+ let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
+ let dockerfileArray = yield helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles);
+ for (let dockerfile of dockerfileArray) {
+ dockerfile.pull(localDockerRegistry, suffix);
+ }
});
exports.test = () => __awaiter(this, void 0, void 0, function* () {
- return yield exports.readDockerfiles()
- .then(exports.testDockerfiles);
+ return yield helpers.readDockerfiles()
+ .then(helpers.testDockerfiles);
});
-/**
- * creates instance of class Dockerfile for all Dockerfiles in cwd
- * @returns Promise
- */
-exports.readDockerfiles = () => __awaiter(this, void 0, void 0, function* () {
- let fileTree = yield plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
- // create the Dockerfile array
- let readDockerfilesArray = [];
- plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`);
- console.log(fileTree);
- for (let dockerfilePath of fileTree) {
- let myDockerfile = new Dockerfile({
- filePath: dockerfilePath,
- read: true
- });
- readDockerfilesArray.push(myDockerfile);
- }
- return readDockerfilesArray;
-});
-/**
- * sorts Dockerfiles into a dependency chain
- * @param sortableArrayArg an array of instances of class Dockerfile
- * @returns Promise
- */
-exports.sortDockerfiles = (sortableArrayArg) => {
- let done = plugins.q.defer();
- plugins.beautylog.info('sorting Dockerfiles:');
- let sortedArray = [];
- let cleanTagsOriginal = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
- let sorterFunctionCounter = 0;
- let sorterFunction = function () {
- sortableArrayArg.forEach((dockerfileArg) => {
- let cleanTags = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
- if (cleanTags.indexOf(dockerfileArg.baseImage) === -1 && sortedArray.indexOf(dockerfileArg) === -1) {
- sortedArray.push(dockerfileArg);
- }
- if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) !== -1) {
- dockerfileArg.localBaseImageDependent = true;
- }
- });
- if (sortableArrayArg.length === sortedArray.length) {
- let counter = 1;
- for (let dockerfile of sortedArray) {
- plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`);
- counter++;
- }
- done.resolve(sortedArray);
- }
- else if (sorterFunctionCounter < 10) {
- sorterFunctionCounter++;
- sorterFunction();
- }
- };
- sorterFunction();
- return done.promise;
-};
-/**
- * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
- */
-exports.mapDockerfiles = (sortedArray) => __awaiter(this, void 0, void 0, function* () {
- sortedArray.forEach((dockerfileArg) => {
- if (dockerfileArg.localBaseImageDependent) {
- sortedArray.forEach((dockfile2) => {
- if (dockfile2.cleanTag === dockerfileArg.baseImage) {
- dockerfileArg.localBaseDockerfile = dockfile2;
- }
- });
- }
- });
- return sortedArray;
-});
-/**
- * builds the correspoding real docker image for each Dockerfile class instance
- */
-exports.buildDockerfiles = (sortedArrayArg) => __awaiter(this, void 0, void 0, function* () {
- for (let dockerfileArg of sortedArrayArg) {
- yield dockerfileArg.build();
- }
- return sortedArrayArg;
-});
-/**
- * pushes the real Dockerfile images to a Docker registry
- */
-exports.pushDockerfiles = (sortedArrayArg) => __awaiter(this, void 0, void 0, function* () {
- let stageArg = (function () {
- if (exports.modArgvArg._ && exports.modArgvArg._.length >= 3) {
- return exports.modArgvArg._[2];
- }
- else {
- return NpmciEnv.buildStage;
- }
- })();
- for (let dockerfileArg of sortedArrayArg) {
- yield dockerfileArg.push(stageArg);
- }
- return sortedArrayArg;
-});
-/**
- * pulls corresponding real Docker images for instances of Dockerfile from a registry.
- * This is needed if building, testing, and publishing of Docker images is carried out in seperate CI stages.
- */
-exports.pullDockerfileImages = (sortableArrayArg, registryArg = 'registry.gitlab.com') => __awaiter(this, void 0, void 0, function* () {
- for (let dockerfileArg of sortableArrayArg) {
- yield dockerfileArg.pull(registryArg);
- }
- return sortableArrayArg;
-});
-/**
- * tests all Dockerfiles in by calling class Dockerfile.test();
- * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
- */
-exports.testDockerfiles = (sortedArrayArg) => __awaiter(this, void 0, void 0, function* () {
- for (let dockerfileArg of sortedArrayArg) {
- yield dockerfileArg.test();
- }
- return sortedArrayArg;
-});
-/**
- * class Dockerfile represents a Dockerfile on disk in npmci
- */
-class Dockerfile {
- constructor(options) {
- this.filePath = options.filePath;
- this.repo = NpmciEnv.repo.user + '/' + NpmciEnv.repo.repo;
- this.version = exports.dockerFileVersion(plugins.path.parse(options.filePath).base);
- this.cleanTag = this.repo + ':' + this.version;
- this.buildTag = this.cleanTag;
- this.gitlabTestTag = exports.getDockerTagString('docker.io', this.repo, this.version, 'test'); // TODO: using docker.io until gitlab is fixed
- this.gitlabReleaseTag = exports.getDockerTagString('docker.io', this.repo, this.version); // TODO: using docker.io until gitlab is fixed
- // the releaseTag determines where the image gets released
- this.releaseTag = exports.getDockerTagString('docker.io', this.repo, this.version);
- this.containerName = 'dockerfile-' + this.version;
- if (options.filePath && options.read) {
- this.content = plugins.smartfile.fs.toStringSync(plugins.path.resolve(options.filePath));
- }
- this.baseImage = exports.dockerBaseImage(this.content);
- this.localBaseImageDependent = false;
- }
- /**
- * builds the Dockerfile
- */
- build() {
- return __awaiter(this, void 0, void 0, function* () {
- plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag);
- let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} .`;
- yield npmci_bash_1.bash(buildCommand);
- NpmciEnv.dockerFilesBuilt.push(this);
- return;
- });
- }
- /**
- * pushes the Dockerfile to a registry
- */
- push(stageArg) {
- return __awaiter(this, void 0, void 0, function* () {
- yield npmci_bash_1.bash(`docker tag ${this.buildTag} ${this.releaseTag}`);
- yield npmci_bash_1.bash(`docker tag ${this.buildTag} ${this.gitlabReleaseTag}`);
- yield npmci_bash_1.bash(`docker tag ${this.buildTag} ${this.gitlabTestTag}`);
- switch (stageArg) {
- case 'release':
- yield npmci_bash_1.bash(`docker push ${this.gitlabReleaseTag}`);
- yield npmci_bash_1.bash(`docker push ${this.releaseTag}`);
- break;
- case 'test':
- default:
- yield npmci_bash_1.bash(`docker push ${this.gitlabTestTag}`);
- break;
- }
- });
- }
- /**
- * pulls the Dockerfile from a registry
- */
- pull(registryArg) {
- return __awaiter(this, void 0, void 0, function* () {
- yield npmci_bash_1.bash(`docker pull ${this.gitlabTestTag}`);
- yield npmci_bash_1.bash(`docker tag ${this.gitlabTestTag} ${this.buildTag}`);
- });
- }
- /**
- * tests the Dockerfile;
- */
- test() {
- return __awaiter(this, void 0, void 0, function* () {
- let testFile = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh');
- let testFileExists = plugins.smartfile.fs.fileExistsSync(testFile);
- if (testFileExists) {
- // run tests
- yield npmci_bash_1.bash('docker run --name npmci_test_container ' + this.buildTag + ' mkdir /npmci_test');
- yield npmci_bash_1.bash('docker cp ' + testFile + ' npmci_test_container:/npmci_test/test.sh');
- yield npmci_bash_1.bash('docker commit npmci_test_container npmci_test_image');
- yield npmci_bash_1.bash('docker run npmci_test_image sh /npmci_test/test.sh');
- yield npmci_bash_1.bash('docker rm npmci_test_container');
- yield npmci_bash_1.bash('docker rmi --force npmci_test_image');
- }
- else {
- plugins.beautylog.warn('skipping tests for ' + this.cleanTag + ' because no testfile was found!');
- }
- });
- }
- /**
- * gets the id of a Dockerfile
- */
- getId() {
- return __awaiter(this, void 0, void 0, function* () {
- let containerId = yield npmci_bash_1.bash('docker inspect --type=image --format=\"{{.Id}}\" ' + this.buildTag);
- return containerId;
- });
- }
-}
-exports.Dockerfile = Dockerfile;
-/**
- * returns a version for a docker file
- * @execution SYNC
- */
-exports.dockerFileVersion = (dockerfileNameArg) => {
- let versionString;
- let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
- let regexResultArray = versionRegex.exec(dockerfileNameArg);
- if (regexResultArray && regexResultArray.length === 2) {
- versionString = regexResultArray[1];
- }
- else {
- versionString = 'latest';
- }
- return versionString;
-};
-/**
- * returns the docker base image for a Dockerfile
- */
-exports.dockerBaseImage = function (dockerfileContentArg) {
- let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
- let regexResultArray = baseImageRegex.exec(dockerfileContentArg);
- return regexResultArray[1];
-};
-/**
- * returns the docker tag
- */
-exports.getDockerTagString = function (registryArg, repoArg, versionArg, suffixArg) {
- // determine wether the suffix is needed
- let version = versionArg;
- if (suffixArg) {
- version = versionArg + '_' + suffixArg;
- }
- let tagString = `${registryArg}/${repoArg}:${version}`;
- return tagString;
-};
-/**
- *
- */
-exports.cleanTagsArrayFunction = function (dockerfileArrayArg, trackingArrayArg) {
- let cleanTagsArray = [];
- dockerfileArrayArg.forEach(function (dockerfileArg) {
- if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
- cleanTagsArray.push(dockerfileArg.cleanTag);
- }
- });
- return cleanTagsArray;
-};
-//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfZG9ja2VyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx5Q0FBd0M7QUFDeEMsd0NBQXVDO0FBQ3ZDLHlDQUF3QztBQUN4Qyw4Q0FBb0M7QUFJcEM7OztHQUdHO0FBQ1EsUUFBQSxTQUFTLEdBQUcsQ0FBTyxPQUFPO0lBQ25DLGtCQUFVLEdBQUcsT0FBTyxDQUFBO0lBQ3BCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsSUFBSSxNQUFNLEdBQVcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNqQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ2YsS0FBSyxPQUFPO2dCQUNWLE1BQU0sYUFBSyxFQUFFLENBQUE7Z0JBQ2IsS0FBSyxDQUFBO1lBQ1AsS0FBSyxTQUFTO2dCQUNaLE1BQU0sZUFBTyxFQUFFLENBQUE7Z0JBQ2YsS0FBSyxDQUFBO1lBQ1AsS0FBSyxNQUFNO2dCQUNULE1BQU0sWUFBSSxFQUFFLENBQUE7Z0JBQ1osS0FBSyxDQUFBO1lBQ1A7Z0JBQ0UsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsK0JBQStCLE1BQU0sa0JBQWtCLENBQUMsQ0FBQTtRQUNwRixDQUFDO0lBQ0gsQ0FBQztJQUFDLElBQUksQ0FBQyxDQUFDO1FBQ04sT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsNEVBQTRFLENBQUMsQ0FBQTtJQUNyRyxDQUFDO0FBQ0gsQ0FBQyxDQUFBLENBQUE7QUFHRDs7R0FFRztBQUNRLFFBQUEsT0FBTyxHQUFHO0lBQ25CLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQSxDQUFDLHFDQUFxQztJQUU3RSxvQkFBb0I7SUFDcEIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLHFCQUFxQixFQUFFLENBQU8sU0FBUztRQUN0RixJQUFJLHNCQUFzQixHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDakQsRUFBRSxDQUFDLENBQUMsc0JBQXNCLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQTtZQUN0RCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2YsTUFBTSxDQUFBO1FBQ1IsQ0FBQztRQUNELElBQUksUUFBUSxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hDLElBQUksUUFBUSxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hDLElBQUksUUFBUSxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsS0FBSyxXQUFXLENBQUMsQ0FBQyxDQUFDO1lBQzdCLE1BQU0saUJBQUksQ0FBQyxtQkFBbUIsUUFBUSxPQUFPLFFBQVEsRUFBRSxDQUFDLENBQUE7WUFDeEQsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsa0NBQWtDLENBQUMsQ0FBQTtRQUM1RCxDQUFDO1FBQUMsSUFBSSxDQUFDLENBQUM7WUFDTixNQUFNLGlCQUFJLENBQUMsbUJBQW1CLFFBQVEsT0FBTyxRQUFRLElBQUksUUFBUSxFQUFFLENBQUMsQ0FBQTtRQUN0RSxDQUFDO1FBQ0QsT0FBTyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsNEJBQTRCLFFBQVEsR0FBRyxDQUFDLENBQUE7SUFDcEUsQ0FBQyxDQUFBLENBQUMsQ0FBQTtJQUVGLGtDQUFrQztJQUNsQyxFQUFFLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsY0FBYyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDckUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsd0NBQXdDLENBQUMsQ0FBQTtRQUNqRSxNQUFNLENBQUE7SUFDUixDQUFDO0lBQ0QsTUFBTSxpQkFBSSxDQUFDLHNDQUFzQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsc0JBQXNCLENBQUMsQ0FBQTtJQUNsRyxPQUFPLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQywrQ0FBK0MsQ0FBQyxDQUFBO0lBQzFFLE1BQU0sQ0FBQTtBQUNSLENBQUMsQ0FBQSxDQUFBO0FBRUQ7O0dBRUc7QUFDUSxRQUFBLEtBQUssR0FBRztJQUNqQixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFBO0lBQ3BELE1BQU0sdUJBQWUsRUFBRTtTQUNwQixJQUFJLENBQUMsdUJBQWUsQ0FBQztTQUNyQixJQUFJLENBQUMsc0JBQWMsQ0FBQztTQUNwQixJQUFJLENBQUMsd0JBQWdCLENBQUMsQ0FBQTtBQUMzQixDQUFDLENBQUEsQ0FBQTtBQUVVLFFBQUEsSUFBSSxHQUFHO0lBQ2hCLE1BQU0sdUJBQWUsRUFBRTtTQUNwQixJQUFJLENBQUMsdUJBQWUsQ0FBQztTQUNyQixJQUFJLENBQUMsc0JBQWMsQ0FBQztTQUNwQixJQUFJLENBQUMsdUJBQWUsQ0FBQyxDQUFBO0FBQzFCLENBQUMsQ0FBQSxDQUFBO0FBRVUsUUFBQSxJQUFJLEdBQUc7SUFDaEIsTUFBTSxDQUFDLE1BQU0sdUJBQWUsRUFBRTtTQUMzQixJQUFJLENBQUMsNEJBQW9CLENBQUMsQ0FBQTtBQUMvQixDQUFDLENBQUEsQ0FBQTtBQUVVLFFBQUEsSUFBSSxHQUFHO0lBQ2hCLE1BQU0sQ0FBQyxNQUFNLHVCQUFlLEVBQUU7U0FDM0IsSUFBSSxDQUFDLHVCQUFlLENBQUMsQ0FBQTtBQUMxQixDQUFDLENBQUEsQ0FBQTtBQUVEOzs7R0FHRztBQUNRLFFBQUEsZUFBZSxHQUFHO0lBQzNCLElBQUksUUFBUSxHQUFHLE1BQU0sT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsYUFBYSxDQUFDLENBQUE7SUFFaEYsOEJBQThCO0lBQzlCLElBQUksb0JBQW9CLEdBQWlCLEVBQUUsQ0FBQTtJQUMzQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLFFBQVEsQ0FBQyxNQUFNLGVBQWUsQ0FBQyxDQUFBO0lBQy9ELE9BQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDckIsR0FBRyxDQUFDLENBQUMsSUFBSSxjQUFjLElBQUksUUFBUSxDQUFDLENBQUMsQ0FBQztRQUNwQyxJQUFJLFlBQVksR0FBRyxJQUFJLFVBQVUsQ0FBQztZQUNoQyxRQUFRLEVBQUUsY0FBYztZQUN4QixJQUFJLEVBQUUsSUFBSTtTQUNYLENBQUMsQ0FBQTtRQUNGLG9CQUFvQixDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUN6QyxDQUFDO0lBRUQsTUFBTSxDQUFDLG9CQUFvQixDQUFBO0FBRTdCLENBQUMsQ0FBQSxDQUFBO0FBRUQ7Ozs7R0FJRztBQUNRLFFBQUEsZUFBZSxHQUFHLENBQUMsZ0JBQThCO0lBQzFELElBQUksSUFBSSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFnQixDQUFBO0lBQzFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUE7SUFDOUMsSUFBSSxXQUFXLEdBQWlCLEVBQUUsQ0FBQTtJQUNsQyxJQUFJLGlCQUFpQixHQUFHLDhCQUFzQixDQUFDLGdCQUFnQixFQUFFLFdBQVcsQ0FBQyxDQUFBO0lBQzdFLElBQUkscUJBQXFCLEdBQVcsQ0FBQyxDQUFBO0lBQ3JDLElBQUksY0FBYyxHQUFHO1FBQ25CLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLGFBQWE7WUFDckMsSUFBSSxTQUFTLEdBQUcsOEJBQXNCLENBQUMsZ0JBQWdCLEVBQUUsV0FBVyxDQUFDLENBQUE7WUFDckUsRUFBRSxDQUFDLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksV0FBVyxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ25HLFdBQVcsQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUE7WUFDakMsQ0FBQztZQUNELEVBQUUsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUM5RCxhQUFhLENBQUMsdUJBQXVCLEdBQUcsSUFBSSxDQUFBO1lBQzlDLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQTtRQUNGLEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLE1BQU0sS0FBSyxXQUFXLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNuRCxJQUFJLE9BQU8sR0FBRyxDQUFDLENBQUE7WUFDZixHQUFHLENBQUMsQ0FBQyxJQUFJLFVBQVUsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDO2dCQUNuQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxPQUFPLE9BQU8sUUFBUSxVQUFVLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtnQkFDbEUsT0FBTyxFQUFFLENBQUE7WUFDWCxDQUFDO1lBQ0QsSUFBSSxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtRQUMzQixDQUFDO1FBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLHFCQUFxQixHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDdEMscUJBQXFCLEVBQUUsQ0FBQTtZQUN2QixjQUFjLEVBQUUsQ0FBQTtRQUNsQixDQUFDO0lBQ0gsQ0FBQyxDQUFBO0lBQ0QsY0FBYyxFQUFFLENBQUE7SUFDaEIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUE7QUFDckIsQ0FBQyxDQUFBO0FBRUQ7O0dBRUc7QUFDUSxRQUFBLGNBQWMsR0FBRyxDQUFPLFdBQXlCO0lBQzFELFdBQVcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxhQUFhO1FBQ2hDLEVBQUUsQ0FBQyxDQUFDLGFBQWEsQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDLENBQUM7WUFDMUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFNBQXFCO2dCQUN4QyxFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxLQUFLLGFBQWEsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO29CQUNuRCxhQUFhLENBQUMsbUJBQW1CLEdBQUcsU0FBUyxDQUFBO2dCQUMvQyxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUE7UUFDSixDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDRixNQUFNLENBQUMsV0FBVyxDQUFBO0FBQ3BCLENBQUMsQ0FBQSxDQUFBO0FBRUQ7O0dBRUc7QUFDUSxRQUFBLGdCQUFnQixHQUFHLENBQU8sY0FBNEI7SUFDL0QsR0FBRyxDQUFDLENBQUMsSUFBSSxhQUFhLElBQUksY0FBYyxDQUFDLENBQUMsQ0FBQztRQUN6QyxNQUFNLGFBQWEsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtJQUM3QixDQUFDO0lBQ0QsTUFBTSxDQUFDLGNBQWMsQ0FBQTtBQUN2QixDQUFDLENBQUEsQ0FBQTtBQUVEOztHQUVHO0FBQ1EsUUFBQSxlQUFlLEdBQUcsQ0FBTyxjQUE0QjtJQUM5RCxJQUFJLFFBQVEsR0FBRyxDQUFDO1FBQ2QsRUFBRSxDQUFDLENBQUMsa0JBQVUsQ0FBQyxDQUFDLElBQUksa0JBQVUsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDN0MsTUFBTSxDQUFDLGtCQUFVLENBQUMsQ0FBQyxDQUFFLENBQUMsQ0FBRSxDQUFBO1FBQzFCLENBQUM7UUFBQyxJQUFJLENBQUMsQ0FBQztZQUNOLE1BQU0sQ0FBQyxRQUFRLENBQUMsVUFBVSxDQUFBO1FBQzVCLENBQUM7SUFDSCxDQUFDLENBQUMsRUFBRSxDQUFBO0lBQ0osR0FBRyxDQUFDLENBQUMsSUFBSSxhQUFhLElBQUksY0FBYyxDQUFDLENBQUMsQ0FBQztRQUN6QyxNQUFNLGFBQWEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7SUFDcEMsQ0FBQztJQUNELE1BQU0sQ0FBQyxjQUFjLENBQUE7QUFDdkIsQ0FBQyxDQUFBLENBQUE7QUFFRDs7O0dBR0c7QUFDUSxRQUFBLG9CQUFvQixHQUFHLENBQU8sZ0JBQThCLEVBQUUsV0FBVyxHQUFHLHFCQUFxQjtJQUMxRyxHQUFHLENBQUMsQ0FBQyxJQUFJLGFBQWEsSUFBSSxnQkFBZ0IsQ0FBQyxDQUFDLENBQUM7UUFDM0MsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO0lBQ3ZDLENBQUM7SUFDRCxNQUFNLENBQUMsZ0JBQWdCLENBQUE7QUFDekIsQ0FBQyxDQUFBLENBQUE7QUFFRDs7O0dBR0c7QUFDUSxRQUFBLGVBQWUsR0FBRyxDQUFPLGNBQTRCO0lBQzlELEdBQUcsQ0FBQyxDQUFDLElBQUksYUFBYSxJQUFJLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDekMsTUFBTSxhQUFhLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDNUIsQ0FBQztJQUNELE1BQU0sQ0FBQyxjQUFjLENBQUE7QUFDdkIsQ0FBQyxDQUFBLENBQUE7QUFFRDs7R0FFRztBQUNIO0lBY0UsWUFBWSxPQUE4RTtRQUN4RixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUE7UUFDaEMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUE7UUFDekQsSUFBSSxDQUFDLE9BQU8sR0FBRyx5QkFBaUIsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDM0UsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsSUFBSSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFBO1FBQzlDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQTtRQUM3QixJQUFJLENBQUMsYUFBYSxHQUFHLDBCQUFrQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUEsQ0FBQyw4Q0FBOEM7UUFDcEksSUFBSSxDQUFDLGdCQUFnQixHQUFHLDBCQUFrQixDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQSxDQUFDLDhDQUE4QztRQUUvSCwwREFBMEQ7UUFDMUQsSUFBSSxDQUFDLFVBQVUsR0FBRywwQkFBa0IsQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFMUUsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQTtRQUNqRCxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFBO1FBQzFGLENBQUM7UUFDRCxJQUFJLENBQUMsU0FBUyxHQUFHLHVCQUFlLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQzlDLElBQUksQ0FBQyx1QkFBdUIsR0FBRyxLQUFLLENBQUE7SUFDdEMsQ0FBQztJQUVEOztPQUVHO0lBQ0csS0FBSzs7WUFDVCxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyw4QkFBOEIsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDdEUsSUFBSSxZQUFZLEdBQUcsbUJBQW1CLElBQUksQ0FBQyxRQUFRLE9BQU8sSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFBO1lBQzNFLE1BQU0saUJBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQTtZQUN4QixRQUFRLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1lBQ3BDLE1BQU0sQ0FBQTtRQUNSLENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0csSUFBSSxDQUFFLFFBQVE7O1lBQ2xCLE1BQU0saUJBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7WUFDNUQsTUFBTSxpQkFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFBO1lBQ2xFLE1BQU0saUJBQUksQ0FBQyxjQUFjLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUE7WUFDL0QsTUFBTSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQztnQkFDakIsS0FBSyxTQUFTO29CQUNaLE1BQU0saUJBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDLENBQUE7b0JBQ2xELE1BQU0saUJBQUksQ0FBQyxlQUFlLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFBO29CQUM1QyxLQUFLLENBQUE7Z0JBQ1AsS0FBSyxNQUFNLENBQUM7Z0JBQ1o7b0JBQ0UsTUFBTSxpQkFBSSxDQUFDLGVBQWUsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUE7b0JBQy9DLEtBQUssQ0FBQTtZQUNULENBQUM7UUFDSCxDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNHLElBQUksQ0FBRSxXQUFtQjs7WUFDN0IsTUFBTSxpQkFBSSxDQUFDLGVBQWUsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUE7WUFDL0MsTUFBTSxpQkFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLGFBQWEsSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtRQUNqRSxDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNHLElBQUk7O1lBQ1IsSUFBSSxRQUFRLEdBQVcsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUMsQ0FBQTtZQUM1RixJQUFJLGNBQWMsR0FBWSxPQUFPLENBQUMsU0FBUyxDQUFDLEVBQUUsQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDM0UsRUFBRSxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQztnQkFDbkIsWUFBWTtnQkFDWixNQUFNLGlCQUFJLENBQUMseUNBQXlDLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxvQkFBb0IsQ0FBQyxDQUFBO2dCQUM1RixNQUFNLGlCQUFJLENBQUMsWUFBWSxHQUFHLFFBQVEsR0FBRywyQ0FBMkMsQ0FBQyxDQUFBO2dCQUNqRixNQUFNLGlCQUFJLENBQUMscURBQXFELENBQUMsQ0FBQTtnQkFDakUsTUFBTSxpQkFBSSxDQUFDLG9EQUFvRCxDQUFDLENBQUE7Z0JBQ2hFLE1BQU0saUJBQUksQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFBO2dCQUM1QyxNQUFNLGlCQUFJLENBQUMscUNBQXFDLENBQUMsQ0FBQTtZQUNuRCxDQUFDO1lBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ04sT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMscUJBQXFCLEdBQUcsSUFBSSxDQUFDLFFBQVEsR0FBRyxpQ0FBaUMsQ0FBQyxDQUFBO1lBQ25HLENBQUM7UUFDSCxDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNHLEtBQUs7O1lBQ1QsSUFBSSxXQUFXLEdBQUcsTUFBTSxpQkFBSSxDQUFDLG1EQUFtRCxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQTtZQUNqRyxNQUFNLENBQUMsV0FBVyxDQUFBO1FBQ3BCLENBQUM7S0FBQTtDQUNGO0FBbEdELGdDQWtHQztBQUVEOzs7R0FHRztBQUNRLFFBQUEsaUJBQWlCLEdBQUcsQ0FBQyxpQkFBeUI7SUFDdkQsSUFBSSxhQUFxQixDQUFBO0lBQ3pCLElBQUksWUFBWSxHQUFHLDhCQUE4QixDQUFBO0lBQ2pELElBQUksZ0JBQWdCLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFBO0lBQzNELEVBQUUsQ0FBQyxDQUFDLGdCQUFnQixJQUFJLGdCQUFnQixDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RELGFBQWEsR0FBRyxnQkFBZ0IsQ0FBRSxDQUFDLENBQUUsQ0FBQTtJQUN2QyxDQUFDO0lBQUMsSUFBSSxDQUFDLENBQUM7UUFDTixhQUFhLEdBQUcsUUFBUSxDQUFBO0lBQzFCLENBQUM7SUFDRCxNQUFNLENBQUMsYUFBYSxDQUFBO0FBQ3RCLENBQUMsQ0FBQTtBQUVEOztHQUVHO0FBQ1EsUUFBQSxlQUFlLEdBQUcsVUFBVSxvQkFBNEI7SUFDakUsSUFBSSxjQUFjLEdBQUcsK0JBQStCLENBQUE7SUFDcEQsSUFBSSxnQkFBZ0IsR0FBRyxjQUFjLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUE7SUFDaEUsTUFBTSxDQUFDLGdCQUFnQixDQUFFLENBQUMsQ0FBRSxDQUFBO0FBQzlCLENBQUMsQ0FBQTtBQUVEOztHQUVHO0FBQ1EsUUFBQSxrQkFBa0IsR0FBRyxVQUFVLFdBQW1CLEVBQUUsT0FBZSxFQUFFLFVBQWtCLEVBQUUsU0FBa0I7SUFDcEgsd0NBQXdDO0lBQ3hDLElBQUksT0FBTyxHQUFHLFVBQVUsQ0FBQTtJQUN4QixFQUFFLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1FBQ2QsT0FBTyxHQUFHLFVBQVUsR0FBRyxHQUFHLEdBQUcsU0FBUyxDQUFBO0lBQ3hDLENBQUM7SUFDRCxJQUFJLFNBQVMsR0FBRyxHQUFHLFdBQVcsSUFBSSxPQUFPLElBQUksT0FBTyxFQUFFLENBQUE7SUFDdEQsTUFBTSxDQUFDLFNBQVMsQ0FBQTtBQUNsQixDQUFDLENBQUE7QUFFRDs7R0FFRztBQUNRLFFBQUEsc0JBQXNCLEdBQUcsVUFBVSxrQkFBZ0MsRUFBRSxnQkFBOEI7SUFDNUcsSUFBSSxjQUFjLEdBQWEsRUFBRSxDQUFBO0lBQ2pDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxVQUFVLGFBQWE7UUFDaEQsRUFBRSxDQUFDLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNuRCxjQUFjLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUM3QyxDQUFDO0lBQ0gsQ0FBQyxDQUFDLENBQUE7SUFDRixNQUFNLENBQUMsY0FBYyxDQUFBO0FBQ3ZCLENBQUMsQ0FBQSJ9
\ No newline at end of file
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfZG9ja2VyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx5Q0FBd0M7QUFFeEMseUNBQXdDO0FBR3hDLHlDQUF3QztBQVl0QywwQkFBTztBQVZULFVBQVU7QUFDVixxRUFBcUQ7QUFRbkQscUJBUk8sbUNBQVUsQ0FRUDtBQVBaLDZFQUE2RDtBQUM3RCwrRUFBK0Q7QUFFL0QsWUFBWTtBQUNaLElBQUksb0JBQW9CLEdBQUcsSUFBSSw2Q0FBZSxFQUFFLENBQUE7QUFTaEQ7OztHQUdHO0FBQ1EsUUFBQSxTQUFTLEdBQUcsQ0FBTyxPQUFPO0lBQ25DLGtCQUFVLEdBQUcsT0FBTyxDQUFBO0lBQ3BCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsSUFBSSxNQUFNLEdBQVcsT0FBTyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUUsQ0FBQTtRQUNuQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ2YsS0FBSyxPQUFPO2dCQUNWLE1BQU0sYUFBSyxFQUFFLENBQUE7Z0JBQ2IsS0FBSyxDQUFBO1lBQ1AsS0FBSyxTQUFTO2dCQUNaLE1BQU0sZUFBTyxFQUFFLENBQUE7Z0JBQ2YsS0FBSyxDQUFBO1lBQ1AsS0FBSyxNQUFNO2dCQUNULE1BQU0sWUFBSSxFQUFFLENBQUE7Z0JBQ1osS0FBSyxDQUFBO1lBQ1AsS0FBSyxNQUFNO2dCQUNULE1BQU0sWUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO2dCQUNuQixLQUFLLENBQUE7WUFDUCxLQUFLLE1BQU07Z0JBQ1QsTUFBTSxZQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7Z0JBQ25CLEtBQUssQ0FBQTtZQUNQO2dCQUNFLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLCtCQUErQixNQUFNLGtCQUFrQixDQUFDLENBQUE7UUFDcEYsQ0FBQztJQUNILENBQUM7SUFBQyxJQUFJLENBQUMsQ0FBQztRQUNOLE9BQU8sQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLDRFQUE0RSxDQUFDLENBQUE7SUFDckcsQ0FBQztBQUNILENBQUMsQ0FBQSxDQUFBO0FBRUQ7O0dBRUc7QUFDUSxRQUFBLEtBQUssR0FBRztJQUNqQixPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyw2QkFBNkIsQ0FBQyxDQUFBO0lBQ3BELE1BQU0sT0FBTyxDQUFDLGVBQWUsRUFBRTtTQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQztTQUM3QixJQUFJLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQztTQUM1QixJQUFJLENBQUMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBQUE7QUFDbkMsQ0FBQyxDQUFBLENBQUE7QUFFRDs7R0FFRztBQUNRLFFBQUEsT0FBTyxHQUFHO0lBQ25CLFFBQVEsQ0FBQyxpQkFBaUIsQ0FBQyxXQUFXLENBQUMsQ0FBQSxDQUFDLHFDQUFxQztJQUU3RSxrQ0FBa0M7SUFDbEMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3JFLE9BQU8sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLHdDQUF3QyxDQUFDLENBQUE7UUFDakUsTUFBTSxDQUFBO0lBQ1IsQ0FBQztJQUNELG9CQUFvQixDQUFDLFdBQVcsQ0FBQyxJQUFJLDJDQUFjLENBQUM7UUFDbEQsV0FBVyxFQUFFLHFCQUFxQjtRQUNsQyxRQUFRLEVBQUUsaUJBQWlCO1FBQzNCLFFBQVEsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGNBQWM7S0FDckMsQ0FBQyxDQUFDLENBQUE7SUFFSCxvQkFBb0I7SUFDcEIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsR0FBRyxFQUFFLHFCQUFxQixFQUFFLENBQU8sU0FBUztRQUN0RixvQkFBb0IsQ0FBQyxXQUFXLENBQzlCLDJDQUFjLENBQUMsYUFBYSxDQUFDLFNBQVMsQ0FBQyxDQUN4QyxDQUFBO1FBQ0QsTUFBTSxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtJQUN2QyxDQUFDLENBQUEsQ0FBQyxDQUFBO0lBQ0YsTUFBTSxDQUFBO0FBQ1IsQ0FBQyxDQUFBLENBQUE7QUFFVSxRQUFBLElBQUksR0FBRyxDQUFPLE9BQU87SUFDOUIsSUFBSSxjQUFjLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUUsQ0FBQTtJQUNuQyxJQUFJLE1BQU0sR0FBRyxJQUFJLENBQUE7SUFDakIsRUFBRSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxQixNQUFNLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBRSxDQUFDLENBQUUsQ0FBQTtJQUN6QixDQUFDO0lBQ0QsSUFBSSxlQUFlLEdBQUcsTUFBTSxPQUFPLENBQUMsZUFBZSxFQUFFO1NBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO1NBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7SUFDL0IsSUFBSSxtQkFBbUIsR0FBRyxvQkFBb0IsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQUMsQ0FBQTtJQUMvRSxHQUFHLENBQUMsQ0FBQyxJQUFJLFVBQVUsSUFBSSxlQUFlLENBQUMsQ0FBQyxDQUFDO1FBQ3ZDLFVBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLEVBQUUsTUFBTSxDQUFDLENBQUE7SUFDOUMsQ0FBQztBQUNILENBQUMsQ0FBQSxDQUFBO0FBRVUsUUFBQSxJQUFJLEdBQUcsQ0FBTyxPQUFPO0lBQzlCLElBQUksY0FBYyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUUsQ0FBQyxDQUFFLENBQUE7SUFDbkMsSUFBSSxNQUFNLEdBQUcsSUFBSSxDQUFBO0lBQ2pCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDMUIsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUUsQ0FBQyxDQUFFLENBQUE7SUFDekIsQ0FBQztJQUNELElBQUksbUJBQW1CLEdBQUcsb0JBQW9CLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxDQUFDLENBQUE7SUFDL0UsSUFBSSxlQUFlLEdBQUcsTUFBTSxPQUFPLENBQUMsZUFBZSxFQUFFO1NBQ2xELElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDO1NBQzdCLElBQUksQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUE7SUFDL0IsR0FBRyxDQUFDLENBQUMsSUFBSSxVQUFVLElBQUksZUFBZSxDQUFDLENBQUMsQ0FBQztRQUN2QyxVQUFVLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQzlDLENBQUM7QUFDSCxDQUFDLENBQUEsQ0FBQTtBQUVVLFFBQUEsSUFBSSxHQUFHO0lBQ2hCLE1BQU0sQ0FBQyxNQUFNLE9BQU8sQ0FBQyxlQUFlLEVBQUU7U0FDbkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQTtBQUNsQyxDQUFDLENBQUEsQ0FBQSJ9
\ No newline at end of file
diff --git a/dist/mod_docker/mod.classes.dockerfile.d.ts b/dist/mod_docker/mod.classes.dockerfile.d.ts
new file mode 100644
index 0000000..c936c22
--- /dev/null
+++ b/dist/mod_docker/mod.classes.dockerfile.d.ts
@@ -0,0 +1,42 @@
+///
+import { DockerRegistry } from './mod.classes.dockerregistry';
+/**
+ * class Dockerfile represents a Dockerfile on disk in npmci
+ */
+export declare class Dockerfile {
+ filePath: string;
+ repo: string;
+ version: string;
+ cleanTag: string;
+ buildTag: string;
+ containerName: string;
+ content: string;
+ baseImage: string;
+ localBaseImageDependent: boolean;
+ localBaseDockerfile: Dockerfile;
+ constructor(options: {
+ filePath?: string;
+ fileContents?: string | Buffer;
+ read?: boolean;
+ });
+ /**
+ * builds the Dockerfile
+ */
+ build(): Promise;
+ /**
+ * pushes the Dockerfile to a registry
+ */
+ push(dockerRegistryArg: DockerRegistry, versionSuffix?: string): Promise;
+ /**
+ * pulls the Dockerfile from a registry
+ */
+ pull(registryArg: DockerRegistry, versionSuffixArg?: string): Promise;
+ /**
+ * tests the Dockerfile;
+ */
+ test(): Promise;
+ /**
+ * gets the id of a Dockerfile
+ */
+ getId(): Promise;
+}
diff --git a/dist/mod_docker/mod.classes.dockerfile.js b/dist/mod_docker/mod.classes.dockerfile.js
new file mode 100644
index 0000000..193ab44
--- /dev/null
+++ b/dist/mod_docker/mod.classes.dockerfile.js
@@ -0,0 +1,96 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const plugins = require("./mod.plugins");
+const NpmciEnv = require("../npmci.env");
+const npmci_bash_1 = require("../npmci.bash");
+const paths = require("../npmci.paths");
+const helpers = require("./mod.helpers");
+/**
+ * class Dockerfile represents a Dockerfile on disk in npmci
+ */
+class Dockerfile {
+ constructor(options) {
+ this.filePath = options.filePath;
+ this.repo = NpmciEnv.repo.user + '/' + NpmciEnv.repo.repo;
+ this.version = helpers.dockerFileVersion(plugins.path.parse(options.filePath).base);
+ this.cleanTag = this.repo + ':' + this.version;
+ this.buildTag = this.cleanTag;
+ this.containerName = 'dockerfile-' + this.version;
+ if (options.filePath && options.read) {
+ this.content = plugins.smartfile.fs.toStringSync(plugins.path.resolve(options.filePath));
+ }
+ this.baseImage = helpers.dockerBaseImage(this.content);
+ this.localBaseImageDependent = false;
+ }
+ /**
+ * builds the Dockerfile
+ */
+ build() {
+ return __awaiter(this, void 0, void 0, function* () {
+ plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag);
+ let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} .`;
+ yield npmci_bash_1.bash(buildCommand);
+ NpmciEnv.dockerFilesBuilt.push(this);
+ return;
+ });
+ }
+ /**
+ * pushes the Dockerfile to a registry
+ */
+ push(dockerRegistryArg, versionSuffix = null) {
+ return __awaiter(this, void 0, void 0, function* () {
+ let pushTag = helpers.getDockerTagString(dockerRegistryArg.registryUrl, this.repo, this.version, versionSuffix);
+ yield npmci_bash_1.bash(`docker tag ${this.buildTag} ${pushTag}`);
+ yield npmci_bash_1.bash(`docker push ${pushTag}`);
+ });
+ }
+ /**
+ * pulls the Dockerfile from a registry
+ */
+ pull(registryArg, versionSuffixArg = null) {
+ return __awaiter(this, void 0, void 0, function* () {
+ let pullTag = helpers.getDockerTagString(registryArg.registryUrl, this.repo, this.version, versionSuffixArg);
+ yield npmci_bash_1.bash(`docker tag ${pullTag} ${this.buildTag}`);
+ });
+ }
+ /**
+ * tests the Dockerfile;
+ */
+ test() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let testFile = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh');
+ let testFileExists = plugins.smartfile.fs.fileExistsSync(testFile);
+ if (testFileExists) {
+ // run tests
+ yield npmci_bash_1.bash('docker run --name npmci_test_container ' + this.buildTag + ' mkdir /npmci_test');
+ yield npmci_bash_1.bash('docker cp ' + testFile + ' npmci_test_container:/npmci_test/test.sh');
+ yield npmci_bash_1.bash('docker commit npmci_test_container npmci_test_image');
+ yield npmci_bash_1.bash('docker run npmci_test_image sh /npmci_test/test.sh');
+ yield npmci_bash_1.bash('docker rm npmci_test_container');
+ yield npmci_bash_1.bash('docker rmi --force npmci_test_image');
+ }
+ else {
+ plugins.beautylog.warn('skipping tests for ' + this.cleanTag + ' because no testfile was found!');
+ }
+ });
+ }
+ /**
+ * gets the id of a Dockerfile
+ */
+ getId() {
+ return __awaiter(this, void 0, void 0, function* () {
+ let containerId = yield npmci_bash_1.bash('docker inspect --type=image --format=\"{{.Id}}\" ' + this.buildTag);
+ return containerId;
+ });
+ }
+}
+exports.Dockerfile = Dockerfile;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kLmNsYXNzZXMuZG9ja2VyZmlsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL21vZF9kb2NrZXIvbW9kLmNsYXNzZXMuZG9ja2VyZmlsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7O0FBQUEseUNBQXdDO0FBQ3hDLHlDQUF3QztBQUN4Qyw4Q0FBb0M7QUFDcEMsd0NBQXVDO0FBR3ZDLHlDQUF3QztBQUV4Qzs7R0FFRztBQUNIO0lBV0UsWUFBYSxPQUE4RTtRQUN6RixJQUFJLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUE7UUFDaEMsSUFBSSxDQUFDLElBQUksR0FBRyxRQUFRLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUE7UUFDekQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUMsaUJBQWlCLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1FBQ25GLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDLElBQUksR0FBRyxHQUFHLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQTtRQUM5QyxJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUE7UUFFN0IsSUFBSSxDQUFDLGFBQWEsR0FBRyxhQUFhLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQTtRQUNqRCxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ3JDLElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFBO1FBQzFGLENBQUM7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
\ No newline at end of file
diff --git a/dist/mod_docker/mod.classes.dockerregistry.d.ts b/dist/mod_docker/mod.classes.dockerregistry.d.ts
new file mode 100644
index 0000000..31218f4
--- /dev/null
+++ b/dist/mod_docker/mod.classes.dockerregistry.d.ts
@@ -0,0 +1,13 @@
+export interface IDockerRegistryConstructorOptions {
+ registryUrl: string;
+ username: string;
+ password: string;
+}
+export declare class DockerRegistry {
+ registryUrl: string;
+ username: string;
+ password: string;
+ constructor(optionsArg: IDockerRegistryConstructorOptions);
+ static fromEnvString(envString: string): DockerRegistry;
+ login(): Promise;
+}
diff --git a/dist/mod_docker/mod.classes.dockerregistry.js b/dist/mod_docker/mod.classes.dockerregistry.js
new file mode 100644
index 0000000..24cfc21
--- /dev/null
+++ b/dist/mod_docker/mod.classes.dockerregistry.js
@@ -0,0 +1,49 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const plugins = require("./mod.plugins");
+const npmci_bash_1 = require("../npmci.bash");
+class DockerRegistry {
+ constructor(optionsArg) {
+ this.registryUrl = optionsArg.registryUrl;
+ this.username = optionsArg.username;
+ this.password = optionsArg.password;
+ }
+ static fromEnvString(envString) {
+ let dockerRegexResultArray = envString.split('|');
+ if (dockerRegexResultArray.length !== 3) {
+ plugins.beautylog.error('malformed docker env var...');
+ process.exit(1);
+ return;
+ }
+ let registryUrl = dockerRegexResultArray[0];
+ let username = dockerRegexResultArray[1];
+ let password = dockerRegexResultArray[2];
+ return new DockerRegistry({
+ registryUrl: registryUrl,
+ username: username,
+ password: password
+ });
+ }
+ login() {
+ return __awaiter(this, void 0, void 0, function* () {
+ if (this.registryUrl === 'docker.io') {
+ yield npmci_bash_1.bash(`docker login -u ${this.username} -p ${this.password}`);
+ plugins.beautylog.info('Logged in to standard docker hub');
+ }
+ else {
+ yield npmci_bash_1.bash(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`);
+ }
+ plugins.beautylog.success(`docker authenticated for ${this.registryUrl}!`);
+ });
+ }
+}
+exports.DockerRegistry = DockerRegistry;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kLmNsYXNzZXMuZG9ja2VycmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfZG9ja2VyL21vZC5jbGFzc2VzLmRvY2tlcnJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx5Q0FBd0M7QUFDeEMsOENBQW9DO0FBUXBDO0lBSUUsWUFBYSxVQUE2QztRQUN4RCxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsQ0FBQyxXQUFXLENBQUE7UUFDekMsSUFBSSxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFBO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQTtJQUNyQyxDQUFDO0lBRUQsTUFBTSxDQUFDLGFBQWEsQ0FBRSxTQUFpQjtRQUNyQyxJQUFJLHNCQUFzQixHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDakQsRUFBRSxDQUFDLENBQUMsc0JBQXNCLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsNkJBQTZCLENBQUMsQ0FBQTtZQUN0RCxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ2YsTUFBTSxDQUFBO1FBQ1IsQ0FBQztRQUNELElBQUksV0FBVyxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQzNDLElBQUksUUFBUSxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hDLElBQUksUUFBUSxHQUFHLHNCQUFzQixDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3hDLE1BQU0sQ0FBQyxJQUFJLGNBQWMsQ0FBQztZQUN4QixXQUFXLEVBQUUsV0FBVztZQUN4QixRQUFRLEVBQUUsUUFBUTtZQUNsQixRQUFRLEVBQUUsUUFBUTtTQUNuQixDQUFDLENBQUE7SUFDSixDQUFDO0lBRUssS0FBSzs7WUFDVCxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxLQUFLLFdBQVcsQ0FBQyxDQUFDLENBQUM7Z0JBQ3JDLE1BQU0saUJBQUksQ0FBQyxtQkFBbUIsSUFBSSxDQUFDLFFBQVEsT0FBTyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtnQkFDbEUsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsa0NBQWtDLENBQUMsQ0FBQTtZQUM1RCxDQUFDO1lBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ04sTUFBTSxpQkFBSSxDQUFDLG1CQUFtQixJQUFJLENBQUMsUUFBUSxPQUFPLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDLENBQUE7WUFDeEYsQ0FBQztZQUNELE9BQU8sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLDRCQUE0QixJQUFJLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQTtRQUM1RSxDQUFDO0tBQUE7Q0FDRjtBQXBDRCx3Q0FvQ0MifQ==
\ No newline at end of file
diff --git a/dist/mod_docker/mod.classes.registrystorage.d.ts b/dist/mod_docker/mod.classes.registrystorage.d.ts
new file mode 100644
index 0000000..1e8e655
--- /dev/null
+++ b/dist/mod_docker/mod.classes.registrystorage.d.ts
@@ -0,0 +1,9 @@
+import { Objectmap } from 'lik';
+import { DockerRegistry } from './mod.classes.dockerregistry';
+export declare class RegistryStorage {
+ objectMap: Objectmap;
+ constructor();
+ addRegistry(registryArg: DockerRegistry): void;
+ getRegistryByUrl(registryUrlArg: string): DockerRegistry;
+ loginAll(): Promise;
+}
diff --git a/dist/mod_docker/mod.classes.registrystorage.js b/dist/mod_docker/mod.classes.registrystorage.js
new file mode 100644
index 0000000..0647df8
--- /dev/null
+++ b/dist/mod_docker/mod.classes.registrystorage.js
@@ -0,0 +1,34 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const lik_1 = require("lik");
+class RegistryStorage {
+ constructor() {
+ this.objectMap = new lik_1.Objectmap();
+ // Nothing here
+ }
+ addRegistry(registryArg) {
+ this.objectMap.add(registryArg);
+ }
+ getRegistryByUrl(registryUrlArg) {
+ return this.objectMap.find(registryArg => {
+ return registryArg.registryUrl === registryUrlArg;
+ });
+ }
+ loginAll() {
+ return __awaiter(this, void 0, void 0, function* () {
+ yield this.objectMap.forEach((registryArg) => __awaiter(this, void 0, void 0, function* () {
+ yield registryArg.login();
+ }));
+ });
+ }
+}
+exports.RegistryStorage = RegistryStorage;
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kLmNsYXNzZXMucmVnaXN0cnlzdG9yYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvbW9kX2RvY2tlci9tb2QuY2xhc3Nlcy5yZWdpc3RyeXN0b3JhZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7OztBQUNBLDZCQUErQjtBQUkvQjtJQUVFO1FBREEsY0FBUyxHQUFHLElBQUksZUFBUyxFQUFrQixDQUFBO1FBRXpDLGVBQWU7SUFDakIsQ0FBQztJQUVELFdBQVcsQ0FBRSxXQUEyQjtRQUN0QyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQTtJQUNqQyxDQUFDO0lBRUQsZ0JBQWdCLENBQUUsY0FBc0I7UUFDdEMsTUFBTSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFdBQVc7WUFDcEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxXQUFXLEtBQUssY0FBYyxDQUFBO1FBQ25ELENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVLLFFBQVE7O1lBQ1osTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFNLFdBQVc7Z0JBQzVDLE1BQU0sV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFBO1lBQzNCLENBQUMsQ0FBQSxDQUFDLENBQUE7UUFDSixDQUFDO0tBQUE7Q0FDRjtBQXJCRCwwQ0FxQkMifQ==
\ No newline at end of file
diff --git a/dist/mod_docker/mod.helpers.d.ts b/dist/mod_docker/mod.helpers.d.ts
new file mode 100644
index 0000000..4ba728b
--- /dev/null
+++ b/dist/mod_docker/mod.helpers.d.ts
@@ -0,0 +1,42 @@
+import { Dockerfile } from './mod.classes.dockerfile';
+/**
+ * creates instance of class Dockerfile for all Dockerfiles in cwd
+ * @returns Promise
+ */
+export declare let readDockerfiles: () => Promise;
+/**
+ * sorts Dockerfiles into a dependency chain
+ * @param sortableArrayArg an array of instances of class Dockerfile
+ * @returns Promise
+ */
+export declare let sortDockerfiles: (sortableArrayArg: Dockerfile[]) => Promise;
+/**
+ * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
+ */
+export declare let mapDockerfiles: (sortedArray: Dockerfile[]) => Promise;
+/**
+ * builds the correspoding real docker image for each Dockerfile class instance
+ */
+export declare let buildDockerfiles: (sortedArrayArg: Dockerfile[]) => Promise;
+/**
+ * tests all Dockerfiles in by calling class Dockerfile.test();
+ * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
+ */
+export declare let testDockerfiles: (sortedArrayArg: Dockerfile[]) => Promise;
+/**
+ * returns a version for a docker file
+ * @execution SYNC
+ */
+export declare let dockerFileVersion: (dockerfileNameArg: string) => string;
+/**
+ * returns the docker base image for a Dockerfile
+ */
+export declare let dockerBaseImage: (dockerfileContentArg: string) => string;
+/**
+ * returns the docker tag
+ */
+export declare let getDockerTagString: (registryArg: string, repoArg: string, versionArg: string, suffixArg?: string) => string;
+/**
+ *
+ */
+export declare let cleanTagsArrayFunction: (dockerfileArrayArg: Dockerfile[], trackingArrayArg: Dockerfile[]) => string[];
diff --git a/dist/mod_docker/mod.helpers.js b/dist/mod_docker/mod.helpers.js
new file mode 100644
index 0000000..87d0fe9
--- /dev/null
+++ b/dist/mod_docker/mod.helpers.js
@@ -0,0 +1,152 @@
+"use strict";
+var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
+ return new (P || (P = Promise))(function (resolve, reject) {
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
+ function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
+ });
+};
+Object.defineProperty(exports, "__esModule", { value: true });
+const plugins = require("./mod.plugins");
+const paths = require("../npmci.paths");
+const mod_classes_dockerfile_1 = require("./mod.classes.dockerfile");
+/**
+ * creates instance of class Dockerfile for all Dockerfiles in cwd
+ * @returns Promise
+ */
+exports.readDockerfiles = () => __awaiter(this, void 0, void 0, function* () {
+ let fileTree = yield plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
+ // create the Dockerfile array
+ let readDockerfilesArray = [];
+ plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`);
+ console.log(fileTree);
+ for (let dockerfilePath of fileTree) {
+ let myDockerfile = new mod_classes_dockerfile_1.Dockerfile({
+ filePath: dockerfilePath,
+ read: true
+ });
+ readDockerfilesArray.push(myDockerfile);
+ }
+ return readDockerfilesArray;
+});
+/**
+ * sorts Dockerfiles into a dependency chain
+ * @param sortableArrayArg an array of instances of class Dockerfile
+ * @returns Promise
+ */
+exports.sortDockerfiles = (sortableArrayArg) => {
+ let done = plugins.q.defer();
+ plugins.beautylog.info('sorting Dockerfiles:');
+ let sortedArray = [];
+ let cleanTagsOriginal = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
+ let sorterFunctionCounter = 0;
+ let sorterFunction = function () {
+ sortableArrayArg.forEach((dockerfileArg) => {
+ let cleanTags = exports.cleanTagsArrayFunction(sortableArrayArg, sortedArray);
+ if (cleanTags.indexOf(dockerfileArg.baseImage) === -1 && sortedArray.indexOf(dockerfileArg) === -1) {
+ sortedArray.push(dockerfileArg);
+ }
+ if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) !== -1) {
+ dockerfileArg.localBaseImageDependent = true;
+ }
+ });
+ if (sortableArrayArg.length === sortedArray.length) {
+ let counter = 1;
+ for (let dockerfile of sortedArray) {
+ plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`);
+ counter++;
+ }
+ done.resolve(sortedArray);
+ }
+ else if (sorterFunctionCounter < 10) {
+ sorterFunctionCounter++;
+ sorterFunction();
+ }
+ };
+ sorterFunction();
+ return done.promise;
+};
+/**
+ * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
+ */
+exports.mapDockerfiles = (sortedArray) => __awaiter(this, void 0, void 0, function* () {
+ sortedArray.forEach((dockerfileArg) => {
+ if (dockerfileArg.localBaseImageDependent) {
+ sortedArray.forEach((dockfile2) => {
+ if (dockfile2.cleanTag === dockerfileArg.baseImage) {
+ dockerfileArg.localBaseDockerfile = dockfile2;
+ }
+ });
+ }
+ });
+ return sortedArray;
+});
+/**
+ * builds the correspoding real docker image for each Dockerfile class instance
+ */
+exports.buildDockerfiles = (sortedArrayArg) => __awaiter(this, void 0, void 0, function* () {
+ for (let dockerfileArg of sortedArrayArg) {
+ yield dockerfileArg.build();
+ }
+ return sortedArrayArg;
+});
+/**
+ * tests all Dockerfiles in by calling class Dockerfile.test();
+ * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
+ */
+exports.testDockerfiles = (sortedArrayArg) => __awaiter(this, void 0, void 0, function* () {
+ for (let dockerfileArg of sortedArrayArg) {
+ yield dockerfileArg.test();
+ }
+ return sortedArrayArg;
+});
+/**
+ * returns a version for a docker file
+ * @execution SYNC
+ */
+exports.dockerFileVersion = (dockerfileNameArg) => {
+ let versionString;
+ let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
+ let regexResultArray = versionRegex.exec(dockerfileNameArg);
+ if (regexResultArray && regexResultArray.length === 2) {
+ versionString = regexResultArray[1];
+ }
+ else {
+ versionString = 'latest';
+ }
+ return versionString;
+};
+/**
+ * returns the docker base image for a Dockerfile
+ */
+exports.dockerBaseImage = function (dockerfileContentArg) {
+ let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
+ let regexResultArray = baseImageRegex.exec(dockerfileContentArg);
+ return regexResultArray[1];
+};
+/**
+ * returns the docker tag
+ */
+exports.getDockerTagString = function (registryArg, repoArg, versionArg, suffixArg) {
+ // determine wether the suffix is needed
+ let version = versionArg;
+ if (suffixArg) {
+ version = versionArg + '_' + suffixArg;
+ }
+ let tagString = `${registryArg}/${repoArg}:${version}`;
+ return tagString;
+};
+/**
+ *
+ */
+exports.cleanTagsArrayFunction = function (dockerfileArrayArg, trackingArrayArg) {
+ let cleanTagsArray = [];
+ dockerfileArrayArg.forEach(function (dockerfileArg) {
+ if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
+ cleanTagsArray.push(dockerfileArg.cleanTag);
+ }
+ });
+ return cleanTagsArray;
+};
+//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9kLmhlbHBlcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi90cy9tb2RfZG9ja2VyL21vZC5oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7QUFBQSx5Q0FBd0M7QUFDeEMsd0NBQXVDO0FBSXZDLHFFQUFxRDtBQUVyRDs7O0dBR0c7QUFDUSxRQUFBLGVBQWUsR0FBRztJQUMzQixJQUFJLFFBQVEsR0FBRyxNQUFNLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFLGFBQWEsQ0FBQyxDQUFBO0lBRWhGLDhCQUE4QjtJQUM5QixJQUFJLG9CQUFvQixHQUFpQixFQUFFLENBQUE7SUFDM0MsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxRQUFRLENBQUMsTUFBTSxlQUFlLENBQUMsQ0FBQTtJQUMvRCxPQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ3JCLEdBQUcsQ0FBQyxDQUFDLElBQUksY0FBYyxJQUFJLFFBQVEsQ0FBQyxDQUFDLENBQUM7UUFDcEMsSUFBSSxZQUFZLEdBQUcsSUFBSSxtQ0FBVSxDQUFDO1lBQ2hDLFFBQVEsRUFBRSxjQUFjO1lBQ3hCLElBQUksRUFBRSxJQUFJO1NBQ1gsQ0FBQyxDQUFBO1FBQ0Ysb0JBQW9CLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFBO0lBQ3pDLENBQUM7SUFFRCxNQUFNLENBQUMsb0JBQW9CLENBQUE7QUFFN0IsQ0FBQyxDQUFBLENBQUE7QUFFRDs7OztHQUlHO0FBQ1EsUUFBQSxlQUFlLEdBQUcsQ0FBQyxnQkFBOEI7SUFDMUQsSUFBSSxJQUFJLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQWdCLENBQUE7SUFDMUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtJQUM5QyxJQUFJLFdBQVcsR0FBaUIsRUFBRSxD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
\ No newline at end of file
diff --git a/package.json b/package.json
index 2267eeb..e4597ab 100644
--- a/package.json
+++ b/package.json
@@ -33,6 +33,7 @@
"cflare": "^1.0.5",
"gulp": "^3.9.1",
"gulp-function": "^2.2.9",
+ "lik": "^1.0.39",
"lodash": "^4.17.4",
"npmextra": "^2.0.9",
"projectinfo": "^3.0.2",
diff --git a/test/test.ts b/test/test.ts
index 602173c..2d318cd 100644
--- a/test/test.ts
+++ b/test/test.ts
@@ -33,7 +33,7 @@ tap.test('should return valid Dockerfiles', async () => {
})
tap.test('should read a directory of Dockerfiles', async () => {
- return npmciModDocker.readDockerfiles()
+ return npmciModDocker.helpers.readDockerfiles()
.then(async (readDockerfilesArrayArg: npmciModDocker.Dockerfile[]) => {
sortableArray = readDockerfilesArrayArg
return expect(readDockerfilesArrayArg[1].version).to.equal('sometag1')
@@ -41,7 +41,7 @@ tap.test('should read a directory of Dockerfiles', async () => {
})
tap.test('should sort an array of Dockerfiles', async () => {
- return npmciModDocker.sortDockerfiles(sortableArray)
+ return npmciModDocker.helpers.sortDockerfiles(sortableArray)
.then(async (sortedArrayArg: npmciModDocker.Dockerfile[]) => {
console.log(sortedArrayArg)
})
diff --git a/ts/mod_docker/index.ts b/ts/mod_docker/index.ts
index e824714..1dbfedd 100644
--- a/ts/mod_docker/index.ts
+++ b/ts/mod_docker/index.ts
@@ -3,6 +3,21 @@ import * as paths from '../npmci.paths'
import * as NpmciEnv from '../npmci.env'
import { bash } from '../npmci.bash'
+import * as helpers from './mod.helpers'
+
+// classes
+import { Dockerfile } from './mod.classes.dockerfile'
+import { DockerRegistry } from './mod.classes.dockerregistry'
+import { RegistryStorage } from './mod.classes.registrystorage'
+
+// instances
+let npmciRegistryStorage = new RegistryStorage()
+
+export {
+ Dockerfile,
+ helpers
+}
+
export let modArgvArg // will be set through the build command
/**
@@ -12,7 +27,7 @@ export let modArgvArg // will be set through the build command
export let handleCli = async (argvArg) => {
modArgvArg = argvArg
if (argvArg._.length >= 2) {
- let action: string = argvArg._[1]
+ let action: string = argvArg._[ 1 ]
switch (action) {
case 'build':
await build()
@@ -23,6 +38,12 @@ export let handleCli = async (argvArg) => {
case 'test':
await test()
break
+ case 'push':
+ await push(argvArg)
+ break
+ case 'pull':
+ await pull(argvArg)
+ break
default:
plugins.beautylog.error(`>>npmci node ...<< action >>${action}<< not supported`)
}
@@ -31,6 +52,16 @@ export let handleCli = async (argvArg) => {
}
}
+/**
+ * builds a cwd of Dockerfiles by triggering a promisechain
+ */
+export let build = async () => {
+ plugins.beautylog.log('now building Dockerfiles...')
+ await helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles)
+ .then(helpers.buildDockerfiles)
+}
/**
* logs in docker
@@ -38,339 +69,58 @@ export let handleCli = async (argvArg) => {
export let prepare = async () => {
NpmciEnv.setDockerRegistry('docker.io') // TODO: checkup why we set this here
- // handle registries
- plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_LOGIN_DOCKER*', async (envString) => {
- let dockerRegexResultArray = envString.split('|')
- if (dockerRegexResultArray.length !== 3) {
- plugins.beautylog.error('malformed docker env var...')
- process.exit(1)
- return
- }
- let registry = dockerRegexResultArray[0]
- let username = dockerRegexResultArray[1]
- let password = dockerRegexResultArray[2]
- if (registry === 'docker.io') {
- await bash(`docker login -u ${username} -p ${password}`)
- plugins.beautylog.info('Logged in to standard docker hub')
- } else {
- await bash(`docker login -u ${username} -p ${password} ${registry}`)
- }
- plugins.beautylog.success(`docker authenticated for ${registry}!`)
- })
-
// Always login to GitLab Registry
if (!process.env.CI_BUILD_TOKEN || process.env.CI_BUILD_TOKEN === '') {
plugins.beautylog.error('No registry token specified by gitlab!')
return
}
- await bash(`docker login -u gitlab-ci-token -p ${process.env.CI_BUILD_TOKEN} registry.gitlab.com`)
- plugins.beautylog.success(`docker authenticated for registry.gitlab.com!`)
+ npmciRegistryStorage.addRegistry(new DockerRegistry({
+ registryUrl: 'registry.gitlab.com',
+ username: 'gitlab-ci-token',
+ password: process.env.CI_BUILD_TOKEN
+ }))
+
+ // handle registries
+ plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_LOGIN_DOCKER*', async (envString) => {
+ npmciRegistryStorage.addRegistry(
+ DockerRegistry.fromEnvString(envString)
+ )
+ await npmciRegistryStorage.loginAll()
+ })
return
}
-/**
- * builds a cwd of Dockerfiles by triggering a promisechain
- */
-export let build = async () => {
- plugins.beautylog.log('now building Dockerfiles...')
- await readDockerfiles()
- .then(sortDockerfiles)
- .then(mapDockerfiles)
- .then(buildDockerfiles)
+export let push = async (argvArg) => {
+ let registryUrlArg = argvArg._[ 2 ]
+ let suffix = null
+ if (argvArg._.length >= 4) {
+ suffix = argvArg._[ 3 ]
+ }
+ let dockerfileArray = await helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles)
+ let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg)
+ for (let dockerfile of dockerfileArray) {
+ dockerfile.push(localDockerRegistry, suffix)
+ }
}
-export let push = async () => {
- await readDockerfiles()
- .then(sortDockerfiles)
- .then(mapDockerfiles)
- .then(pushDockerfiles)
-}
-
-export let pull = async () => {
- return await readDockerfiles()
- .then(pullDockerfileImages)
+export let pull = async (argvArg) => {
+ let registryUrlArg = argvArg._[ 2 ]
+ let suffix = null
+ if (argvArg._.length >= 4) {
+ suffix = argvArg._[ 3 ]
+ }
+ let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg)
+ let dockerfileArray = await helpers.readDockerfiles()
+ .then(helpers.sortDockerfiles)
+ .then(helpers.mapDockerfiles)
+ for (let dockerfile of dockerfileArray) {
+ dockerfile.pull(localDockerRegistry, suffix)
+ }
}
export let test = async () => {
- return await readDockerfiles()
- .then(testDockerfiles)
-}
-
-/**
- * creates instance of class Dockerfile for all Dockerfiles in cwd
- * @returns Promise
- */
-export let readDockerfiles = async (): Promise => {
- let fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*')
-
- // create the Dockerfile array
- let readDockerfilesArray: Dockerfile[] = []
- plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`)
- console.log(fileTree)
- for (let dockerfilePath of fileTree) {
- let myDockerfile = new Dockerfile({
- filePath: dockerfilePath,
- read: true
- })
- readDockerfilesArray.push(myDockerfile)
- }
-
- return readDockerfilesArray
-
-}
-
-/**
- * sorts Dockerfiles into a dependency chain
- * @param sortableArrayArg an array of instances of class Dockerfile
- * @returns Promise
- */
-export let sortDockerfiles = (sortableArrayArg: Dockerfile[]): Promise => {
- let done = plugins.q.defer()
- plugins.beautylog.info('sorting Dockerfiles:')
- let sortedArray: Dockerfile[] = []
- let cleanTagsOriginal = cleanTagsArrayFunction(sortableArrayArg, sortedArray)
- let sorterFunctionCounter: number = 0
- let sorterFunction = function () {
- sortableArrayArg.forEach((dockerfileArg) => {
- let cleanTags = cleanTagsArrayFunction(sortableArrayArg, sortedArray)
- if (cleanTags.indexOf(dockerfileArg.baseImage) === -1 && sortedArray.indexOf(dockerfileArg) === -1) {
- sortedArray.push(dockerfileArg)
- }
- if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) !== -1) {
- dockerfileArg.localBaseImageDependent = true
- }
- })
- if (sortableArrayArg.length === sortedArray.length) {
- let counter = 1
- for (let dockerfile of sortedArray) {
- plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`)
- counter++
- }
- done.resolve(sortedArray)
- } else if (sorterFunctionCounter < 10) {
- sorterFunctionCounter++
- sorterFunction()
- }
- }
- sorterFunction()
- return done.promise
-}
-
-/**
- * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
- */
-export let mapDockerfiles = async (sortedArray: Dockerfile[]): Promise => {
- sortedArray.forEach((dockerfileArg) => {
- if (dockerfileArg.localBaseImageDependent) {
- sortedArray.forEach((dockfile2: Dockerfile) => {
- if (dockfile2.cleanTag === dockerfileArg.baseImage) {
- dockerfileArg.localBaseDockerfile = dockfile2
- }
- })
- }
- })
- return sortedArray
-}
-
-/**
- * builds the correspoding real docker image for each Dockerfile class instance
- */
-export let buildDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
- for (let dockerfileArg of sortedArrayArg) {
- await dockerfileArg.build()
- }
- return sortedArrayArg
-}
-
-/**
- * pushes the real Dockerfile images to a Docker registry
- */
-export let pushDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
- let stageArg = (function () {
- if (modArgvArg._ && modArgvArg._.length >= 3) {
- return modArgvArg._[ 2 ]
- } else {
- return NpmciEnv.buildStage
- }
- })()
- for (let dockerfileArg of sortedArrayArg) {
- await dockerfileArg.push(stageArg)
- }
- return sortedArrayArg
-}
-
-/**
- * pulls corresponding real Docker images for instances of Dockerfile from a registry.
- * This is needed if building, testing, and publishing of Docker images is carried out in seperate CI stages.
- */
-export let pullDockerfileImages = async (sortableArrayArg: Dockerfile[], registryArg = 'registry.gitlab.com') => {
- for (let dockerfileArg of sortableArrayArg) {
- await dockerfileArg.pull(registryArg)
- }
- return sortableArrayArg
-}
-
-/**
- * tests all Dockerfiles in by calling class Dockerfile.test();
- * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
- */
-export let testDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
- for (let dockerfileArg of sortedArrayArg) {
- await dockerfileArg.test()
- }
- return sortedArrayArg
-}
-
-/**
- * class Dockerfile represents a Dockerfile on disk in npmci
- */
-export class Dockerfile {
- filePath: string
- repo: string
- version: string
- cleanTag: string
- buildTag: string
- gitlabTestTag: string
- gitlabReleaseTag: string
- releaseTag: string
- containerName: string
- content: string
- baseImage: string
- localBaseImageDependent: boolean
- localBaseDockerfile: Dockerfile
- constructor(options: { filePath?: string, fileContents?: string | Buffer, read?: boolean }) {
- this.filePath = options.filePath
- this.repo = NpmciEnv.repo.user + '/' + NpmciEnv.repo.repo
- this.version = dockerFileVersion(plugins.path.parse(options.filePath).base)
- this.cleanTag = this.repo + ':' + this.version
- this.buildTag = this.cleanTag
- this.gitlabTestTag = getDockerTagString('docker.io', this.repo, this.version, 'test') // TODO: using docker.io until gitlab is fixed
- this.gitlabReleaseTag = getDockerTagString('docker.io', this.repo, this.version) // TODO: using docker.io until gitlab is fixed
-
- // the releaseTag determines where the image gets released
- this.releaseTag = getDockerTagString('docker.io', this.repo, this.version)
-
- this.containerName = 'dockerfile-' + this.version
- if (options.filePath && options.read) {
- this.content = plugins.smartfile.fs.toStringSync(plugins.path.resolve(options.filePath))
- }
- this.baseImage = dockerBaseImage(this.content)
- this.localBaseImageDependent = false
- }
-
- /**
- * builds the Dockerfile
- */
- async build () {
- plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag)
- let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} .`
- await bash(buildCommand)
- NpmciEnv.dockerFilesBuilt.push(this)
- return
- }
-
- /**
- * pushes the Dockerfile to a registry
- */
- async push (stageArg) {
- await bash(`docker tag ${this.buildTag} ${this.releaseTag}`)
- await bash(`docker tag ${this.buildTag} ${this.gitlabReleaseTag}`)
- await bash(`docker tag ${this.buildTag} ${this.gitlabTestTag}`)
- switch (stageArg) {
- case 'release':
- await bash(`docker push ${this.gitlabReleaseTag}`)
- await bash(`docker push ${this.releaseTag}`)
- break
- case 'test':
- default:
- await bash(`docker push ${this.gitlabTestTag}`)
- break
- }
- }
-
- /**
- * pulls the Dockerfile from a registry
- */
- async pull (registryArg: string) {
- await bash(`docker pull ${this.gitlabTestTag}`)
- await bash(`docker tag ${this.gitlabTestTag} ${this.buildTag}`)
- }
-
- /**
- * tests the Dockerfile;
- */
- async test () {
- let testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh')
- let testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile)
- if (testFileExists) {
- // run tests
- await bash('docker run --name npmci_test_container ' + this.buildTag + ' mkdir /npmci_test')
- await bash('docker cp ' + testFile + ' npmci_test_container:/npmci_test/test.sh')
- await bash('docker commit npmci_test_container npmci_test_image')
- await bash('docker run npmci_test_image sh /npmci_test/test.sh')
- await bash('docker rm npmci_test_container')
- await bash('docker rmi --force npmci_test_image')
- } else {
- plugins.beautylog.warn('skipping tests for ' + this.cleanTag + ' because no testfile was found!')
- }
- }
-
- /**
- * gets the id of a Dockerfile
- */
- async getId () {
- let containerId = await bash('docker inspect --type=image --format=\"{{.Id}}\" ' + this.buildTag)
- return containerId
- }
-}
-
-/**
- * returns a version for a docker file
- * @execution SYNC
- */
-export let dockerFileVersion = (dockerfileNameArg: string): string => {
- let versionString: string
- let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/
- let regexResultArray = versionRegex.exec(dockerfileNameArg)
- if (regexResultArray && regexResultArray.length === 2) {
- versionString = regexResultArray[ 1 ]
- } else {
- versionString = 'latest'
- }
- return versionString
-}
-
-/**
- * returns the docker base image for a Dockerfile
- */
-export let dockerBaseImage = function (dockerfileContentArg: string) {
- let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/
- let regexResultArray = baseImageRegex.exec(dockerfileContentArg)
- return regexResultArray[ 1 ]
-}
-
-/**
- * returns the docker tag
- */
-export let getDockerTagString = function (registryArg: string, repoArg: string, versionArg: string, suffixArg?: string): string {
- // determine wether the suffix is needed
- let version = versionArg
- if (suffixArg) {
- version = versionArg + '_' + suffixArg
- }
- let tagString = `${registryArg}/${repoArg}:${version}`
- return tagString
-}
-
-/**
- *
- */
-export let cleanTagsArrayFunction = function (dockerfileArrayArg: Dockerfile[], trackingArrayArg: Dockerfile[]): string[] {
- let cleanTagsArray: string[] = []
- dockerfileArrayArg.forEach(function (dockerfileArg) {
- if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
- cleanTagsArray.push(dockerfileArg.cleanTag)
- }
- })
- return cleanTagsArray
+ return await helpers.readDockerfiles()
+ .then(helpers.testDockerfiles)
}
diff --git a/ts/mod_docker/mod.classes.dockerfile.ts b/ts/mod_docker/mod.classes.dockerfile.ts
new file mode 100644
index 0000000..dcf0d5b
--- /dev/null
+++ b/ts/mod_docker/mod.classes.dockerfile.ts
@@ -0,0 +1,92 @@
+import * as plugins from './mod.plugins'
+import * as NpmciEnv from '../npmci.env'
+import { bash } from '../npmci.bash'
+import * as paths from '../npmci.paths'
+
+import { DockerRegistry } from './mod.classes.dockerregistry'
+import * as helpers from './mod.helpers'
+
+/**
+ * class Dockerfile represents a Dockerfile on disk in npmci
+ */
+export class Dockerfile {
+ filePath: string
+ repo: string
+ version: string
+ cleanTag: string
+ buildTag: string
+ containerName: string
+ content: string
+ baseImage: string
+ localBaseImageDependent: boolean
+ localBaseDockerfile: Dockerfile
+ constructor (options: { filePath?: string, fileContents?: string | Buffer, read?: boolean }) {
+ this.filePath = options.filePath
+ this.repo = NpmciEnv.repo.user + '/' + NpmciEnv.repo.repo
+ this.version = helpers.dockerFileVersion(plugins.path.parse(options.filePath).base)
+ this.cleanTag = this.repo + ':' + this.version
+ this.buildTag = this.cleanTag
+
+ this.containerName = 'dockerfile-' + this.version
+ if (options.filePath && options.read) {
+ this.content = plugins.smartfile.fs.toStringSync(plugins.path.resolve(options.filePath))
+ }
+ this.baseImage = helpers.dockerBaseImage(this.content)
+ this.localBaseImageDependent = false
+ }
+
+ /**
+ * builds the Dockerfile
+ */
+ async build () {
+ plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag)
+ let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} .`
+ await bash(buildCommand)
+ NpmciEnv.dockerFilesBuilt.push(this)
+ return
+ }
+
+ /**
+ * pushes the Dockerfile to a registry
+ */
+ async push (dockerRegistryArg: DockerRegistry, versionSuffix: string = null) {
+ let pushTag = helpers.getDockerTagString(dockerRegistryArg.registryUrl, this.repo, this.version, versionSuffix)
+ await bash(`docker tag ${this.buildTag} ${pushTag}`)
+ await bash(`docker push ${pushTag}`)
+ }
+
+ /**
+ * pulls the Dockerfile from a registry
+ */
+ async pull (registryArg: DockerRegistry, versionSuffixArg: string = null) {
+ let pullTag = helpers.getDockerTagString(registryArg.registryUrl,this.repo, this.version, versionSuffixArg)
+ await bash(`docker tag ${pullTag} ${this.buildTag}`)
+ }
+
+ /**
+ * tests the Dockerfile;
+ */
+ async test () {
+ let testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh')
+ let testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile)
+ if (testFileExists) {
+ // run tests
+ await bash('docker run --name npmci_test_container ' + this.buildTag + ' mkdir /npmci_test')
+ await bash('docker cp ' + testFile + ' npmci_test_container:/npmci_test/test.sh')
+ await bash('docker commit npmci_test_container npmci_test_image')
+ await bash('docker run npmci_test_image sh /npmci_test/test.sh')
+ await bash('docker rm npmci_test_container')
+ await bash('docker rmi --force npmci_test_image')
+ } else {
+ plugins.beautylog.warn('skipping tests for ' + this.cleanTag + ' because no testfile was found!')
+ }
+ }
+
+ /**
+ * gets the id of a Dockerfile
+ */
+ async getId () {
+ let containerId = await bash('docker inspect --type=image --format=\"{{.Id}}\" ' + this.buildTag)
+ return containerId
+ }
+}
diff --git a/ts/mod_docker/mod.classes.dockerregistry.ts b/ts/mod_docker/mod.classes.dockerregistry.ts
new file mode 100644
index 0000000..e55be99
--- /dev/null
+++ b/ts/mod_docker/mod.classes.dockerregistry.ts
@@ -0,0 +1,46 @@
+import * as plugins from './mod.plugins'
+import { bash } from '../npmci.bash'
+
+export interface IDockerRegistryConstructorOptions {
+ registryUrl: string,
+ username: string,
+ password: string
+}
+
+export class DockerRegistry {
+ registryUrl: string
+ username: string
+ password: string
+ constructor (optionsArg: IDockerRegistryConstructorOptions) {
+ this.registryUrl = optionsArg.registryUrl
+ this.username = optionsArg.username
+ this.password = optionsArg.password
+ }
+
+ static fromEnvString (envString: string): DockerRegistry {
+ let dockerRegexResultArray = envString.split('|')
+ if (dockerRegexResultArray.length !== 3) {
+ plugins.beautylog.error('malformed docker env var...')
+ process.exit(1)
+ return
+ }
+ let registryUrl = dockerRegexResultArray[0]
+ let username = dockerRegexResultArray[1]
+ let password = dockerRegexResultArray[2]
+ return new DockerRegistry({
+ registryUrl: registryUrl,
+ username: username,
+ password: password
+ })
+ }
+
+ async login () {
+ if (this.registryUrl === 'docker.io') {
+ await bash(`docker login -u ${this.username} -p ${this.password}`)
+ plugins.beautylog.info('Logged in to standard docker hub')
+ } else {
+ await bash(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`)
+ }
+ plugins.beautylog.success(`docker authenticated for ${this.registryUrl}!`)
+ }
+}
diff --git a/ts/mod_docker/mod.classes.registrystorage.ts b/ts/mod_docker/mod.classes.registrystorage.ts
new file mode 100644
index 0000000..4badb01
--- /dev/null
+++ b/ts/mod_docker/mod.classes.registrystorage.ts
@@ -0,0 +1,27 @@
+import * as plugins from './mod.plugins'
+import { Objectmap } from 'lik'
+
+import { DockerRegistry } from './mod.classes.dockerregistry'
+
+export class RegistryStorage {
+ objectMap = new Objectmap()
+ constructor () {
+ // Nothing here
+ }
+
+ addRegistry (registryArg: DockerRegistry) {
+ this.objectMap.add(registryArg)
+ }
+
+ getRegistryByUrl (registryUrlArg: string) {
+ return this.objectMap.find(registryArg => {
+ return registryArg.registryUrl === registryUrlArg
+ })
+ }
+
+ async loginAll () {
+ await this.objectMap.forEach(async registryArg => {
+ await registryArg.login()
+ })
+ }
+}
diff --git a/ts/mod_docker/mod.helpers.ts b/ts/mod_docker/mod.helpers.ts
new file mode 100644
index 0000000..5c3fd65
--- /dev/null
+++ b/ts/mod_docker/mod.helpers.ts
@@ -0,0 +1,154 @@
+import * as plugins from './mod.plugins'
+import * as paths from '../npmci.paths'
+import * as NpmciEnv from '../npmci.env'
+import { bash } from '../npmci.bash'
+
+import { Dockerfile } from './mod.classes.dockerfile'
+
+/**
+ * creates instance of class Dockerfile for all Dockerfiles in cwd
+ * @returns Promise
+ */
+export let readDockerfiles = async (): Promise => {
+ let fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*')
+
+ // create the Dockerfile array
+ let readDockerfilesArray: Dockerfile[] = []
+ plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`)
+ console.log(fileTree)
+ for (let dockerfilePath of fileTree) {
+ let myDockerfile = new Dockerfile({
+ filePath: dockerfilePath,
+ read: true
+ })
+ readDockerfilesArray.push(myDockerfile)
+ }
+
+ return readDockerfilesArray
+
+}
+
+/**
+ * sorts Dockerfiles into a dependency chain
+ * @param sortableArrayArg an array of instances of class Dockerfile
+ * @returns Promise
+ */
+export let sortDockerfiles = (sortableArrayArg: Dockerfile[]): Promise => {
+ let done = plugins.q.defer()
+ plugins.beautylog.info('sorting Dockerfiles:')
+ let sortedArray: Dockerfile[] = []
+ let cleanTagsOriginal = cleanTagsArrayFunction(sortableArrayArg, sortedArray)
+ let sorterFunctionCounter: number = 0
+ let sorterFunction = function () {
+ sortableArrayArg.forEach((dockerfileArg) => {
+ let cleanTags = cleanTagsArrayFunction(sortableArrayArg, sortedArray)
+ if (cleanTags.indexOf(dockerfileArg.baseImage) === -1 && sortedArray.indexOf(dockerfileArg) === -1) {
+ sortedArray.push(dockerfileArg)
+ }
+ if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) !== -1) {
+ dockerfileArg.localBaseImageDependent = true
+ }
+ })
+ if (sortableArrayArg.length === sortedArray.length) {
+ let counter = 1
+ for (let dockerfile of sortedArray) {
+ plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`)
+ counter++
+ }
+ done.resolve(sortedArray)
+ } else if (sorterFunctionCounter < 10) {
+ sorterFunctionCounter++
+ sorterFunction()
+ }
+ }
+ sorterFunction()
+ return done.promise
+}
+
+/**
+ * maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
+ */
+export let mapDockerfiles = async (sortedArray: Dockerfile[]): Promise => {
+ sortedArray.forEach((dockerfileArg) => {
+ if (dockerfileArg.localBaseImageDependent) {
+ sortedArray.forEach((dockfile2: Dockerfile) => {
+ if (dockfile2.cleanTag === dockerfileArg.baseImage) {
+ dockerfileArg.localBaseDockerfile = dockfile2
+ }
+ })
+ }
+ })
+ return sortedArray
+}
+
+/**
+ * builds the correspoding real docker image for each Dockerfile class instance
+ */
+export let buildDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
+ for (let dockerfileArg of sortedArrayArg) {
+ await dockerfileArg.build()
+ }
+ return sortedArrayArg
+}
+
+/**
+ * tests all Dockerfiles in by calling class Dockerfile.test();
+ * @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
+ */
+export let testDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
+ for (let dockerfileArg of sortedArrayArg) {
+ await dockerfileArg.test()
+ }
+ return sortedArrayArg
+}
+
+/**
+ * returns a version for a docker file
+ * @execution SYNC
+ */
+export let dockerFileVersion = (dockerfileNameArg: string): string => {
+ let versionString: string
+ let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/
+ let regexResultArray = versionRegex.exec(dockerfileNameArg)
+ if (regexResultArray && regexResultArray.length === 2) {
+ versionString = regexResultArray[ 1 ]
+ } else {
+ versionString = 'latest'
+ }
+ return versionString
+}
+
+/**
+ * returns the docker base image for a Dockerfile
+ */
+export let dockerBaseImage = function (dockerfileContentArg: string) {
+ let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/
+ let regexResultArray = baseImageRegex.exec(dockerfileContentArg)
+ return regexResultArray[ 1 ]
+}
+
+/**
+ * returns the docker tag
+ */
+export let getDockerTagString = function (registryArg: string, repoArg: string, versionArg: string, suffixArg?: string): string {
+ // determine wether the suffix is needed
+ let version = versionArg
+ if (suffixArg) {
+ version = versionArg + '_' + suffixArg
+ }
+ let tagString = `${registryArg}/${repoArg}:${version}`
+ return tagString
+}
+
+/**
+ *
+ */
+export let cleanTagsArrayFunction = function (dockerfileArrayArg: Dockerfile[], trackingArrayArg: Dockerfile[]): string[] {
+ let cleanTagsArray: string[] = []
+ dockerfileArrayArg.forEach(function (dockerfileArg) {
+ if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
+ cleanTagsArray.push(dockerfileArg.cleanTag)
+ }
+ })
+ return cleanTagsArray
+}
diff --git a/yarn.lock b/yarn.lock
index d1b2b50..9d84a9a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1501,9 +1501,9 @@ liftoff@^2.1.0:
rechoir "^0.6.2"
resolve "^1.1.7"
-lik@^1.0.30, lik@^1.0.38:
- version "1.0.38"
- resolved "https://registry.yarnpkg.com/lik/-/lik-1.0.38.tgz#ccff0abd3d9236a5e4b7d80d514c5c210f18469b"
+lik@^1.0.30, lik@^1.0.38, lik@^1.0.39:
+ version "1.0.39"
+ resolved "https://registry.yarnpkg.com/lik/-/lik-1.0.39.tgz#20eeaa93167a19f03ba2c9650939145326051ee6"
dependencies:
"@types/lodash" "^4.14.67"
"@types/minimatch" "2.x.x"