Compare commits
273 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4b202ce00e | |||
| 16ca787314 | |||
| 3a9b6f658a | |||
| 5c5dbf303f | |||
| 4c07131e51 | |||
| ba039469ff | |||
| 49f2498ecd | |||
| 1060060366 | |||
| 0fa3a579f7 | |||
| 0e4556d59e | |||
| e2e7967fba | |||
| 45b8d67abf | |||
| 0a69aa5d62 | |||
| dfbab1a1df | |||
| e58f009a24 | |||
| 2afd9cddc5 | |||
| d79c5366ef | |||
| 8e4f7ad244 | |||
| 39de3a1601 | |||
| cb3d2964d1 | |||
| 6b5390cef8 | |||
| 2736b85de3 | |||
| 82d7778f59 | |||
| 8c99cc0491 | |||
| 955e3d0dbe | |||
| 702ae8bed8 | |||
| b6f0723b75 | |||
| 8a2fb30e59 | |||
| 95b4030120 | |||
| 5c77cfbdc2 | |||
| 5ea42320a9 | |||
| d07ebfc9c6 | |||
| bbb5718184 | |||
| 0d8b54637c | |||
| e51b2e28b9 | |||
| f767140cc8 | |||
| 0d4d69f072 | |||
| a3e628c43f | |||
| a58fa135c1 | |||
| 93c7af6c91 | |||
| ad0e12bf7b | |||
| 498dd6eff6 | |||
| b3aa964739 | |||
| 03eb9d2657 | |||
| 373a838a6a | |||
| 960e3f4675 | |||
| 09bf676b58 | |||
| 76ba8e2ab9 | |||
| aaaaca2d19 | |||
| 71b27eda17 | |||
| 2d00882fd7 | |||
| ba5e69041f | |||
| d2871d601a | |||
| 9c66d88dc0 | |||
| fb4c84e1de | |||
| 57aca36f11 | |||
| 905f594af1 | |||
| b788b7f96b | |||
| 319a2dc41a | |||
| e01a998f0e | |||
| e40606d97b | |||
| 449c7b2c04 | |||
| 006782b57f | |||
| d643da29b0 | |||
| 635f92d2bc | |||
| 9a2cb56094 | |||
| 5886283002 | |||
| f886194c9c | |||
| e4efec89d9 | |||
| dbc12a593f | |||
| d7666e862b | |||
| e262d29510 | |||
| 858d97cb5c | |||
| b8a2df66fe | |||
| 1c128dd694 | |||
| 2744d0bf7f | |||
| 9eb232da39 | |||
| 52af1d5188 | |||
| 4325f21c8c | |||
| 6cd3eaceb4 | |||
| f850c79b6c | |||
| efdf789575 | |||
| 6ef6446022 | |||
| ef7d85e7c4 | |||
| 93b5d9869b | |||
| 2a0cfeffe9 | |||
| 909aafbd5f | |||
| 91288e2d74 | |||
| 25709b1f9a | |||
| 8a03d9aa94 | |||
| bbe1cf770a | |||
| ac8190282f | |||
| 446d140e32 | |||
| 726948651e | |||
| dd0a7bb782 | |||
| fca00ffcf8 | |||
| 13f6334ae5 | |||
| 7275a858d6 | |||
| 5a3befe5af | |||
| 385a93a05e | |||
| b4d444ff05 | |||
| 487bcb9a70 | |||
| aaf11b66d7 | |||
| 83d7d46896 | |||
| 693bda6a49 | |||
| bfe3e266ee | |||
| 5f33ebd8a7 | |||
| f78c80e100 | |||
| f4d8656831 | |||
| 2290081ef0 | |||
| 189d02a16f | |||
| 55aee04334 | |||
| 0e407b9b9d | |||
| 24095bbd40 | |||
| f97ee94b5a | |||
| 4cf7aea374 | |||
| 6ab5e9cb30 | |||
| 95c1145bf5 | |||
| ea04a1b788 | |||
| 3bc2499d09 | |||
| 1f5967ac45 | |||
| fd952f086b | |||
| 79500cb2c2 | |||
| 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 | |||
| 28541a838d | |||
| c3ab527341 | |||
| 52cc249098 | |||
| 2e189b0660 | |||
| f876c7414b | |||
| 08b7585cfc | |||
| 76311fab72 | |||
| 1b73df64f5 | |||
| 701cee573b | |||
| 3dd086f711 | |||
| 67ff5d09d4 | |||
| 5cb8a79b6a | |||
| 2dcbca2362 | |||
| bd63194f4b | |||
| 2763fdef5f | |||
| bbedde01b9 | |||
| f26606f757 | |||
| 99b03aa796 | |||
| f30dd3da65 | |||
| d4decddb4b | |||
| 5c2880da1a | |||
| bfffc5b130 | |||
| 8900a13c6b | |||
| d42acf737f | |||
| 77e3b2912d | |||
| 103e470eb4 | |||
| 74c1324e55 | |||
| a1876963a8 | |||
| 5d88e25c99 | |||
| b3c47546e2 | |||
| 6316e81958 | |||
| ff10afbee4 | |||
| 9dbfa77084 | |||
| 46dbd61d89 | |||
| 713df1867a | |||
| 23886c1ed3 | |||
| 0c46b627be | |||
| 622ccd8dd9 | |||
| 0079addfc5 | |||
| 8604c63d37 | |||
| db0b38bd7b | |||
| edde87b6be | |||
| 5085d664cb | |||
| 5d468fc840 | |||
| e2ac6cdcc9 | |||
| fcd04415be | |||
| 1fd1899099 | |||
| 7df7f882d1 | |||
| 348b4d60fd | |||
| 37589fb5e5 | |||
| 3dd115fe42 | |||
| 01c88a6a6c | |||
| f5cacb7400 | |||
| 887da51d78 | |||
| 585703fc55 | |||
| ec3e296d73 | |||
| 33f234cf73 | |||
| e7ec765ed5 | |||
| 2f46197864 | |||
| da44233263 | |||
| cb2430f7b2 | |||
| 5fe9134f4a | |||
| 7681f09d38 | |||
| d55c77560a | |||
| 0e337a3574 | |||
| 94c5567b75 | |||
| 7b37506d4e | |||
| a401633b73 | |||
| 948a8e64d7 | |||
| 9e8fbac573 | |||
| 362740a55f | |||
| 3edc08b0ed | |||
| 15d7e6cbfc | |||
| 6824210da0 | |||
| 41d2d04958 | |||
| e490c6f730 | |||
| bdf4815145 | |||
| 84fdf8b139 | |||
| 545896821d | |||
| c7516458bd | |||
| c2f92e63c5 | |||
| d4116aefdb | |||
| 0f5f1f7772 | |||
| 7722187ea5 | |||
| 734a21c925 |
66
.gitea/workflows/default_nottags.yaml
Normal file
66
.gitea/workflows/default_nottags.yaml
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
name: Default (not tags)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags-ignore:
|
||||||
|
- '**'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
|
NPMCI_TOKEN_NPM2: ${{secrets.NPMCI_TOKEN_NPM2}}
|
||||||
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
|
NPMCI_URL_CLOUDLY: ${{secrets.NPMCI_URL_CLOUDLY}}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install pnpm and npmci
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
|
||||||
|
- name: Run npm prepare
|
||||||
|
run: npmci npm prepare
|
||||||
|
|
||||||
|
- name: Audit production dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --prod
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Audit development dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --dev
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
test:
|
||||||
|
if: ${{ always() }}
|
||||||
|
needs: security
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Test stable
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm test
|
||||||
|
|
||||||
|
- name: Test build
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm build
|
||||||
108
.gitea/workflows/default_tags.yaml
Normal file
108
.gitea/workflows/default_tags.yaml
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
name: Default (tags)
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
IMAGE: registry.gitlab.com/hosttoday/ht-docker-node:npmci
|
||||||
|
NPMCI_TOKEN_NPM: ${{secrets.NPMCI_TOKEN_NPM}}
|
||||||
|
NPMCI_GIT_GITHUBTOKEN: ${{secrets.NPMCI_GIT_GITHUBTOKEN}}
|
||||||
|
NPMCI_LOGIN_DOCKER_GITEA: ${{secrets.NPMCI_DOCKER_REGISTRYURL_DEFAULT}}|${{ gitea.repository_owner }}|${{ secrets.GITEA_TOKEN }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
continue-on-error: true
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Install pnpm and npmci
|
||||||
|
run: |
|
||||||
|
pnpm install -g pnpm
|
||||||
|
pnpm install -g @shipzone/npmci
|
||||||
|
|
||||||
|
- name: Run npm prepare
|
||||||
|
run: npmci npm prepare
|
||||||
|
|
||||||
|
- name: Audit production dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --prod
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
- name: Audit development dependencies
|
||||||
|
run: |
|
||||||
|
npmci command npm config set registry https://registry.npmjs.org
|
||||||
|
npmci command pnpm audit --audit-level=high --dev
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
test:
|
||||||
|
if: ${{ always() }}
|
||||||
|
needs: security
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Test stable
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm test
|
||||||
|
|
||||||
|
- name: Test build
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
npmci npm build
|
||||||
|
|
||||||
|
release:
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Release
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm publish
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
needs: test
|
||||||
|
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: ${{ env.IMAGE }}
|
||||||
|
continue-on-error: true
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Code quality
|
||||||
|
run: |
|
||||||
|
npmci command npm install -g typescript
|
||||||
|
npmci npm prepare
|
||||||
|
npmci npm install
|
||||||
|
|
||||||
|
- name: Trigger
|
||||||
|
run: npmci trigger
|
||||||
|
|
||||||
|
- name: Build docs and upload artifacts
|
||||||
|
run: |
|
||||||
|
npmci node install stable
|
||||||
|
npmci npm install
|
||||||
|
pnpm install -g @gitzone/tsdoc
|
||||||
|
npmci command tsdoc
|
||||||
|
continue-on-error: true
|
||||||
20
.gitignore
vendored
20
.gitignore
vendored
@@ -1,6 +1,20 @@
|
|||||||
dist/
|
.nogit/
|
||||||
node_modules/
|
|
||||||
|
# artifacts
|
||||||
coverage/
|
coverage/
|
||||||
public/
|
public/
|
||||||
config.json
|
pages/
|
||||||
|
|
||||||
|
# installs
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# caches
|
||||||
.yarn/
|
.yarn/
|
||||||
|
.cache/
|
||||||
|
.rpt2_cache
|
||||||
|
|
||||||
|
# builds
|
||||||
|
dist/
|
||||||
|
dist_*/
|
||||||
|
|
||||||
|
# custom
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
# gitzone standard
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
|
|
||||||
cache:
|
|
||||||
paths:
|
|
||||||
- .yarn/
|
|
||||||
key: "$CI_BUILD_STAGE"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- security
|
|
||||||
- test
|
|
||||||
- release
|
|
||||||
- trigger
|
|
||||||
- pages
|
|
||||||
|
|
||||||
mirror:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci git mirror
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
snyk:
|
|
||||||
stage: security
|
|
||||||
script:
|
|
||||||
- npmci command yarn global add snyk
|
|
||||||
- npmci command yarn install --ignore-scripts
|
|
||||||
- npmci command snyk test
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
testLEGACY:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install legacy
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
allow_failure: true
|
|
||||||
|
|
||||||
testLTS:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install lts
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
testSTABLE:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm install
|
|
||||||
- npmci npm test
|
|
||||||
coverage: /\d+.?\d+?\%\s*coverage/
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
release:
|
|
||||||
stage: release
|
|
||||||
script:
|
|
||||||
- npmci node install stable
|
|
||||||
- npmci npm prepare
|
|
||||||
- npmci npm publish
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
trigger:
|
|
||||||
stage: trigger
|
|
||||||
script:
|
|
||||||
- npmci trigger
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
pages:
|
|
||||||
image: hosttoday/ht-docker-node:npmci
|
|
||||||
stage: pages
|
|
||||||
script:
|
|
||||||
- npmci command yarn global add npmpage
|
|
||||||
- npmci command npmpage
|
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
only:
|
|
||||||
- tags
|
|
||||||
artifacts:
|
|
||||||
expire_in: 1 week
|
|
||||||
paths:
|
|
||||||
- public
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
pages/
|
|
||||||
coverage/
|
|
||||||
test/
|
|
||||||
node_modules/
|
|
||||||
config.json
|
|
||||||
15
.snyk
15
.snyk
@@ -1,15 +0,0 @@
|
|||||||
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
|
|
||||||
version: v1.10.2
|
|
||||||
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
|
|
||||||
ignore:
|
|
||||||
'npm:shelljs:20140723':
|
|
||||||
- shelljs:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-05-04T20:41:54.426Z'
|
|
||||||
- smartshell > shelljs:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-05-04T20:41:54.426Z'
|
|
||||||
- smartssh > shelljs:
|
|
||||||
reason: None given
|
|
||||||
expires: '2018-05-04T20:41:54.426Z'
|
|
||||||
patch: {}
|
|
||||||
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"command": "npm test",
|
||||||
|
"name": "Run npm test",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "node-terminal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
.vscode/settings.json
vendored
Normal file
26
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": ["/npmextra.json"],
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"npmci": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for npmci"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "settings for gitzone",
|
||||||
|
"properties": {
|
||||||
|
"projectType": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["website", "element", "service", "npm", "wcc"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
4
cli.child.ts
Normal file
4
cli.child.ts
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
process.env.CLI_CALL = 'true';
|
||||||
|
import * as cliTool from './ts/index.js';
|
||||||
|
cliTool.runCli();
|
||||||
4
cli.js
Normal file
4
cli.js
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
process.env.CLI_CALL = 'true';
|
||||||
|
const cliTool = await import('./dist_ts/index.js');
|
||||||
|
cliTool.runCli();
|
||||||
5
cli.ts.js
Normal file
5
cli.ts.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
process.env.CLI_CALL = 'true';
|
||||||
|
|
||||||
|
import * as tsrun from '@gitzone/tsrun';
|
||||||
|
tsrun.runPath('./cli.child.js', import.meta.url);
|
||||||
100
docs/index.md
100
docs/index.md
@@ -1,100 +0,0 @@
|
|||||||
# npmci
|
|
||||||
|
|
||||||
node and docker in gitlab ci on steroids
|
|
||||||
|
|
||||||
## Availabililty
|
|
||||||
|
|
||||||
[](https://www.npmjs.com/package/npmci)
|
|
||||||
[](https://GitLab.com/gitzone/npmci)
|
|
||||||
[](https://github.com/gitzone/npmci)
|
|
||||||
[](https://gitzone.gitlab.io/npmci/)
|
|
||||||
|
|
||||||
## Status for master
|
|
||||||
|
|
||||||
[](https://GitLab.com/gitzone/npmci/commits/master)
|
|
||||||
[](https://GitLab.com/gitzone/npmci/commits/master)
|
|
||||||
[](https://www.npmjs.com/package/npmci)
|
|
||||||
[](https://david-dm.org/gitzonetools/npmci)
|
|
||||||
[](https://www.bithound.io/github/gitzonetools/npmci/master/dependencies/npm)
|
|
||||||
[](https://www.bithound.io/github/gitzonetools/npmci)
|
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
|
||||||
[](http://standardjs.com/)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
Use TypeScript for best in class instellisense.
|
|
||||||
|
|
||||||
npmci is designed to work in docker CI environments. The following docker images come with npmci presinstalled:
|
|
||||||
|
|
||||||
Docker Hub:
|
|
||||||
|
|
||||||
* [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/)
|
|
||||||
based on docker:git, can be used to build docker images in conjunction with docker:dind
|
|
||||||
|
|
||||||
npmci can be called from commandline:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
# Install any node version:
|
|
||||||
npmci install lts # will install latest LTS node version and update PATH for node and npm versions
|
|
||||||
npmci install stable # will install latest stable node version and update PATH for node and npm
|
|
||||||
npmci install legacy # will install latest legacy node version and update PATH for node and npm
|
|
||||||
npmci install x.x.x # will install any specific node version.
|
|
||||||
|
|
||||||
# Install any node version, install dependencies and run test in cwd:
|
|
||||||
npmci test lts # will install latest lts node version and run "npm install" and "npm test".
|
|
||||||
npmci test stable # will install latest stable node version and run "npm install" and "npm test".
|
|
||||||
npmci test legacy # will install latest legacy node version and run "npm install" and "npm test".
|
|
||||||
npmci test x.x.x # will install any specific node version and run "npm install" and "npm test".
|
|
||||||
npmci test docker # will test any build image with tests defined in ./npmci/dockertest_1.sh to ./npmci/dockertest_100.sh
|
|
||||||
## npmci test docker will look at all Dockerfiles and look for according tags on GitLab container registry
|
|
||||||
|
|
||||||
|
|
||||||
# prepare tools
|
|
||||||
npmci prepare npm # will look for $NPMCI_TOKEN_NPM env var and create .npmrc, so npm is authenticated
|
|
||||||
npmci prepare docker # will look for $NPMCI_LOGIN_DOCKER in form username|password and authenticate docker
|
|
||||||
npmci prepare docker-gitlab # will authenticate docker for gitlab container registry
|
|
||||||
|
|
||||||
# build containers
|
|
||||||
npmci build docker # will build containers
|
|
||||||
## all Dockerfiles named Dockerfile* are picked up.
|
|
||||||
## specify tags like this Dockerfile_[tag]
|
|
||||||
## uploads all built images as [username]/[reponame]:[tag]_test to GitLab
|
|
||||||
## then test in next step with "npmci test docker"
|
|
||||||
|
|
||||||
# publish npm module
|
|
||||||
npmci publish npm # will look vor $NPMCI_TOKEN_NPM env var and push any module in cwd to npm
|
|
||||||
npmci publish docker
|
|
||||||
|
|
||||||
# trigger webhooks
|
|
||||||
npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
npmci supports the use of npmextra.
|
|
||||||
|
|
||||||
To configure npmci create a `npmextra.json` file at the root of your project
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"npmci": {
|
|
||||||
"globalNpmTools": ["npm-check-updates", "protractor", "npmts", "gitzone"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Available options**
|
|
||||||
|
|
||||||
| setting | example | description |
|
|
||||||
| -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------- |
|
|
||||||
| globalNpmTools | "globalNpmTools": ["gitbook"] | Will look for the specified package names locally and (if not yet present) install them from npm. |
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
[](https://push.rocks)
|
|
||||||
22
docs/ssh.md
22
docs/ssh.md
@@ -1,22 +0,0 @@
|
|||||||
# SSH
|
|
||||||
|
|
||||||
npmci allows easy usage of ssh:
|
|
||||||
|
|
||||||
## Add the SSH KEY to the environment
|
|
||||||
|
|
||||||
To make npmci aware of any SSH KEY add it to the environment in the following format
|
|
||||||
|
|
||||||
```
|
|
||||||
# Key
|
|
||||||
NPMCI_SSHKEY_[A_NAME_FROM_YOU]
|
|
||||||
# Value:
|
|
||||||
[targeted host]|[privatekey as base64]|***
|
|
||||||
```
|
|
||||||
|
|
||||||
## Use npmci cli tool in your ci script
|
|
||||||
|
|
||||||
```
|
|
||||||
npmci prepare ssh
|
|
||||||
npmci command git remote add heroku ssh://git@heroku.com/[you project name].git
|
|
||||||
npmci command git push heroku master
|
|
||||||
```
|
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
{
|
{
|
||||||
"npmts":{
|
|
||||||
"mode":"default",
|
|
||||||
"coverageTreshold": "70",
|
|
||||||
"cli": true
|
|
||||||
},
|
|
||||||
"npmci": {
|
"npmci": {
|
||||||
"npmGlobalTools": [
|
"npmGlobalTools": [],
|
||||||
"@gitzone/npmts"
|
"npmAccessLevel": "public",
|
||||||
],
|
"npmRegistryUrl": "registry.npmjs.org"
|
||||||
"npmAccessLevel": "public"
|
|
||||||
},
|
},
|
||||||
"npmdocker": {
|
"npmdocker": {
|
||||||
"baseImage": "hosttoday/ht-docker-node:npmci",
|
"baseImage": "hosttoday/ht-docker-node:npmci",
|
||||||
"command": "npmci test stable"
|
"command": "npmci test stable"
|
||||||
|
},
|
||||||
|
"gitzone": {
|
||||||
|
"projectType": "npm",
|
||||||
|
"module": {
|
||||||
|
"githost": "gitlab.com",
|
||||||
|
"gitscope": "shipzone",
|
||||||
|
"gitrepo": "npmci",
|
||||||
|
"description": "node and docker in gitlab ci on steroids",
|
||||||
|
"npmPackagename": "@shipzone/npmci",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
88
package.json
88
package.json
@@ -1,16 +1,19 @@
|
|||||||
{
|
{
|
||||||
"name": "@shipzone/npmci",
|
"name": "@shipzone/npmci",
|
||||||
"version": "3.0.35",
|
"version": "4.1.19",
|
||||||
|
"private": false,
|
||||||
"description": "node and docker in gitlab ci on steroids",
|
"description": "node and docker in gitlab ci on steroids",
|
||||||
"main": "dist/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
|
"type": "module",
|
||||||
"bin": {
|
"bin": {
|
||||||
"npmci": "dist/cli.js"
|
"npmci": "cli.js"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(rm -f config.json) && (npmts) && (npm run testVersion)",
|
"test": "tstest test/",
|
||||||
"build": "(rm -f config.json) && (npmts) && (npm run testVersion)",
|
"build": "tsbuild --allowimplicitany && (npm run testVersion)",
|
||||||
"testVersion": "(cd test/assets/ && node ../../dist/cli.js -v)"
|
"testVersion": "(cd test/assets/ && node ../../cli.js -v)",
|
||||||
|
"buildDocs": "tsdoc"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -23,31 +26,52 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://gitlab.com/gitzone/npmci#README",
|
"homepage": "https://gitlab.com/gitzone/npmci#README",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"tapbundle": "^2.0.0"
|
"@gitzone/tsbuild": "^2.1.66",
|
||||||
|
"@gitzone/tsrun": "^1.2.42",
|
||||||
|
"@gitzone/tstest": "^1.0.74",
|
||||||
|
"@pushrocks/tapbundle": "^5.0.8",
|
||||||
|
"@types/node": "^20.3.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/lodash": "^4.14.74",
|
"@apiglobal/typedrequest": "^2.0.12",
|
||||||
"@types/shelljs": "^0.7.4",
|
"@pushrocks/lik": "^6.0.2",
|
||||||
"@types/through2": "^2.0.33",
|
"@pushrocks/npmextra": "^3.0.9",
|
||||||
"beautylog": "^6.1.10",
|
"@pushrocks/projectinfo": "^5.0.1",
|
||||||
"cflare": "^1.0.5",
|
"@pushrocks/qenv": "^5.0.2",
|
||||||
"lik": "^2.0.5",
|
"@pushrocks/smartanalytics": "^2.0.15",
|
||||||
"lodash": "^4.17.4",
|
"@pushrocks/smartcli": "^4.0.6",
|
||||||
"npmextra": "^2.0.9",
|
"@pushrocks/smartdelay": "^3.0.1",
|
||||||
"projectinfo": "^3.0.2",
|
"@pushrocks/smartenv": "^5.0.5",
|
||||||
"request": "^2.81.0",
|
"@pushrocks/smartfile": "^10.0.25",
|
||||||
"shelljs": "^0.8.1",
|
"@pushrocks/smartgit": "^3.0.0",
|
||||||
"smartanalytics": "^2.0.9",
|
"@pushrocks/smartlog": "^3.0.2",
|
||||||
"smartcli": "^2.0.7",
|
"@pushrocks/smartlog-destination-local": "^9.0.0",
|
||||||
"smartdelay": "^1.0.3",
|
"@pushrocks/smartparam": "^1.1.6",
|
||||||
"smartfile": "^4.2.20",
|
"@pushrocks/smartpath": "^5.0.5",
|
||||||
"smartparam": "^1.0.2",
|
"@pushrocks/smartpromise": "^4.0.2",
|
||||||
"smartq": "^1.1.6",
|
"@pushrocks/smartrequest": "^2.0.15",
|
||||||
"smartshell": "^1.0.18",
|
"@pushrocks/smartshell": "^3.0.3",
|
||||||
"smartsocket": "^1.1.10",
|
"@pushrocks/smartsocket": "^2.0.19",
|
||||||
"smartssh": "^1.2.2",
|
"@pushrocks/smartssh": "^2.0.0",
|
||||||
"smartstring": "^2.0.24",
|
"@pushrocks/smartstring": "^4.0.7",
|
||||||
"smartsystem": "^2.0.2",
|
"@servezone/interfaces": "^1.0.3",
|
||||||
"through2": "^2.0.3"
|
"@tsclass/tsclass": "^4.0.42",
|
||||||
}
|
"@types/through2": "^2.0.38",
|
||||||
|
"through2": "^4.0.2"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"ts/**/*",
|
||||||
|
"ts_web/**/*",
|
||||||
|
"dist/**/*",
|
||||||
|
"dist_*/**/*",
|
||||||
|
"dist_ts/**/*",
|
||||||
|
"dist_ts_web/**/*",
|
||||||
|
"assets/**/*",
|
||||||
|
"cli.js",
|
||||||
|
"npmextra.json",
|
||||||
|
"readme.md"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 1 chrome versions"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
4649
pnpm-lock.yaml
generated
Normal file
4649
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
117
readme.md
117
readme.md
@@ -1,33 +1,110 @@
|
|||||||
# npmci
|
# @shipzone/npmci
|
||||||
|
|
||||||
node and docker in gitlab ci on steroids
|
node and docker in gitlab ci on steroids
|
||||||
|
|
||||||
## Availabililty
|
## Availabililty and Links
|
||||||
|
* [npmjs.org (npm package)](https://www.npmjs.com/package/@shipzone/npmci)
|
||||||
[](https://www.npmjs.com/package/@shipzone/npmci)
|
* [gitlab.com (source)](https://gitlab.com/shipzone/npmci)
|
||||||
[](https://GitLab.com/shipzone/npmci)
|
* [github.com (source mirror)](https://github.com/shipzone/npmci)
|
||||||
[](https://github.com/shipzone/npmci)
|
* [docs (typedoc)](https://shipzone.gitlab.io/npmci/)
|
||||||
[](https://shipzone.gitlab.io/npmci/)
|
|
||||||
|
|
||||||
## Status for master
|
## Status for master
|
||||||
|
|
||||||
[](https://GitLab.com/shipzone/npmci/commits/master)
|
Status Category | Status Badge
|
||||||
[](https://GitLab.com/shipzone/npmci/commits/master)
|
-- | --
|
||||||
[](https://www.npmjs.com/package/@shipzone/npmci)
|
GitLab Pipelines | [](https://lossless.cloud)
|
||||||
[](https://david-dm.org/shipzone/npmci)
|
GitLab Pipline Test Coverage | [](https://lossless.cloud)
|
||||||
[](https://www.bithound.io/github/shipzone/npmci/master/dependencies/npm)
|
npm | [](https://lossless.cloud)
|
||||||
[](https://www.bithound.io/github/shipzone/npmci)
|
Snyk | [](https://lossless.cloud)
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
TypeScript Support | [](https://lossless.cloud)
|
||||||
[](https://nodejs.org/dist/latest-v6.x/docs/api/)
|
node Support | [](https://nodejs.org/dist/latest-v10.x/docs/api/)
|
||||||
[](http://standardjs.com/)
|
Code Style | [](https://lossless.cloud)
|
||||||
|
PackagePhobia (total standalone install weight) | [](https://lossless.cloud)
|
||||||
|
PackagePhobia (package size on registry) | [](https://lossless.cloud)
|
||||||
|
BundlePhobia (total size when bundled) | [](https://lossless.cloud)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Use TypeScript for best in class instellisense.
|
Use TypeScript for best in class instellisense.
|
||||||
|
|
||||||
|
npmci is designed to work in docker CI environments. The following docker images come with npmci presinstalled:
|
||||||
|
|
||||||
|
Docker Hub:
|
||||||
|
|
||||||
|
- [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/)
|
||||||
|
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:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
# Handle node versions
|
||||||
|
npmci node install stable # will install latest stable node version and update PATH for node and npm
|
||||||
|
npmci node install lts # will install latest LTS node version and update PATH for node and npm versions
|
||||||
|
npmci node install legacy # will install latest legacy node version and update PATH for node and npm
|
||||||
|
npmci node install x.x.x # will install any specific node version.
|
||||||
|
|
||||||
|
# Handle npm and yarn tasks
|
||||||
|
npmcu npm login # logs in npm using the auth key provided at env var "NPMCI_TOKEN_NPM"
|
||||||
|
npmci npm install # installs dependencies using npm or yarn dependending on availablity
|
||||||
|
npmci npm test # tests the package
|
||||||
|
npmci npm publish # builds a package and publishes it
|
||||||
|
|
||||||
|
# handle docker tasks
|
||||||
|
npmci docker prepare
|
||||||
|
## npmci test docker will look at all Dockerfiles and look for according tags on GitLab container registry
|
||||||
|
|
||||||
|
|
||||||
|
# prepare tools
|
||||||
|
npmci prepare npm # will look for $NPMCI_TOKEN_NPM env var and create .npmrc, so npm is authenticated
|
||||||
|
npmci prepare docker # will look for $NPMCI_LOGIN_DOCKER in form username|password and authenticate docker
|
||||||
|
npmci prepare docker-gitlab # will authenticate docker for gitlab container registry
|
||||||
|
|
||||||
|
# build containers
|
||||||
|
npmci docker build # will build containers
|
||||||
|
## all Dockerfiles named Dockerfile* are picked up.
|
||||||
|
## specify tags like this Dockerfile_[tag]
|
||||||
|
## uploads all built images as [username]/[reponame]:[tag]_test to GitLab
|
||||||
|
## then test in next step with "npmci test docker"
|
||||||
|
|
||||||
|
# publish npm module
|
||||||
|
npmci publish npm # will look vor $NPMCI_TOKEN_NPM env var and push any module in cwd to npm
|
||||||
|
npmci publish docker
|
||||||
|
|
||||||
|
# trigger webhooks
|
||||||
|
npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
npmci supports the use of npmextra.
|
||||||
|
|
||||||
|
To configure npmci create a `npmextra.json` file at the root of your project
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"npmci": {
|
||||||
|
"globalNpmTools": ["npm-check-updates", "protractor", "npmts", "gitzone"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Available options**
|
||||||
|
|
||||||
|
| setting | example | description |
|
||||||
|
| -------------- | ----------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||||
|
| globalNpmTools | "globalNpmTools": ["gitbook"] | Will look for the specified package names locally and (if not yet present) install them from npm. |
|
||||||
|
|
||||||
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)
|
Use TypeScript for best in class instellisense.
|
||||||
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
|
|
||||||
|
|
||||||
[](https://push.rocks)
|
## Contribution
|
||||||
|
|
||||||
|
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
|
||||||
|
|
||||||
|
For further information read the linked docs at the top of this readme.
|
||||||
|
|
||||||
|
## Legal
|
||||||
|
> MIT licensed | **©** [Task Venture Capital GmbH](https://task.vc)
|
||||||
|
| By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy)
|
||||||
|
|||||||
26
test/test.cloudly.ts
Normal file
26
test/test.cloudly.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
|
||||||
|
import { tap, expect } from '@pushrocks/tapbundle';
|
||||||
|
|
||||||
|
import * as cloudlyConnectorMod from '../ts/connector.cloudly/cloudlyconnector.js';
|
||||||
|
|
||||||
|
tap.test('should be able to announce a container to cloudly', async () => {
|
||||||
|
const cloudlyConnector = new cloudlyConnectorMod.CloudlyConnector(null);
|
||||||
|
await cloudlyConnector.announceDockerContainer(
|
||||||
|
{
|
||||||
|
registryUrl: 'registry.losssless.com',
|
||||||
|
tag: 'testcontainer',
|
||||||
|
version: 'x.x.x',
|
||||||
|
labels: [],
|
||||||
|
},
|
||||||
|
'cloudly.lossless.one'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.test('should close the program despite socket timeout', async (toolsArg) => {
|
||||||
|
// TODO: remove when unreffed timeouts in webrequest have been solved.
|
||||||
|
toolsArg.delayFor(0).then(() => {
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
tap.start();
|
||||||
97
test/test.ts
97
test/test.ts
@@ -1,8 +1,9 @@
|
|||||||
import { tap, expect } from 'tapbundle';
|
import { tap, expect } from '@pushrocks/tapbundle';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as smartpath from '@pushrocks/smartpath';
|
||||||
|
|
||||||
// Setup test
|
|
||||||
process.env.NPMTS_TEST = 'true';
|
process.env.NPMTS_TEST = 'true';
|
||||||
|
process.env.NPMCI_URL_CLOUDLY = 'localhost';
|
||||||
|
|
||||||
// set up environment
|
// set up environment
|
||||||
process.env.CI_REPOSITORY_URL = 'https://yyyyyy:xxxxxxxx@gitlab.com/mygroup/myrepo.git';
|
process.env.CI_REPOSITORY_URL = 'https://yyyyyy:xxxxxxxx@gitlab.com/mygroup/myrepo.git';
|
||||||
@@ -15,70 +16,82 @@ process.env.NPMCI_LOGIN_DOCKER = 'docker.io|someuser|somepass';
|
|||||||
process.env.NPMCI_SSHKEY_1 = 'hostString|somePrivKey|##';
|
process.env.NPMCI_SSHKEY_1 = 'hostString|somePrivKey|##';
|
||||||
|
|
||||||
process.cwd = () => {
|
process.cwd = () => {
|
||||||
return path.join(__dirname, 'assets/');
|
return path.join(smartpath.get.dirnameFromImportMetaUrl(import.meta.url), 'assets/');
|
||||||
};
|
};
|
||||||
|
|
||||||
// require NPMCI files
|
let npmci: typeof import('../ts/index.js');
|
||||||
import '../ts/index';
|
|
||||||
import npmciModDocker = require('../ts/mod_docker/index');
|
type TNpmciTypes = typeof import('../ts/index.js');
|
||||||
import npmciModNpm = require('../ts/mod_npm/index');
|
|
||||||
import npmciModNode = require('../ts/mod_node/index');
|
tap.preTask('should import npmci', async () => {
|
||||||
import npmciModSsh = require('../ts/mod_ssh/index');
|
npmci = await import('../ts/index.js');
|
||||||
import npmciEnv = require('../ts/npmci.env');
|
});
|
||||||
|
|
||||||
// ======
|
// ======
|
||||||
// Docker
|
// Docker
|
||||||
// ======
|
// ======
|
||||||
|
|
||||||
let dockerfile1: npmciModDocker.Dockerfile;
|
let dockerfile1: npmci.Dockerfile;
|
||||||
let dockerfile2: npmciModDocker.Dockerfile;
|
let dockerfile2: npmci.Dockerfile;
|
||||||
let sortableArray: npmciModDocker.Dockerfile[];
|
let sortableArray: npmci.Dockerfile[];
|
||||||
|
|
||||||
tap.test('should return valid Dockerfiles', async () => {
|
tap.test('should return valid Dockerfiles', async () => {
|
||||||
dockerfile1 = new npmciModDocker.Dockerfile({ filePath: './Dockerfile', read: true });
|
const npmciInstance = new npmci.Npmci();
|
||||||
dockerfile2 = new npmciModDocker.Dockerfile({ filePath: './Dockerfile_sometag1', read: true });
|
dockerfile1 = new npmci.Dockerfile(npmciInstance.dockerManager, {
|
||||||
expect(dockerfile1.version).to.equal('latest');
|
filePath: './Dockerfile',
|
||||||
return expect(dockerfile2.version).to.equal('sometag1');
|
read: true,
|
||||||
|
});
|
||||||
|
dockerfile2 = new npmci.Dockerfile(npmciInstance.dockerManager, {
|
||||||
|
filePath: './Dockerfile_sometag1',
|
||||||
|
read: true,
|
||||||
|
});
|
||||||
|
expect(dockerfile1.version).toEqual('latest');
|
||||||
|
return expect(dockerfile2.version).toEqual('sometag1');
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should read a directory of Dockerfiles', async () => {
|
tap.test('should read a directory of Dockerfiles', async () => {
|
||||||
return npmciModDocker.helpers
|
const npmciInstance = new npmci.Npmci();
|
||||||
.readDockerfiles()
|
return npmci.Dockerfile.readDockerfiles(npmciInstance.dockerManager).then(
|
||||||
.then(async (readDockerfilesArrayArg: npmciModDocker.Dockerfile[]) => {
|
async (readDockerfilesArrayArg: npmci.Dockerfile[]) => {
|
||||||
sortableArray = readDockerfilesArrayArg;
|
sortableArray = readDockerfilesArrayArg;
|
||||||
return expect(readDockerfilesArrayArg[1].version).to.equal('sometag1');
|
return expect(readDockerfilesArrayArg[1].version).toEqual('sometag1');
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should sort an array of Dockerfiles', async () => {
|
tap.test('should sort an array of Dockerfiles', async () => {
|
||||||
return npmciModDocker.helpers
|
return npmci.Dockerfile.sortDockerfiles(sortableArray).then(
|
||||||
.sortDockerfiles(sortableArray)
|
async (sortedArrayArg: npmci.Dockerfile[]) => {
|
||||||
.then(async (sortedArrayArg: npmciModDocker.Dockerfile[]) => {
|
|
||||||
console.log(sortedArrayArg);
|
console.log(sortedArrayArg);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should build all Dockerfiles', async () => {
|
tap.test('should build all Dockerfiles', async () => {
|
||||||
return npmciModDocker.handleCli({
|
const npmciInstance = new npmci.Npmci();
|
||||||
_: ['docker', 'build']
|
return npmciInstance.dockerManager.handleCli({
|
||||||
|
_: ['docker', 'build'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should test all Dockerfiles', async () => {
|
tap.test('should test all Dockerfiles', async () => {
|
||||||
return await npmciModDocker.handleCli({
|
const npmciInstance = new npmci.Npmci();
|
||||||
_: ['docker', 'test']
|
return npmciInstance.dockerManager.handleCli({
|
||||||
|
_: ['docker', 'test'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should test dockerfiles', async () => {
|
tap.test('should test dockerfiles', async () => {
|
||||||
return await npmciModDocker.handleCli({
|
const npmciInstance = new npmci.Npmci();
|
||||||
_: ['docker', 'test']
|
return npmciInstance.dockerManager.handleCli({
|
||||||
|
_: ['docker', 'test'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
tap.test('should login docker daemon', async () => {
|
tap.test('should login docker daemon', async () => {
|
||||||
return await npmciModDocker.handleCli({
|
const npmciInstance = new npmci.Npmci();
|
||||||
_: ['docker', 'login']
|
return npmciInstance.dockerManager.handleCli({
|
||||||
|
_: ['docker', 'login'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -86,8 +99,9 @@ tap.test('should login docker daemon', async () => {
|
|||||||
// SSH
|
// SSH
|
||||||
// ===
|
// ===
|
||||||
tap.test('should prepare SSH keys', async () => {
|
tap.test('should prepare SSH keys', async () => {
|
||||||
|
const npmciModSsh = await import('../ts/mod_ssh/index.js');
|
||||||
return await npmciModSsh.handleCli({
|
return await npmciModSsh.handleCli({
|
||||||
_: ['ssh', 'prepare']
|
_: ['ssh', 'prepare'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,14 +109,15 @@ tap.test('should prepare SSH keys', async () => {
|
|||||||
// node
|
// node
|
||||||
// ====
|
// ====
|
||||||
tap.test('should install a certain version of node', async () => {
|
tap.test('should install a certain version of node', async () => {
|
||||||
await npmciModNode.handleCli({
|
const npmciInstance = new npmci.Npmci();
|
||||||
_: ['node', 'install', 'stable']
|
await npmciInstance.nodejsManager.handleCli({
|
||||||
|
_: ['node', 'install', 'stable'],
|
||||||
});
|
});
|
||||||
await npmciModNode.handleCli({
|
await npmciInstance.nodejsManager.handleCli({
|
||||||
_: ['node', 'install', 'lts']
|
_: ['node', 'install', 'lts'],
|
||||||
});
|
});
|
||||||
await npmciModNode.handleCli({
|
await npmciInstance.nodejsManager.handleCli({
|
||||||
_: ['node', 'install', 'legacy']
|
_: ['node', 'install', 'legacy'],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
8
ts/00_commitinfo_data.ts
Normal file
8
ts/00_commitinfo_data.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* autocreated commitinfo by @pushrocks/commitinfo
|
||||||
|
*/
|
||||||
|
export const commitinfo = {
|
||||||
|
name: '@shipzone/npmci',
|
||||||
|
version: '4.1.19',
|
||||||
|
description: 'node and docker in gitlab ci on steroids'
|
||||||
|
}
|
||||||
39
ts/connector.cloudly/cloudlyconnector.ts
Normal file
39
ts/connector.cloudly/cloudlyconnector.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import * as plugins from '../npmci.plugins.js';
|
||||||
|
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* connects to cloudly
|
||||||
|
*/
|
||||||
|
export class CloudlyConnector {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
constructor(npmciRefArg: Npmci) {
|
||||||
|
this.npmciRef = npmciRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async announceDockerContainer(
|
||||||
|
optionsArg: plugins.tsclass.container.IContainer,
|
||||||
|
testCloudlyUrlArg?: string
|
||||||
|
) {
|
||||||
|
const cloudlyUrl = testCloudlyUrlArg || 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.requests.IRequest_InformAboutNewContainerImage>(
|
||||||
|
`https://${cloudlyUrl}/typedrequest`,
|
||||||
|
'servezonestandard_InformAboutNewContainerVersion'
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await typedrequest.fire({
|
||||||
|
containerImageInfo: optionsArg,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
11
ts/index.ts
11
ts/index.ts
@@ -1 +1,10 @@
|
|||||||
import './npmci.cli';
|
import { Npmci } from './npmci.classes.npmci.js';
|
||||||
|
import { Dockerfile } from './manager.docker/mod.classes.dockerfile.js';
|
||||||
|
|
||||||
|
export const npmciInstance = new Npmci();
|
||||||
|
|
||||||
|
export { Dockerfile, Npmci };
|
||||||
|
|
||||||
|
export const runCli = async () => {
|
||||||
|
npmciInstance.start();
|
||||||
|
};
|
||||||
|
|||||||
68
ts/manager.cloudron/index.ts
Normal file
68
ts/manager.cloudron/index.ts
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
import { bash } from '../npmci.bash.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export class NpmciCloudronManager {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
constructor(npmciArg: Npmci) {
|
||||||
|
this.npmciRef = npmciArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle cli input
|
||||||
|
* @param argvArg
|
||||||
|
*/
|
||||||
|
public handleCli = async (argvArg: any) => {
|
||||||
|
if (argvArg._.length >= 2) {
|
||||||
|
const action: string = argvArg._[1];
|
||||||
|
switch (action) {
|
||||||
|
case 'deploy':
|
||||||
|
await this.deploy();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.log('error', `>>npmci cloudron ...<< action >>${action}<< not supported`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.log(
|
||||||
|
'info',
|
||||||
|
`>>npmci cloudron ...<< cli arguments invalid... Please read the documentation.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces the version string in CloudronManifest file
|
||||||
|
* @param versionArg
|
||||||
|
*/
|
||||||
|
public deploy = async () => {
|
||||||
|
logger.log('info', 'now deploying to cloudron...');
|
||||||
|
logger.log('info', 'installing cloudron cli...');
|
||||||
|
await bash(`pnpm install -g cloudron`);
|
||||||
|
logger.log('ok', 'cloudron cli installed');
|
||||||
|
|
||||||
|
// lets set the version in the CloudronManifest file
|
||||||
|
await this.prepareCloudronManifest(this.npmciRef.npmciConfig.getConfig().projectInfo.npm.version);
|
||||||
|
logger.log('ok', 'CloudronManifest prepared');
|
||||||
|
|
||||||
|
// lets figure out the docker image tag
|
||||||
|
const dockerfiles = await this.npmciRef.dockerManager.getDockerfiles();
|
||||||
|
const dockerImageTag = dockerfiles[0].pushTag;
|
||||||
|
const appName = this.npmciRef.npmciConfig.getConfig().cloudronAppName;
|
||||||
|
|
||||||
|
const cloudronEnvVar = process.env.NPMCI_LOGIN_CLOUDRON;
|
||||||
|
const cloudronServer = cloudronEnvVar.split('|')[0];
|
||||||
|
const cloudronToken = cloudronEnvVar.split('|')[1];
|
||||||
|
await bash(`cloudron update --server ${cloudronServer} --token ${cloudronToken} --image ${dockerImageTag} --app ${appName}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
private prepareCloudronManifest = async (versionArg: string) => {
|
||||||
|
const manifestPath = plugins.path.join(paths.cwd, 'CloudronManifest.json');
|
||||||
|
let manifestFile = plugins.smartfile.fs.toStringSync(manifestPath);
|
||||||
|
manifestFile = manifestFile.replace(/##version##/g, versionArg);
|
||||||
|
plugins.smartfile.memory.toFsSync(manifestFile, manifestPath);
|
||||||
|
logger.log('info', 'Version replaced in CloudronManifest file');
|
||||||
|
}
|
||||||
|
}
|
||||||
1
ts/manager.cloudron/mod.plugins.ts
Normal file
1
ts/manager.cloudron/mod.plugins.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../npmci.plugins.js';
|
||||||
190
ts/manager.docker/index.ts
Normal file
190
ts/manager.docker/index.ts
Normal file
@@ -0,0 +1,190 @@
|
|||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
import { bash } from '../npmci.bash.js';
|
||||||
|
|
||||||
|
// classes
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
import { Dockerfile } from './mod.classes.dockerfile.js';
|
||||||
|
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
||||||
|
import { RegistryStorage } from './mod.classes.registrystorage.js';
|
||||||
|
|
||||||
|
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: any) => {
|
||||||
|
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.GITLAB_CI) {
|
||||||
|
console.log('gitlab ci detected');
|
||||||
|
if (!process.env.CI_JOB_TOKEN || process.env.CI_JOB_TOKEN === '') {
|
||||||
|
logger.log('error', 'Running in Gitlab CI, but 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_JOB_TOKEN,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle registries
|
||||||
|
await plugins.smartparam.forEachMinimatch(
|
||||||
|
process.env,
|
||||||
|
'NPMCI_LOGIN_DOCKER*',
|
||||||
|
async (envString: string) => {
|
||||||
|
this.npmciRegistryStorage.addRegistry(DockerRegistry.fromEnvString(envString));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pushes an image towards a registry
|
||||||
|
* @param argvArg
|
||||||
|
*/
|
||||||
|
public push = async (argvArg: any) => {
|
||||||
|
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 = await 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: any) => {
|
||||||
|
await this.prepare();
|
||||||
|
const registryUrlArg = argvArg._[2];
|
||||||
|
let suffix = null;
|
||||||
|
if (argvArg._.length >= 4) {
|
||||||
|
suffix = argvArg._[3];
|
||||||
|
}
|
||||||
|
const localDockerRegistry = await 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);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can be used to get the Dockerfiles in the directory
|
||||||
|
*/
|
||||||
|
getDockerfiles = async () => {
|
||||||
|
const dockerfiles = await Dockerfile.readDockerfiles(this);
|
||||||
|
return dockerfiles;
|
||||||
|
}
|
||||||
|
}
|
||||||
335
ts/manager.docker/mod.classes.dockerfile.ts
Normal file
335
ts/manager.docker/mod.classes.dockerfile.ts
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import { bash } from '../npmci.bash.js';
|
||||||
|
|
||||||
|
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
||||||
|
import * as helpers from './mod.helpers.js';
|
||||||
|
import { NpmciDockerManager } from './index.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(dockerfileInstanceArg: Dockerfile, dockerfileNameArg: string): string {
|
||||||
|
let versionString: string;
|
||||||
|
const versionRegex = /Dockerfile_([^:_]*)$/;
|
||||||
|
const regexResultArray = versionRegex.exec(dockerfileNameArg);
|
||||||
|
if (regexResultArray && regexResultArray.length === 2) {
|
||||||
|
versionString = regexResultArray[1];
|
||||||
|
} else {
|
||||||
|
versionString = 'latest';
|
||||||
|
}
|
||||||
|
versionString = versionString.replace(
|
||||||
|
'##version##',
|
||||||
|
dockerfileInstanceArg.npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().projectInfo.npm.version
|
||||||
|
);
|
||||||
|
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 dockerArgKey of Object.keys(
|
||||||
|
npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap
|
||||||
|
)) {
|
||||||
|
const dockerArgOuterEnvVar =
|
||||||
|
npmciDockerManagerRef.npmciRef.npmciConfig.getConfig().dockerBuildargEnvMap[dockerArgKey];
|
||||||
|
logger.log(
|
||||||
|
'note',
|
||||||
|
`docker ARG "${dockerArgKey}" maps to outer env var "${dockerArgOuterEnvVar}"`
|
||||||
|
);
|
||||||
|
const targetValue = process.env[dockerArgOuterEnvVar];
|
||||||
|
buildArgsString = `${buildArgsString} --build-arg ${dockerArgKey}="${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(this, 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({
|
||||||
|
registryUrl: this.pushTag,
|
||||||
|
tag: this.buildTag,
|
||||||
|
labels: [],
|
||||||
|
version: 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
ts/manager.docker/mod.classes.dockerregistry.ts
Normal file
48
ts/manager.docker/mod.classes.dockerregistry.ts
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import { bash } from '../npmci.bash.js';
|
||||||
|
|
||||||
|
export interface IDockerRegistryConstructorOptions {
|
||||||
|
registryUrl: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DockerRegistry {
|
||||||
|
public registryUrl: string;
|
||||||
|
public username: string;
|
||||||
|
public password: string;
|
||||||
|
constructor(optionsArg: IDockerRegistryConstructorOptions) {
|
||||||
|
this.registryUrl = optionsArg.registryUrl;
|
||||||
|
this.username = optionsArg.username;
|
||||||
|
this.password = optionsArg.password;
|
||||||
|
logger.log('info', `created DockerRegistry for ${this.registryUrl}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static fromEnvString(envString: string): DockerRegistry {
|
||||||
|
const dockerRegexResultArray = envString.split('|');
|
||||||
|
if (dockerRegexResultArray.length !== 3) {
|
||||||
|
logger.log('error', 'malformed docker env var...');
|
||||||
|
process.exit(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const registryUrl = dockerRegexResultArray[0].replace('https://', '').replace('http://', '');
|
||||||
|
const username = dockerRegexResultArray[1];
|
||||||
|
const password = dockerRegexResultArray[2];
|
||||||
|
return new DockerRegistry({
|
||||||
|
registryUrl: registryUrl,
|
||||||
|
username: username,
|
||||||
|
password: password,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async login() {
|
||||||
|
if (this.registryUrl === 'docker.io') {
|
||||||
|
await bash(`docker login -u ${this.username} -p ${this.password}`);
|
||||||
|
logger.log('info', 'Logged in to standard docker hub');
|
||||||
|
} else {
|
||||||
|
await bash(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`);
|
||||||
|
}
|
||||||
|
logger.log('ok', `docker authenticated for ${this.registryUrl}!`);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
ts/manager.docker/mod.classes.registrystorage.ts
Normal file
29
ts/manager.docker/mod.classes.registrystorage.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import { ObjectMap } from '@pushrocks/lik';
|
||||||
|
|
||||||
|
import { DockerRegistry } from './mod.classes.dockerregistry.js';
|
||||||
|
|
||||||
|
export class RegistryStorage {
|
||||||
|
objectMap = new ObjectMap<DockerRegistry>();
|
||||||
|
constructor() {
|
||||||
|
// Nothing here
|
||||||
|
}
|
||||||
|
|
||||||
|
addRegistry(registryArg: DockerRegistry) {
|
||||||
|
this.objectMap.add(registryArg);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRegistryByUrl(registryUrlArg: string) {
|
||||||
|
return this.objectMap.findSync((registryArg) => {
|
||||||
|
return registryArg.registryUrl === registryUrlArg;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async loginAll() {
|
||||||
|
await this.objectMap.forEach(async (registryArg) => {
|
||||||
|
await registryArg.login();
|
||||||
|
});
|
||||||
|
logger.log('success', 'logged in successfully into all available DockerRegistries!');
|
||||||
|
}
|
||||||
|
}
|
||||||
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.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
|
||||||
|
import { Dockerfile } from './mod.classes.dockerfile.js';
|
||||||
1
ts/manager.docker/mod.plugins.ts
Normal file
1
ts/manager.docker/mod.plugins.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../npmci.plugins.js';
|
||||||
71
ts/manager.git/index.ts
Normal file
71
ts/manager.git/index.ts
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import { bash, bashNoError } from '../npmci.bash.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export class NpmciGitManager {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
constructor(npmciRefArg: Npmci) {
|
||||||
|
this.npmciRef = npmciRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle cli input
|
||||||
|
* @param argvArg
|
||||||
|
*/
|
||||||
|
public handleCli = async (argvArg: any) => {
|
||||||
|
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.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');
|
||||||
|
|
||||||
|
// remove old mirrors
|
||||||
|
await bashNoError('git remote rm mirror');
|
||||||
|
|
||||||
|
await bash(`git fetch`);
|
||||||
|
// add the mirror
|
||||||
|
await bashNoError(
|
||||||
|
`git remote add mirror https://${githubToken}@github.com/${githubUser}/${githubRepo}.git`
|
||||||
|
);
|
||||||
|
await bashNoError(`git push mirror --all`);
|
||||||
|
await bashNoError(`git checkout origin/master`);
|
||||||
|
await bashNoError(`git push mirror master`);
|
||||||
|
logger.log('ok', 'pushed all branches to mirror!');
|
||||||
|
await bashNoError(`git push mirror --tags`);
|
||||||
|
logger.log('ok', 'pushed all tags to mirror!');
|
||||||
|
// remove old mirrors
|
||||||
|
await bashNoError('git remote rm mirror');
|
||||||
|
} else {
|
||||||
|
logger.log('error', `cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
1
ts/manager.git/mod.plugins.ts
Normal file
1
ts/manager.git/mod.plugins.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../npmci.plugins.js';
|
||||||
82
ts/manager.nodejs/index.ts
Normal file
82
ts/manager.nodejs/index.ts
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
import * as plugins from '../npmci.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import { bash, bashNoError, nvmAvailable } from '../npmci.bash.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export class NpmciNodeJsManager {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
constructor(npmciRefArg: Npmci) {
|
||||||
|
this.npmciRef = npmciRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle cli input
|
||||||
|
* @param argvArg
|
||||||
|
*/
|
||||||
|
public async handleCli(argvArg: any) {
|
||||||
|
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: any) {
|
||||||
|
logger.log('info', `now installing node version ${versionArg}`);
|
||||||
|
let version: string;
|
||||||
|
if (versionArg === 'stable') {
|
||||||
|
version = '18';
|
||||||
|
} else if (versionArg === 'lts') {
|
||||||
|
version = '16';
|
||||||
|
} else if (versionArg === 'legacy') {
|
||||||
|
version = '14';
|
||||||
|
} 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');
|
||||||
|
|
||||||
|
// 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!');
|
||||||
|
}
|
||||||
|
}
|
||||||
189
ts/manager.npm/index.ts
Normal file
189
ts/manager.npm/index.ts
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import { bash, bashNoError, nvmAvailable } from '../npmci.bash.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export class NpmciNpmManager {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
constructor(npmciRefArg: Npmci) {
|
||||||
|
this.npmciRef = npmciRefArg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* handle cli input
|
||||||
|
* @param argvArg
|
||||||
|
*/
|
||||||
|
public async handleCli(argvArg: any) {
|
||||||
|
if (argvArg._.length >= 2) {
|
||||||
|
const action: string = argvArg._[1];
|
||||||
|
switch (action) {
|
||||||
|
case 'install':
|
||||||
|
await this.install();
|
||||||
|
break;
|
||||||
|
case 'build':
|
||||||
|
await this.build();
|
||||||
|
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: string) => {
|
||||||
|
const npmRegistryUrl = npmEnvArg.split('|')[0];
|
||||||
|
logger.log('ok', `found token for ${npmRegistryUrl}`);
|
||||||
|
let npmToken = npmEnvArg.split('|')[1];
|
||||||
|
if (npmEnvArg.split('|')[2] && npmEnvArg.split('|')[2] === 'plain') {
|
||||||
|
logger.log('ok', 'npm token not base64 encoded.');
|
||||||
|
} else {
|
||||||
|
logger.log('ok', 'npm token base64 encoded.');
|
||||||
|
npmToken = plugins.smartstring.base64.decode(npmToken);
|
||||||
|
}
|
||||||
|
npmrcFileString += `//${npmRegistryUrl}/:_authToken="${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');
|
||||||
|
|
||||||
|
// lets set the cache directory
|
||||||
|
await bash(`npm config set cache ${paths.NpmciCacheDir} --global `);
|
||||||
|
|
||||||
|
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: string) => {
|
||||||
|
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`);
|
||||||
|
await bash(`pnpm -v`);
|
||||||
|
|
||||||
|
// -> build it
|
||||||
|
await this.install();
|
||||||
|
await this.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('pnpm install');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async build(): Promise<void> {
|
||||||
|
logger.log('info', 'now building the project:');
|
||||||
|
await bash('pnpm run build');
|
||||||
|
}
|
||||||
|
|
||||||
|
public async test(): Promise<void> {
|
||||||
|
logger.log('info', 'now starting tests:');
|
||||||
|
await bash('pnpm test');
|
||||||
|
}
|
||||||
|
}
|
||||||
1
ts/manager.npm/mod.plugins.ts
Normal file
1
ts/manager.npm/mod.plugins.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../npmci.plugins.js';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from './mod.plugins';
|
import * as plugins from './mod.plugins.js';
|
||||||
import * as paths from '../npmci.paths';
|
import * as paths from '../npmci.paths.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* cleans npmci config files
|
* cleans npmci config files
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins';
|
export * from '../npmci.plugins.js';
|
||||||
|
|||||||
@@ -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]);
|
|
||||||
};
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
export * from '../npmci.plugins';
|
|
||||||
|
|
||||||
import * as cflare from 'cflare';
|
|
||||||
|
|
||||||
export { cflare };
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import * as plugins from './mod.plugins';
|
import * as plugins from './mod.plugins.js';
|
||||||
import { bash } from '../npmci.bash';
|
import { bash } from '../npmci.bash.js';
|
||||||
|
|
||||||
export let command = async () => {
|
export let command = async () => {
|
||||||
let wrappedCommand: string = '';
|
let wrappedCommand: string = '';
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins';
|
export * from '../npmci.plugins.js';
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
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
|
|
||||||
let 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) {
|
|
||||||
let 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:
|
|
||||||
plugins.beautylog.error(`>>npmci docker ...<< action >>${action}<< not supported`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.log(
|
|
||||||
`>>npmci docker ...<< cli arguments invalid... Please read the documentation.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* builds a cwd of Dockerfiles by triggering a promisechain
|
|
||||||
*/
|
|
||||||
export let build = async () => {
|
|
||||||
await prepare();
|
|
||||||
plugins.beautylog.log('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 === '') {
|
|
||||||
plugins.beautylog.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();
|
|
||||||
let registryUrlArg = argvArg._[2];
|
|
||||||
let suffix = null;
|
|
||||||
if (argvArg._.length >= 4) {
|
|
||||||
suffix = argvArg._[3];
|
|
||||||
}
|
|
||||||
let dockerfileArray = await helpers
|
|
||||||
.readDockerfiles()
|
|
||||||
.then(helpers.sortDockerfiles)
|
|
||||||
.then(helpers.mapDockerfiles);
|
|
||||||
let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export let pull = async argvArg => {
|
|
||||||
await prepare();
|
|
||||||
let registryUrlArg = argvArg._[2];
|
|
||||||
let suffix = null;
|
|
||||||
if (argvArg._.length >= 4) {
|
|
||||||
suffix = argvArg._[3];
|
|
||||||
}
|
|
||||||
let localDockerRegistry = npmciRegistryStorage.getRegistryByUrl(registryUrlArg);
|
|
||||||
let dockerfileArray = await helpers
|
|
||||||
.readDockerfiles()
|
|
||||||
.then(helpers.sortDockerfiles)
|
|
||||||
.then(helpers.mapDockerfiles);
|
|
||||||
for (let dockerfile of dockerfileArray) {
|
|
||||||
await dockerfile.pull(localDockerRegistry, suffix);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export let test = async () => {
|
|
||||||
await prepare();
|
|
||||||
return await helpers.readDockerfiles().then(helpers.testDockerfiles);
|
|
||||||
};
|
|
||||||
@@ -1,109 +0,0 @@
|
|||||||
import * as plugins from './mod.plugins';
|
|
||||||
import * as NpmciEnv from '../npmci.env';
|
|
||||||
import { bash } from '../npmci.bash';
|
|
||||||
import * as paths from '../npmci.paths';
|
|
||||||
|
|
||||||
import { DockerRegistry } from './mod.classes.dockerregistry';
|
|
||||||
import * as helpers from './mod.helpers';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* class Dockerfile represents a Dockerfile on disk in npmci
|
|
||||||
*/
|
|
||||||
export class Dockerfile {
|
|
||||||
filePath: string;
|
|
||||||
repo: string;
|
|
||||||
version: string;
|
|
||||||
cleanTag: string;
|
|
||||||
buildTag: string;
|
|
||||||
containerName: string;
|
|
||||||
content: string;
|
|
||||||
baseImage: string;
|
|
||||||
localBaseImageDependent: boolean;
|
|
||||||
localBaseDockerfile: Dockerfile;
|
|
||||||
constructor(options: { filePath?: string; fileContents?: string | Buffer; read?: boolean }) {
|
|
||||||
this.filePath = options.filePath;
|
|
||||||
this.repo = NpmciEnv.repo.user + '/' + NpmciEnv.repo.repo;
|
|
||||||
this.version = helpers.dockerFileVersion(plugins.path.parse(options.filePath).base);
|
|
||||||
this.cleanTag = this.repo + ':' + this.version;
|
|
||||||
this.buildTag = this.cleanTag;
|
|
||||||
|
|
||||||
this.containerName = 'dockerfile-' + this.version;
|
|
||||||
if (options.filePath && options.read) {
|
|
||||||
this.content = plugins.smartfile.fs.toStringSync(plugins.path.resolve(options.filePath));
|
|
||||||
}
|
|
||||||
this.baseImage = helpers.dockerBaseImage(this.content);
|
|
||||||
this.localBaseImageDependent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* builds the Dockerfile
|
|
||||||
*/
|
|
||||||
async build() {
|
|
||||||
plugins.beautylog.info('now building Dockerfile for ' + this.cleanTag);
|
|
||||||
let buildArgsString = await helpers.getDockerBuildArgs();
|
|
||||||
let buildCommand = `docker build -t ${this.buildTag} -f ${this.filePath} ${buildArgsString} .`;
|
|
||||||
await bash(buildCommand);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pushes the Dockerfile to a registry
|
|
||||||
*/
|
|
||||||
async push(dockerRegistryArg: DockerRegistry, versionSuffix: string = null) {
|
|
||||||
let pushTag = helpers.getDockerTagString(
|
|
||||||
dockerRegistryArg.registryUrl,
|
|
||||||
this.repo,
|
|
||||||
this.version,
|
|
||||||
versionSuffix
|
|
||||||
);
|
|
||||||
await bash(`docker tag ${this.buildTag} ${pushTag}`);
|
|
||||||
await bash(`docker push ${pushTag}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* pulls the Dockerfile from a registry
|
|
||||||
*/
|
|
||||||
async pull(registryArg: DockerRegistry, versionSuffixArg: string = null) {
|
|
||||||
let pullTag = helpers.getDockerTagString(
|
|
||||||
registryArg.registryUrl,
|
|
||||||
this.repo,
|
|
||||||
this.version,
|
|
||||||
versionSuffixArg
|
|
||||||
);
|
|
||||||
await bash(`docker pull ${pullTag}`);
|
|
||||||
await bash(`docker tag ${pullTag} ${this.buildTag}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tests the Dockerfile;
|
|
||||||
*/
|
|
||||||
async test() {
|
|
||||||
let testFile: string = plugins.path.join(paths.NpmciTestDir, 'test_' + this.version + '.sh');
|
|
||||||
let testFileExists: boolean = plugins.smartfile.fs.fileExistsSync(testFile);
|
|
||||||
if (testFileExists) {
|
|
||||||
// run tests
|
|
||||||
await bash(
|
|
||||||
`docker run --name npmci_test_container --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 {
|
|
||||||
plugins.beautylog.warn(
|
|
||||||
'skipping tests for ' + this.cleanTag + ' because no testfile was found!'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* gets the id of a Dockerfile
|
|
||||||
*/
|
|
||||||
async getId() {
|
|
||||||
let containerId = await bash('docker inspect --type=image --format="{{.Id}}" ' + this.buildTag);
|
|
||||||
return containerId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import * as plugins from './mod.plugins';
|
|
||||||
import { bash } from '../npmci.bash';
|
|
||||||
|
|
||||||
export interface IDockerRegistryConstructorOptions {
|
|
||||||
registryUrl: string;
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DockerRegistry {
|
|
||||||
registryUrl: string;
|
|
||||||
username: string;
|
|
||||||
password: string;
|
|
||||||
constructor(optionsArg: IDockerRegistryConstructorOptions) {
|
|
||||||
this.registryUrl = optionsArg.registryUrl;
|
|
||||||
this.username = optionsArg.username;
|
|
||||||
this.password = optionsArg.password;
|
|
||||||
plugins.beautylog.info(`created DockerRegistry for ${this.registryUrl}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static fromEnvString(envString: string): DockerRegistry {
|
|
||||||
let dockerRegexResultArray = envString.split('|');
|
|
||||||
if (dockerRegexResultArray.length !== 3) {
|
|
||||||
plugins.beautylog.error('malformed docker env var...');
|
|
||||||
process.exit(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let registryUrl = dockerRegexResultArray[0];
|
|
||||||
let username = dockerRegexResultArray[1];
|
|
||||||
let password = dockerRegexResultArray[2];
|
|
||||||
return new DockerRegistry({
|
|
||||||
registryUrl: registryUrl,
|
|
||||||
username: username,
|
|
||||||
password: password
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async login() {
|
|
||||||
if (this.registryUrl === 'docker.io') {
|
|
||||||
await bash(`docker login -u ${this.username} -p ${this.password}`);
|
|
||||||
plugins.beautylog.info('Logged in to standard docker hub');
|
|
||||||
} else {
|
|
||||||
await bash(`docker login -u ${this.username} -p ${this.password} ${this.registryUrl}`);
|
|
||||||
}
|
|
||||||
plugins.beautylog.ok(`docker authenticated for ${this.registryUrl}!`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
import * as plugins from './mod.plugins';
|
|
||||||
import { Objectmap } from 'lik';
|
|
||||||
|
|
||||||
import { DockerRegistry } from './mod.classes.dockerregistry';
|
|
||||||
|
|
||||||
export class RegistryStorage {
|
|
||||||
objectMap = new Objectmap<DockerRegistry>();
|
|
||||||
constructor() {
|
|
||||||
// Nothing here
|
|
||||||
}
|
|
||||||
|
|
||||||
addRegistry(registryArg: DockerRegistry) {
|
|
||||||
this.objectMap.add(registryArg);
|
|
||||||
}
|
|
||||||
|
|
||||||
getRegistryByUrl(registryUrlArg: string) {
|
|
||||||
return this.objectMap.find(registryArg => {
|
|
||||||
return registryArg.registryUrl === registryUrlArg;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async loginAll() {
|
|
||||||
await this.objectMap.forEach(async registryArg => {
|
|
||||||
await registryArg.login();
|
|
||||||
});
|
|
||||||
plugins.beautylog.success('logged in successfully into all available DockerRegistries!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,186 +0,0 @@
|
|||||||
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[]> => {
|
|
||||||
let fileTree = await plugins.smartfile.fs.listFileTree(paths.cwd, 'Dockerfile*');
|
|
||||||
|
|
||||||
// create the Dockerfile array
|
|
||||||
let readDockerfilesArray: Dockerfile[] = [];
|
|
||||||
plugins.beautylog.info(`found ${fileTree.length} Dockerfiles:`);
|
|
||||||
console.log(fileTree);
|
|
||||||
for (let dockerfilePath of fileTree) {
|
|
||||||
let myDockerfile = new Dockerfile({
|
|
||||||
filePath: dockerfilePath,
|
|
||||||
read: true
|
|
||||||
});
|
|
||||||
readDockerfilesArray.push(myDockerfile);
|
|
||||||
}
|
|
||||||
|
|
||||||
return readDockerfilesArray;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* sorts Dockerfiles into a dependency chain
|
|
||||||
* @param sortableArrayArg an array of instances of class Dockerfile
|
|
||||||
* @returns Promise<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);
|
|
||||||
let sorterFunctionCounter: number = 0;
|
|
||||||
let sorterFunction = function() {
|
|
||||||
sortableArrayArg.forEach(dockerfileArg => {
|
|
||||||
let cleanTags = cleanTagsArrayFunction(sortableArrayArg, sortedArray);
|
|
||||||
if (
|
|
||||||
cleanTags.indexOf(dockerfileArg.baseImage) === -1 &&
|
|
||||||
sortedArray.indexOf(dockerfileArg) === -1
|
|
||||||
) {
|
|
||||||
sortedArray.push(dockerfileArg);
|
|
||||||
}
|
|
||||||
if (cleanTagsOriginal.indexOf(dockerfileArg.baseImage) !== -1) {
|
|
||||||
dockerfileArg.localBaseImageDependent = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (sortableArrayArg.length === sortedArray.length) {
|
|
||||||
let counter = 1;
|
|
||||||
for (let dockerfile of sortedArray) {
|
|
||||||
plugins.beautylog.log(`tag ${counter}: -> ${dockerfile.cleanTag}`);
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
done.resolve(sortedArray);
|
|
||||||
} else if (sorterFunctionCounter < 10) {
|
|
||||||
sorterFunctionCounter++;
|
|
||||||
sorterFunction();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
sorterFunction();
|
|
||||||
return done.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* maps local Dockerfiles dependencies to the correspoding Dockerfile class instances
|
|
||||||
*/
|
|
||||||
export let mapDockerfiles = async (sortedArray: Dockerfile[]): Promise<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 (let dockerfileArg of sortedArrayArg) {
|
|
||||||
await dockerfileArg.build();
|
|
||||||
}
|
|
||||||
return sortedArrayArg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* tests all Dockerfiles in by calling class Dockerfile.test();
|
|
||||||
* @param sortedArrayArg Dockerfile[] that contains all Dockerfiles in cwd
|
|
||||||
*/
|
|
||||||
export let testDockerfiles = async (sortedArrayArg: Dockerfile[]) => {
|
|
||||||
for (let dockerfileArg of sortedArrayArg) {
|
|
||||||
await dockerfileArg.test();
|
|
||||||
}
|
|
||||||
return sortedArrayArg;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns a version for a docker file
|
|
||||||
* @execution SYNC
|
|
||||||
*/
|
|
||||||
export let dockerFileVersion = (dockerfileNameArg: string): string => {
|
|
||||||
let versionString: string;
|
|
||||||
let versionRegex = /Dockerfile_([a-zA-Z0-9\.]*)$/;
|
|
||||||
let regexResultArray = versionRegex.exec(dockerfileNameArg);
|
|
||||||
if (regexResultArray && regexResultArray.length === 2) {
|
|
||||||
versionString = regexResultArray[1];
|
|
||||||
} else {
|
|
||||||
versionString = 'latest';
|
|
||||||
}
|
|
||||||
return versionString;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the docker base image for a Dockerfile
|
|
||||||
*/
|
|
||||||
export let dockerBaseImage = function(dockerfileContentArg: string) {
|
|
||||||
let baseImageRegex = /FROM\s([a-zA-z0-9\/\-\:]*)\n?/;
|
|
||||||
let regexResultArray = baseImageRegex.exec(dockerfileContentArg);
|
|
||||||
return regexResultArray[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns the docker tag
|
|
||||||
*/
|
|
||||||
export let getDockerTagString = (
|
|
||||||
registryArg: string,
|
|
||||||
repoArg: string,
|
|
||||||
versionArg: string,
|
|
||||||
suffixArg?: string
|
|
||||||
): string => {
|
|
||||||
// determine wether the repo should be mapped accordingly to the registry
|
|
||||||
let mappedRepo = NpmciConfig.configObject.dockerRegistryRepoMap[registryArg];
|
|
||||||
let repo = (() => {
|
|
||||||
if (mappedRepo) {
|
|
||||||
return mappedRepo;
|
|
||||||
} else {
|
|
||||||
return repoArg;
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// determine wether the version contais a suffix
|
|
||||||
let version = versionArg;
|
|
||||||
if (suffixArg) {
|
|
||||||
version = versionArg + '_' + suffixArg;
|
|
||||||
}
|
|
||||||
|
|
||||||
let 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');
|
|
||||||
let buildArgsString: string = '';
|
|
||||||
for (let key in NpmciConfig.configObject.dockerBuildargEnvMap) {
|
|
||||||
let targetValue = process.env[NpmciConfig.configObject.dockerBuildargEnvMap[key]];
|
|
||||||
buildArgsString = `${buildArgsString} --build-arg ${key}=${targetValue}`;
|
|
||||||
}
|
|
||||||
return buildArgsString;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
export let cleanTagsArrayFunction = function(
|
|
||||||
dockerfileArrayArg: Dockerfile[],
|
|
||||||
trackingArrayArg: Dockerfile[]
|
|
||||||
): string[] {
|
|
||||||
let cleanTagsArray: string[] = [];
|
|
||||||
dockerfileArrayArg.forEach(function(dockerfileArg) {
|
|
||||||
if (trackingArrayArg.indexOf(dockerfileArg) === -1) {
|
|
||||||
cleanTagsArray.push(dockerfileArg.cleanTag);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return cleanTagsArray;
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from '../npmci.plugins';
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import * as plugins from './mod.plugins';
|
|
||||||
import { bash } from '../npmci.bash';
|
|
||||||
import { repo } from '../npmci.env';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handle cli input
|
|
||||||
* @param argvArg
|
|
||||||
*/
|
|
||||||
export let handleCli = async argvArg => {
|
|
||||||
if (argvArg._.length >= 2) {
|
|
||||||
let action: string = argvArg._[1];
|
|
||||||
switch (action) {
|
|
||||||
case 'mirror':
|
|
||||||
await mirror();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
plugins.beautylog.error(`>>npmci git ...<< action >>${action}<< not supported`);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.log(
|
|
||||||
`>>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;
|
|
||||||
if (githubToken) {
|
|
||||||
plugins.beautylog.info('found github token.');
|
|
||||||
plugins.beautylog.log('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`);
|
|
||||||
plugins.beautylog.ok('pushed all branches to mirror!');
|
|
||||||
await bash(`git push mirror --tags`);
|
|
||||||
plugins.beautylog.ok('pushed all tags to mirror!');
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.error(`cannot find NPMCI_GIT_GITHUBTOKEN env var!`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from '../npmci.plugins';
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import * as plugins from '../npmci.plugins';
|
|
||||||
import * as npmciConfig from '../npmci.config';
|
|
||||||
import { bash, bashNoError, nvmAvailable, yarnAvailable } from '../npmci.bash';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handle cli input
|
|
||||||
* @param argvArg
|
|
||||||
*/
|
|
||||||
export let handleCli = async argvArg => {
|
|
||||||
if (argvArg._.length >= 3) {
|
|
||||||
let action: string = argvArg._[1];
|
|
||||||
switch (action) {
|
|
||||||
case 'install':
|
|
||||||
await install(argvArg._[2]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
plugins.beautylog.error(`>>npmci node ...<< action >>${action}<< not supported`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.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 => {
|
|
||||||
plugins.beautylog.log(`now installing node version ${versionArg}`);
|
|
||||||
let version: string;
|
|
||||||
if (versionArg === 'stable') {
|
|
||||||
version = '9';
|
|
||||||
} else if (versionArg === 'lts') {
|
|
||||||
version = '8';
|
|
||||||
} else if (versionArg === 'legacy') {
|
|
||||||
version = '8';
|
|
||||||
} else {
|
|
||||||
version = versionArg;
|
|
||||||
}
|
|
||||||
if (await nvmAvailable.promise) {
|
|
||||||
await bash(`nvm install ${version} && nvm alias default ${version}`);
|
|
||||||
plugins.beautylog.success(`Node version ${version} successfully installed!`);
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.warn('Nvm not in path so staying at installed node version!');
|
|
||||||
}
|
|
||||||
await bash('node -v');
|
|
||||||
await bash('npm -v');
|
|
||||||
// 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 === '');
|
|
||||||
if (toolAvailable) {
|
|
||||||
plugins.beautylog.log(`Tool ${npmTool} is available`);
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.info(`globally installing ${npmTool} from npm`);
|
|
||||||
if (await yarnAvailable.promise) {
|
|
||||||
await bash(`yarn global add ${npmTool}`);
|
|
||||||
} else {
|
|
||||||
await bash(`npm install ${npmTool} -q -g`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
plugins.beautylog.success('all global npm tools specified in npmextra.json are now available!');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
import * as plugins from './mod.plugins';
|
|
||||||
import * as configModule from '../npmci.config';
|
|
||||||
import { bash, bashNoError, nvmAvailable, yarnAvailable } from '../npmci.bash';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* handle cli input
|
|
||||||
* @param argvArg
|
|
||||||
*/
|
|
||||||
export let handleCli = async argvArg => {
|
|
||||||
if (argvArg._.length >= 2) {
|
|
||||||
let 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:
|
|
||||||
plugins.beautylog.error(`>>npmci npm ...<< action >>${action}<< not supported`);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.log(
|
|
||||||
`>>npmci npm ...<< cli arguments invalid... Please read the documentation.`
|
|
||||||
);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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');
|
|
||||||
} else {
|
|
||||||
plugins.beautylog.error('no access token found! Exiting!');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
plugins.smartfile.memory.toFsSync(npmrcFileString, '/root/.npmrc');
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* publish a package to npm
|
|
||||||
*/
|
|
||||||
let publish = async () => {
|
|
||||||
let npmAccessCliString = ``;
|
|
||||||
const config = await configModule.getConfig();
|
|
||||||
|
|
||||||
// -> configure package access level
|
|
||||||
if (
|
|
||||||
config.npmAccessLevel &&
|
|
||||||
(config.npmAccessLevel === 'public' || config.npmAccessLevel === 'private')
|
|
||||||
) {
|
|
||||||
npmAccessCliString = `--access=${config.npmAccessLevel}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// -> build it
|
|
||||||
await bash(`yarn install`);
|
|
||||||
await bash(`yarn run build`);
|
|
||||||
|
|
||||||
// -> publish it
|
|
||||||
await bash(`npm publish ${npmAccessCliString}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
let install = async (): Promise<void> => {
|
|
||||||
plugins.beautylog.info('now installing dependencies:');
|
|
||||||
if (await yarnAvailable.promise) {
|
|
||||||
await bash('yarn install');
|
|
||||||
} else {
|
|
||||||
await bash('npm install');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export let test = async (): Promise<void> => {
|
|
||||||
plugins.beautylog.info('now starting tests:');
|
|
||||||
await bash('yarn test');
|
|
||||||
};
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export * from '../npmci.plugins';
|
|
||||||
24
ts/mod_precheck/index.ts
Normal file
24
ts/mod_precheck/index.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import * as plugins from './plugins.js';
|
||||||
|
import * as paths from '../npmci.paths.js';
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import { Npmci } from '../npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export const handleCli = async (npmciRefArg: Npmci, argvArg: any) => {
|
||||||
|
logger.log('info', 'checking execution context');
|
||||||
|
const presentRunnerTags = process.env.CI_RUNNER_TAGS.split(',').map((stringArg) =>
|
||||||
|
stringArg.trim()
|
||||||
|
);
|
||||||
|
let allDesiredGitlabRunnerTagsPresent = true;
|
||||||
|
for (const desiredRunnerTag of npmciRefArg.npmciConfig.getConfig().gitlabRunnerTags) {
|
||||||
|
if (!presentRunnerTags.includes(desiredRunnerTag)) {
|
||||||
|
allDesiredGitlabRunnerTagsPresent = false;
|
||||||
|
logger.log(
|
||||||
|
'error',
|
||||||
|
`Desired runnerRag ${desiredRunnerTag} is missing in current execution context.`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!allDesiredGitlabRunnerTagsPresent) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
1
ts/mod_precheck/plugins.ts
Normal file
1
ts/mod_precheck/plugins.ts
Normal file
@@ -0,0 +1 @@
|
|||||||
|
export * from '../npmci.plugins.js';
|
||||||
@@ -1,19 +1,20 @@
|
|||||||
import * as plugins from './mod.plugins';
|
import { logger } from '../npmci.logging.js';
|
||||||
|
import * as plugins from './mod.plugins.js';
|
||||||
let sshInstance: plugins.smartssh.SshInstance;
|
let sshInstance: plugins.smartssh.SshInstance;
|
||||||
|
|
||||||
export let handleCli = async argvArg => {
|
export let handleCli = async (argvArg: any) => {
|
||||||
if (argvArg._.length >= 2) {
|
if (argvArg._.length >= 2) {
|
||||||
let action: string = argvArg._[1];
|
const action: string = argvArg._[1];
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'prepare':
|
case 'prepare':
|
||||||
await prepare();
|
await prepare();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
plugins.beautylog.error(`action >>${action}<< not supported`);
|
logger.log('error', `action >>${action}<< not supported`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
plugins.beautylog.error(`>>npmci ssh ...<< please specify an action!`);
|
logger.log('error', `>>npmci ssh ...<< please specify an action!`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -21,7 +22,7 @@ export let handleCli = async argvArg => {
|
|||||||
/**
|
/**
|
||||||
* checks if not undefined
|
* checks if not undefined
|
||||||
*/
|
*/
|
||||||
let notUndefined = (stringArg: string) => {
|
const notUndefined = (stringArg: string) => {
|
||||||
return stringArg && stringArg !== 'undefined' && stringArg !== '##';
|
return stringArg && stringArg !== 'undefined' && stringArg !== '##';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34,27 +35,27 @@ export let prepare = async () => {
|
|||||||
if (!process.env.NPMTS_TEST) {
|
if (!process.env.NPMTS_TEST) {
|
||||||
sshInstance.writeToDisk();
|
sshInstance.writeToDisk();
|
||||||
} else {
|
} 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
|
* gets called for each found SSH ENV Var and deploys it
|
||||||
*/
|
*/
|
||||||
let evaluateSshEnv = async (sshkeyEnvVarArg: string) => {
|
const evaluateSshEnv = async (sshkeyEnvVarArg: string) => {
|
||||||
let sshEnvArray = sshkeyEnvVarArg.split('|');
|
const sshEnvArray = sshkeyEnvVarArg.split('|');
|
||||||
let sshKey = new plugins.smartssh.SshKey();
|
const sshKey = new plugins.smartssh.SshKey();
|
||||||
plugins.beautylog.info('Found SSH identity for ' + sshEnvArray[1]);
|
logger.log('info', 'Found SSH identity for ' + sshEnvArray[1]);
|
||||||
if (notUndefined(sshEnvArray[0])) {
|
if (notUndefined(sshEnvArray[0])) {
|
||||||
plugins.beautylog.log('---> host defined!');
|
logger.log('info', '---> host defined!');
|
||||||
sshKey.host = sshEnvArray[0];
|
sshKey.host = sshEnvArray[0];
|
||||||
}
|
}
|
||||||
if (notUndefined(sshEnvArray[1])) {
|
if (notUndefined(sshEnvArray[1])) {
|
||||||
plugins.beautylog.log('---> privKey defined!');
|
logger.log('info', '---> privKey defined!');
|
||||||
sshKey.privKeyBase64 = sshEnvArray[1];
|
sshKey.privKeyBase64 = sshEnvArray[1];
|
||||||
}
|
}
|
||||||
if (notUndefined(sshEnvArray[2])) {
|
if (notUndefined(sshEnvArray[2])) {
|
||||||
plugins.beautylog.log('---> pubKey defined!');
|
logger.log('info', '---> pubKey defined!');
|
||||||
sshKey.pubKeyBase64 = sshEnvArray[2];
|
sshKey.pubKeyBase64 = sshEnvArray[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins';
|
export * from '../npmci.plugins.js';
|
||||||
|
|||||||
@@ -1,28 +1,43 @@
|
|||||||
import * as plugins from './mod.plugins';
|
import * as plugins from './mod.plugins.js';
|
||||||
import { bash } from '../npmci.bash';
|
import { bash } from '../npmci.bash.js';
|
||||||
|
import { logger } from '../npmci.logging.js';
|
||||||
|
|
||||||
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 () => {
|
export let trigger = async () => {
|
||||||
plugins.beautylog.info('now running triggers');
|
logger.log('info', 'now running triggers');
|
||||||
plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TRIGGER_*', evaluateTrigger);
|
await plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_TRIGGER_*', evaluateTrigger);
|
||||||
};
|
};
|
||||||
|
|
||||||
let evaluateTrigger = async triggerEnvVarArg => {
|
const evaluateTrigger = async (triggerEnvVarArg) => {
|
||||||
let triggerRegexResultArray = triggerValueRegex.exec(triggerEnvVarArg);
|
const triggerRegexResultArray = triggerValueRegex.exec(triggerEnvVarArg);
|
||||||
let regexDomain = triggerRegexResultArray[1];
|
const regexDomain = triggerRegexResultArray[1];
|
||||||
let regexProjectId = triggerRegexResultArray[2];
|
const regexProjectId = triggerRegexResultArray[2];
|
||||||
let regexProjectTriggerToken = triggerRegexResultArray[3];
|
const regexProjectTriggerToken = triggerRegexResultArray[3];
|
||||||
let regexRefName = triggerRegexResultArray[4];
|
const regexRefName = triggerRegexResultArray[4];
|
||||||
let regexTriggerName;
|
let regexTriggerName;
|
||||||
if (triggerRegexResultArray.length === 6) {
|
if (triggerRegexResultArray.length === 6) {
|
||||||
regexTriggerName = triggerRegexResultArray[5];
|
regexTriggerName = triggerRegexResultArray[5];
|
||||||
} else {
|
} else {
|
||||||
regexTriggerName = 'Unnamed Trigger';
|
regexTriggerName = 'Unnamed Trigger';
|
||||||
}
|
}
|
||||||
plugins.beautylog.info('Found Trigger!');
|
logger.log('info', 'Found Trigger!');
|
||||||
plugins.beautylog.log('triggering build for ref ' + regexRefName + ' of ' + regexTriggerName);
|
logger.log('info', 'triggering build for ref ' + regexRefName + ' of ' + regexTriggerName);
|
||||||
plugins.request.post('https://gitlab.com/api/v3/projects/' + regexProjectId + '/trigger/builds', {
|
plugins.smartrequest.postFormData(
|
||||||
form: { token: regexProjectTriggerToken, ref: regexRefName }
|
'https://gitlab.com/api/v3/projects/' + regexProjectId + '/trigger/builds',
|
||||||
});
|
{},
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'token',
|
||||||
|
payload: regexProjectTriggerToken,
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ref',
|
||||||
|
payload: regexRefName,
|
||||||
|
type: 'string',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
export * from '../npmci.plugins';
|
export * from '../npmci.plugins.js';
|
||||||
|
|||||||
@@ -1,56 +1,42 @@
|
|||||||
import * as plugins from './npmci.plugins';
|
import { logger } from './npmci.logging.js';
|
||||||
import * as paths from './npmci.paths';
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
import * as paths from './npmci.paths.js';
|
||||||
|
|
||||||
import * as smartq from 'smartq';
|
import * as smartpromise from '@pushrocks/smartpromise';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* wether nvm is available or not
|
* wether nvm is available or not
|
||||||
*/
|
*/
|
||||||
export let nvmAvailable = smartq.defer<boolean>();
|
export let nvmAvailable = smartpromise.defer<boolean>();
|
||||||
export let yarnAvailable = smartq.defer<boolean>();
|
|
||||||
/**
|
/**
|
||||||
* the smartshell instance for npmci
|
* the smartshell instance for npmci
|
||||||
*/
|
*/
|
||||||
let npmciSmartshell = new plugins.smartshell.Smartshell({
|
const npmciSmartshell = new plugins.smartshell.Smartshell({
|
||||||
executor: 'bash',
|
executor: 'bash',
|
||||||
sourceFilePaths: []
|
sourceFilePaths: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* check for tools.
|
* check for tools.
|
||||||
*/
|
*/
|
||||||
let checkToolsAvailable = async () => {
|
const checkToolsAvailable = async () => {
|
||||||
// check for nvm
|
// check for nvm
|
||||||
if (!process.env.NPMTS_TEST) {
|
if (!process.env.NPMTS_TEST) {
|
||||||
if (
|
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);
|
nvmAvailable.resolve(true);
|
||||||
} else if (
|
} 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);
|
nvmAvailable.resolve(true);
|
||||||
} else {
|
} else {
|
||||||
nvmAvailable.resolve(false);
|
nvmAvailable.resolve(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for yarn
|
|
||||||
await plugins.smartshell.which('yarn').then(
|
|
||||||
async () => {
|
|
||||||
await plugins.smartshell.exec(
|
|
||||||
`yarn config set cache-folder ${plugins.path.join(paths.cwd, '.yarn')}`
|
|
||||||
);
|
|
||||||
yarnAvailable.resolve(true);
|
|
||||||
},
|
|
||||||
() => {
|
|
||||||
yarnAvailable.resolve(false);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
nvmAvailable.resolve(true);
|
nvmAvailable.resolve(true);
|
||||||
yarnAvailable.resolve(true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
checkToolsAvailable();
|
checkToolsAvailable();
|
||||||
@@ -83,24 +69,22 @@ export let bash = async (commandArg: string, retryArg: number = 2): Promise<stri
|
|||||||
if (execResult.exitCode !== 0 && i === retryArg) {
|
if (execResult.exitCode !== 0 && i === retryArg) {
|
||||||
// something went wrong and retries are exhausted
|
// something went wrong and retries are exhausted
|
||||||
if (failOnError) {
|
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);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
} else if (execResult.exitCode === 0) {
|
} else if (execResult.exitCode === 0) {
|
||||||
// everything went fine, or no error wanted
|
// everything went fine, or no error wanted
|
||||||
i = retryArg + 1; // retry +1 breaks for loop, if everything works out ok retrials are not wanted
|
i = retryArg + 1; // retry +1 breaks for loop, if everything works out ok retrials are not wanted
|
||||||
} else {
|
} else {
|
||||||
plugins.beautylog.warn(
|
logger.log('warn', 'Something went wrong! Exit Code: ' + execResult.exitCode.toString());
|
||||||
'Something went wrong! Exit Code: ' + execResult.exitCode.toString()
|
logger.log('info', 'Retry ' + (i + 1).toString() + ' of ' + retryArg.toString());
|
||||||
);
|
|
||||||
plugins.beautylog.info('Retry ' + (i + 1).toString() + ' of ' + retryArg.toString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
plugins.beautylog.log('ShellExec would be: ' + commandArg);
|
logger.log('info', 'ShellExec would be: ' + commandArg);
|
||||||
execResult = {
|
execResult = {
|
||||||
exitCode: 0,
|
exitCode: 0,
|
||||||
stdout: 'testOutput'
|
stdout: 'testOutput',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return execResult.stdout;
|
return execResult.stdout;
|
||||||
|
|||||||
61
ts/npmci.classes.npmci.ts
Normal file
61
ts/npmci.classes.npmci.ts
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
|
||||||
|
|
||||||
|
// env
|
||||||
|
import { NpmciEnv } from './npmci.classes.npmcienv.js';
|
||||||
|
import { NpmciInfo } from './npmci.classes.npmciinfo.js';
|
||||||
|
import { NpmciCli } from './npmci.classes.npmcicli.js';
|
||||||
|
import { NpmciConfig } from './npmci.classes.npmciconfig.js';
|
||||||
|
|
||||||
|
// connectors
|
||||||
|
import { CloudlyConnector } from './connector.cloudly/cloudlyconnector.js';
|
||||||
|
|
||||||
|
// managers
|
||||||
|
import { NpmciCloudronManager } from './manager.cloudron/index.js';
|
||||||
|
import { NpmciDockerManager } from './manager.docker/index.js';
|
||||||
|
import { NpmciGitManager } from './manager.git/index.js';
|
||||||
|
import { NpmciNodeJsManager } from './manager.nodejs/index.js';
|
||||||
|
import { NpmciNpmManager } from './manager.npm/index.js';
|
||||||
|
|
||||||
|
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 cloudronManager: NpmciCloudronManager;
|
||||||
|
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.cloudronManager = new NpmciCloudronManager(this);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
120
ts/npmci.classes.npmcicli.ts
Normal file
120
ts/npmci.classes.npmcicli.ts
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { logger } from './npmci.logging.js';
|
||||||
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
import * as paths from './npmci.paths.js';
|
||||||
|
import { Npmci } from './npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
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.js');
|
||||||
|
await modClean.clean();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// cloudron
|
||||||
|
this.smartcli.addCommand('cloudron').subscribe(
|
||||||
|
async (argv) => {
|
||||||
|
await this.npmciRef.cloudronManager.handleCli(argv);
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// command
|
||||||
|
this.smartcli.addCommand('command').subscribe(
|
||||||
|
async (argv) => {
|
||||||
|
const modCommand = await import('./mod_command/index.js');
|
||||||
|
await modCommand.command();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// git
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.smartcli.addCommand('precheck').subscribe(async (argvArg) => {
|
||||||
|
const modPrecheck = await import('./mod_precheck/index.js');
|
||||||
|
await modPrecheck.handleCli(this.npmciRef, argvArg);
|
||||||
|
});
|
||||||
|
|
||||||
|
// trigger
|
||||||
|
this.smartcli.addCommand('ssh').subscribe(async (argvArg) => {
|
||||||
|
const modSsh = await import('./mod_ssh/index.js');
|
||||||
|
await modSsh.handleCli(argvArg);
|
||||||
|
});
|
||||||
|
|
||||||
|
// trigger
|
||||||
|
this.smartcli.addCommand('trigger').subscribe(
|
||||||
|
async (argv) => {
|
||||||
|
const modTrigger = await import('./mod_trigger/index.js');
|
||||||
|
await modTrigger.trigger();
|
||||||
|
},
|
||||||
|
(err) => {
|
||||||
|
console.log(err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public startParse = () => {
|
||||||
|
this.smartcli.startParse();
|
||||||
|
};
|
||||||
|
}
|
||||||
79
ts/npmci.classes.npmciconfig.ts
Normal file
79
ts/npmci.classes.npmciconfig.ts
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
import * as paths from './npmci.paths.js';
|
||||||
|
|
||||||
|
import { logger } from './npmci.logging.js';
|
||||||
|
import { Npmci } from './npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 };
|
||||||
|
|
||||||
|
// gitlab
|
||||||
|
gitlabRunnerTags: string[];
|
||||||
|
|
||||||
|
// urls
|
||||||
|
urlCloudly: string;
|
||||||
|
|
||||||
|
// cloudron
|
||||||
|
cloudronAppName?: 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
|
||||||
|
);
|
||||||
|
|
||||||
|
this.configObject = {
|
||||||
|
projectInfo: new plugins.projectinfo.ProjectInfo(paths.cwd),
|
||||||
|
npmGlobalTools: [],
|
||||||
|
dockerRegistries: [],
|
||||||
|
dockerRegistryRepoMap: {},
|
||||||
|
npmAccessLevel: 'private',
|
||||||
|
npmRegistryUrl: 'registry.npmjs.org',
|
||||||
|
gitlabRunnerTags: [],
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
ts/npmci.classes.npmcienv.ts
Normal file
23
ts/npmci.classes.npmcienv.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
import { Npmci } from './npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
export class NpmciEnv {
|
||||||
|
public npmciRef: Npmci;
|
||||||
|
|
||||||
|
public repoString: string;
|
||||||
|
public repo: plugins.smartstring.GitRepo;
|
||||||
|
|
||||||
|
constructor(npmciRefArg: Npmci) {
|
||||||
|
this.npmciRef = npmciRefArg;
|
||||||
|
if (process.env.GITLAB_CI) {
|
||||||
|
this.repoString = process.env.CI_REPOSITORY_URL;
|
||||||
|
}
|
||||||
|
if (process.env.NPMCI_COMPUTED_REPOURL) {
|
||||||
|
this.repoString = process.env.NPMCI_COMPUTED_REPOURL;
|
||||||
|
}
|
||||||
|
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.js';
|
||||||
|
import * as paths from './npmci.paths.js';
|
||||||
|
import { logger } from './npmci.logging.js';
|
||||||
|
import { Npmci } from './npmci.classes.npmci.js';
|
||||||
|
|
||||||
|
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}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
122
ts/npmci.cli.ts
122
ts/npmci.cli.ts
@@ -1,122 +0,0 @@
|
|||||||
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);
|
|
||||||
|
|
||||||
import * as NpmciEnv from './npmci.env';
|
|
||||||
|
|
||||||
import * as npmciMods from './npmci.mods';
|
|
||||||
|
|
||||||
let smartcli = new plugins.smartcli.Smartcli();
|
|
||||||
smartcli.addVersion(npmciInfo.version);
|
|
||||||
|
|
||||||
// clean
|
|
||||||
smartcli
|
|
||||||
.addCommand('clean')
|
|
||||||
.then(async argv => {
|
|
||||||
let modClean = await npmciMods.modClean.load();
|
|
||||||
await modClean.clean();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// cloudflare
|
|
||||||
smartcli
|
|
||||||
.addCommand('cloudflare')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modPurge = await npmciMods.modCloudflare.load();
|
|
||||||
await modPurge.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// command
|
|
||||||
smartcli
|
|
||||||
.addCommand('command')
|
|
||||||
.then(async argv => {
|
|
||||||
let modCommand = await npmciMods.modCommand.load();
|
|
||||||
await modCommand.command();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// command
|
|
||||||
smartcli
|
|
||||||
.addCommand('git')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modGit = await npmciMods.modGit.load();
|
|
||||||
await modGit.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// build
|
|
||||||
smartcli
|
|
||||||
.addCommand('docker')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modDocker = await npmciMods.modDocker.load();
|
|
||||||
await modDocker.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// node
|
|
||||||
smartcli
|
|
||||||
.addCommand('node')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modNode = await npmciMods.modNode.load();
|
|
||||||
await modNode.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// npm
|
|
||||||
smartcli
|
|
||||||
.addCommand('npm')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modNpm = await npmciMods.modNpm.load();
|
|
||||||
await modNpm.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
|
|
||||||
// trigger
|
|
||||||
smartcli
|
|
||||||
.addCommand('ssh')
|
|
||||||
.then(async argvArg => {
|
|
||||||
let modSsh = await npmciMods.modSsh.load();
|
|
||||||
await modSsh.handleCli(argvArg);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
// trigger
|
|
||||||
smartcli
|
|
||||||
.addCommand('trigger')
|
|
||||||
.then(async argv => {
|
|
||||||
let modTrigger = await npmciMods.modTrigger.load();
|
|
||||||
await modTrigger.trigger();
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log(err);
|
|
||||||
process.exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
smartcli.startParse();
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
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';
|
|
||||||
|
|
||||||
export interface INpmciOptions {
|
|
||||||
npmGlobalTools: string[];
|
|
||||||
npmAccessLevel?: 'private' | 'public';
|
|
||||||
dockerRegistryRepoMap: any;
|
|
||||||
dockerBuildargEnvMap: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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 = {
|
|
||||||
npmGlobalTools: [],
|
|
||||||
dockerRegistryRepoMap: {},
|
|
||||||
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 '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);
|
|
||||||
14
ts/npmci.logging.ts
Normal file
14
ts/npmci.logging.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
|
||||||
|
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());
|
||||||
@@ -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);
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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 => {
|
|
||||||
plugins.beautylog.warn('Lossless Analytics API not available...');
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,16 @@
|
|||||||
import * as plugins from './npmci.plugins';
|
import * as plugins from './npmci.plugins.js';
|
||||||
|
|
||||||
export let cwd = process.cwd();
|
export const cwd = process.cwd();
|
||||||
|
|
||||||
export let NpmciPackageRoot = plugins.path.join(__dirname, '../');
|
// package paths
|
||||||
export let NpmciPackageConfig = plugins.path.join(NpmciPackageRoot, './config.json');
|
export const NpmciPackageRoot = plugins.path.join(
|
||||||
export let NpmciProjectDir = cwd;
|
plugins.smartpath.get.dirnameFromImportMetaUrl(import.meta.url),
|
||||||
export let NpmciTestDir = plugins.path.join(cwd, './test');
|
'../'
|
||||||
|
);
|
||||||
|
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');
|
||||||
|
|||||||
@@ -1,19 +1,65 @@
|
|||||||
export import beautylog = require('beautylog');
|
// node native
|
||||||
export import lodash = require('lodash');
|
import * as path from 'path';
|
||||||
export import npmextra = require('npmextra');
|
|
||||||
export import path = require('path');
|
export { path };
|
||||||
export import projectinfo = require('projectinfo');
|
|
||||||
export import q = require('smartq');
|
// @apiglobal
|
||||||
export let request = require('request');
|
import * as typedrequest from '@apiglobal/typedrequest';
|
||||||
export import smartcli = require('smartcli');
|
|
||||||
export import smartdelay = require('smartdelay');
|
export { typedrequest };
|
||||||
export import smartfile = require('smartfile');
|
|
||||||
export import shelljs = require('shelljs');
|
// @servezone
|
||||||
export import smartparam = require('smartparam');
|
import * as servezoneInterfaces from '@servezone/interfaces';
|
||||||
export import smartq = require('smartq');
|
|
||||||
export import smartshell = require('smartshell');
|
export { servezoneInterfaces };
|
||||||
export import smartsocket = require('smartsocket');
|
|
||||||
export import smartsystem = require('smartsystem');
|
// @pushrocks
|
||||||
export import smartssh = require('smartssh');
|
import * as npmextra from '@pushrocks/npmextra';
|
||||||
export import smartstring = require('smartstring');
|
import * as projectinfo from '@pushrocks/projectinfo';
|
||||||
export import through2 = require('through2');
|
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';
|
||||||
|
import * as smartgit from '@pushrocks/smartgit';
|
||||||
|
import * as smartlog from '@pushrocks/smartlog';
|
||||||
|
import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local';
|
||||||
|
import * as smartparam from '@pushrocks/smartparam';
|
||||||
|
import * as smartpath from '@pushrocks/smartpath';
|
||||||
|
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 {
|
||||||
|
npmextra,
|
||||||
|
projectinfo,
|
||||||
|
qenv,
|
||||||
|
smartanalytics,
|
||||||
|
smartdelay,
|
||||||
|
smartfile,
|
||||||
|
smartgit,
|
||||||
|
smartcli,
|
||||||
|
smartlog,
|
||||||
|
smartlogDestinationLocal,
|
||||||
|
smartparam,
|
||||||
|
smartpath,
|
||||||
|
smartpromise,
|
||||||
|
smartrequest,
|
||||||
|
smartshell,
|
||||||
|
smartsocket,
|
||||||
|
smartssh,
|
||||||
|
smartstring,
|
||||||
|
};
|
||||||
|
|
||||||
|
// @tsclass scope
|
||||||
|
import * as tsclass from '@tsclass/tsclass';
|
||||||
|
|
||||||
|
export { tsclass };
|
||||||
|
|
||||||
|
// third party
|
||||||
|
import * as through2 from 'through2';
|
||||||
|
|
||||||
|
export { through2 };
|
||||||
|
|||||||
10
tsconfig.json
Normal file
10
tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"useDefineForClassFields": false,
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ES2022",
|
||||||
|
"moduleResolution": "nodenext",
|
||||||
|
"esModuleInterop": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "tslint-config-standard"
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user