Compare commits

...

91 Commits

Author SHA1 Message Date
c696730e55 3.1.36 2019-07-17 17:57:21 +02:00
38d38ce246 fix(core): update 2019-07-17 17:57:20 +02:00
adfdf68c38 3.1.35 2019-07-17 17:55:03 +02:00
d4a4d69941 fix(core): update 2019-07-17 17:55:02 +02:00
c1fed2c758 3.1.34 2019-07-17 17:04:10 +02:00
9918d81f59 fix(core): update 2019-07-17 17:04:10 +02:00
59d8338f6e 3.1.33 2019-06-19 14:00:24 +02:00
a4f8bd3320 fix(core): update 2019-06-19 14:00:24 +02:00
7c2fdb7224 3.1.32 2019-06-19 11:36:05 +02:00
37384aeb57 fix(core): update 2019-06-19 11:36:04 +02:00
60efda263f 3.1.31 2019-06-19 11:35:19 +02:00
19831037ec fix(core): update 2019-06-19 11:35:19 +02:00
a1d52af813 3.1.30 2019-06-19 10:41:58 +02:00
0a49ff9b03 fix(core): update 2019-06-19 10:41:58 +02:00
ca62326b46 3.1.29 2019-06-18 22:24:53 +02:00
e1de0ee479 fix(core): update 2019-06-18 22:24:53 +02:00
0dea101c07 3.1.28 2019-06-18 22:24:12 +02:00
380a49c59f fix(core): update 2019-06-18 22:24:12 +02:00
5133651e34 3.1.27 2019-06-18 17:30:05 +02:00
c8f26c7c48 fix(core): update 2019-06-18 17:30:04 +02:00
3bb5912046 3.1.26 2019-06-18 16:19:07 +02:00
d75258d9dd fix(core): update 2019-06-18 16:19:07 +02:00
b1577e7542 3.1.25 2019-05-08 22:50:57 +02:00
d5cdeffd17 fix(core): update 2019-05-08 22:50:57 +02:00
c62ce415e9 3.1.24 2019-05-08 22:44:34 +02:00
99014da1e8 fix(core): update 2019-05-08 22:44:34 +02:00
0b5dada524 3.1.23 2019-05-08 22:43:49 +02:00
40bddba3b5 fix(core): update 2019-05-08 22:43:48 +02:00
6f6ee6d799 3.1.22 2019-02-24 22:50:12 +01:00
e30cc3f5a0 fix(core): update 2019-02-24 22:50:12 +01:00
a4562d4d1b 3.1.21 2018-12-24 02:13:05 +01:00
524b405773 fix(core): update 2018-12-24 02:13:04 +01:00
0d19c1c68d 3.1.20 2018-12-23 18:57:15 +01:00
cff79bc3b4 fix(mirror): now refusing to mirror for private code 2018-12-23 18:57:15 +01:00
28541a838d 3.1.19 2018-12-23 18:54:17 +01:00
c3ab527341 fix(core): update 2018-12-23 18:54:16 +01:00
52cc249098 3.1.18 2018-12-23 17:29:25 +01:00
2e189b0660 fix(core): update 2018-12-23 17:29:25 +01:00
f876c7414b 3.1.17 2018-12-12 22:29:59 +01:00
08b7585cfc fix(core): update 2018-12-12 22:29:59 +01:00
76311fab72 3.1.16 2018-12-11 01:02:22 +01:00
1b73df64f5 fix(core): update 2018-12-11 01:02:21 +01:00
701cee573b 3.1.15 2018-12-11 00:25:40 +01:00
3dd086f711 fix(core): update 2018-12-11 00:25:39 +01:00
67ff5d09d4 3.1.14 2018-12-09 16:48:33 +01:00
5cb8a79b6a fix(core): update 2018-12-09 16:48:33 +01:00
2dcbca2362 3.1.13 2018-12-09 16:26:28 +01:00
bd63194f4b fix(core): update 2018-12-09 16:26:28 +01:00
2763fdef5f 3.1.12 2018-12-09 15:53:39 +01:00
bbedde01b9 fix(core): update 2018-12-09 15:53:38 +01:00
f26606f757 3.1.11 2018-12-09 15:22:20 +01:00
99b03aa796 fix(core): update 2018-12-09 15:22:20 +01:00
f30dd3da65 3.1.10 2018-12-09 14:59:51 +01:00
d4decddb4b fix(core): update 2018-12-09 14:59:51 +01:00
5c2880da1a 3.1.9 2018-12-09 14:53:44 +01:00
bfffc5b130 3.1.8 2018-12-09 14:39:25 +01:00
8900a13c6b fix(core): update 2018-12-09 14:39:24 +01:00
d42acf737f 3.1.7 2018-12-09 02:51:04 +01:00
77e3b2912d fix(core): update 2018-12-09 02:51:03 +01:00
103e470eb4 3.1.6 2018-12-09 02:50:00 +01:00
74c1324e55 fix(core): update 2018-12-09 02:50:00 +01:00
a1876963a8 3.1.5 2018-11-28 21:06:12 +01:00
5d88e25c99 fix(dependencies): update 2018-11-28 21:06:12 +01:00
b3c47546e2 3.1.4 2018-11-26 18:01:55 +01:00
6316e81958 fix(core): update 2018-11-26 18:01:54 +01:00
ff10afbee4 3.1.3 2018-11-24 15:12:55 +01:00
9dbfa77084 fix(ci): remove npmts build dependency 2018-11-24 15:12:55 +01:00
46dbd61d89 3.1.2 2018-11-24 15:10:56 +01:00
713df1867a fix(core): update 2018-11-24 15:10:55 +01:00
23886c1ed3 3.1.1 2018-11-24 15:08:08 +01:00
0c46b627be fix(core): update 2018-11-24 15:08:07 +01:00
622ccd8dd9 3.1.0 2018-11-24 15:00:19 +01:00
0079addfc5 feat(logging): use smartlog 2018-11-24 15:00:19 +01:00
8604c63d37 3.0.59 2018-09-22 15:18:21 +02:00
db0b38bd7b fix(cli): update cli files to be in line with gitzone cli template 2018-09-22 15:18:21 +02:00
edde87b6be 3.0.58 2018-09-22 14:36:26 +02:00
5085d664cb fix(fix request package usage): update 2018-09-22 14:36:25 +02:00
5d468fc840 3.0.57 2018-09-22 14:13:26 +02:00
e2ac6cdcc9 fix(dependencies): update 2018-09-22 14:13:25 +02:00
fcd04415be 3.0.56 2018-07-16 00:04:24 +02:00
1fd1899099 fix(ci): update to latest standards 2018-07-16 00:04:24 +02:00
7df7f882d1 3.0.55 2018-07-16 00:02:30 +02:00
348b4d60fd fix(security): snyk 2018-07-16 00:02:29 +02:00
37589fb5e5 3.0.54 2018-07-15 23:58:43 +02:00
3dd115fe42 fix(ci): adjust to newer build system 2018-07-15 23:58:43 +02:00
01c88a6a6c 3.0.53 2018-07-15 23:49:38 +02:00
f5cacb7400 fix(core): update 2018-07-15 23:49:37 +02:00
887da51d78 3.0.52 2018-07-02 23:15:25 +02:00
585703fc55 fix(core): switch to @pushrocks/smartpromise 2018-07-02 23:15:24 +02:00
ec3e296d73 3.0.51 2018-07-02 23:09:52 +02:00
33f234cf73 fix(core): update to latest standards 2018-07-02 23:09:52 +02:00
32 changed files with 4340 additions and 440 deletions

23
.gitignore vendored
View File

@@ -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

View File

@@ -1,9 +1,9 @@
# gitzone standard
image: hosttoday/ht-docker-node:npmci
# gitzone ci_default
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache:
paths:
- .yarn/
- .npmci_cache/
key: "$CI_BUILD_STAGE"
stages:
@@ -26,8 +26,9 @@ mirror:
snyk:
stage: security
script:
- npmci command yarn global add snyk
- npmci command yarn install --ignore-scripts
- npmci npm prepare
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts
- npmci command snyk test
tags:
- docker
@@ -36,21 +37,11 @@ snyk:
# ====================
# test stage
# ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS:
stage: test
script:
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
@@ -58,13 +49,14 @@ testLTS:
tags:
- docker
- notpriv
testSTABLE:
testBuild:
stage: test
script:
- npmci node install stable
- npmci npm prepare
- npmci node install lts
- npmci npm install
- npmci npm test
- npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
@@ -73,7 +65,7 @@ testSTABLE:
release:
stage: release
script:
- npmci node install stable
- npmci node install lts
- npmci npm publish
only:
- tags
@@ -86,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
@@ -117,8 +101,10 @@ pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command yarn global add npmpage
- npmci command npmpage
- npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare
- npmci npm install
- npmci command tsdoc
tags:
- docker
- notpriv
@@ -128,3 +114,4 @@ pages:
expire_in: 1 week
paths:
- public
allow_failure: true

15
.snyk
View File

@@ -1,15 +1,4 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.12.0
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
'npm:shelljs:20140723':
- shelljs:
reason: None given
expires: '2018-06-02T22:48:10.660Z'
- smartshell > shelljs:
reason: None given
expires: '2018-06-02T22:48:10.660Z'
- smartssh > shelljs:
reason: None given
expires: '2018-06-02T22:48:10.660Z'
version: v1.13.1
ignore: {}
patch: {}

3
cli.js Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
process.env.CLI_CALL = 'true';
require('./dist/index');

4
cli.ts.js Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env node
process.env.CLI_CALL = 'true';
require('@gitzone/tsrun');
require('./ts/index');

View File

@@ -1,17 +1,26 @@
{
"npmts":{
"mode":"default",
"coverageTreshold": "70",
"cli": true
},
"npmci": {
"npmGlobalTools": [
"@gitzone/npmts"
],
"npmAccessLevel": "public"
},
"npmdocker":{
"baseImage":"hosttoday/ht-docker-node:npmci",
"command": "npmci test stable"
"npmts": {
"mode": "default",
"coverageTreshold": "70",
"cli": true
},
"npmci": {
"npmGlobalTools": [],
"npmAccessLevel": "public",
"npmRegistryUrl": "registry.npmjs.org"
},
"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"
}
}
}

3782
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,17 @@
{
"name": "@shipzone/npmci",
"version": "3.0.50",
"version": "3.1.36",
"private": false,
"description": "node and docker in gitlab ci on steroids",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"bin": {
"npmci": "dist/cli.js"
"npmci": "cli.js"
},
"scripts": {
"test": "(rm -f config.json) && (npmts) && (npm run testVersion)",
"build": "(rm -f config.json) && (npmts) && (npm run testVersion)",
"testVersion": "(cd test/assets/ && node ../../dist/cli.js -v)"
"test": "(rm -f config.json) && tstest test/",
"build": "(rm -f config.json) && tsbuild && (npm run testVersion)",
"testVersion": "(cd test/assets/ && node ../../cli.js -v)"
},
"repository": {
"type": "git",
@@ -23,32 +24,45 @@
},
"homepage": "https://gitlab.com/gitzone/npmci#README",
"devDependencies": {
"tapbundle": "^2.0.0"
"@gitzone/tsbuild": "^2.1.11",
"@gitzone/tsrun": "^1.2.6",
"@gitzone/tstest": "^1.0.24",
"@pushrocks/tapbundle": "^3.0.9",
"@types/node": "^12.0.8",
"tslint": "^5.17.0",
"tslint-config-prettier": "^1.18.0"
},
"dependencies": {
"@pushrocks/smartcli": "^3.0.1",
"@types/lodash": "^4.14.74",
"@types/shelljs": "^0.7.4",
"@types/through2": "^2.0.33",
"beautylog": "^6.1.10",
"cflare": "^1.0.5",
"lik": "^2.0.5",
"lodash": "^4.17.4",
"npmextra": "^2.0.9",
"projectinfo": "^3.0.2",
"request": "^2.81.0",
"shelljs": "^0.8.1",
"smartanalytics": "^2.0.9",
"smartdelay": "^1.0.3",
"smartfile": "^4.2.20",
"smartparam": "^1.0.2",
"smartq": "^1.1.6",
"smartshell": "^1.0.18",
"smartsocket": "^1.1.10",
"smartssh": "^1.2.2",
"smartstring": "^2.0.24",
"smartsystem": "^2.0.2",
"through2": "^2.0.3"
"@pushrocks/lik": "^3.0.5",
"@pushrocks/npmextra": "^3.0.5",
"@pushrocks/projectinfo": "^4.0.2",
"@pushrocks/smartanalytics": "^2.0.15",
"@pushrocks/smartcli": "^3.0.7",
"@pushrocks/smartdelay": "^2.0.3",
"@pushrocks/smartfile": "^7.0.2",
"@pushrocks/smartgit": "^1.0.9",
"@pushrocks/smartlog": "^2.0.19",
"@pushrocks/smartlog-destination-local": "^8.0.2",
"@pushrocks/smartparam": "^1.0.4",
"@pushrocks/smartpromise": "^3.0.2",
"@pushrocks/smartrequest": "^1.1.16",
"@pushrocks/smartshell": "^2.0.23",
"@pushrocks/smartsocket": "^1.1.38",
"@pushrocks/smartssh": "^1.2.3",
"@pushrocks/smartstring": "^3.0.10",
"@types/shelljs": "^0.8.5",
"@types/through2": "^2.0.34",
"through2": "^3.0.1"
},
"private": false
"files": [
"ts/*",
"ts_web/*",
"dist/*",
"dist_web/*",
"dist_ts_web/*",
"assets/*",
"cli.js",
"npmextra.json",
"readme.md"
]
}

View File

@@ -1,25 +1,20 @@
# npmci
# @shipzone/npmci
node and docker in gitlab ci on steroids
## Availabililty
[![npm](https://shipzone.gitlab.io/assets/repo-button-npm.svg)](https://www.npmjs.com/package/@shipzone/npmci)
[![git](https://shipzone.gitlab.io/assets/repo-button-git.svg)](https://GitLab.com/shipzone/npmci)
[![git](https://shipzone.gitlab.io/assets/repo-button-mirror.svg)](https://github.com/shipzone/npmci)
[![docs](https://shipzone.gitlab.io/assets/repo-button-docs.svg)](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
[![build status](https://GitLab.com/shipzone/npmci/badges/master/build.svg)](https://GitLab.com/shipzone/npmci/commits/master)
[![coverage report](https://GitLab.com/shipzone/npmci/badges/master/coverage.svg)](https://GitLab.com/shipzone/npmci/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/npmci.svg)](https://www.npmjs.com/package/@shipzone/npmci)
[![Dependency Status](https://david-dm.org/shipzone/npmci.svg)](https://david-dm.org/shipzone/npmci)
[![bitHound Dependencies](https://www.bithound.io/github/shipzone/npmci/badges/dependencies.svg)](https://www.bithound.io/github/shipzone/npmci/master/dependencies/npm)
[![bitHound Code](https://www.bithound.io/github/shipzone/npmci/badges/code.svg)](https://www.bithound.io/github/shipzone/npmci)
[![TypeScript](https://img.shields.io/badge/TypeScript-2.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/)
[![build status](https://gitlab.com/shipzone/npmci/badges/master/build.svg)](https://gitlab.com/shipzone/npmci/commits/master)
[![coverage report](https://gitlab.com/shipzone/npmci/badges/master/coverage.svg)](https://gitlab.com/shipzone/npmci/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@shipzone/npmci.svg)](https://www.npmjs.com/package/@shipzone/npmci)
[![Known Vulnerabilities](https://snyk.io/test/npm/@shipzone/npmci/badge.svg)](https://snyk.io/test/npm/@shipzone/npmci)
[![TypeScript](https://img.shields.io/badge/TypeScript->=%203.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-prettier-ff69b4.svg)](https://prettier.io/)
## Usage
@@ -29,9 +24,9 @@ npmci is designed to work in docker CI environments. The following docker images
Docker Hub:
* [hosttoday/ht-docker-node:npmci](https://hub.docker.com/r/hosttoday/ht-docker-node/)
- [hosttoday/ht-docker-node:npmci](https://hub.docker.com/r/hosttoday/ht-docker-node/)
has LTS node version and npmci preinstalled.
* [hosttoday/ht-docker-dbase](https://hub.docker.com/r/hosttoday/ht-docker-dbase/)
- [hosttoday/ht-docker-dbase](https://hub.docker.com/r/hosttoday/ht-docker-dbase/)
based on docker:git, can be used to build docker images in conjunction with docker:dind
npmci can be called from commandline and handle a lot of tasks durug ci:
@@ -71,7 +66,7 @@ npmci publish npm # will look vor $NPMCI_TOKEN_NPM env var and push any module i
npmci publish docker
# trigger webhooks
npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name
npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name
```
## Configuration
@@ -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.html)
[![repo-footer](https://shipzone.gitlab.io/assets/repo-footer.svg)](https://push.rocks)
[![repo-footer](https://shipzone.gitlab.io/assets/repo-footer.svg)](https://maintainedby.lossless.com)

View File

@@ -1,4 +1,4 @@
import { tap, expect } from 'tapbundle';
import { tap, expect } from '@pushrocks/tapbundle';
import * as path from 'path';
// Setup test

View File

@@ -1,31 +0,0 @@
import * as plugins from './mod.plugins';
let npmciCflare = new plugins.cflare.CflareAccount();
/**
* handle cli input
* @param argvArg
*/
export let handleCli = async argvArg => {
if (argvArg._.length >= 2) {
let action: string = argvArg._[1];
switch (action) {
default:
plugins.beautylog.error(`>>npmci cloudflare ...<< action >>${action}<< not supported`);
process.exit(1);
}
} else {
plugins.beautylog.log(
`>>npmci cloudflare ...<< cli arguments invalid... Please read the documentation.`
);
process.exit(1);
}
};
export let purge = async argvArg => {
npmciCflare.auth({
email: '',
key: ''
});
npmciCflare.purgeZone(argvArg._[1]);
};

View File

@@ -1,5 +0,0 @@
export * from '../npmci.plugins';
import * as cflare from 'cflare';
export { cflare };

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import * as paths from '../npmci.paths';
import { bash } from '../npmci.bash';
@@ -9,8 +10,11 @@ import { Dockerfile } from './mod.classes.dockerfile';
import { DockerRegistry } from './mod.classes.dockerregistry';
import { RegistryStorage } from './mod.classes.registrystorage';
// config
import { configObject } from '../npmci.config';
// instances
let npmciRegistryStorage = new RegistryStorage();
const npmciRegistryStorage = new RegistryStorage();
export { Dockerfile, helpers };
@@ -20,10 +24,10 @@ export let modArgvArg; // will be set through the build command
* handle cli input
* @param argvArg
*/
export let handleCli = async argvArg => {
export const handleCli = async argvArg => {
modArgvArg = argvArg;
if (argvArg._.length >= 2) {
let action: string = argvArg._[1];
const action: string = argvArg._[1];
switch (action) {
case 'build':
await build();
@@ -42,10 +46,11 @@ export let handleCli = async argvArg => {
await pull(argvArg);
break;
default:
plugins.beautylog.error(`>>npmci docker ...<< action >>${action}<< not supported`);
logger.log('error', `>>npmci docker ...<< action >>${action}<< not supported`);
}
} else {
plugins.beautylog.log(
logger.log(
'info',
`>>npmci docker ...<< cli arguments invalid... Please read the documentation.`
);
}
@@ -54,9 +59,9 @@ export let handleCli = async argvArg => {
/**
* builds a cwd of Dockerfiles by triggering a promisechain
*/
export let build = async () => {
export const build = async () => {
await prepare();
plugins.beautylog.log('now building Dockerfiles...');
logger.log('info', 'now building Dockerfiles...');
await helpers
.readDockerfiles()
.then(helpers.sortDockerfiles)
@@ -67,7 +72,7 @@ export let build = async () => {
/**
* login to the DockerRegistries
*/
export let login = async () => {
export const login = async () => {
await prepare();
await npmciRegistryStorage.loginAll();
};
@@ -75,10 +80,10 @@ export let login = async () => {
/**
* logs in docker
*/
export let prepare = async () => {
export const prepare = async () => {
// Always login to GitLab Registry
if (!process.env.CI_BUILD_TOKEN || process.env.CI_BUILD_TOKEN === '') {
plugins.beautylog.error('No registry token specified by gitlab!');
logger.log('error', 'No registry token specified by gitlab!');
process.exit(1);
}
npmciRegistryStorage.addRegistry(
@@ -96,47 +101,74 @@ export let prepare = async () => {
return;
};
export let push = async argvArg => {
/**
* pushes an image towards a registry
* @param argvArg
*/
export const push = async argvArg => {
await prepare();
let registryUrlArg = argvArg._[2];
let dockerRegistryUrls: string[] = [];
// lets parse the input of cli and npmextra
if (argvArg._.length >= 3 && argvArg._[2] !== 'npmextra') {
dockerRegistryUrls.push(argvArg._[2]);
} else {
if (configObject.dockerRegistries.length === 0) {
logger.log(
'warn',
`There are no docker registries listed in npmextra.json! This is strange!`
);
}
dockerRegistryUrls = dockerRegistryUrls.concat(configObject.dockerRegistries);
}
// lets determine the suffix
let suffix = null;
if (argvArg._.length >= 4) {
suffix = argvArg._[3];
}
let dockerfileArray = await helpers
.readDockerfiles()
.then(helpers.sortDockerfiles)
.then(helpers.mapDockerfiles);
let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
if (!localDockerRegistry) {
plugins.beautylog.error(
`Cannot push to registry ${registryUrlArg}, because it was not found in the authenticated registry list.`
);
process.exit(1);
}
for (let dockerfile of dockerfileArray) {
await dockerfile.push(localDockerRegistry, suffix);
// lets push to the registries
for (const dockerRegistryUrl of dockerRegistryUrls) {
const dockerfileArray = await helpers
.readDockerfiles()
.then(helpers.sortDockerfiles)
.then(helpers.mapDockerfiles);
const dockerRegistryToPushTo = 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);
}
}
};
export let pull = async argvArg => {
export const pull = async argvArg => {
await prepare();
let registryUrlArg = argvArg._[2];
const registryUrlArg = argvArg._[2];
let suffix = null;
if (argvArg._.length >= 4) {
suffix = argvArg._[3];
}
let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
let dockerfileArray = await helpers
const localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
const dockerfileArray = await helpers
.readDockerfiles()
.then(helpers.sortDockerfiles)
.then(helpers.mapDockerfiles);
for (let dockerfile of dockerfileArray) {
for (const dockerfile of dockerfileArray) {
await dockerfile.pull(localDockerRegistry, suffix);
}
};
export let test = async () => {
/**
* tests docker files
*/
export const test = async () => {
await prepare();
return await helpers.readDockerfiles().then(helpers.testDockerfiles);
};

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import * as NpmciEnv from '../npmci.env';
import { bash } from '../npmci.bash';
@@ -10,16 +11,16 @@ import * as helpers from './mod.helpers';
* class Dockerfile represents a Dockerfile on disk in npmci
*/
export class Dockerfile {
filePath: string;
repo: string;
version: string;
cleanTag: string;
buildTag: string;
containerName: string;
content: string;
baseImage: string;
localBaseImageDependent: boolean;
localBaseDockerfile: Dockerfile;
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;
@@ -38,10 +39,10 @@ export class Dockerfile {
/**
* builds the Dockerfile
*/
async build() {
plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag);
let buildArgsString = await helpers.getDockerBuildArgs();
let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
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;
}
@@ -49,8 +50,8 @@ export class Dockerfile {
/**
* pushes the Dockerfile to a registry
*/
async push(dockerRegistryArg: DockerRegistry, versionSuffix: string = null) {
let pushTag = helpers.getDockerTagString(
public async push(dockerRegistryArg: DockerRegistry, versionSuffix: string = null) {
const pushTag = helpers.getDockerTagString(
dockerRegistryArg.registryUrl,
this.repo,
this.version,
@@ -63,8 +64,8 @@ export class Dockerfile {
/**
* pulls the Dockerfile from a registry
*/
async pull(registryArg: DockerRegistry, versionSuffixArg: string = null) {
let pullTag = helpers.getDockerTagString(
public async pull(registryArg: DockerRegistry, versionSuffixArg: string = null) {
const pullTag = helpers.getDockerTagString(
registryArg.registryUrl,
this.repo,
this.version,
@@ -77,15 +78,13 @@ export class Dockerfile {
/**
* tests the Dockerfile;
*/
async test() {
let testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh');
let testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile);
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"`
`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`);
@@ -93,17 +92,17 @@ export class Dockerfile {
await bash(`docker rm npmci_test_container`);
await bash(`docker rmi --force npmci_test_image`);
} else {
plugins.beautylog.warn(
'skipping tests for ' + this.cleanTag + ' because no testfile was found!'
);
logger.log('warn', 'skipping tests for ' + this.cleanTag + ' because no testfile was found!');
}
}
/**
* gets the id of a Dockerfile
*/
async getId() {
let containerId = await bash('docker inspect --type=image --format="{{.Id}}" ' + this.buildTag);
public async getId() {
const containerId = await bash(
'docker inspect --type=image --format="{{.Id}}" ' + this.buildTag
);
return containerId;
}
}

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import { bash } from '../npmci.bash';
@@ -8,26 +9,26 @@ export interface IDockerRegistryConstructorOptions {
}
export class DockerRegistry {
registryUrl: string;
username: string;
password: string;
public registryUrl: string;
public username: string;
public password: string;
constructor(optionsArg: IDockerRegistryConstructorOptions) {
this.registryUrl = optionsArg.registryUrl;
this.username = optionsArg.username;
this.password = optionsArg.password;
plugins.beautylog.info(`created DockerRegistry for ${this.registryUrl}`);
logger.log('info', `created DockerRegistry for ${this.registryUrl}`);
}
static fromEnvString(envString: string): DockerRegistry {
let dockerRegexResultArray = envString.split('|');
public static fromEnvString(envString: string): DockerRegistry {
const dockerRegexResultArray = envString.split('|');
if (dockerRegexResultArray.length !== 3) {
plugins.beautylog.error('malformed docker env var...');
logger.log('error', 'malformed docker env var...');
process.exit(1);
return;
}
let registryUrl = dockerRegexResultArray[0];
let username = dockerRegexResultArray[1];
let password = dockerRegexResultArray[2];
const registryUrl = dockerRegexResultArray[0];
const username = dockerRegexResultArray[1];
const password = dockerRegexResultArray[2];
return new DockerRegistry({
registryUrl: registryUrl,
username: username,
@@ -35,13 +36,13 @@ export class DockerRegistry {
});
}
async login() {
public async login() {
if (this.registryUrl === 'docker.io') {
await bash(`docker login -u ${this.username} -p ${this.password}`);
plugins.beautylog.info('Logged in to standard docker hub');
logger.log('info', 'Logged in to standard docker hub');
} else {
await bash(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`);
}
plugins.beautylog.ok(`docker authenticated for ${this.registryUrl}!`);
logger.log('ok', `docker authenticated for ${this.registryUrl}!`);
}
}

View File

@@ -1,5 +1,6 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import { Objectmap } from 'lik';
import { Objectmap } from '@pushrocks/lik';
import { DockerRegistry } from './mod.classes.dockerregistry';
@@ -23,6 +24,6 @@ export class RegistryStorage {
await this.objectMap.forEach(async registryArg => {
await registryArg.login();
});
plugins.beautylog.success('logged in successfully into all available DockerRegistries!');
logger.log('success', 'logged in successfully into all available DockerRegistries!');
}
}

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import * as paths from '../npmci.paths';
import * as NpmciEnv from '../npmci.env';
@@ -11,14 +12,14 @@ import { Dockerfile } from './mod.classes.dockerfile';
* @returns Promise<Dockerfile[]>
*/
export let readDockerfiles = async (): Promise<Dockerfile[]> => {
let fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
const fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
// create the Dockerfile array
let readDockerfilesArray: Dockerfile[] = [];
plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`);
const readDockerfilesArray: Dockerfile[] = [];
logger.log('info', `found ${fileTree.length} Dockerfiles:`);
console.log(fileTree);
for (let dockerfilePath of fileTree) {
let myDockerfile = new Dockerfile({
for (const dockerfilePath of fileTree) {
const myDockerfile = new Dockerfile({
filePath: dockerfilePath,
read: true
});
@@ -34,14 +35,14 @@ export let readDockerfiles = async (): Promise<Dockerfile[]> => {
* @returns Promise<Dockerfile[]>
*/
export let sortDockerfiles = (sortableArrayArg: Dockerfile[]): Promise<Dockerfile[]> => {
let done = plugins.q.defer<Dockerfile[]>();
plugins.beautylog.info('sorting Dockerfiles:');
let sortedArray: Dockerfile[] = [];
let cleanTagsOriginal = cleanTagsArrayFunction(sortableArrayArg, sortedArray);
const done = plugins.smartpromise.defer<Dockerfile[]>();
logger.log('info', 'sorting Dockerfiles:');
const sortedArray: Dockerfile[] = [];
const cleanTagsOriginal = cleanTagsArrayFunction(sortableArrayArg, sortedArray);
let sorterFunctionCounter: number = 0;
let sorterFunction = function() {
const sorterFunction = () => {
sortableArrayArg.forEach(dockerfileArg => {
let cleanTags = cleanTagsArrayFunction(sortableArrayArg, sortedArray);
const cleanTags = cleanTagsArrayFunction(sortableArrayArg, sortedArray);
if (
cleanTags.indexOf(dockerfileArg.baseImage) === -1 &&
sortedArray.indexOf(dockerfileArg) === -1
@@ -54,8 +55,8 @@ export let sortDockerfiles = (sortableArrayArg: Dockerfile[]): Promise<Dockerfil
});
if (sortableArrayArg.length === sortedArray.length) {
let counter = 1;
for (let dockerfile of sortedArray) {
plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`);
for (const dockerfile of sortedArray) {
logger.log('info', `tag ${counter}: -> ${dockerfile.cleanTag}`);
counter++;
}
done.resolve(sortedArray);
@@ -88,7 +89,7 @@ export let mapDockerfiles = async (sortedArray: Dockerfile[]): Promise<Dockerfil
* builds the correspoding real docker image for each Dockerfile class instance
*/
export let buildDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
for (let dockerfileArg of sortedArrayArg) {
for (const dockerfileArg of sortedArrayArg) {
await dockerfileArg.build();
}
return sortedArrayArg;
@@ -99,7 +100,7 @@ export let buildDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
* @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
*/
export let testDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
for (let dockerfileArg of sortedArrayArg) {
for (const dockerfileArg of sortedArrayArg) {
await dockerfileArg.test();
}
return sortedArrayArg;
@@ -111,8 +112,8 @@ export let testDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
*/
export let dockerFileVersion = (dockerfileNameArg: string): string => {
let versionString: string;
let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
let regexResultArray = versionRegex.exec(dockerfileNameArg);
const versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
const regexResultArray = versionRegex.exec(dockerfileNameArg);
if (regexResultArray && regexResultArray.length === 2) {
versionString = regexResultArray[1];
} else {
@@ -124,9 +125,9 @@ export let dockerFileVersion = (dockerfileNameArg: string): string => {
/**
* returns the docker base image for a Dockerfile
*/
export let dockerBaseImage = function(dockerfileContentArg: string) {
let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
let regexResultArray = baseImageRegex.exec(dockerfileContentArg);
export let dockerBaseImage = (dockerfileContentArg: string) => {
const baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
const regexResultArray = baseImageRegex.exec(dockerfileContentArg);
return regexResultArray[1];
};
@@ -140,8 +141,8 @@ export let getDockerTagString = (
suffixArg?: string
): string => {
// determine wether the repo should be mapped accordingly to the registry
let mappedRepo = NpmciConfig.configObject.dockerRegistryRepoMap[registryArg];
let repo = (() => {
const mappedRepo = NpmciConfig.configObject.dockerRegistryRepoMap[registryArg];
const repo = (() => {
if (mappedRepo) {
return mappedRepo;
} else {
@@ -155,16 +156,16 @@ export let getDockerTagString = (
version = versionArg + '_' + suffixArg;
}
let tagString = `${registryArg}/${repo}:${version}`;
const tagString = `${registryArg}/${repo}:${version}`;
return tagString;
};
export let getDockerBuildArgs = async (): Promise<string> => {
plugins.beautylog.info('checking for env vars to be supplied to the docker build');
logger.log('info', 'checking for env vars to be supplied to the docker build');
let buildArgsString: string = '';
for (let key in NpmciConfig.configObject.dockerBuildargEnvMap) {
let targetValue = process.env[NpmciConfig.configObject.dockerBuildargEnvMap[key]];
buildArgsString = `${buildArgsString} --build-arg ${key}=${targetValue}`;
for (const key in NpmciConfig.configObject.dockerBuildargEnvMap) {
const targetValue = process.env[NpmciConfig.configObject.dockerBuildargEnvMap[key]];
buildArgsString = `${buildArgsString} --build-arg ${key}="${targetValue}"`;
}
return buildArgsString;
};
@@ -172,12 +173,12 @@ export let getDockerBuildArgs = async (): Promise<string> => {
/**
*
*/
export let cleanTagsArrayFunction = function(
export let cleanTagsArrayFunction = (
dockerfileArrayArg: Dockerfile[],
trackingArrayArg: Dockerfile[]
): string[] {
let cleanTagsArray: string[] = [];
dockerfileArrayArg.forEach(function(dockerfileArg) {
): string[] => {
const cleanTagsArray: string[] = [];
dockerfileArrayArg.forEach(dockerfileArg => {
if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
cleanTagsArray.push(dockerfileArg.cleanTag);
}

View File

@@ -1,45 +1,59 @@
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) {
let action: string = argvArg._[1];
const action: string = argvArg._[1];
switch (action) {
case 'mirror':
await mirror();
break;
default:
plugins.beautylog.error(`>>npmci git ...<< action >>${action}<< not supported`);
logger.log('error', `npmci git -> action >>${action}<< not supported!`);
}
} else {
plugins.beautylog.log(
`>>npmci git ...<< cli arguments invalid... Please read the documentation.`
);
logger.log('info', `npmci git -> cli arguments invalid! Please read the documentation.`);
}
};
export let mirror = async () => {
let githubToken = process.env.NPMCI_GIT_GITHUBTOKEN;
let githubUser = process.env.NPMCI_GIT_GITHUBGROUP || repo.user;
let githubRepo = process.env.NPMCI_GIT_GITHUB || repo.repo;
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 ||
configObject.npmAccessLevel === 'private'
) {
logger.log(
'warn',
`refusing to mirror due to private property use a private mirror location instead`
);
return;
}
if (githubToken) {
plugins.beautylog.info('found github token.');
plugins.beautylog.log('attempting the mirror the repository to GitHub');
logger.log('info', 'found github token.');
logger.log('info', 'attempting the mirror the repository to GitHub');
plugins.smartgit.GitRepo;
// add the mirror
await bash(
`git remote add mirror https://${githubToken}@github.com/${githubUser}/${githubRepo}.git`
);
await bash(`git push mirror --all`);
plugins.beautylog.ok('pushed all branches to mirror!');
logger.log('ok', 'pushed all branches to mirror!');
await bash(`git push mirror --tags`);
plugins.beautylog.ok('pushed all tags to mirror!');
logger.log('ok', 'pushed all tags to mirror!');
} else {
plugins.beautylog.error(`cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
process.exit(1);
}
};

View File

@@ -1 +1,5 @@
export * from '../npmci.plugins';
import * as smartgit from '@pushrocks/smartgit';
export { smartgit };

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from '../npmci.plugins';
import * as paths from '../npmci.paths';
import * as npmciConfig from '../npmci.config';
@@ -9,17 +10,18 @@ import { bash, bashNoError, nvmAvailable } from '../npmci.bash';
*/
export let handleCli = async argvArg => {
if (argvArg._.length >= 3) {
let action: string = argvArg._[1];
const action: string = argvArg._[1];
switch (action) {
case 'install':
await install(argvArg._[2]);
break;
default:
plugins.beautylog.error(`>>npmci node ...<< action >>${action}<< not supported`);
logger.log('error', `>>npmci node ...<< action >>${action}<< not supported`);
process.exit(1);
}
} else {
plugins.beautylog.error(
logger.log(
'error',
`>>npmci node ...<< cli arguments invalid... Please read the documentation.`
);
process.exit(1);
@@ -31,12 +33,12 @@ export let handleCli = async argvArg => {
* @param versionArg
*/
export let install = async versionArg => {
plugins.beautylog.log(`now installing node version ${versionArg}`);
logger.log('info', `now installing node version ${versionArg}`);
let version: string;
if (versionArg === 'stable') {
version = '9';
version = '12';
} else if (versionArg === 'lts') {
version = '8';
version = '10';
} else if (versionArg === 'legacy') {
version = '8';
} else {
@@ -44,27 +46,27 @@ export let install = async versionArg => {
}
if (await nvmAvailable.promise) {
await bash(`nvm install ${version} && nvm alias default ${version}`);
plugins.beautylog.success(`Node version ${version} successfully installed!`);
logger.log('success', `Node version ${version} successfully installed!`);
} else {
plugins.beautylog.warn('Nvm not in path so staying at installed node version!');
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 => {
plugins.beautylog.log('Now checking for needed global npm tools...');
for (let npmTool of configArg.npmGlobalTools) {
plugins.beautylog.info(`Checking for global "${npmTool}"`);
let whichOutput: string = await bashNoError(`which ${npmTool}`);
let toolAvailable: boolean = !(/not\sfound/.test(whichOutput) || whichOutput === '');
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) {
plugins.beautylog.log(`Tool ${npmTool} is available`);
logger.log('info', `Tool ${npmTool} is available`);
} else {
plugins.beautylog.info(`globally installing ${npmTool} from npm`);
logger.log('info', `globally installing ${npmTool} from npm`);
await bash(`npm install ${npmTool} -q -g`);
}
}
plugins.beautylog.success('all global npm tools specified in npmextra.json are now available!');
logger.log('success', 'all global npm tools specified in npmextra.json are now available!');
});
};

View File

@@ -1,3 +1,4 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
import * as configModule from '../npmci.config';
import { bash, bashNoError, nvmAvailable } from '../npmci.bash';
@@ -8,7 +9,7 @@ import { bash, bashNoError, nvmAvailable } from '../npmci.bash';
*/
export let handleCli = async argvArg => {
if (argvArg._.length >= 2) {
let action: string = argvArg._[1];
const action: string = argvArg._[1];
switch (action) {
case 'install':
await install();
@@ -23,13 +24,11 @@ export let handleCli = async argvArg => {
await publish();
break;
default:
plugins.beautylog.error(`>>npmci npm ...<< action >>${action}<< not supported`);
logger.log('error', `>>npmci npm ...<< action >>${action}<< not supported`);
process.exit(1);
}
} else {
plugins.beautylog.log(
`>>npmci npm ...<< cli arguments invalid... Please read the documentation.`
);
logger.log('info', `>>npmci npm ...<< cli arguments invalid... Please read the documentation.`);
process.exit(1);
}
};
@@ -37,16 +36,28 @@ export let handleCli = async argvArg => {
/**
* authenticates npm with token from env var
*/
let prepare = async () => {
let npmrcPrefix: string = '//registry.npmjs.org/:_authToken=';
let npmToken: string = process.env.NPMCI_TOKEN_NPM;
let npmrcFileString: string = npmrcPrefix + npmToken;
if (npmToken) {
plugins.beautylog.info('found access token');
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 {
plugins.beautylog.error('no access token found! Exiting!');
logger.log('error', 'no access token found! Exiting!');
process.exit(1);
}
// lets save it to disk
plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc');
return;
};
@@ -54,20 +65,52 @@ let prepare = async () => {
/**
* publish a package to npm
*/
let publish = async () => {
let npmAccessCliString = ``;
const config = await configModule.getConfig();
const publish = async () => {
const buildPublishCommand = async () => {
let npmAccessCliString = ``;
let npmRegistryCliString = ``;
let publishVerdaccioAsWell = false;
const config = await configModule.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 &&
(config.npmAccessLevel === 'public' || config.npmAccessLevel === 'private')
) {
npmAccessCliString = `--access=${config.npmAccessLevel}`;
}
// -> configure package access level
if (config.npmAccessLevel) {
npmAccessCliString = `--access=${config.npmAccessLevel}`;
if (config.npmAccessLevel === 'public') {
publishVerdaccioAsWell = true;
}
}
// -> 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}`;
}
}
return publishCommand;
};
// -> preparing
plugins.beautylog.log(`now preparing environment:`);
logger.log('info', `now preparing environment:`);
prepare();
await bash(`npm -v`);
@@ -75,26 +118,26 @@ let publish = async () => {
await bash(`npm install`);
await bash(`npm run build`);
plugins.beautylog.success(`Nice!!! The build for the publication was successfull!`);
plugins.beautylog.log(`Lets clean up so we don't publish any packages that don't belong to us:`);
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`);
plugins.beautylog.success(`Cleaned up!:`);
logger.log('success', `Cleaned up!:`);
// -> publish it
plugins.beautylog.log(`now invoking npm to publish the package!`);
await bash(`npm publish ${npmAccessCliString}`);
plugins.beautylog.success(`Package was successfully published!`);
logger.log('info', `now invoking npm to publish the package!`);
await bash(await buildPublishCommand());
logger.log('success', `Package was successfully published!`);
};
let install = async (): Promise<void> => {
plugins.beautylog.info('now installing dependencies:');
const install = async (): Promise<void> => {
logger.log('info', 'now installing dependencies:');
await bash('npm install');
};
export let test = async (): Promise<void> => {
plugins.beautylog.info('now starting tests:');
logger.log('info', 'now starting tests:');
await bash('npm test');
};

View File

@@ -1,19 +1,20 @@
import { logger } from '../npmci.logging';
import * as plugins from './mod.plugins';
let sshInstance: plugins.smartssh.SshInstance;
export let handleCli = async argvArg => {
if (argvArg._.length >= 2) {
let action: string = argvArg._[1];
const action: string = argvArg._[1];
switch (action) {
case 'prepare':
await prepare();
break;
default:
plugins.beautylog.error(`action >>${action}<< not supported`);
logger.log('error', `action >>${action}<< not supported`);
process.exit(1);
}
} else {
plugins.beautylog.error(`>>npmci ssh ...<< please specify an action!`);
logger.log('error', `>>npmci ssh ...<< please specify an action!`);
process.exit(1);
}
};
@@ -21,7 +22,7 @@ export let handleCli = async argvArg => {
/**
* checks if not undefined
*/
let notUndefined = (stringArg: string) => {
const notUndefined = (stringArg: string) => {
return stringArg && stringArg !== 'undefined' && stringArg !== '##';
};
@@ -34,27 +35,27 @@ export let prepare = async () => {
if (!process.env.NPMTS_TEST) {
sshInstance.writeToDisk();
} else {
plugins.beautylog.log('In test mode, so not storing SSH keys to disk!');
logger.log('info', 'In test mode, so not storing SSH keys to disk!');
}
};
/**
* gets called for each found SSH ENV Var and deploys it
*/
let evaluateSshEnv = async (sshkeyEnvVarArg: string) => {
let sshEnvArray = sshkeyEnvVarArg.split('|');
let sshKey = new plugins.smartssh.SshKey();
plugins.beautylog.info('Found SSH identity for ' + sshEnvArray[1]);
const evaluateSshEnv = async (sshkeyEnvVarArg: string) => {
const sshEnvArray = sshkeyEnvVarArg.split('|');
const sshKey = new plugins.smartssh.SshKey();
logger.log('info', 'Found SSH identity for ' + sshEnvArray[1]);
if (notUndefined(sshEnvArray[0])) {
plugins.beautylog.log('---> host defined!');
logger.log('info', '---> host defined!');
sshKey.host = sshEnvArray[0];
}
if (notUndefined(sshEnvArray[1])) {
plugins.beautylog.log('---> privKey defined!');
logger.log('info', '---> privKey defined!');
sshKey.privKeyBase64 = sshEnvArray[1];
}
if (notUndefined(sshEnvArray[2])) {
plugins.beautylog.log('---> pubKey defined!');
logger.log('info', '---> pubKey defined!');
sshKey.pubKeyBase64 = sshEnvArray[2];
}

View File

@@ -1,28 +1,42 @@
import * as plugins from './mod.plugins';
import { bash } from '../npmci.bash';
import { logger } from '../npmci.logging';
let triggerValueRegex = /^([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|?([a-zA-Z0-9\.\-\/]*)/;
const triggerValueRegex = /^([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|([a-zA-Z0-9\.]*)\|?([a-zA-Z0-9\.\-\/]*)/;
export let trigger = async () => {
plugins.beautylog.info('now running triggers');
plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TRIGGER_*', evaluateTrigger);
logger.log('info', 'now running triggers');
await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TRIGGER_*', evaluateTrigger);
};
let evaluateTrigger = async triggerEnvVarArg => {
let triggerRegexResultArray = triggerValueRegex.exec(triggerEnvVarArg);
let regexDomain = triggerRegexResultArray[1];
let regexProjectId = triggerRegexResultArray[2];
let regexProjectTriggerToken = triggerRegexResultArray[3];
let regexRefName = triggerRegexResultArray[4];
const evaluateTrigger = async triggerEnvVarArg => {
const triggerRegexResultArray = triggerValueRegex.exec(triggerEnvVarArg);
const regexDomain = triggerRegexResultArray[1];
const regexProjectId = triggerRegexResultArray[2];
const regexProjectTriggerToken = triggerRegexResultArray[3];
const regexRefName = triggerRegexResultArray[4];
let regexTriggerName;
if (triggerRegexResultArray.length === 6) {
regexTriggerName = triggerRegexResultArray[5];
} else {
regexTriggerName = 'Unnamed Trigger';
}
plugins.beautylog.info('Found Trigger!');
plugins.beautylog.log('triggering build for ref ' + regexRefName + ' of ' + regexTriggerName);
plugins.request.post('https://gitlab.com/api/v3/projects/' + regexProjectId + '/trigger/builds', {
form: { token: regexProjectTriggerToken, ref: regexRefName }
});
logger.log('info', 'Found Trigger!');
logger.log('info', 'triggering build for ref ' + regexRefName + ' of ' + regexTriggerName);
plugins.smartrequest.postFormData(
'https://gitlab.com/api/v3/projects/' + regexProjectId + '/trigger/builds',
{},
[
{
name: 'token',
payload: regexProjectTriggerToken,
type: 'string'
},
{
name: 'ref',
payload: regexRefName,
type: 'string'
}
]
);
};

View File

@@ -1,16 +1,17 @@
import { logger } from './npmci.logging';
import * as plugins from './npmci.plugins';
import * as paths from './npmci.paths';
import * as smartq from 'smartq';
import * as smartpromise from '@pushrocks/smartpromise';
/**
* wether nvm is available or not
*/
export let nvmAvailable = smartq.defer<boolean>();
export let nvmAvailable = smartpromise.defer<boolean>();
/**
* the smartshell instance for npmci
*/
let npmciSmartshell = new plugins.smartshell.Smartshell({
const npmciSmartshell = new plugins.smartshell.Smartshell({
executor: 'bash',
sourceFilePaths: []
});
@@ -18,18 +19,18 @@ let npmciSmartshell = new plugins.smartshell.Smartshell({
/**
* check for tools.
*/
let checkToolsAvailable = async () => {
const checkToolsAvailable = async () => {
// check for nvm
if (!process.env.NPMTS_TEST) {
if (
(await plugins.smartshell.execSilent(`bash -c "source /usr/local/nvm/nvm.sh"`)).exitCode === 0
(await npmciSmartshell.execSilent(`bash -c "source /usr/local/nvm/nvm.sh"`)).exitCode === 0
) {
npmciSmartshell.addSourceFiles([`/usr/local/nvm/nvm.sh`]);
npmciSmartshell.shellEnv.addSourceFiles([`/usr/local/nvm/nvm.sh`]);
nvmAvailable.resolve(true);
} else if (
(await plugins.smartshell.execSilent(`bash -c "source ~/.nvm/nvm.sh"`)).exitCode === 0
(await npmciSmartshell.execSilent(`bash -c "source ~/.nvm/nvm.sh"`)).exitCode === 0
) {
npmciSmartshell.addSourceFiles([`~/.nvm/nvm.sh`]);
npmciSmartshell.shellEnv.addSourceFiles([`~/.nvm/nvm.sh`]);
nvmAvailable.resolve(true);
} else {
nvmAvailable.resolve(false);
@@ -68,21 +69,19 @@ export let bash = async (commandArg: string, retryArg: number = 2): Promise<stri
if (execResult.exitCode !== 0 && i === retryArg) {
// something went wrong and retries are exhausted
if (failOnError) {
plugins.beautylog.error('something went wrong and retries are exhausted');
logger.log('error', 'something went wrong and retries are exhausted');
process.exit(1);
}
} else if (execResult.exitCode === 0) {
// everything went fine, or no error wanted
i = retryArg + 1; // retry +1 breaks for loop, if everything works out ok retrials are not wanted
} else {
plugins.beautylog.warn(
'Something went wrong! Exit Code: ' + execResult.exitCode.toString()
);
plugins.beautylog.info('Retry ' + (i + 1).toString() + ' of ' + retryArg.toString());
logger.log('warn', 'Something went wrong! Exit Code: ' + execResult.exitCode.toString());
logger.log('info', 'Retry ' + (i + 1).toString() + ' of ' + retryArg.toString());
}
}
} else {
plugins.beautylog.log('ShellExec would be: ' + commandArg);
logger.log('info', 'ShellExec would be: ' + commandArg);
execResult = {
exitCode: 0,
stdout: 'testOutput'

View File

@@ -1,23 +1,22 @@
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
let npmciInfo = new plugins.projectinfo.ProjectinfoNpm(paths.NpmciPackageRoot);
plugins.beautylog.log('npmci version: ' + npmciInfo.version);
const npmciInfo = new plugins.projectinfo.ProjectinfoNpm(paths.NpmciPackageRoot);
logger.log('info', 'npmci version: ' + npmciInfo.version);
import * as NpmciEnv from './npmci.env';
import * as npmciMods from './npmci.mods';
const npmciSmartcli = new plugins.smartcli.Smartcli();
npmciSmartcli.addVersion(npmciInfo.version);
// clean
npmciSmartcli.addCommand('clean').subscribe(
async argv => {
let modClean = await npmciMods.modClean.load();
const modClean = await import('./mod_clean/index');
await modClean.clean();
},
err => {
@@ -26,21 +25,10 @@ npmciSmartcli.addCommand('clean').subscribe(
}
);
// cloudflare
npmciSmartcli.addCommand('cloudflare').subscribe(
async argvArg => {
let modPurge = await npmciMods.modCloudflare.load();
await modPurge.handleCli(argvArg);
},
err => {
console.log(err);
}
);
// command
npmciSmartcli.addCommand('command').subscribe(
async argv => {
let modCommand = await npmciMods.modCommand.load();
const modCommand = await import('./mod_command/index');
await modCommand.command();
},
err => {
@@ -52,7 +40,7 @@ npmciSmartcli.addCommand('command').subscribe(
// command
npmciSmartcli.addCommand('git').subscribe(
async argvArg => {
let modGit = await npmciMods.modGit.load();
const modGit = await import('./mod_git/index');
await modGit.handleCli(argvArg);
},
err => {
@@ -64,7 +52,7 @@ npmciSmartcli.addCommand('git').subscribe(
// build
npmciSmartcli.addCommand('docker').subscribe(
async argvArg => {
let modDocker = await npmciMods.modDocker.load();
const modDocker = await import('./mod_docker/index');
await modDocker.handleCli(argvArg);
},
err => {
@@ -76,7 +64,7 @@ npmciSmartcli.addCommand('docker').subscribe(
// node
npmciSmartcli.addCommand('node').subscribe(
async argvArg => {
let modNode = await npmciMods.modNode.load();
const modNode = await import('./mod_node/index');
await modNode.handleCli(argvArg);
},
err => {
@@ -88,7 +76,7 @@ npmciSmartcli.addCommand('node').subscribe(
// npm
npmciSmartcli.addCommand('npm').subscribe(
async argvArg => {
let modNpm = await npmciMods.modNpm.load();
const modNpm = await import('./mod_npm/index');
await modNpm.handleCli(argvArg);
},
err => {
@@ -99,7 +87,7 @@ npmciSmartcli.addCommand('npm').subscribe(
// trigger
npmciSmartcli.addCommand('ssh').subscribe(
async argvArg => {
let modSsh = await npmciMods.modSsh.load();
const modSsh = await import('./mod_ssh/index');
await modSsh.handleCli(argvArg);
},
err => {
@@ -111,7 +99,7 @@ npmciSmartcli.addCommand('ssh').subscribe(
// trigger
npmciSmartcli.addCommand('trigger').subscribe(
async argv => {
let modTrigger = await npmciMods.modTrigger.load();
const modTrigger = await import('./mod_trigger/index');
await modTrigger.trigger();
},
err => {

View File

@@ -1,27 +1,39 @@
import * as q from 'q';
import * as plugins from './npmci.plugins';
import * as paths from './npmci.paths';
import { repo } from './npmci.env';
import { KeyValueStore } from 'npmextra';
import { KeyValueStore } from '@pushrocks/npmextra';
/**
* the main config interface for npmci
*/
export interface INpmciOptions {
projectInfo: plugins.projectinfo.ProjectInfo;
// npm
npmGlobalTools: string[];
npmAccessLevel?: 'private' | 'public';
dockerRegistryRepoMap: any;
dockerBuildargEnvMap: any;
npmRegistryUrl: string;
// docker
dockerRegistries: string[];
dockerRegistryRepoMap: { [key: string]: string };
dockerBuildargEnvMap: { [key: string]: string };
}
// instantiate a kvStorage for the current directory
export let kvStorage = new KeyValueStore('custom', `${repo.user}_${repo.repo}`);
// handle config retrival
let npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd);
let defaultConfig: INpmciOptions = {
const npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd);
const defaultConfig: INpmciOptions = {
projectInfo: new plugins.projectinfo.ProjectInfo(paths.cwd),
npmGlobalTools: [],
dockerRegistries: [],
dockerRegistryRepoMap: {},
npmAccessLevel: 'private',
npmRegistryUrl: 'registry.npmjs.org',
dockerBuildargEnvMap: {}
};
export let configObject = npmciNpmextra.dataFor<INpmciOptions>('npmci', defaultConfig);

View File

@@ -1,6 +1,6 @@
import * as plugins from './npmci.plugins';
import * as paths from './npmci.paths';
import { GitRepo } from 'smartstring';
import { GitRepo } from '@pushrocks/smartstring';
import { Dockerfile } from './mod_docker/index';
/**

14
ts/npmci.logging.ts Normal file
View File

@@ -0,0 +1,14 @@
import * as plugins from './npmci.plugins';
export const logger = new plugins.smartlog.Smartlog({
logContext: {
company: 'Some Company',
companyunit: 'Some Unit',
containerName: 'Some ContainerName',
environment: 'test',
runtime: 'node',
zone: 'Some Zone'
}
});
logger.addLogDestination(new plugins.smartlogDestinationLocal.DestinationLocal());

View File

@@ -1,24 +0,0 @@
import * as _modClean from './mod_clean/index';
import * as _modCloudflare from './mod_cloudflare/index';
import * as _modCommand from './mod_command/index';
import * as _modDocker from './mod_docker/index';
import * as _modGit from './mod_git/index';
import * as _modNpm from './mod_npm/index';
import * as _modNode from './mod_node/index';
import * as _modSsh from './mod_ssh/index';
import * as _modTrigger from './mod_trigger/index';
import { LazyModule } from 'smartsystem';
export let modClean = new LazyModule<typeof _modClean>('./mod_clean/index', __dirname);
export let modCloudflare = new LazyModule<typeof _modCloudflare>(
'./mod_cloudflare/index',
__dirname
);
export let modCommand = new LazyModule<typeof _modCommand>('./mod_command/index', __dirname);
export let modGit = new LazyModule<typeof _modGit>('./mod_git/index', __dirname);
export let modDocker = new LazyModule<typeof _modDocker>('./mod_docker/index', __dirname);
export let modNode = new LazyModule<typeof _modNode>('./mod_node/index', __dirname);
export let modNpm = new LazyModule<typeof _modNpm>('./mod_npm/index', __dirname);
export let modSsh = new LazyModule<typeof _modSsh>('./mod_ssh/index', __dirname);
export let modTrigger = new LazyModule<typeof _modTrigger>('./mod_trigger/index', __dirname);

View File

@@ -1,7 +1,8 @@
import { logger } from './npmci.logging';
import * as plugins from './npmci.plugins';
import * as env from './npmci.env';
import { Analytics } from 'smartanalytics';
import { Analytics } from '@pushrocks/smartanalytics';
export let npmciAnalytics = new Analytics({
apiEndPoint: 'https://pubapi.lossless.one/analytics',
@@ -17,6 +18,6 @@ export let run = async () => {
repo: env.repo.repo
})
.catch(err => {
plugins.beautylog.warn('Lossless Analytics API not available...');
logger.log('warn', 'Lossless Analytics API not available...');
});
};

View File

@@ -1,19 +1,41 @@
export import beautylog = require('beautylog');
export import lodash = require('lodash');
export import npmextra = require('npmextra');
export import path = require('path');
export import projectinfo = require('projectinfo');
export import q = require('smartq');
export let request = require('request');
export import smartcli = require('@pushrocks/smartcli');
export import smartdelay = require('smartdelay');
export import smartfile = require('smartfile');
export import shelljs = require('shelljs');
export import smartparam = require('smartparam');
export import smartq = require('smartq');
export import smartshell = require('smartshell');
export import smartsocket = require('smartsocket');
export import smartsystem = require('smartsystem');
export import smartssh = require('smartssh');
export import smartstring = require('smartstring');
export import through2 = require('through2');
// node native
import * as path from 'path';
export { path };
// @pushrocks
import * as projectinfo from '@pushrocks/projectinfo';
import * as npmextra from '@pushrocks/npmextra';
import * as smartdelay from '@pushrocks/smartdelay';
import * as smartfile from '@pushrocks/smartfile';
import * as smartcli from '@pushrocks/smartcli';
import * as smartlog from '@pushrocks/smartlog';
import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local';
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 '@pushrocks/smartsocket';
import * as smartssh from '@pushrocks/smartssh';
import * as smartstring from '@pushrocks/smartstring';
export {
projectinfo,
npmextra,
smartdelay,
smartfile,
smartcli,
smartlog,
smartlogDestinationLocal,
smartparam,
smartpromise,
smartrequest,
smartshell,
smartsocket,
smartssh,
smartstring
};
import * as through2 from 'through2';
export { through2 };

View File

@@ -1,3 +1,17 @@
{
"extends": "tslint-config-standard"
"extends": ["tslint:latest", "tslint-config-prettier"],
"rules": {
"semicolon": [true, "always"],
"no-console": false,
"ordered-imports": false,
"object-literal-sort-keys": false,
"member-ordering": {
"options":{
"order": [
"static-method"
]
}
}
},
"defaultSeverity": "warning"
}