Compare commits
	
		
			65 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6c58864fcf | |||
| 7ea3ac182d | |||
| 8979d26005 | |||
| c8876dac88 | |||
| 9c8a257c2a | |||
| 8b77930ece | |||
| ba672d030f | |||
| 8ad7e016e7 | |||
| d843311d7b | |||
| 14ef2cfa9b | |||
| 648effcf86 | |||
| 572738e88f | |||
| 129ae93044 | |||
| e910892231 | |||
| 6d9cabf7ee | |||
| 7c7787e811 | |||
| bde26cc312 | |||
| 29e81f3ae7 | |||
| 6337b20d62 | |||
| 6dd537fe43 | |||
| 7191b172a4 | |||
| 9a4611b70f | |||
| 189dbc3654 | |||
| fc95fc96ed | |||
| 467eed57d7 | |||
| a5ca5444a0 | |||
| 17610cb834 | |||
| e1f2b5c6fe | |||
| edbbae0bd0 | |||
| 0e820bec27 | |||
| 91a3d612c6 | |||
| c696730e55 | |||
| 38d38ce246 | |||
| adfdf68c38 | |||
| d4a4d69941 | |||
| c1fed2c758 | |||
| 9918d81f59 | |||
| 59d8338f6e | |||
| a4f8bd3320 | |||
| 7c2fdb7224 | |||
| 37384aeb57 | |||
| 60efda263f | |||
| 19831037ec | |||
| a1d52af813 | |||
| 0a49ff9b03 | |||
| ca62326b46 | |||
| e1de0ee479 | |||
| 0dea101c07 | |||
| 380a49c59f | |||
| 5133651e34 | |||
| c8f26c7c48 | |||
| 3bb5912046 | |||
| d75258d9dd | |||
| b1577e7542 | |||
| d5cdeffd17 | |||
| c62ce415e9 | |||
| 99014da1e8 | |||
| 0b5dada524 | |||
| 40bddba3b5 | |||
| 6f6ee6d799 | |||
| e30cc3f5a0 | |||
| a4562d4d1b | |||
| 524b405773 | |||
| 0d19c1c68d | |||
| cff79bc3b4 | 
							
								
								
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,7 +1,22 @@ | ||||
| dist/ | ||||
| node_modules/ | ||||
| .nogit/ | ||||
|  | ||||
| # artifacts | ||||
| coverage/ | ||||
| public/ | ||||
| config.json | ||||
| pages/ | ||||
|  | ||||
| # installs | ||||
| node_modules/ | ||||
|  | ||||
| # caches | ||||
| .yarn/ | ||||
| .npmci_cache | ||||
| .cache/ | ||||
| .rpt2_cache | ||||
|  | ||||
| # builds | ||||
| dist/ | ||||
| dist_web/ | ||||
| dist_serve/ | ||||
| dist_ts_web/ | ||||
|  | ||||
| # custom | ||||
| @@ -1,5 +1,5 @@ | ||||
| # gitzone standard | ||||
| image: hosttoday/ht-docker-node:npmci | ||||
| # gitzone ci_default | ||||
| image: registry.gitlab.com/hosttoday/ht-docker-node:npmci | ||||
|  | ||||
| cache: | ||||
|   paths: | ||||
| @@ -38,19 +38,7 @@ snyk: | ||||
| # test stage | ||||
| # ==================== | ||||
|  | ||||
| testLTS: | ||||
|   stage: test | ||||
|   script: | ||||
|   - npmci npm prepare | ||||
|   - npmci node install lts | ||||
|   - npmci npm install | ||||
|   - npmci npm test | ||||
|   coverage: /\d+.?\d+?\%\s*coverage/ | ||||
|   tags: | ||||
|   - docker | ||||
|   - notpriv | ||||
|      | ||||
| testSTABLE: | ||||
| testStable: | ||||
|   stage: test | ||||
|   script: | ||||
|   - npmci npm prepare | ||||
| @@ -60,12 +48,24 @@ testSTABLE: | ||||
|   coverage: /\d+.?\d+?\%\s*coverage/ | ||||
|   tags: | ||||
|   - docker | ||||
|   - priv | ||||
|  | ||||
| testBuild: | ||||
|   stage: test | ||||
|   script: | ||||
|   - npmci npm prepare | ||||
|   - npmci node install lts | ||||
|   - npmci npm install | ||||
|   - npmci command npm run build | ||||
|   coverage: /\d+.?\d+?\%\s*coverage/ | ||||
|   tags: | ||||
|   - docker | ||||
|   - notpriv | ||||
|  | ||||
| release: | ||||
|   stage: release | ||||
|   script: | ||||
|   - npmci node install stable | ||||
|   - npmci node install lts | ||||
|   - npmci npm publish | ||||
|   only: | ||||
|   - tags | ||||
| @@ -78,19 +78,11 @@ release: | ||||
| # ==================== | ||||
| codequality: | ||||
|   stage: metadata | ||||
|   image: docker:stable | ||||
|   allow_failure: true | ||||
|   services: | ||||
|     - docker:stable-dind | ||||
|   script: | ||||
|     - export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/') | ||||
|     - docker run | ||||
|         --env SOURCE_CODE="$PWD" | ||||
|         --volume "$PWD":/code | ||||
|         --volume /var/run/docker.sock:/var/run/docker.sock | ||||
|         "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code | ||||
|   artifacts: | ||||
|     paths: [codeclimate.json] | ||||
|     - npmci command npm install -g tslint typescript | ||||
|     - npmci npm install | ||||
|     - npmci command "tslint -c tslint.json ./ts/**/*.ts" | ||||
|   tags: | ||||
|   - docker | ||||
|   - priv | ||||
| @@ -106,13 +98,15 @@ trigger: | ||||
|   - notpriv | ||||
|  | ||||
| pages: | ||||
|   image: hosttoday/ht-docker-node:npmci | ||||
|   image: hosttoday/ht-docker-dbase:npmci | ||||
|   services: | ||||
|    - docker:stable-dind | ||||
|   stage: metadata | ||||
|   script: | ||||
|     - npmci command npm install -g typedoc typescript | ||||
|     - npmci command npm install -g @gitzone/tsdoc | ||||
|     - npmci npm prepare | ||||
|     - npmci npm install | ||||
|     - npmci command typedoc --module "commonjs" --target "ES2016" --out public/ ts/ | ||||
|     - npmci command tsdoc | ||||
|   tags: | ||||
|     - docker | ||||
|     - notpriv | ||||
|   | ||||
							
								
								
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| { | ||||
|   "workbench.colorCustomizations": {} | ||||
| } | ||||
| @@ -1,16 +1,21 @@ | ||||
| { | ||||
|     "npmts":{ | ||||
|         "mode":"default", | ||||
|         "coverageTreshold": "70", | ||||
|         "cli": true | ||||
|     }, | ||||
|   "npmci": { | ||||
|     "npmGlobalTools": [], | ||||
|     "npmAccessLevel": "public", | ||||
|     "npmRegistryUrl": "registry.npmjs.org" | ||||
|   }, | ||||
|     "npmdocker":{ | ||||
|         "baseImage":"hosttoday/ht-docker-node:npmci", | ||||
|   "npmdocker": { | ||||
|     "baseImage": "hosttoday/ht-docker-node:npmci", | ||||
|     "command": "npmci test stable" | ||||
|   }, | ||||
|   "gitzone": { | ||||
|     "module": { | ||||
|       "githost": "gitlab.com", | ||||
|       "gitscope": "shipzone", | ||||
|       "gitrepo": "npmci", | ||||
|       "shortDescription": "node and docker in gitlab ci on steroids", | ||||
|       "npmPackagename": "@shipzone/npmci", | ||||
|       "license": "MIT" | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										4851
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4851
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										69
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								package.json
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|   "name": "@shipzone/npmci", | ||||
|   "version": "3.1.19", | ||||
|   "version": "3.1.52", | ||||
|   "private": false, | ||||
|   "description": "node and docker in gitlab ci on steroids", | ||||
|   "main": "dist/index.js", | ||||
| @@ -9,8 +9,8 @@ | ||||
|     "npmci": "cli.js" | ||||
|   }, | ||||
|   "scripts": { | ||||
|     "test": "(rm -f config.json) && tstest test/", | ||||
|     "build": "(rm -f config.json) && tsbuild && (npm run testVersion)", | ||||
|     "test": "tstest test/", | ||||
|     "build": "tsbuild && (npm run testVersion)", | ||||
|     "testVersion": "(cd test/assets/ && node ../../cli.js -v)" | ||||
|   }, | ||||
|   "repository": { | ||||
| @@ -24,35 +24,48 @@ | ||||
|   }, | ||||
|   "homepage": "https://gitlab.com/gitzone/npmci#README", | ||||
|   "devDependencies": { | ||||
|     "@gitzone/tsbuild": "^2.0.22", | ||||
|     "@gitzone/tsrun": "^1.1.13", | ||||
|     "@gitzone/tstest": "^1.0.15", | ||||
|     "@pushrocks/tapbundle": "^3.0.7", | ||||
|     "@types/node": "^10.12.10", | ||||
|     "tslint": "^5.11.0", | ||||
|     "tslint-config-prettier": "^1.17.0" | ||||
|     "@gitzone/tsbuild": "^2.1.17", | ||||
|     "@gitzone/tsrun": "^1.2.6", | ||||
|     "@gitzone/tstest": "^1.0.24", | ||||
|     "@pushrocks/tapbundle": "^3.0.13", | ||||
|     "@types/node": "^12.7.3", | ||||
|     "tslint": "^5.19.0", | ||||
|     "tslint-config-prettier": "^1.18.0" | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@pushrocks/lik": "^3.0.2", | ||||
|     "@pushrocks/npmextra": "^3.0.1", | ||||
|     "@apiglobal/typedrequest": "^1.0.17", | ||||
|     "@pushrocks/lik": "^3.0.11", | ||||
|     "@pushrocks/npmextra": "^3.0.5", | ||||
|     "@pushrocks/projectinfo": "^4.0.2", | ||||
|     "@pushrocks/smartcli": "^3.0.6", | ||||
|     "@pushrocks/smartdelay": "^2.0.2", | ||||
|     "@pushrocks/smartfile": "^6.0.11", | ||||
|     "@pushrocks/smartlog": "^2.0.9", | ||||
|     "@pushrocks/smartlog-destination-local": "^7.0.5", | ||||
|     "@pushrocks/qenv": "^4.0.4", | ||||
|     "@pushrocks/smartanalytics": "^2.0.15", | ||||
|     "@pushrocks/smartcli": "^3.0.7", | ||||
|     "@pushrocks/smartdelay": "^2.0.3", | ||||
|     "@pushrocks/smartfile": "^7.0.2", | ||||
|     "@pushrocks/smartgit": "^1.0.13", | ||||
|     "@pushrocks/smartlog": "^2.0.19", | ||||
|     "@pushrocks/smartlog-destination-local": "^8.0.2", | ||||
|     "@pushrocks/smartparam": "^1.0.4", | ||||
|     "@pushrocks/smartpromise": "^2.0.5", | ||||
|     "@pushrocks/smartrequest": "^1.1.14", | ||||
|     "@pushrocks/smartshell": "^2.0.11", | ||||
|     "@pushrocks/smartpromise": "^3.0.2", | ||||
|     "@pushrocks/smartrequest": "^1.1.23", | ||||
|     "@pushrocks/smartshell": "^2.0.25", | ||||
|     "@pushrocks/smartsocket": "^1.1.45", | ||||
|     "@pushrocks/smartssh": "^1.2.3", | ||||
|     "@pushrocks/smartstring": "^3.0.5", | ||||
|     "@types/lodash": "^4.14.118", | ||||
|     "@types/shelljs": "^0.8.0", | ||||
|     "@pushrocks/smartstring": "^3.0.10", | ||||
|     "@servezone/servezone-interfaces": "^2.0.29", | ||||
|     "@types/shelljs": "^0.8.5", | ||||
|     "@types/through2": "^2.0.34", | ||||
|     "lodash": "^4.17.11", | ||||
|     "smartanalytics": "^2.0.9", | ||||
|     "smartsocket": "^1.1.19", | ||||
|     "through2": "^3.0.0" | ||||
|   } | ||||
|     "through2": "^3.0.1" | ||||
|   }, | ||||
|   "files": [ | ||||
|     "ts/*", | ||||
|     "ts_web/*", | ||||
|     "dist/*", | ||||
|     "dist_web/*", | ||||
|     "dist_ts_web/*", | ||||
|     "assets/*", | ||||
|     "cli.js", | ||||
|     "npmextra.json", | ||||
|     "readme.md" | ||||
|   ] | ||||
| } | ||||
|   | ||||
							
								
								
									
										37
									
								
								readme.md
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								readme.md
									
									
									
									
									
								
							| @@ -1,25 +1,20 @@ | ||||
| # npmci | ||||
|  | ||||
| # @shipzone/npmci | ||||
| node and docker in gitlab ci on steroids | ||||
|  | ||||
| ## Availabililty | ||||
|  | ||||
| [](https://www.npmjs.com/package/@shipzone/npmci) | ||||
| [](https://GitLab.com/shipzone/npmci) | ||||
| [](https://github.com/shipzone/npmci) | ||||
| [](https://shipzone.gitlab.io/npmci/) | ||||
| ## Availabililty and Links | ||||
| * [npmjs.org (npm package)](https://www.npmjs.com/package/@shipzone/npmci) | ||||
| * [gitlab.com (source)](https://gitlab.com/shipzone/npmci) | ||||
| * [github.com (source mirror)](https://github.com/shipzone/npmci) | ||||
| * [docs (typedoc)](https://shipzone.gitlab.io/npmci/) | ||||
|  | ||||
| ## Status for master | ||||
|  | ||||
| [](https://GitLab.com/shipzone/npmci/commits/master) | ||||
| [](https://GitLab.com/shipzone/npmci/commits/master) | ||||
| [](https://www.npmjs.com/package/@shipzone/npmci) | ||||
| [](https://david-dm.org/shipzone/npmci) | ||||
| [](https://www.bithound.io/github/shipzone/npmci/master/dependencies/npm) | ||||
| [](https://www.bithound.io/github/shipzone/npmci) | ||||
| [](https://nodejs.org/dist/latest-v6.x/docs/api/) | ||||
| [](https://nodejs.org/dist/latest-v6.x/docs/api/) | ||||
| [](http://standardjs.com/) | ||||
| [](https://gitlab.com/shipzone/npmci/commits/master) | ||||
| [](https://gitlab.com/shipzone/npmci/commits/master) | ||||
| [](https://www.npmjs.com/package/@shipzone/npmci) | ||||
| [](https://snyk.io/test/npm/@shipzone/npmci) | ||||
| [](https://nodejs.org/dist/latest-v10.x/docs/api/) | ||||
| [](https://nodejs.org/dist/latest-v10.x/docs/api/) | ||||
| [](https://prettier.io/) | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| @@ -98,9 +93,9 @@ For further information read the linked docs at the top of this README. | ||||
|  | ||||
| Use TypeScript for best in class instellisense. | ||||
|  | ||||
| For further information read the linked docs at the top of this README. | ||||
| For further information read the linked docs at the top of this readme. | ||||
|  | ||||
| > MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh) | ||||
| > | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html) | ||||
| | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy) | ||||
|  | ||||
| [](https://push.rocks) | ||||
| [](https://maintainedby.lossless.com) | ||||
|   | ||||
							
								
								
									
										63
									
								
								test/test.ts
									
									
									
									
									
								
							
							
						
						
									
										63
									
								
								test/test.ts
									
									
									
									
									
								
							| @@ -1,7 +1,6 @@ | ||||
| import { tap, expect } from '@pushrocks/tapbundle'; | ||||
| import * as path from 'path'; | ||||
|  | ||||
| // Setup test | ||||
| process.env.NPMTS_TEST = 'true'; | ||||
|  | ||||
| // set up environment | ||||
| @@ -18,66 +17,72 @@ process.cwd = () => { | ||||
|   return path.join(__dirname, 'assets/'); | ||||
| }; | ||||
|  | ||||
| // require NPMCI files | ||||
| import '../ts/index'; | ||||
| import npmciModDocker = require('../ts/mod_docker/index'); | ||||
| import npmciModNpm = require('../ts/mod_npm/index'); | ||||
| import npmciModNode = require('../ts/mod_node/index'); | ||||
| import npmciModSsh = require('../ts/mod_ssh/index'); | ||||
| import npmciEnv = require('../ts/npmci.env'); | ||||
| import * as npmci from '../ts'; | ||||
|  | ||||
| // ====== | ||||
| // Docker | ||||
| // ====== | ||||
|  | ||||
| let dockerfile1: npmciModDocker.Dockerfile; | ||||
| let dockerfile2: npmciModDocker.Dockerfile; | ||||
| let sortableArray: npmciModDocker.Dockerfile[]; | ||||
| let dockerfile1: npmci.Dockerfile; | ||||
| let dockerfile2: npmci.Dockerfile; | ||||
| let sortableArray: npmci.Dockerfile[]; | ||||
|  | ||||
| tap.test('should return valid Dockerfiles', async () => { | ||||
|   dockerfile1 = new npmciModDocker.Dockerfile({ filePath: './Dockerfile', read: true }); | ||||
|   dockerfile2 = new npmciModDocker.Dockerfile({ filePath: './Dockerfile_sometag1', read: true }); | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   dockerfile1 = new npmci.Dockerfile(npmciInstance.dockerManager, { | ||||
|     filePath: './Dockerfile', | ||||
|     read: true | ||||
|   }); | ||||
|   dockerfile2 = new npmci.Dockerfile(npmciInstance.dockerManager, { | ||||
|     filePath: './Dockerfile_sometag1', | ||||
|     read: true | ||||
|   }); | ||||
|   expect(dockerfile1.version).to.equal('latest'); | ||||
|   return expect(dockerfile2.version).to.equal('sometag1'); | ||||
| }); | ||||
|  | ||||
| tap.test('should read a directory of Dockerfiles', async () => { | ||||
|   return npmciModDocker.helpers | ||||
|     .readDockerfiles() | ||||
|     .then(async (readDockerfilesArrayArg: npmciModDocker.Dockerfile[]) => { | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   return npmci.Dockerfile.readDockerfiles(npmciInstance.dockerManager).then( | ||||
|     async (readDockerfilesArrayArg: npmci.Dockerfile[]) => { | ||||
|       sortableArray = readDockerfilesArrayArg; | ||||
|       return expect(readDockerfilesArrayArg[1].version).to.equal('sometag1'); | ||||
|     }); | ||||
|     } | ||||
|   ); | ||||
| }); | ||||
|  | ||||
| tap.test('should sort an array of Dockerfiles', async () => { | ||||
|   return npmciModDocker.helpers | ||||
|     .sortDockerfiles(sortableArray) | ||||
|     .then(async (sortedArrayArg: npmciModDocker.Dockerfile[]) => { | ||||
|   return npmci.Dockerfile.sortDockerfiles(sortableArray).then( | ||||
|     async (sortedArrayArg: npmci.Dockerfile[]) => { | ||||
|       console.log(sortedArrayArg); | ||||
|     }); | ||||
|     } | ||||
|   ); | ||||
| }); | ||||
|  | ||||
| tap.test('should build all Dockerfiles', async () => { | ||||
|   return npmciModDocker.handleCli({ | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   return npmciInstance.dockerManager.handleCli({ | ||||
|     _: ['docker', 'build'] | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| tap.test('should test all Dockerfiles', async () => { | ||||
|   return await npmciModDocker.handleCli({ | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   return npmciInstance.dockerManager.handleCli({ | ||||
|     _: ['docker', 'test'] | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| tap.test('should test dockerfiles', async () => { | ||||
|   return await npmciModDocker.handleCli({ | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   return npmciInstance.dockerManager.handleCli({ | ||||
|     _: ['docker', 'test'] | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| tap.test('should login docker daemon', async () => { | ||||
|   return await npmciModDocker.handleCli({ | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   return npmciInstance.dockerManager.handleCli({ | ||||
|     _: ['docker', 'login'] | ||||
|   }); | ||||
| }); | ||||
| @@ -86,6 +91,7 @@ tap.test('should login docker daemon', async () => { | ||||
| // SSH | ||||
| // === | ||||
| tap.test('should prepare SSH keys', async () => { | ||||
|   const npmciModSsh = await import('../ts/mod_ssh'); | ||||
|   return await npmciModSsh.handleCli({ | ||||
|     _: ['ssh', 'prepare'] | ||||
|   }); | ||||
| @@ -95,13 +101,14 @@ tap.test('should prepare SSH keys', async () => { | ||||
| // node | ||||
| // ==== | ||||
| tap.test('should install a certain version of node', async () => { | ||||
|   await npmciModNode.handleCli({ | ||||
|   const npmciInstance = new npmci.Npmci(); | ||||
|   await npmciInstance.nodejsManager.handleCli({ | ||||
|     _: ['node', 'install', 'stable'] | ||||
|   }); | ||||
|   await npmciModNode.handleCli({ | ||||
|   await npmciInstance.nodejsManager.handleCli({ | ||||
|     _: ['node', 'install', 'lts'] | ||||
|   }); | ||||
|   await npmciModNode.handleCli({ | ||||
|   await npmciInstance.nodejsManager.handleCli({ | ||||
|     _: ['node', 'install', 'legacy'] | ||||
|   }); | ||||
| }); | ||||
|   | ||||
							
								
								
									
										30
									
								
								ts/connector.cloudly/cloudlyconnector.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								ts/connector.cloudly/cloudlyconnector.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| import * as plugins from '../npmci.plugins'; | ||||
|  | ||||
| import {Npmci} from '../npmci.classes.npmci'; | ||||
| import { logger } from '../npmci.logging'; | ||||
|  | ||||
| /** | ||||
|  * connects to cloudly | ||||
|  */ | ||||
| export class CloudlyConnector { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   constructor(npmciRefArg: Npmci) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   public async announceDockerContainer(optionsArg: plugins.servezoneInterfaces.IVersionData) { | ||||
|     const cloudlyUrl = this.npmciRef.npmciConfig.getConfig().urlCloudly; | ||||
|     if (!cloudlyUrl) { | ||||
|       logger.log('warn', 'no cloudly url provided. Thus we cannot announce the newly built Dockerimage!'); | ||||
|       return; | ||||
|     } | ||||
|      | ||||
|     const typedrequest = new plugins.typedrequest.TypedRequest< | ||||
|       plugins.servezoneInterfaces.IRequest_Any_Cloudly_VersionManager_Update | ||||
|     >(`https://${cloudlyUrl}/versionmanager`, 'update'); | ||||
|  | ||||
|     const response = (await typedrequest.fire(optionsArg)); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										11
									
								
								ts/index.ts
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								ts/index.ts
									
									
									
									
									
								
							| @@ -1 +1,10 @@ | ||||
| import './npmci.cli'; | ||||
| import { Npmci } from './npmci.classes.npmci'; | ||||
| import { Dockerfile } from './manager.docker/mod.classes.dockerfile'; | ||||
|  | ||||
| export const npmciInstance = new Npmci(); | ||||
|  | ||||
| export { Dockerfile, Npmci }; | ||||
|  | ||||
| if (process.env.CLI_CALL) { | ||||
|   npmciInstance.start(); | ||||
| } | ||||
|   | ||||
							
								
								
									
										177
									
								
								ts/manager.docker/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								ts/manager.docker/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
| import { bash } from '../npmci.bash'; | ||||
|  | ||||
| // classes | ||||
| import { Npmci } from '../npmci.classes.npmci'; | ||||
| import { Dockerfile } from './mod.classes.dockerfile'; | ||||
| import { DockerRegistry } from './mod.classes.dockerregistry'; | ||||
| import { RegistryStorage } from './mod.classes.registrystorage'; | ||||
|  | ||||
| export class NpmciDockerManager { | ||||
|   public npmciRef: Npmci; | ||||
|   public npmciRegistryStorage = new RegistryStorage(); | ||||
|  | ||||
|   constructor(npmciArg: Npmci) { | ||||
|     this.npmciRef = npmciArg; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * handle cli input | ||||
|    * @param argvArg | ||||
|    */ | ||||
|   public handleCli = async argvArg => { | ||||
|     if (argvArg._.length >= 2) { | ||||
|       const action: string = argvArg._[1]; | ||||
|       switch (action) { | ||||
|         case 'build': | ||||
|           await this.build(); | ||||
|           break; | ||||
|         case 'login': | ||||
|         case 'prepare': | ||||
|           await this.login(); | ||||
|           break; | ||||
|         case 'test': | ||||
|           await this.test(); | ||||
|           break; | ||||
|         case 'push': | ||||
|           await this.push(argvArg); | ||||
|           break; | ||||
|         case 'pull': | ||||
|           await this.pull(argvArg); | ||||
|           break; | ||||
|         default: | ||||
|           logger.log('error', `>>npmci docker ...<< action >>${action}<< not supported`); | ||||
|       } | ||||
|     } else { | ||||
|       logger.log( | ||||
|         'info', | ||||
|         `>>npmci docker ...<< cli arguments invalid... Please read the documentation.` | ||||
|       ); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * builds a cwd of Dockerfiles by triggering a promisechain | ||||
|    */ | ||||
|   public build = async () => { | ||||
|     await this.prepare(); | ||||
|     logger.log('info', 'now building Dockerfiles...'); | ||||
|     await Dockerfile.readDockerfiles(this) | ||||
|       .then(Dockerfile.sortDockerfiles) | ||||
|       .then(Dockerfile.mapDockerfiles) | ||||
|       .then(Dockerfile.buildDockerfiles); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * login to the DockerRegistries | ||||
|    */ | ||||
|   public login = async () => { | ||||
|     await this.prepare(); | ||||
|     await this.npmciRegistryStorage.loginAll(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * logs in docker | ||||
|    */ | ||||
|   public prepare = async () => { | ||||
|     // Always login to GitLab Registry | ||||
|     if (!process.env.CI_BUILD_TOKEN || process.env.CI_BUILD_TOKEN === '') { | ||||
|       logger.log('error', 'No registry token specified by gitlab!'); | ||||
|       process.exit(1); | ||||
|     } | ||||
|     this.npmciRegistryStorage.addRegistry( | ||||
|       new DockerRegistry({ | ||||
|         registryUrl: 'registry.gitlab.com', | ||||
|         username: 'gitlab-ci-token', | ||||
|         password: process.env.CI_BUILD_TOKEN | ||||
|       }) | ||||
|     ); | ||||
|  | ||||
|     // handle registries | ||||
|     await plugins.smartparam.forEachMinimatch( | ||||
|       process.env, | ||||
|       'NPMCI_LOGIN_DOCKER*', | ||||
|       async envString => { | ||||
|         this.npmciRegistryStorage.addRegistry(DockerRegistry.fromEnvString(envString)); | ||||
|       } | ||||
|     ); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * pushes an image towards a registry | ||||
|    * @param argvArg | ||||
|    */ | ||||
|   public push = async argvArg => { | ||||
|     await this.prepare(); | ||||
|     let dockerRegistryUrls: string[] = []; | ||||
|  | ||||
|     // lets parse the input of cli and npmextra | ||||
|     if (argvArg._.length >= 3 && argvArg._[2] !== 'npmextra') { | ||||
|       dockerRegistryUrls.push(argvArg._[2]); | ||||
|     } else { | ||||
|       if (this.npmciRef.npmciConfig.getConfig().dockerRegistries.length === 0) { | ||||
|         logger.log( | ||||
|           'warn', | ||||
|           `There are no docker registries listed in npmextra.json! This is strange!` | ||||
|         ); | ||||
|       } | ||||
|       dockerRegistryUrls = dockerRegistryUrls.concat( | ||||
|         this.npmciRef.npmciConfig.getConfig().dockerRegistries | ||||
|       ); | ||||
|     } | ||||
|  | ||||
|     // lets determine the suffix | ||||
|     let suffix = null; | ||||
|     if (argvArg._.length >= 4) { | ||||
|       suffix = argvArg._[3]; | ||||
|     } | ||||
|  | ||||
|     // lets push to the registries | ||||
|     for (const dockerRegistryUrl of dockerRegistryUrls) { | ||||
|       const dockerfileArray = await Dockerfile.readDockerfiles(this) | ||||
|         .then(Dockerfile.sortDockerfiles) | ||||
|         .then(Dockerfile.mapDockerfiles); | ||||
|       const dockerRegistryToPushTo = this.npmciRegistryStorage.getRegistryByUrl(dockerRegistryUrl); | ||||
|       if (!dockerRegistryToPushTo) { | ||||
|         logger.log( | ||||
|           'error', | ||||
|           `Cannot push to registry ${dockerRegistryUrl}, because it was not found in the authenticated registry list.` | ||||
|         ); | ||||
|         process.exit(1); | ||||
|       } | ||||
|       for (const dockerfile of dockerfileArray) { | ||||
|         await dockerfile.push(dockerRegistryToPushTo, suffix); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * pulls an image | ||||
|    */ | ||||
|   public pull = async argvArg => { | ||||
|     await this.prepare(); | ||||
|     const registryUrlArg = argvArg._[2]; | ||||
|     let suffix = null; | ||||
|     if (argvArg._.length >= 4) { | ||||
|       suffix = argvArg._[3]; | ||||
|     } | ||||
|     const localDockerRegistry = this.npmciRegistryStorage.getRegistryByUrl(registryUrlArg); | ||||
|     const dockerfileArray = await Dockerfile.readDockerfiles(this) | ||||
|       .then(Dockerfile.sortDockerfiles) | ||||
|       .then(Dockerfile.mapDockerfiles); | ||||
|     for (const dockerfile of dockerfileArray) { | ||||
|       await dockerfile.pull(localDockerRegistry, suffix); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * tests docker files | ||||
|    */ | ||||
|   public test = async () => { | ||||
|     await this.prepare(); | ||||
|     return await Dockerfile.readDockerfiles(this).then(Dockerfile.testDockerfiles); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										328
									
								
								ts/manager.docker/mod.classes.dockerfile.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										328
									
								
								ts/manager.docker/mod.classes.dockerfile.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,328 @@ | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
|  | ||||
| import { logger } from '../npmci.logging'; | ||||
| import { bash } from '../npmci.bash'; | ||||
|  | ||||
| import { DockerRegistry } from './mod.classes.dockerregistry'; | ||||
| import * as helpers from './mod.helpers'; | ||||
| import { NpmciDockerManager } from '.'; | ||||
| import { Npmci } from '../npmci.classes.npmci'; | ||||
|  | ||||
| /** | ||||
|  * class Dockerfile represents a Dockerfile on disk in npmci | ||||
|  */ | ||||
| export class Dockerfile { | ||||
|   // STATIC | ||||
|  | ||||
|   /** | ||||
|    * creates instance of class Dockerfile for all Dockerfiles in cwd | ||||
|    * @returns Promise<Dockerfile[]> | ||||
|    */ | ||||
|   public static async readDockerfiles( | ||||
|     npmciDockerManagerRefArg: NpmciDockerManager | ||||
|   ): Promise<Dockerfile[]> { | ||||
|     const fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*'); | ||||
|  | ||||
|     // create the Dockerfile array | ||||
|     const readDockerfilesArray: Dockerfile[] = []; | ||||
|     logger.log('info', `found ${fileTree.length} Dockerfiles:`); | ||||
|     console.log(fileTree); | ||||
|     for (const dockerfilePath of fileTree) { | ||||
|       const myDockerfile = new Dockerfile(npmciDockerManagerRefArg, { | ||||
|         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<Dockerfile[]> | ||||
|    */ | ||||
|   public static async sortDockerfiles(sortableArrayArg: Dockerfile[]): Promise<Dockerfile[]> { | ||||
|     const done = plugins.smartpromise.defer<Dockerfile[]>(); | ||||
|     logger.log('info', 'sorting Dockerfiles:'); | ||||
|     const sortedArray: Dockerfile[] = []; | ||||
|     const cleanTagsOriginal = Dockerfile.cleanTagsArrayFunction(sortableArrayArg, sortedArray); | ||||
|     let sorterFunctionCounter: number = 0; | ||||
|     const sorterFunction = () => { | ||||
|       sortableArrayArg.forEach(dockerfileArg => { | ||||
|         const cleanTags = Dockerfile.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 (const dockerfile of sortedArray) { | ||||
|           logger.log('info', `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 | ||||
|    */ | ||||
|   public static async mapDockerfiles(sortedDockerfileArray: Dockerfile[]): Promise<Dockerfile[]> { | ||||
|     sortedDockerfileArray.forEach(dockerfileArg => { | ||||
|       if (dockerfileArg.localBaseImageDependent) { | ||||
|         sortedDockerfileArray.forEach((dockfile2: Dockerfile) => { | ||||
|           if (dockfile2.cleanTag === dockerfileArg.baseImage) { | ||||
|             dockerfileArg.localBaseDockerfile = dockfile2; | ||||
|           } | ||||
|         }); | ||||
|       } | ||||
|     }); | ||||
|     return sortedDockerfileArray; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * builds the correspoding real docker image for each Dockerfile class instance | ||||
|    */ | ||||
|   public static async buildDockerfiles(sortedArrayArg: Dockerfile[]) { | ||||
|     for (const 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 | ||||
|    */ | ||||
|   public static async testDockerfiles(sortedArrayArg: Dockerfile[]) { | ||||
|     for (const dockerfileArg of sortedArrayArg) { | ||||
|       await dockerfileArg.test(); | ||||
|     } | ||||
|     return sortedArrayArg; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * returns a version for a docker file | ||||
|    * @execution SYNC | ||||
|    */ | ||||
|   public static dockerFileVersion(dockerfileNameArg: string): string { | ||||
|     let versionString: string; | ||||
|     const versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/; | ||||
|     const 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 | ||||
|    */ | ||||
|   public static dockerBaseImage(dockerfileContentArg: string): string { | ||||
|     const baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/; | ||||
|     const regexResultArray = baseImageRegex.exec(dockerfileContentArg); | ||||
|     return regexResultArray[1]; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * returns the docker tag | ||||
|    */ | ||||
|   public static getDockerTagString( | ||||
|     npmciDockerManagerRef: NpmciDockerManager, | ||||
|     registryArg: string, | ||||
|     repoArg: string, | ||||
|     versionArg: string, | ||||
|     suffixArg?: string | ||||
|   ): string { | ||||
|     // determine wether the repo should be mapped accordingly to the registry | ||||
|     const mappedRepo = npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerRegistryRepoMap[ | ||||
|       registryArg | ||||
|     ]; | ||||
|     const repo = (() => { | ||||
|       if (mappedRepo) { | ||||
|         return mappedRepo; | ||||
|       } else { | ||||
|         return repoArg; | ||||
|       } | ||||
|     })(); | ||||
|  | ||||
|     // determine wether the version contais a suffix | ||||
|     let version = versionArg; | ||||
|     if (suffixArg) { | ||||
|       version = versionArg + '_' + suffixArg; | ||||
|     } | ||||
|  | ||||
|     const tagString = `${registryArg}/${repo}:${version}`; | ||||
|     return tagString; | ||||
|   } | ||||
|  | ||||
|   public static async getDockerBuildArgs( | ||||
|     npmciDockerManagerRef: NpmciDockerManager | ||||
|   ): Promise<string> { | ||||
|     logger.log('info', 'checking for env vars to be supplied to the docker build'); | ||||
|     let buildArgsString: string = ''; | ||||
|     for (const key of Object.keys( | ||||
|       npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap | ||||
|     )) { | ||||
|       const targetValue = | ||||
|         process.env[ | ||||
|           npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap[key] | ||||
|         ]; | ||||
|       buildArgsString = `${buildArgsString} --build-arg ${key}="${targetValue}"`; | ||||
|     } | ||||
|     return buildArgsString; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * | ||||
|    */ | ||||
|   public static cleanTagsArrayFunction( | ||||
|     dockerfileArrayArg: Dockerfile[], | ||||
|     trackingArrayArg: Dockerfile[] | ||||
|   ): string[] { | ||||
|     const cleanTagsArray: string[] = []; | ||||
|     dockerfileArrayArg.forEach(dockerfileArg => { | ||||
|       if (trackingArrayArg.indexOf(dockerfileArg) === -1) { | ||||
|         cleanTagsArray.push(dockerfileArg.cleanTag); | ||||
|       } | ||||
|     }); | ||||
|     return cleanTagsArray; | ||||
|   } | ||||
|  | ||||
|   // INSTANCE | ||||
|   public npmciDockerManagerRef: NpmciDockerManager; | ||||
|  | ||||
|   public filePath: string; | ||||
|   public repo: string; | ||||
|   public version: string; | ||||
|   public cleanTag: string; | ||||
|   public buildTag: string; | ||||
|   public pushTag: string; | ||||
|   public containerName: string; | ||||
|   public content: string; | ||||
|   public baseImage: string; | ||||
|   public localBaseImageDependent: boolean; | ||||
|   public localBaseDockerfile: Dockerfile; | ||||
|  | ||||
|   constructor( | ||||
|     dockerManagerRefArg: NpmciDockerManager, | ||||
|     options: { filePath?: string; fileContents?: string | Buffer; read?: boolean } | ||||
|   ) { | ||||
|     this.npmciDockerManagerRef = dockerManagerRefArg; | ||||
|     this.filePath = options.filePath; | ||||
|     this.repo = | ||||
|       this.npmciDockerManagerRef.npmciRef.npmciEnv.repo.user + | ||||
|       '/' + | ||||
|       this.npmciDockerManagerRef.npmciRef.npmciEnv.repo.repo; | ||||
|     this.version = Dockerfile.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 = Dockerfile.dockerBaseImage(this.content); | ||||
|     this.localBaseImageDependent = false; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * builds the Dockerfile | ||||
|    */ | ||||
|   public async build() { | ||||
|     logger.log('info', 'now building Dockerfile for ' + this.cleanTag); | ||||
|     const buildArgsString = await Dockerfile.getDockerBuildArgs(this.npmciDockerManagerRef); | ||||
|     const buildCommand = `docker build --label="version=${ | ||||
|       this.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo.npm.version | ||||
|     }" -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`; | ||||
|     await bash(buildCommand); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * pushes the Dockerfile to a registry | ||||
|    */ | ||||
|   public async push(dockerRegistryArg: DockerRegistry, versionSuffix: string = null) { | ||||
|     this.pushTag = Dockerfile.getDockerTagString( | ||||
|       this.npmciDockerManagerRef, | ||||
|       dockerRegistryArg.registryUrl, | ||||
|       this.repo, | ||||
|       this.version, | ||||
|       versionSuffix | ||||
|     ); | ||||
|     await bash(`docker tag ${this.buildTag} ${this.pushTag}`); | ||||
|     await bash(`docker push ${this.pushTag}`); | ||||
|     const imageDigest = (await bash( | ||||
|       `docker inspect --format="{{index .RepoDigests 0}}" ${this.pushTag}` | ||||
|     )).split('@')[1]; | ||||
|     console.log(`The image ${this.pushTag} has digest ${imageDigest}`); | ||||
|     await this.npmciDockerManagerRef.npmciRef.cloudlyConnector.announceDockerContainer({ | ||||
|       dockerImageUrl: this.pushTag, | ||||
|       dockerImageVersion: this.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo | ||||
|         .npm.version | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * pulls the Dockerfile from a registry | ||||
|    */ | ||||
|   public async pull(registryArg: DockerRegistry, versionSuffixArg: string = null) { | ||||
|     const pullTag = Dockerfile.getDockerTagString( | ||||
|       this.npmciDockerManagerRef, | ||||
|       registryArg.registryUrl, | ||||
|       this.repo, | ||||
|       this.version, | ||||
|       versionSuffixArg | ||||
|     ); | ||||
|     await bash(`docker pull ${pullTag}`); | ||||
|     await bash(`docker tag ${pullTag} ${this.buildTag}`); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * tests the Dockerfile; | ||||
|    */ | ||||
|   public async test() { | ||||
|     const testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh'); | ||||
|     const testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile); | ||||
|     if (testFileExists) { | ||||
|       // run tests | ||||
|       await bash( | ||||
|         `docker run --name npmci_test_container --entrypoint="bash" ${this.buildTag} -c "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 --entrypoint="bash" npmci_test_image -x /npmci_test/test.sh`); | ||||
|       await bash(`docker rm npmci_test_container`); | ||||
|       await bash(`docker rmi --force npmci_test_image`); | ||||
|     } else { | ||||
|       logger.log('warn', 'skipping tests for ' + this.cleanTag + ' because no testfile was found!'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * gets the id of a Dockerfile | ||||
|    */ | ||||
|   public async getId() { | ||||
|     const containerId = await bash( | ||||
|       'docker inspect --type=image --format="{{.Id}}" ' + this.buildTag | ||||
|     ); | ||||
|     return containerId; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										5
									
								
								ts/manager.docker/mod.helpers.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								ts/manager.docker/mod.helpers.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
|  | ||||
| import { Dockerfile } from './mod.classes.dockerfile'; | ||||
							
								
								
									
										66
									
								
								ts/manager.git/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								ts/manager.git/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import { bash } from '../npmci.bash'; | ||||
| import { Npmci } from '../npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciGitManager { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   constructor(npmciRefArg: Npmci) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * handle cli input | ||||
|    * @param argvArg | ||||
|    */ | ||||
|   public handleCli = async argvArg => { | ||||
|     if (argvArg._.length >= 2) { | ||||
|       const action: string = argvArg._[1]; | ||||
|       switch (action) { | ||||
|         case 'mirror': | ||||
|           await this.mirror(); | ||||
|           break; | ||||
|         default: | ||||
|           logger.log('error', `npmci git -> action >>${action}<< not supported!`); | ||||
|       } | ||||
|     } else { | ||||
|       logger.log('info', `npmci git -> cli arguments invalid! Please read the documentation.`); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|   public mirror = async () => { | ||||
|     const githubToken = process.env.NPMCI_GIT_GITHUBTOKEN; | ||||
|     const githubUser = process.env.NPMCI_GIT_GITHUBGROUP || this.npmciRef.npmciEnv.repo.user; | ||||
|     const githubRepo = process.env.NPMCI_GIT_GITHUB || this.npmciRef.npmciEnv.repo; | ||||
|     if ( | ||||
|       this.npmciRef.npmciConfig.getConfig().projectInfo.npm.packageJson.private === true || | ||||
|       this.npmciRef.npmciConfig.getConfig().npmAccessLevel === 'private' | ||||
|     ) { | ||||
|       logger.log( | ||||
|         'warn', | ||||
|         `refusing to mirror due to private property use a private mirror location instead` | ||||
|       ); | ||||
|       return; | ||||
|     } | ||||
|     if (githubToken) { | ||||
|       logger.log('info', 'found github token.'); | ||||
|       logger.log('info', 'attempting the mirror the repository to GitHub'); | ||||
|  | ||||
|       // plugins.smartgit.GitRepo; | ||||
|  | ||||
|       // add the mirror | ||||
|       console.log(`git remote add mirror https://${githubToken}@github.com/${githubUser}/${githubRepo}.git`); | ||||
|       await bash( | ||||
|         `git remote add mirror https://${githubToken}@github.com/${githubUser}/${githubRepo}.git` | ||||
|       ); | ||||
|       await bash(`git push mirror --all`); | ||||
|       logger.log('ok', 'pushed all branches to mirror!'); | ||||
|       await bash(`git push mirror --tags`); | ||||
|       logger.log('ok', 'pushed all tags to mirror!'); | ||||
|     } else { | ||||
|       logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`); | ||||
|       process.exit(1); | ||||
|     } | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										5
									
								
								ts/manager.git/mod.plugins.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								ts/manager.git/mod.plugins.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| export * from '../npmci.plugins'; | ||||
|  | ||||
| import * as smartgit from '@pushrocks/smartgit'; | ||||
|  | ||||
| export { smartgit }; | ||||
							
								
								
									
										83
									
								
								ts/manager.nodejs/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								ts/manager.nodejs/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| import * as plugins from '../npmci.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
|  | ||||
| import { logger } from '../npmci.logging'; | ||||
| import { bash, bashNoError, nvmAvailable } from '../npmci.bash'; | ||||
| import { Npmci } from '../npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciNodeJsManager { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   constructor(npmciRefArg: Npmci) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * handle cli input | ||||
|    * @param argvArg | ||||
|    */ | ||||
|   public async handleCli(argvArg) { | ||||
|     if (argvArg._.length >= 3) { | ||||
|       const action: string = argvArg._[1]; | ||||
|       switch (action) { | ||||
|         case 'install': | ||||
|           await this.install(argvArg._[2]); | ||||
|           break; | ||||
|         default: | ||||
|           logger.log('error', `>>npmci node ...<< action >>${action}<< not supported`); | ||||
|           process.exit(1); | ||||
|       } | ||||
|     } else { | ||||
|       logger.log( | ||||
|         'error', | ||||
|         `>>npmci node ...<< cli arguments invalid... Please read the documentation.` | ||||
|       ); | ||||
|       process.exit(1); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Install a specific version of node | ||||
|    * @param versionArg | ||||
|    */ | ||||
|   public async install(versionArg) { | ||||
|     logger.log('info', `now installing node version ${versionArg}`); | ||||
|     let version: string; | ||||
|     if (versionArg === 'stable') { | ||||
|       version = '12'; | ||||
|     } else if (versionArg === 'lts') { | ||||
|       version = '10'; | ||||
|     } else if (versionArg === 'legacy') { | ||||
|       version = '8'; | ||||
|     } else { | ||||
|       version = versionArg; | ||||
|     } | ||||
|     if (await nvmAvailable.promise) { | ||||
|       await bash(`nvm install ${version} && nvm alias default ${version}`); | ||||
|       logger.log('success', `Node version ${version} successfully installed!`); | ||||
|     } else { | ||||
|       logger.log('warn', 'Nvm not in path so staying at installed node version!'); | ||||
|     } | ||||
|     logger.log('info', 'now installing latest npm version'); | ||||
|     await bash('npm install -g npm'); | ||||
|     await bash('node -v'); | ||||
|     await bash('npm -v'); | ||||
|     await bash(`npm config set cache ${paths.NpmciCacheDir}  --global `); | ||||
|  | ||||
|     // lets look for further config | ||||
|     const config = await this.npmciRef.npmciConfig.getConfig(); | ||||
|     logger.log('info', 'Now checking for needed global npm tools...'); | ||||
|     for (const npmTool of config.npmGlobalTools) { | ||||
|       logger.log('info', `Checking for global "${npmTool}"`); | ||||
|       const whichOutput: string = await bashNoError(`which ${npmTool}`); | ||||
|       const toolAvailable: boolean = !(/not\sfound/.test(whichOutput) || whichOutput === ''); | ||||
|       if (toolAvailable) { | ||||
|         logger.log('info', `Tool ${npmTool} is available`); | ||||
|       } else { | ||||
|         logger.log('info', `globally installing ${npmTool} from npm`); | ||||
|         await bash(`npm install ${npmTool} -q -g`); | ||||
|       } | ||||
|     } | ||||
|     logger.log('success', 'all global npm tools specified in npmextra.json are now available!'); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										162
									
								
								ts/manager.npm/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								ts/manager.npm/index.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| import * as plugins from './mod.plugins'; | ||||
|  | ||||
| import { logger } from '../npmci.logging'; | ||||
| import { bash, bashNoError, nvmAvailable } from '../npmci.bash'; | ||||
| import { Npmci } from '../npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciNpmManager { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   constructor(npmciRefArg) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * handle cli input | ||||
|    * @param argvArg | ||||
|    */ | ||||
|   public async handleCli(argvArg) { | ||||
|     if (argvArg._.length >= 2) { | ||||
|       const action: string = argvArg._[1]; | ||||
|       switch (action) { | ||||
|         case 'install': | ||||
|           await this.install(); | ||||
|           break; | ||||
|         case 'prepare': | ||||
|           await this.prepare(); | ||||
|           break; | ||||
|         case 'test': | ||||
|           await this.test(); | ||||
|           break; | ||||
|         case 'publish': | ||||
|           await this.publish(); | ||||
|           break; | ||||
|         default: | ||||
|           logger.log('error', `>>npmci npm ...<< action >>${action}<< not supported`); | ||||
|           process.exit(1); | ||||
|       } | ||||
|     } else { | ||||
|       logger.log( | ||||
|         'info', | ||||
|         `>>npmci npm ...<< cli arguments invalid... Please read the documentation.` | ||||
|       ); | ||||
|       process.exit(1); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * authenticates npm with token from env var | ||||
|    */ | ||||
|   public async prepare() { | ||||
|     const config = this.npmciRef.npmciConfig.getConfig(); | ||||
|     let npmrcFileString: string = ''; | ||||
|     await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TOKEN_NPM*', npmEnvArg => { | ||||
|       const npmRegistryUrl = npmEnvArg.split('|')[0]; | ||||
|       const npmToken = npmEnvArg.split('|')[1]; | ||||
|       npmrcFileString += `//${npmRegistryUrl}/:_authToken="${plugins.smartstring.base64.decode( | ||||
|         npmToken | ||||
|       )}"\n`; | ||||
|     }); | ||||
|     logger.log('info', `setting default npm registry to ${config.npmRegistryUrl}`); | ||||
|     npmrcFileString += `registry=https://${config.npmRegistryUrl}\n`; | ||||
|  | ||||
|     // final check | ||||
|     if (npmrcFileString.length > 0) { | ||||
|       logger.log('info', 'found one or more access tokens'); | ||||
|     } else { | ||||
|       logger.log('error', 'no access token found! Exiting!'); | ||||
|       process.exit(1); | ||||
|     } | ||||
|  | ||||
|     // lets save it to disk | ||||
|     plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc'); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * publish a package to npm | ||||
|    */ | ||||
|   public async publish() { | ||||
|     const buildPublishCommand = async () => { | ||||
|       let npmAccessCliString = ``; | ||||
|       let npmRegistryCliString = ``; | ||||
|       let publishVerdaccioAsWell = false; | ||||
|       const config = this.npmciRef.npmciConfig.getConfig(); | ||||
|       const availableRegistries: string[] = []; | ||||
|       await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TOKEN_NPM*', npmEnvArg => { | ||||
|         availableRegistries.push(npmEnvArg.split('|')[0]); | ||||
|       }); | ||||
|  | ||||
|       // -> configure package access level | ||||
|       if (config.npmAccessLevel) { | ||||
|         npmAccessCliString = `--access=${config.npmAccessLevel}`; | ||||
|         if (config.npmAccessLevel === 'public') { | ||||
|           publishVerdaccioAsWell = true; | ||||
|         } | ||||
|       } else { | ||||
|         throw new Error('You need to set a npmAccessLevel!!!'); | ||||
|       } | ||||
|       // -> configure registry url | ||||
|       if (config.npmRegistryUrl) { | ||||
|         npmRegistryCliString = `--registry=https://${config.npmRegistryUrl}`; | ||||
|       } else { | ||||
|         logger.log('error', `no registry url specified. Can't publish!`); | ||||
|         process.exit(1); | ||||
|       } | ||||
|  | ||||
|       let publishCommand = `npm publish ${npmAccessCliString} ${npmRegistryCliString} `; | ||||
|  | ||||
|       // publishEverywhere | ||||
|       if (publishVerdaccioAsWell) { | ||||
|         const verdaccioRegistry = availableRegistries.find(registryString => | ||||
|           registryString.startsWith('verdaccio') | ||||
|         ); | ||||
|         if (verdaccioRegistry) { | ||||
|           logger.log( | ||||
|             'info', | ||||
|             `package is public and verdaccio registry is specified. Also publishing to Verdaccio!` | ||||
|           ); | ||||
|           publishCommand = `${publishCommand} && npm publish ${npmAccessCliString} --registry=https://${verdaccioRegistry}`; | ||||
|         } else { | ||||
|           logger.log( | ||||
|             'error', | ||||
|             `This package should also be published to Verdaccio, however there is no Verdaccio registry data available!` | ||||
|           ); | ||||
|         } | ||||
|       } | ||||
|       return publishCommand; | ||||
|     }; | ||||
|  | ||||
|     // -> preparing | ||||
|     logger.log('info', `now preparing environment:`); | ||||
|     this.prepare(); | ||||
|     await bash(`npm -v`); | ||||
|  | ||||
|     // -> build it | ||||
|     await bash(`npm install`); | ||||
|     await bash(`npm run build`); | ||||
|  | ||||
|     logger.log('success', `Nice!!! The build for the publication was successfull!`); | ||||
|     logger.log('info', `Lets clean up so we don't publish any packages that don't belong to us:`); | ||||
|     // -> clean up before we publish stuff | ||||
|     await bashNoError(`rm -r ./.npmci_cache`); | ||||
|     await bash(`rm -r ./node_modules`); | ||||
|  | ||||
|     logger.log('success', `Cleaned up!:`); | ||||
|  | ||||
|     // -> publish it | ||||
|     logger.log('info', `now invoking npm to publish the package!`); | ||||
|     await bash(await buildPublishCommand()); | ||||
|     logger.log('success', `Package was successfully published!`); | ||||
|   } | ||||
|  | ||||
|   public async install(): Promise<void> { | ||||
|     logger.log('info', 'now installing dependencies:'); | ||||
|     await bash('npm install'); | ||||
|   } | ||||
|  | ||||
|   public async test(): Promise<void> { | ||||
|     logger.log('info', 'now starting tests:'); | ||||
|     await bash('npm test'); | ||||
|   } | ||||
| } | ||||
| @@ -1,145 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
| 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 | ||||
| const npmciRegistryStorage = new RegistryStorage(); | ||||
|  | ||||
| export { Dockerfile, helpers }; | ||||
|  | ||||
| export let modArgvArg; // will be set through the build command | ||||
|  | ||||
| /** | ||||
|  * handle cli input | ||||
|  * @param argvArg | ||||
|  */ | ||||
| export let handleCli = async argvArg => { | ||||
|   modArgvArg = argvArg; | ||||
|   if (argvArg._.length >= 2) { | ||||
|     const action: string = argvArg._[1]; | ||||
|     switch (action) { | ||||
|       case 'build': | ||||
|         await build(); | ||||
|         break; | ||||
|       case 'login': | ||||
|       case 'prepare': | ||||
|         await login(); | ||||
|         break; | ||||
|       case 'test': | ||||
|         await test(); | ||||
|         break; | ||||
|       case 'push': | ||||
|         await push(argvArg); | ||||
|         break; | ||||
|       case 'pull': | ||||
|         await pull(argvArg); | ||||
|         break; | ||||
|       default: | ||||
|         logger.log('error', `>>npmci docker ...<< action >>${action}<< not supported`); | ||||
|     } | ||||
|   } else { | ||||
|     logger.log( | ||||
|       'info', | ||||
|       `>>npmci docker ...<< cli arguments invalid... Please read the documentation.` | ||||
|     ); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * builds a cwd of Dockerfiles by triggering a promisechain | ||||
|  */ | ||||
| export let build = async () => { | ||||
|   await prepare(); | ||||
|   logger.log('info', 'now building Dockerfiles...'); | ||||
|   await helpers | ||||
|     .readDockerfiles() | ||||
|     .then(helpers.sortDockerfiles) | ||||
|     .then(helpers.mapDockerfiles) | ||||
|     .then(helpers.buildDockerfiles); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * login to the DockerRegistries | ||||
|  */ | ||||
| export let login = async () => { | ||||
|   await prepare(); | ||||
|   await npmciRegistryStorage.loginAll(); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * logs in docker | ||||
|  */ | ||||
| export let prepare = async () => { | ||||
|   // Always login to GitLab Registry | ||||
|   if (!process.env.CI_BUILD_TOKEN || process.env.CI_BUILD_TOKEN === '') { | ||||
|     logger.log('error', 'No registry token specified by gitlab!'); | ||||
|     process.exit(1); | ||||
|   } | ||||
|   npmciRegistryStorage.addRegistry( | ||||
|     new DockerRegistry({ | ||||
|       registryUrl: 'registry.gitlab.com', | ||||
|       username: 'gitlab-ci-token', | ||||
|       password: process.env.CI_BUILD_TOKEN | ||||
|     }) | ||||
|   ); | ||||
|  | ||||
|   // handle registries | ||||
|   await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_LOGIN_DOCKER*', async envString => { | ||||
|     npmciRegistryStorage.addRegistry(DockerRegistry.fromEnvString(envString)); | ||||
|   }); | ||||
|   return; | ||||
| }; | ||||
|  | ||||
| export let push = async argvArg => { | ||||
|   await prepare(); | ||||
|   const registryUrlArg = argvArg._[2]; | ||||
|   let suffix = null; | ||||
|   if (argvArg._.length >= 4) { | ||||
|     suffix = argvArg._[3]; | ||||
|   } | ||||
|   const dockerfileArray = await helpers | ||||
|     .readDockerfiles() | ||||
|     .then(helpers.sortDockerfiles) | ||||
|     .then(helpers.mapDockerfiles); | ||||
|   const localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg); | ||||
|   if (!localDockerRegistry) { | ||||
|     logger.log( | ||||
|       'error', | ||||
|       `Cannot push to registry ${registryUrlArg}, because it was not found in the authenticated registry list.` | ||||
|     ); | ||||
|     process.exit(1); | ||||
|   } | ||||
|   for (const dockerfile of dockerfileArray) { | ||||
|     await dockerfile.push(localDockerRegistry, suffix); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export let pull = async argvArg => { | ||||
|   await prepare(); | ||||
|   const registryUrlArg = argvArg._[2]; | ||||
|   let suffix = null; | ||||
|   if (argvArg._.length >= 4) { | ||||
|     suffix = argvArg._[3]; | ||||
|   } | ||||
|   const localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg); | ||||
|   const dockerfileArray = await helpers | ||||
|     .readDockerfiles() | ||||
|     .then(helpers.sortDockerfiles) | ||||
|     .then(helpers.mapDockerfiles); | ||||
|   for (const dockerfile of dockerfileArray) { | ||||
|     await dockerfile.pull(localDockerRegistry, suffix); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export let test = async () => { | ||||
|   await prepare(); | ||||
|   return await helpers.readDockerfiles().then(helpers.testDockerfiles); | ||||
| }; | ||||
| @@ -1,112 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| 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 { | ||||
|   public filePath: string; | ||||
|   public repo: string; | ||||
|   public version: string; | ||||
|   public cleanTag: string; | ||||
|   public buildTag: string; | ||||
|   public containerName: string; | ||||
|   public content: string; | ||||
|   public baseImage: string; | ||||
|   public localBaseImageDependent: boolean; | ||||
|   public 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 | ||||
|    */ | ||||
|   public async build() { | ||||
|     logger.log('info', 'now building Dockerfile for ' + this.cleanTag); | ||||
|     const buildArgsString = await helpers.getDockerBuildArgs(); | ||||
|     const buildCommand = `docker build -t ${this.buildTag} -f ${ | ||||
|       this.filePath | ||||
|     } ${buildArgsString} .`; | ||||
|     await bash(buildCommand); | ||||
|     return; | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * pushes the Dockerfile to a registry | ||||
|    */ | ||||
|   public async push(dockerRegistryArg: DockerRegistry, versionSuffix: string = null) { | ||||
|     const 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 | ||||
|    */ | ||||
|   public async pull(registryArg: DockerRegistry, versionSuffixArg: string = null) { | ||||
|     const pullTag = helpers.getDockerTagString( | ||||
|       registryArg.registryUrl, | ||||
|       this.repo, | ||||
|       this.version, | ||||
|       versionSuffixArg | ||||
|     ); | ||||
|     await bash(`docker pull ${pullTag}`); | ||||
|     await bash(`docker tag ${pullTag} ${this.buildTag}`); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * tests the Dockerfile; | ||||
|    */ | ||||
|   public async test() { | ||||
|     const testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh'); | ||||
|     const testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile); | ||||
|     if (testFileExists) { | ||||
|       // run tests | ||||
|       await bash( | ||||
|         `docker run --name npmci_test_container --entrypoint="bash" ${ | ||||
|           this.buildTag | ||||
|         } -c "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 --entrypoint="bash" npmci_test_image -x /npmci_test/test.sh`); | ||||
|       await bash(`docker rm npmci_test_container`); | ||||
|       await bash(`docker rmi --force npmci_test_image`); | ||||
|     } else { | ||||
|       logger.log('warn', 'skipping tests for ' + this.cleanTag + ' because no testfile was found!'); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * gets the id of a Dockerfile | ||||
|    */ | ||||
|   public async getId() { | ||||
|     const containerId = await bash( | ||||
|       'docker inspect --type=image --format="{{.Id}}" ' + this.buildTag | ||||
|     ); | ||||
|     return containerId; | ||||
|   } | ||||
| } | ||||
| @@ -1,187 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
| import * as NpmciEnv from '../npmci.env'; | ||||
| import * as NpmciConfig from '../npmci.config'; | ||||
| import { bash } from '../npmci.bash'; | ||||
|  | ||||
| import { Dockerfile } from './mod.classes.dockerfile'; | ||||
|  | ||||
| /** | ||||
|  * creates instance of class Dockerfile for all Dockerfiles in cwd | ||||
|  * @returns Promise<Dockerfile[]> | ||||
|  */ | ||||
| export let readDockerfiles = async (): Promise<Dockerfile[]> => { | ||||
|   const fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*'); | ||||
|  | ||||
|   // create the Dockerfile array | ||||
|   const readDockerfilesArray: Dockerfile[] = []; | ||||
|   logger.log('info', `found ${fileTree.length} Dockerfiles:`); | ||||
|   console.log(fileTree); | ||||
|   for (const dockerfilePath of fileTree) { | ||||
|     const 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<Dockerfile[]> | ||||
|  */ | ||||
| export let sortDockerfiles = (sortableArrayArg: Dockerfile[]): Promise<Dockerfile[]> => { | ||||
|   const done = plugins.smartpromise.defer<Dockerfile[]>(); | ||||
|   logger.log('info', 'sorting Dockerfiles:'); | ||||
|   const sortedArray: Dockerfile[] = []; | ||||
|   const cleanTagsOriginal = cleanTagsArrayFunction(sortableArrayArg, sortedArray); | ||||
|   let sorterFunctionCounter: number = 0; | ||||
|   const sorterFunction = () => { | ||||
|     sortableArrayArg.forEach(dockerfileArg => { | ||||
|       const 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 (const dockerfile of sortedArray) { | ||||
|         logger.log('info', `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<Dockerfile[]> => { | ||||
|   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 (const 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 (const 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; | ||||
|   const versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/; | ||||
|   const 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 = (dockerfileContentArg: string) => { | ||||
|   const baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/; | ||||
|   const regexResultArray = baseImageRegex.exec(dockerfileContentArg); | ||||
|   return regexResultArray[1]; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * returns the docker tag | ||||
|  */ | ||||
| export let getDockerTagString = ( | ||||
|   registryArg: string, | ||||
|   repoArg: string, | ||||
|   versionArg: string, | ||||
|   suffixArg?: string | ||||
| ): string => { | ||||
|   // determine wether the repo should be mapped accordingly to the registry | ||||
|   const mappedRepo = NpmciConfig.configObject.dockerRegistryRepoMap[registryArg]; | ||||
|   const repo = (() => { | ||||
|     if (mappedRepo) { | ||||
|       return mappedRepo; | ||||
|     } else { | ||||
|       return repoArg; | ||||
|     } | ||||
|   })(); | ||||
|  | ||||
|   // determine wether the version contais a suffix | ||||
|   let version = versionArg; | ||||
|   if (suffixArg) { | ||||
|     version = versionArg + '_' + suffixArg; | ||||
|   } | ||||
|  | ||||
|   const tagString = `${registryArg}/${repo}:${version}`; | ||||
|   return tagString; | ||||
| }; | ||||
|  | ||||
| export let getDockerBuildArgs = async (): Promise<string> => { | ||||
|   logger.log('info', 'checking for env vars to be supplied to the docker build'); | ||||
|   let buildArgsString: string = ''; | ||||
|   for (const key in NpmciConfig.configObject.dockerBuildargEnvMap) { | ||||
|     const targetValue = process.env[NpmciConfig.configObject.dockerBuildargEnvMap[key]]; | ||||
|     buildArgsString = `${buildArgsString} --build-arg ${key}="${targetValue}"`; | ||||
|   } | ||||
|   return buildArgsString; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  */ | ||||
| export let cleanTagsArrayFunction = ( | ||||
|   dockerfileArrayArg: Dockerfile[], | ||||
|   trackingArrayArg: Dockerfile[] | ||||
| ): string[] => { | ||||
|   const cleanTagsArray: string[] = []; | ||||
|   dockerfileArrayArg.forEach(dockerfileArg => { | ||||
|     if (trackingArrayArg.indexOf(dockerfileArg) === -1) { | ||||
|       cleanTagsArray.push(dockerfileArg.cleanTag); | ||||
|     } | ||||
|   }); | ||||
|   return cleanTagsArray; | ||||
| }; | ||||
| @@ -1,50 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import { bash } from '../npmci.bash'; | ||||
| import { repo } from '../npmci.env'; | ||||
|  | ||||
| import { configObject } from '../npmci.config'; | ||||
|  | ||||
| /** | ||||
|  * handle cli input | ||||
|  * @param argvArg | ||||
|  */ | ||||
| export let handleCli = async argvArg => { | ||||
|   if (argvArg._.length >= 2) { | ||||
|     const action: string = argvArg._[1]; | ||||
|     switch (action) { | ||||
|       case 'mirror': | ||||
|         await mirror(); | ||||
|         break; | ||||
|       default: | ||||
|         logger.log('error', `npmci git -> action >>${action}<< not supported!`); | ||||
|     } | ||||
|   } else { | ||||
|     logger.log('info', `npmci git -> cli arguments invalid! Please read the documentation.`); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export let mirror = async () => { | ||||
|   const githubToken = process.env.NPMCI_GIT_GITHUBTOKEN; | ||||
|   const githubUser = process.env.NPMCI_GIT_GITHUBGROUP || repo.user; | ||||
|   const githubRepo = process.env.NPMCI_GIT_GITHUB || repo.repo; | ||||
|   if(configObject.projectInfo.npm.packageJson.private === true) { | ||||
|     logger.log('warn', `refusing to mirror due to private property`); | ||||
|     return; | ||||
|   } | ||||
|   if (githubToken) { | ||||
|     logger.log('info', 'found github token.'); | ||||
|     logger.log('info', 'attempting the mirror the repository to GitHub'); | ||||
|     // add the mirror | ||||
|     await bash( | ||||
|       `git remote add mirror https://${githubToken}@github.com/${githubUser}/${githubRepo}.git` | ||||
|     ); | ||||
|     await bash(`git push mirror --all`); | ||||
|     logger.log('ok', 'pushed all branches to mirror!'); | ||||
|     await bash(`git push mirror --tags`); | ||||
|     logger.log('ok', 'pushed all tags to mirror!'); | ||||
|   } else { | ||||
|     logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`); | ||||
|     process.exit(1); | ||||
|   } | ||||
| }; | ||||
| @@ -1,72 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from '../npmci.plugins'; | ||||
| import * as paths from '../npmci.paths'; | ||||
| import * as npmciConfig from '../npmci.config'; | ||||
| import { bash, bashNoError, nvmAvailable } from '../npmci.bash'; | ||||
|  | ||||
| /** | ||||
|  * handle cli input | ||||
|  * @param argvArg | ||||
|  */ | ||||
| export let handleCli = async argvArg => { | ||||
|   if (argvArg._.length >= 3) { | ||||
|     const action: string = argvArg._[1]; | ||||
|     switch (action) { | ||||
|       case 'install': | ||||
|         await install(argvArg._[2]); | ||||
|         break; | ||||
|       default: | ||||
|         logger.log('error', `>>npmci node ...<< action >>${action}<< not supported`); | ||||
|         process.exit(1); | ||||
|     } | ||||
|   } else { | ||||
|     logger.log( | ||||
|       'error', | ||||
|       `>>npmci node ...<< cli arguments invalid... Please read the documentation.` | ||||
|     ); | ||||
|     process.exit(1); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Install a specific version of node | ||||
|  * @param versionArg | ||||
|  */ | ||||
| export let install = async versionArg => { | ||||
|   logger.log('info', `now installing node version ${versionArg}`); | ||||
|   let version: string; | ||||
|   if (versionArg === 'stable') { | ||||
|     version = '11'; | ||||
|   } else if (versionArg === 'lts') { | ||||
|     version = '10'; | ||||
|   } else if (versionArg === 'legacy') { | ||||
|     version = '8'; | ||||
|   } else { | ||||
|     version = versionArg; | ||||
|   } | ||||
|   if (await nvmAvailable.promise) { | ||||
|     await bash(`nvm install ${version} && nvm alias default ${version}`); | ||||
|     logger.log('success', `Node version ${version} successfully installed!`); | ||||
|   } else { | ||||
|     logger.log('warn', 'Nvm not in path so staying at installed node version!'); | ||||
|   } | ||||
|   await bash('node -v'); | ||||
|   await bash('npm -v'); | ||||
|   await bash(`npm config set cache ${paths.NpmciCacheDir}  --global `); | ||||
|   // lets look for further config | ||||
|   await npmciConfig.getConfig().then(async configArg => { | ||||
|     logger.log('info', 'Now checking for needed global npm tools...'); | ||||
|     for (const npmTool of configArg.npmGlobalTools) { | ||||
|       logger.log('info', `Checking for global "${npmTool}"`); | ||||
|       const whichOutput: string = await bashNoError(`which ${npmTool}`); | ||||
|       const toolAvailable: boolean = !(/not\sfound/.test(whichOutput) || whichOutput === ''); | ||||
|       if (toolAvailable) { | ||||
|         logger.log('info', `Tool ${npmTool} is available`); | ||||
|       } else { | ||||
|         logger.log('info', `globally installing ${npmTool} from npm`); | ||||
|         await bash(`npm install ${npmTool} -q -g`); | ||||
|       } | ||||
|     } | ||||
|     logger.log('success', 'all global npm tools specified in npmextra.json are now available!'); | ||||
|   }); | ||||
| }; | ||||
| @@ -1,118 +0,0 @@ | ||||
| import { logger } from '../npmci.logging'; | ||||
| import * as plugins from './mod.plugins'; | ||||
| import * as configModule from '../npmci.config'; | ||||
| import { bash, bashNoError, nvmAvailable } from '../npmci.bash'; | ||||
|  | ||||
| /** | ||||
|  * handle cli input | ||||
|  * @param argvArg | ||||
|  */ | ||||
| export let handleCli = async argvArg => { | ||||
|   if (argvArg._.length >= 2) { | ||||
|     const action: string = argvArg._[1]; | ||||
|     switch (action) { | ||||
|       case 'install': | ||||
|         await install(); | ||||
|         break; | ||||
|       case 'prepare': | ||||
|         await prepare(); | ||||
|         break; | ||||
|       case 'test': | ||||
|         await test(); | ||||
|         break; | ||||
|       case 'publish': | ||||
|         await publish(); | ||||
|         break; | ||||
|       default: | ||||
|         logger.log('error', `>>npmci npm ...<< action >>${action}<< not supported`); | ||||
|         process.exit(1); | ||||
|     } | ||||
|   } else { | ||||
|     logger.log('info', `>>npmci npm ...<< cli arguments invalid... Please read the documentation.`); | ||||
|     process.exit(1); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * authenticates npm with token from env var | ||||
|  */ | ||||
| const prepare = async () => { | ||||
|   const config = await configModule.getConfig(); | ||||
|   let npmrcFileString: string = ''; | ||||
|   await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TOKEN_NPM*', npmEnvArg => { | ||||
|     const npmRegistryUrl = npmEnvArg.split('|')[0]; | ||||
|     const npmToken = npmEnvArg.split('|')[1]; | ||||
|     npmrcFileString += `//${npmRegistryUrl}/:_authToken="${plugins.smartstring.base64.decode(npmToken)}"\n`; | ||||
|   }); | ||||
|   logger.log('info', `setting default npm registry to ${config.npmRegistryUrl}`); | ||||
|   npmrcFileString += `registry=https://${config.npmRegistryUrl}\n`; | ||||
|  | ||||
|   // final check | ||||
|   if (npmrcFileString.length > 0) { | ||||
|     logger.log('info', 'found one or more access tokens'); | ||||
|   } else { | ||||
|     logger.log('error', 'no access token found! Exiting!'); | ||||
|     process.exit(1); | ||||
|   } | ||||
|  | ||||
|   // lets save it to disk | ||||
|   plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc'); | ||||
|   return; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * publish a package to npm | ||||
|  */ | ||||
| const publish = async () => { | ||||
|   let npmAccessCliString = ``; | ||||
|   let npmRegistryCliString = ``; | ||||
|   const config = await configModule.getConfig(); | ||||
|  | ||||
|   // -> configure package access level | ||||
|   if ( | ||||
|     config.npmAccessLevel && | ||||
|     (config.npmAccessLevel === 'public' || config.npmAccessLevel === 'private') | ||||
|   ) { | ||||
|     npmAccessCliString = `--access=${config.npmAccessLevel}`; | ||||
|   } | ||||
|  | ||||
|   // -> configure registry url | ||||
|   if (config.npmRegistryUrl) { | ||||
|     npmRegistryCliString = `--registry=https://${config.npmRegistryUrl}`; | ||||
|   } else { | ||||
|     logger.log('error', `no registry url specified. Can't publish!`); | ||||
|     process.exit(1); | ||||
|   } | ||||
|  | ||||
|   // -> preparing | ||||
|   logger.log('info', `now preparing environment:`); | ||||
|   prepare(); | ||||
|   await bash(`npm -v`); | ||||
|  | ||||
|   // -> build it | ||||
|   await bash(`npm install`); | ||||
|   await bash(`npm run build`); | ||||
|  | ||||
|   logger.log('success', `Nice!!! The build for the publication was successfull!`); | ||||
|   logger.log('info', `Lets clean up so we don't publish any packages that don't belong to us:`); | ||||
|   // -> clean up before we publish stuff | ||||
|   await bashNoError(`rm -r ./.npmci_cache`); | ||||
|   await bash(`rm -r ./node_modules`); | ||||
|  | ||||
|   logger.log('success', `Cleaned up!:`); | ||||
|  | ||||
|   // -> publish it | ||||
|   logger.log('info', `now invoking npm to publish the package!`); | ||||
|   await bash(`npm publish ${npmAccessCliString} ${npmRegistryCliString}`); | ||||
|   logger.log('success', `Package was successfully published!`); | ||||
| }; | ||||
|  | ||||
| const install = async (): Promise<void> => { | ||||
|   logger.log('info', 'now installing dependencies:'); | ||||
|   await bash('npm install'); | ||||
| }; | ||||
|  | ||||
| export let test = async (): Promise<void> => { | ||||
|   logger.log('info', 'now starting tests:'); | ||||
|   await bash('npm test'); | ||||
| }; | ||||
| @@ -1 +0,0 @@ | ||||
| export * from '../npmci.plugins'; | ||||
							
								
								
									
										55
									
								
								ts/npmci.classes.npmci.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								ts/npmci.classes.npmci.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
|  | ||||
| import { CloudlyConnector } from './connector.cloudly/cloudlyconnector'; | ||||
|  | ||||
| import { NpmciInfo } from './npmci.classes.npmciinfo'; | ||||
| import { NpmciCli } from './npmci.classes.npmcicli'; | ||||
| import { NpmciConfig } from './npmci.classes.npmciconfig'; | ||||
|  | ||||
| // mods | ||||
| import { NpmciDockerManager } from './manager.docker'; | ||||
| import { NpmciGitManager } from './manager.git'; | ||||
| import { NpmciNodeJsManager } from './manager.nodejs'; | ||||
| import { NpmciNpmManager } from './manager.npm'; | ||||
| import { NpmciEnv } from './npmci.classes.npmcienv'; | ||||
|  | ||||
| export class Npmci { | ||||
|   public analytics: plugins.smartanalytics.Analytics; | ||||
|   public cloudlyConnector: CloudlyConnector; | ||||
|  | ||||
|   public npmciEnv: NpmciEnv; | ||||
|   public npmciInfo: NpmciInfo; | ||||
|   public npmciConfig: NpmciConfig; | ||||
|   public npmciCli: NpmciCli; | ||||
|  | ||||
|   // managers | ||||
|   public dockerManager: NpmciDockerManager; | ||||
|   public gitManager: NpmciGitManager; | ||||
|   public nodejsManager: NpmciNodeJsManager; | ||||
|   public npmManager: NpmciNpmManager; | ||||
|  | ||||
|   constructor() { | ||||
|     this.analytics = new plugins.smartanalytics.Analytics({ | ||||
|       apiEndPoint: 'https://pubapi.lossless.one/analytics', | ||||
|       projectId: 'gitzone', | ||||
|       appName: 'npmci' | ||||
|     }); | ||||
|     this.cloudlyConnector = new CloudlyConnector(this); | ||||
|     this.npmciEnv = new NpmciEnv(this); | ||||
|     this.npmciInfo = new NpmciInfo(this); | ||||
|     this.npmciCli = new NpmciCli(this); | ||||
|     this.npmciConfig = new NpmciConfig(this); | ||||
|  | ||||
|     // managers | ||||
|     this.dockerManager = new NpmciDockerManager(this); | ||||
|     this.gitManager = new NpmciGitManager(this); | ||||
|     this.nodejsManager = new NpmciNodeJsManager(this); | ||||
|     this.npmManager = new NpmciNpmManager(this); | ||||
|   } | ||||
|  | ||||
|   public async start() { | ||||
|     await this.npmciInfo.printToConsole(); | ||||
|     await this.npmciConfig.init(); | ||||
|     this.npmciCli.startParse(); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										110
									
								
								ts/npmci.classes.npmcicli.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								ts/npmci.classes.npmcicli.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| import { logger } from './npmci.logging'; | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
| import { Npmci } from './npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciCli { | ||||
|   public npmciRef: Npmci; | ||||
|   public smartcli: plugins.smartcli.Smartcli; | ||||
|  | ||||
|   constructor(npmciArg: Npmci) { | ||||
|     this.npmciRef = npmciArg; | ||||
|     this.smartcli = new plugins.smartcli.Smartcli(); | ||||
|     this.smartcli.addVersion(this.npmciRef.npmciInfo.projectInfo.version); | ||||
|  | ||||
|     // clean | ||||
|     this.smartcli.addCommand('clean').subscribe( | ||||
|       async argv => { | ||||
|         const modClean = await import('./mod_clean/index'); | ||||
|         await modClean.clean(); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // command | ||||
|     this.smartcli.addCommand('command').subscribe( | ||||
|       async argv => { | ||||
|         const modCommand = await import('./mod_command/index'); | ||||
|         await modCommand.command(); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // command | ||||
|     this.smartcli.addCommand('git').subscribe( | ||||
|       async argvArg => { | ||||
|         await this.npmciRef.gitManager.handleCli(argvArg); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // build | ||||
|     this.smartcli.addCommand('docker').subscribe( | ||||
|       async argvArg => { | ||||
|         await this.npmciRef.dockerManager.handleCli(argvArg); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // node | ||||
|     this.smartcli.addCommand('node').subscribe( | ||||
|       async argvArg => { | ||||
|         await this.npmciRef.nodejsManager.handleCli(argvArg); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // npm | ||||
|     this.smartcli.addCommand('npm').subscribe( | ||||
|       async argvArg => { | ||||
|         await this.npmciRef.npmManager.handleCli(argvArg); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // trigger | ||||
|     this.smartcli.addCommand('ssh').subscribe( | ||||
|       async argvArg => { | ||||
|         const modSsh = await import('./mod_ssh/index'); | ||||
|         await modSsh.handleCli(argvArg); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|  | ||||
|     // trigger | ||||
|     this.smartcli.addCommand('trigger').subscribe( | ||||
|       async argv => { | ||||
|         const modTrigger = await import('./mod_trigger/index'); | ||||
|         await modTrigger.trigger(); | ||||
|       }, | ||||
|       err => { | ||||
|         console.log(err); | ||||
|         process.exit(1); | ||||
|       } | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   public startParse = () => { | ||||
|     this.smartcli.startParse(); | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										73
									
								
								ts/npmci.classes.npmciconfig.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								ts/npmci.classes.npmciconfig.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
|  | ||||
| import { logger } from './npmci.logging'; | ||||
| import { Npmci } from './npmci.classes.npmci'; | ||||
|  | ||||
| /** | ||||
|  * the main config interface for npmci | ||||
|  */ | ||||
| export interface INpmciOptions { | ||||
|   projectInfo: plugins.projectinfo.ProjectInfo; | ||||
|  | ||||
|   // npm | ||||
|   npmGlobalTools: string[]; | ||||
|   npmAccessLevel?: 'private' | 'public'; | ||||
|   npmRegistryUrl: string; | ||||
|  | ||||
|   // docker | ||||
|   dockerRegistries: string[]; | ||||
|   dockerRegistryRepoMap: { [key: string]: string }; | ||||
|   dockerBuildargEnvMap: { [key: string]: string }; | ||||
|  | ||||
|   // urls | ||||
|   urlCloudly: string; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * a config class for Npmci | ||||
|  */ | ||||
| export class NpmciConfig { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   public npmciNpmextra: plugins.npmextra.Npmextra; | ||||
|   public kvStorage: plugins.npmextra.KeyValueStore; | ||||
|   public npmciQenv: plugins.qenv.Qenv; | ||||
|  | ||||
|   private configObject: INpmciOptions; | ||||
|  | ||||
|   constructor(npmciRefArg: Npmci) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|  | ||||
|     this.npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd); | ||||
|     this.kvStorage = new plugins.npmextra.KeyValueStore( | ||||
|       'custom', | ||||
|       `${this.npmciRef.npmciEnv.repo.user}_${this.npmciRef.npmciEnv.repo.repo}` | ||||
|     ); | ||||
|     this.npmciQenv = new plugins.qenv.Qenv( | ||||
|       paths.NpmciProjectDir, | ||||
|       paths.NpmciProjectNogitDir, | ||||
|       false, | ||||
|       logger | ||||
|     ); | ||||
|  | ||||
|     this.configObject = { | ||||
|       projectInfo: new plugins.projectinfo.ProjectInfo(paths.cwd), | ||||
|       npmGlobalTools: [], | ||||
|       dockerRegistries: [], | ||||
|       dockerRegistryRepoMap: {}, | ||||
|       npmAccessLevel: 'private', | ||||
|       npmRegistryUrl: 'registry.npmjs.org', | ||||
|       dockerBuildargEnvMap: {}, | ||||
|       urlCloudly: this.npmciQenv.getEnvVarOnDemand('NPMCI_URL_CLOUDLY') | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   public async init() { | ||||
|     this.configObject = this.npmciNpmextra.dataFor<INpmciOptions>('npmci', this.configObject); | ||||
|   } | ||||
|  | ||||
|   public getConfig(): INpmciOptions { | ||||
|     return this.configObject; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										18
									
								
								ts/npmci.classes.npmcienv.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ts/npmci.classes.npmcienv.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import { Npmci } from './npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciEnv { | ||||
|   public npmciRef: Npmci; | ||||
|  | ||||
|   public repoString: string; | ||||
|   public repo: plugins.smartstring.GitRepo; | ||||
|  | ||||
|   constructor(npmciRefArg: Npmci) { | ||||
|     this.npmciRef = npmciRefArg; | ||||
|     this.repoString = process.env.CI_REPOSITORY_URL; | ||||
|     if (!this.repoString) { | ||||
|       this.repoString = 'https://undefined:undefined@github.com/undefined/undefined.git'; | ||||
|     } | ||||
|     this.repo = new plugins.smartstring.GitRepo(this.repoString); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										17
									
								
								ts/npmci.classes.npmciinfo.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ts/npmci.classes.npmciinfo.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
| import { logger } from './npmci.logging'; | ||||
| import { Npmci } from './npmci.classes.npmci'; | ||||
|  | ||||
| export class NpmciInfo { | ||||
|   public npmciRef: Npmci; | ||||
|   public projectInfo = new plugins.projectinfo.ProjectinfoNpm(paths.NpmciPackageRoot); | ||||
|  | ||||
|   constructor(npmciArg: Npmci) { | ||||
|     this.npmciRef = npmciArg; | ||||
|   } | ||||
|  | ||||
|   public printToConsole() { | ||||
|     logger.log('info', `npmci version: ${this.projectInfo.version}`); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										111
									
								
								ts/npmci.cli.ts
									
									
									
									
									
								
							
							
						
						
									
										111
									
								
								ts/npmci.cli.ts
									
									
									
									
									
								
							| @@ -1,111 +0,0 @@ | ||||
| import { logger } from './npmci.logging'; | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
| import * as npmciMonitor from './npmci.monitor'; | ||||
| npmciMonitor.run(); | ||||
|  | ||||
| // Get Info about npmci itself | ||||
| const npmciInfo = new plugins.projectinfo.ProjectinfoNpm(paths.NpmciPackageRoot); | ||||
| logger.log('info', 'npmci version: ' + npmciInfo.version); | ||||
|  | ||||
| import * as NpmciEnv from './npmci.env'; | ||||
|  | ||||
| const npmciSmartcli = new plugins.smartcli.Smartcli(); | ||||
| npmciSmartcli.addVersion(npmciInfo.version); | ||||
|  | ||||
| // clean | ||||
| npmciSmartcli.addCommand('clean').subscribe( | ||||
|   async argv => { | ||||
|     const modClean = await import('./mod_clean/index'); | ||||
|     await modClean.clean(); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // command | ||||
| npmciSmartcli.addCommand('command').subscribe( | ||||
|   async argv => { | ||||
|     const modCommand = await import('./mod_command/index'); | ||||
|     await modCommand.command(); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // command | ||||
| npmciSmartcli.addCommand('git').subscribe( | ||||
|   async argvArg => { | ||||
|     const modGit = await import('./mod_git/index'); | ||||
|     await modGit.handleCli(argvArg); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // build | ||||
| npmciSmartcli.addCommand('docker').subscribe( | ||||
|   async argvArg => { | ||||
|     const modDocker = await import('./mod_docker/index'); | ||||
|     await modDocker.handleCli(argvArg); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // node | ||||
| npmciSmartcli.addCommand('node').subscribe( | ||||
|   async argvArg => { | ||||
|     const modNode = await import('./mod_node/index'); | ||||
|     await modNode.handleCli(argvArg); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // npm | ||||
| npmciSmartcli.addCommand('npm').subscribe( | ||||
|   async argvArg => { | ||||
|     const modNpm = await import('./mod_npm/index'); | ||||
|     await modNpm.handleCli(argvArg); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // trigger | ||||
| npmciSmartcli.addCommand('ssh').subscribe( | ||||
|   async argvArg => { | ||||
|     const modSsh = await import('./mod_ssh/index'); | ||||
|     await modSsh.handleCli(argvArg); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| // trigger | ||||
| npmciSmartcli.addCommand('trigger').subscribe( | ||||
|   async argv => { | ||||
|     const modTrigger = await import('./mod_trigger/index'); | ||||
|     await modTrigger.trigger(); | ||||
|   }, | ||||
|   err => { | ||||
|     console.log(err); | ||||
|     process.exit(1); | ||||
|   } | ||||
| ); | ||||
|  | ||||
| npmciSmartcli.startParse(); | ||||
| @@ -1,37 +0,0 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
|  | ||||
| import { repo } from './npmci.env'; | ||||
|  | ||||
| import { KeyValueStore } from '@pushrocks/npmextra'; | ||||
|  | ||||
| export interface INpmciOptions { | ||||
|   projectInfo: plugins.projectinfo.ProjectInfo; | ||||
|   npmGlobalTools: string[]; | ||||
|   npmAccessLevel?: 'private' | 'public'; | ||||
|   npmRegistryUrl: string; | ||||
|   dockerRegistryRepoMap: any; | ||||
|   dockerBuildargEnvMap: any; | ||||
| } | ||||
|  | ||||
| // instantiate a kvStorage for the current directory | ||||
| export let kvStorage = new KeyValueStore('custom', `${repo.user}_${repo.repo}`); | ||||
|  | ||||
| // handle config retrival | ||||
| const npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd); | ||||
| const defaultConfig: INpmciOptions = { | ||||
|   projectInfo: new plugins.projectinfo.ProjectInfo(paths.cwd), | ||||
|   npmGlobalTools: [], | ||||
|   dockerRegistryRepoMap: {}, | ||||
|   npmAccessLevel: 'private', | ||||
|   npmRegistryUrl: 'registry.npmjs.org', | ||||
|   dockerBuildargEnvMap: {} | ||||
| }; | ||||
| export let configObject = npmciNpmextra.dataFor<INpmciOptions>('npmci', defaultConfig); | ||||
|  | ||||
| /** | ||||
|  * gets the npmci portion of the npmextra.json file | ||||
|  */ | ||||
| export let getConfig = async (): Promise<INpmciOptions> => { | ||||
|   return configObject; | ||||
| }; | ||||
| @@ -1,13 +0,0 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as paths from './npmci.paths'; | ||||
| import { GitRepo } from '@pushrocks/smartstring'; | ||||
| import { Dockerfile } from './mod_docker/index'; | ||||
|  | ||||
| /** | ||||
|  * a info instance about the git respoitory at cwd :) | ||||
|  */ | ||||
| let repoString: string = process.env.CI_REPOSITORY_URL; | ||||
| if (!repoString) { | ||||
|   repoString = 'https://undefined:undefined@github.com/undefined/undefined.git'; | ||||
| } | ||||
| export let repo = new GitRepo(repoString); | ||||
| @@ -1,23 +0,0 @@ | ||||
| import { logger } from './npmci.logging'; | ||||
| import * as plugins from './npmci.plugins'; | ||||
| import * as env from './npmci.env'; | ||||
|  | ||||
| import { Analytics } from 'smartanalytics'; | ||||
|  | ||||
| export let npmciAnalytics = new Analytics({ | ||||
|   apiEndPoint: 'https://pubapi.lossless.one/analytics', | ||||
|   projectId: 'gitzone', | ||||
|   appName: 'npmci' | ||||
| }); | ||||
|  | ||||
| export let run = async () => { | ||||
|   npmciAnalytics | ||||
|     .recordEvent('npmToolExecution', { | ||||
|       host: env.repo.host, | ||||
|       user: env.repo.user, | ||||
|       repo: env.repo.repo | ||||
|     }) | ||||
|     .catch(err => { | ||||
|       logger.log('warn', 'Lossless Analytics API not available...'); | ||||
|     }); | ||||
| }; | ||||
| @@ -1,9 +1,13 @@ | ||||
| import * as plugins from './npmci.plugins'; | ||||
|  | ||||
| export let cwd = process.cwd(); | ||||
| export const cwd = process.cwd(); | ||||
|  | ||||
| export let NpmciPackageRoot = plugins.path.join(__dirname, '../'); | ||||
| export let NpmciPackageConfig = plugins.path.join(NpmciPackageRoot, './config.json'); | ||||
| export let NpmciProjectDir = cwd; | ||||
| export let NpmciTestDir = plugins.path.join(cwd, './test'); | ||||
| export let NpmciCacheDir = plugins.path.join(cwd, './.npmci_cache'); | ||||
| // package paths | ||||
| export const NpmciPackageRoot = plugins.path.join(__dirname, '../'); | ||||
| export const NpmciPackageConfig = plugins.path.join(NpmciPackageRoot, './config.json'); | ||||
|  | ||||
| // project paths | ||||
| export const NpmciProjectDir = cwd; | ||||
| export const NpmciProjectNogitDir = plugins.path.join(NpmciProjectDir, './.nogit'); | ||||
| export const NpmciTestDir = plugins.path.join(cwd, './test'); | ||||
| export const NpmciCacheDir = plugins.path.join(cwd, './.npmci_cache'); | ||||
|   | ||||
| @@ -3,9 +3,23 @@ import * as path from 'path'; | ||||
|  | ||||
| export { path }; | ||||
|  | ||||
| // @apiglobal | ||||
| import * as typedrequest from '@apiglobal/typedrequest'; | ||||
|  | ||||
| export { | ||||
|   typedrequest | ||||
| }; | ||||
|  | ||||
| // @servezone | ||||
| import * as servezoneInterfaces from '@servezone/servezone-interfaces'; | ||||
|  | ||||
| export { servezoneInterfaces }; | ||||
|  | ||||
| // @pushrocks | ||||
| import * as projectinfo from '@pushrocks/projectinfo'; | ||||
| import * as npmextra from '@pushrocks/npmextra'; | ||||
| import * as projectinfo from '@pushrocks/projectinfo'; | ||||
| import * as qenv from '@pushrocks/qenv'; | ||||
| import * as smartanalytics from '@pushrocks/smartanalytics'; | ||||
| import * as smartdelay from '@pushrocks/smartdelay'; | ||||
| import * as smartfile from '@pushrocks/smartfile'; | ||||
| import * as smartcli from '@pushrocks/smartcli'; | ||||
| @@ -15,13 +29,15 @@ import * as smartparam from '@pushrocks/smartparam'; | ||||
| import * as smartpromise from '@pushrocks/smartpromise'; | ||||
| import * as smartrequest from '@pushrocks/smartrequest'; | ||||
| import * as smartshell from '@pushrocks/smartshell'; | ||||
| import * as smartsocket from 'smartsocket'; | ||||
| import * as smartsocket from '@pushrocks/smartsocket'; | ||||
| import * as smartssh from '@pushrocks/smartssh'; | ||||
| import * as smartstring from '@pushrocks/smartstring'; | ||||
|  | ||||
| export { | ||||
|   projectinfo, | ||||
|   npmextra, | ||||
|   projectinfo, | ||||
|   qenv, | ||||
|   smartanalytics, | ||||
|   smartdelay, | ||||
|   smartfile, | ||||
|   smartcli, | ||||
| @@ -36,8 +52,6 @@ export { | ||||
|   smartstring | ||||
| }; | ||||
|  | ||||
| // third party | ||||
| import * as lodash from 'lodash'; | ||||
| import * as through2 from 'through2'; | ||||
|  | ||||
| export { lodash, through2 }; | ||||
| export { through2 }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user