Compare commits

...

257 Commits

Author SHA1 Message Date
8e9a61bbb2 4.1.29 2024-05-23 21:47:07 +02:00
dc809a6023 fix(core): update 2024-05-23 21:47:06 +02:00
7eeca992b0 4.1.28 2024-05-17 16:23:48 +02:00
d018102014 fix(core): update 2024-05-17 16:23:47 +02:00
838f2d6959 4.1.27 2023-08-24 17:25:56 +02:00
0d42e5f6eb fix(core): update 2023-08-24 17:25:55 +02:00
f96de8cdc3 4.1.26 2023-08-09 11:26:22 +02:00
965833916f fix(core): update 2023-08-09 11:26:22 +02:00
81ec1391e3 4.1.25 2023-08-09 11:23:57 +02:00
bbbca44640 fix(core): update 2023-08-09 11:23:56 +02:00
7ba7dc54a1 4.1.24 2023-08-08 23:32:08 +02:00
4f98eeec2a fix(core): update 2023-08-08 23:32:07 +02:00
419a6b9e5f 4.1.23 2023-07-13 16:00:47 +02:00
9c040c34f5 fix(core): update 2023-07-13 16:00:47 +02:00
50d3f2d795 4.1.22 2023-07-12 18:23:32 +02:00
305856b9e1 fix(core): update 2023-07-12 18:23:31 +02:00
3683743f3c 4.1.21 2023-07-12 15:35:39 +02:00
41237e0e5f fix(core): update 2023-07-12 15:35:38 +02:00
bce84a0e74 4.1.20 2023-07-02 00:10:28 +02:00
79bed919d8 fix(core): update 2023-07-02 00:10:27 +02:00
4b202ce00e 4.1.19 2023-07-01 22:09:54 +02:00
16ca787314 fix(core): update 2023-07-01 22:09:54 +02:00
3a9b6f658a 4.1.18 2023-07-01 22:05:44 +02:00
5c5dbf303f fix(core): update 2023-07-01 22:05:43 +02:00
4c07131e51 4.1.17 2023-07-01 19:23:17 +02:00
ba039469ff fix(core): update 2023-07-01 19:23:17 +02:00
49f2498ecd 4.1.16 2023-07-01 19:02:07 +02:00
1060060366 fix(core): update 2023-07-01 19:02:06 +02:00
0fa3a579f7 4.1.15 2023-06-26 10:09:25 +02:00
0e4556d59e fix(core): update 2023-06-26 10:09:24 +02:00
e2e7967fba 4.1.14 2023-06-26 09:28:19 +02:00
45b8d67abf fix(core): update 2023-06-26 09:28:19 +02:00
0a69aa5d62 4.1.13 2023-06-26 02:43:45 +02:00
dfbab1a1df fix(core): update 2023-06-26 02:43:45 +02:00
e58f009a24 4.1.12 2023-06-26 01:03:44 +02:00
2afd9cddc5 fix(core): update 2023-06-26 01:03:44 +02:00
d79c5366ef 4.1.11 2023-06-26 00:09:56 +02:00
8e4f7ad244 fix(core): update 2023-06-26 00:09:54 +02:00
39de3a1601 4.1.10 2023-06-25 23:59:26 +02:00
cb3d2964d1 fix(core): update 2023-06-25 23:59:25 +02:00
6b5390cef8 4.1.9 2023-06-25 23:26:25 +02:00
2736b85de3 fix(core): update 2023-06-25 23:26:25 +02:00
82d7778f59 4.1.8 2023-06-25 23:18:23 +02:00
8c99cc0491 fix(core): update 2023-06-25 23:18:23 +02:00
955e3d0dbe 4.1.7 2023-06-25 23:16:29 +02:00
702ae8bed8 fix(core): update 2023-06-25 23:16:29 +02:00
b6f0723b75 4.1.6 2023-06-25 22:23:31 +02:00
8a2fb30e59 fix(core): update 2023-06-25 22:23:30 +02:00
95b4030120 4.1.5 2023-06-25 21:15:51 +02:00
5c77cfbdc2 fix(core): update 2023-06-25 21:15:50 +02:00
5ea42320a9 4.1.4 2023-05-07 22:35:19 +02:00
d07ebfc9c6 fix(core): update 2023-05-07 22:35:18 +02:00
bbb5718184 4.1.3 2023-05-07 21:30:59 +02:00
0d8b54637c fix(core): update 2023-05-07 21:30:58 +02:00
e51b2e28b9 4.1.2 2022-11-02 18:57:47 +01:00
f767140cc8 fix(core): update 2022-11-02 18:57:47 +01:00
0d4d69f072 4.1.1 2022-11-02 16:43:54 +01:00
a3e628c43f fix(core): update 2022-11-02 16:43:54 +01:00
a58fa135c1 4.1.0 2022-10-24 21:23:14 +02:00
93c7af6c91 feat(precheck): now includes a precheck for more generic runner execution 2022-10-24 21:23:14 +02:00
ad0e12bf7b 4.0.11 2022-10-23 17:19:42 +02:00
498dd6eff6 fix(core): update 2022-10-23 17:19:41 +02:00
b3aa964739 4.0.10 2022-10-11 14:26:43 +02:00
03eb9d2657 fix(core): update 2022-10-11 14:26:42 +02:00
373a838a6a 4.0.9 2022-10-11 14:08:00 +02:00
960e3f4675 fix(core): update 2022-10-11 14:07:59 +02:00
09bf676b58 4.0.8 2022-10-11 13:59:40 +02:00
76ba8e2ab9 fix(core): update 2022-10-11 13:59:39 +02:00
aaaaca2d19 4.0.7 2022-10-11 13:59:16 +02:00
71b27eda17 fix(core): update 2022-10-11 13:59:15 +02:00
2d00882fd7 4.0.6 2022-10-11 13:58:48 +02:00
ba5e69041f fix(core): update 2022-10-11 13:58:48 +02:00
d2871d601a 4.0.5 2022-10-11 13:40:26 +02:00
9c66d88dc0 fix(core): update 2022-10-11 13:40:25 +02:00
fb4c84e1de 4.0.4 2022-10-11 13:38:40 +02:00
57aca36f11 fix(core): update 2022-10-11 13:38:40 +02:00
905f594af1 4.0.3 2022-10-11 13:26:50 +02:00
b788b7f96b fix(core): update 2022-10-11 13:26:49 +02:00
319a2dc41a 4.0.2 2022-10-11 13:08:10 +02:00
e01a998f0e fix(core): update 2022-10-11 13:08:10 +02:00
e40606d97b 4.0.1 2022-10-11 10:53:12 +02:00
449c7b2c04 fix(core): update 2022-10-11 10:53:12 +02:00
006782b57f 4.0.0 2022-10-09 18:15:37 +02:00
d643da29b0 BREAKING CHANGE(core): switch to esm style module 2022-10-09 18:15:37 +02:00
635f92d2bc 3.1.83 2022-01-18 18:10:28 +01:00
9a2cb56094 fix(core): update 2022-01-18 18:10:27 +01:00
5886283002 3.1.82 2021-11-10 12:42:42 +01:00
f886194c9c 3.1.81 2021-11-10 12:40:13 +01:00
e4efec89d9 fix(core): update 2021-11-10 12:40:12 +01:00
dbc12a593f 3.1.80 2021-11-09 20:27:31 +01:00
d7666e862b fix(core): update 2021-11-09 20:27:30 +01:00
e262d29510 3.1.79 2021-11-07 04:20:14 +01:00
858d97cb5c fix(core): update 2021-11-07 04:20:14 +01:00
b8a2df66fe 3.1.78 2021-10-22 01:51:43 +02:00
1c128dd694 fix(core): update 2021-10-22 01:51:43 +02:00
2744d0bf7f 3.1.77 2021-10-19 03:09:50 +02:00
9eb232da39 fix(core): update 2021-10-19 03:09:50 +02:00
52af1d5188 3.1.76 2021-05-14 18:19:43 +00:00
4325f21c8c fix(core): update 2021-05-14 18:19:42 +00:00
6cd3eaceb4 3.1.75 2021-05-14 18:11:13 +00:00
f850c79b6c fix(core): update 2021-05-14 18:11:12 +00:00
efdf789575 3.1.74 2019-11-26 17:47:22 +00:00
6ef6446022 fix(npm cache): now correctly setting it when preparing npm 2019-11-26 17:47:21 +00:00
ef7d85e7c4 3.1.73 2019-11-24 13:52:19 +00:00
93b5d9869b 3.1.72 2019-11-24 11:51:53 +00:00
2a0cfeffe9 fix(core): update 2019-11-24 11:51:52 +00:00
909aafbd5f 3.1.71 2019-11-23 22:36:34 +00:00
91288e2d74 3.1.70 2019-11-23 22:32:09 +00:00
25709b1f9a fix(core): update 2019-11-23 22:32:08 +00:00
8a03d9aa94 3.1.69 2019-11-23 19:46:24 +00:00
bbe1cf770a 3.1.68 2019-11-23 19:46:02 +00:00
ac8190282f fix(core): update 2019-11-23 19:46:02 +00:00
446d140e32 3.1.68 2019-11-23 19:45:00 +00:00
726948651e fix(core): update 2019-11-23 19:44:59 +00:00
dd0a7bb782 3.1.67 2019-10-04 15:18:51 +02:00
fca00ffcf8 fix(core): update 2019-10-04 15:18:51 +02:00
13f6334ae5 3.1.66 2019-10-03 00:00:20 +02:00
7275a858d6 fix(core): update 2019-10-03 00:00:20 +02:00
5a3befe5af 3.1.65 2019-10-02 23:55:55 +02:00
385a93a05e update 2019-10-02 23:55:51 +02:00
b4d444ff05 3.1.64 2019-10-02 14:54:21 +02:00
487bcb9a70 fix(core): update 2019-10-02 14:54:21 +02:00
aaf11b66d7 3.1.63 2019-10-02 11:57:00 +02:00
83d7d46896 fix(core): update 2019-10-02 11:56:59 +02:00
693bda6a49 3.1.62 2019-10-02 11:56:06 +02:00
bfe3e266ee fix(core): update 2019-10-02 11:56:05 +02:00
5f33ebd8a7 3.1.61 2019-10-02 11:33:52 +02:00
f78c80e100 fix(core): update 2019-10-02 11:33:52 +02:00
f4d8656831 3.1.60 2019-09-01 14:21:30 +02:00
2290081ef0 fix(core): update 2019-09-01 14:21:30 +02:00
189d02a16f 3.1.59 2019-09-01 14:11:35 +02:00
55aee04334 fix(core): update 2019-09-01 14:11:35 +02:00
0e407b9b9d 3.1.58 2019-09-01 13:54:00 +02:00
24095bbd40 fix(core): update 2019-09-01 13:54:00 +02:00
f97ee94b5a 3.1.57 2019-09-01 13:51:12 +02:00
4cf7aea374 fix(core): update 2019-09-01 13:51:11 +02:00
6ab5e9cb30 3.1.56 2019-09-01 13:49:28 +02:00
95c1145bf5 3.1.55 2019-09-01 13:49:12 +02:00
ea04a1b788 fix(core): update 2019-09-01 13:49:11 +02:00
3bc2499d09 3.1.54 2019-09-01 13:46:03 +02:00
1f5967ac45 fix(core): update 2019-09-01 13:46:03 +02:00
fd952f086b 3.1.53 2019-09-01 13:45:19 +02:00
79500cb2c2 fix(core): update 2019-09-01 13:45:18 +02:00
6c58864fcf 3.1.52 2019-09-01 13:44:22 +02:00
7ea3ac182d fix(core): update 2019-09-01 13:44:21 +02:00
8979d26005 3.1.51 2019-09-01 13:41:04 +02:00
c8876dac88 fix(core): update 2019-09-01 13:41:03 +02:00
9c8a257c2a 3.1.50 2019-08-30 18:40:00 +02:00
8b77930ece fix(core): update 2019-08-30 18:39:59 +02:00
ba672d030f 3.1.49 2019-08-30 14:51:04 +02:00
8ad7e016e7 fix(core): update 2019-08-30 14:51:03 +02:00
d843311d7b 3.1.48 2019-08-30 13:30:16 +02:00
14ef2cfa9b 3.1.47 2019-08-30 12:24:01 +02:00
648effcf86 fix(core): update 2019-08-30 12:24:00 +02:00
572738e88f 3.1.46 2019-08-30 10:40:38 +02:00
129ae93044 fix(core): update 2019-08-30 10:40:38 +02:00
e910892231 3.1.45 2019-08-30 10:38:48 +02:00
6d9cabf7ee fix(core): update 2019-08-30 10:38:47 +02:00
7c7787e811 3.1.44 2019-08-29 20:56:03 +02:00
bde26cc312 fix(core): update 2019-08-29 20:56:02 +02:00
29e81f3ae7 3.1.43 2019-08-29 20:38:45 +02:00
6337b20d62 fix(core): update 2019-08-29 20:38:44 +02:00
6dd537fe43 3.1.42 2019-08-29 20:26:24 +02:00
7191b172a4 fix(core): update 2019-08-29 20:26:23 +02:00
9a4611b70f 3.1.41 2019-08-27 16:45:47 +02:00
189dbc3654 fix(core): update 2019-08-27 16:45:46 +02:00
fc95fc96ed 3.1.40 2019-08-23 17:04:29 +02:00
467eed57d7 fix(core): update 2019-08-23 17:04:29 +02:00
a5ca5444a0 3.1.39 2019-08-23 16:48:53 +02:00
17610cb834 fix(core): update 2019-08-23 16:48:52 +02:00
e1f2b5c6fe 3.1.38 2019-08-23 16:42:55 +02:00
edbbae0bd0 fix(core): update 2019-08-23 16:42:55 +02:00
0e820bec27 3.1.37 2019-07-18 14:42:15 +02:00
91a3d612c6 fix(core): update 2019-07-18 14:42:14 +02:00
c696730e55 3.1.36 2019-07-17 17:57:21 +02:00
38d38ce246 fix(core): update 2019-07-17 17:57:20 +02:00
adfdf68c38 3.1.35 2019-07-17 17:55:03 +02:00
d4a4d69941 fix(core): update 2019-07-17 17:55:02 +02:00
c1fed2c758 3.1.34 2019-07-17 17:04:10 +02:00
9918d81f59 fix(core): update 2019-07-17 17:04:10 +02:00
59d8338f6e 3.1.33 2019-06-19 14:00:24 +02:00
a4f8bd3320 fix(core): update 2019-06-19 14:00:24 +02:00
7c2fdb7224 3.1.32 2019-06-19 11:36:05 +02:00
37384aeb57 fix(core): update 2019-06-19 11:36:04 +02:00
60efda263f 3.1.31 2019-06-19 11:35:19 +02:00
19831037ec fix(core): update 2019-06-19 11:35:19 +02:00
a1d52af813 3.1.30 2019-06-19 10:41:58 +02:00
0a49ff9b03 fix(core): update 2019-06-19 10:41:58 +02:00
ca62326b46 3.1.29 2019-06-18 22:24:53 +02:00
e1de0ee479 fix(core): update 2019-06-18 22:24:53 +02:00
0dea101c07 3.1.28 2019-06-18 22:24:12 +02:00
380a49c59f fix(core): update 2019-06-18 22:24:12 +02:00
5133651e34 3.1.27 2019-06-18 17:30:05 +02:00
c8f26c7c48 fix(core): update 2019-06-18 17:30:04 +02:00
3bb5912046 3.1.26 2019-06-18 16:19:07 +02:00
d75258d9dd fix(core): update 2019-06-18 16:19:07 +02:00
b1577e7542 3.1.25 2019-05-08 22:50:57 +02:00
d5cdeffd17 fix(core): update 2019-05-08 22:50:57 +02:00
c62ce415e9 3.1.24 2019-05-08 22:44:34 +02:00
99014da1e8 fix(core): update 2019-05-08 22:44:34 +02:00
0b5dada524 3.1.23 2019-05-08 22:43:49 +02:00
40bddba3b5 fix(core): update 2019-05-08 22:43:48 +02:00
6f6ee6d799 3.1.22 2019-02-24 22:50:12 +01:00
e30cc3f5a0 fix(core): update 2019-02-24 22:50:12 +01:00
a4562d4d1b 3.1.21 2018-12-24 02:13:05 +01:00
524b405773 fix(core): update 2018-12-24 02:13:04 +01:00
0d19c1c68d 3.1.20 2018-12-23 18:57:15 +01:00
cff79bc3b4 fix(mirror): now refusing to mirror for private code 2018-12-23 18:57:15 +01:00
28541a838d 3.1.19 2018-12-23 18:54:17 +01:00
c3ab527341 fix(core): update 2018-12-23 18:54:16 +01:00
52cc249098 3.1.18 2018-12-23 17:29:25 +01:00
2e189b0660 fix(core): update 2018-12-23 17:29:25 +01:00
f876c7414b 3.1.17 2018-12-12 22:29:59 +01:00
08b7585cfc fix(core): update 2018-12-12 22:29:59 +01:00
76311fab72 3.1.16 2018-12-11 01:02:22 +01:00
1b73df64f5 fix(core): update 2018-12-11 01:02:21 +01:00
701cee573b 3.1.15 2018-12-11 00:25:40 +01:00
3dd086f711 fix(core): update 2018-12-11 00:25:39 +01:00
67ff5d09d4 3.1.14 2018-12-09 16:48:33 +01:00
5cb8a79b6a fix(core): update 2018-12-09 16:48:33 +01:00
2dcbca2362 3.1.13 2018-12-09 16:26:28 +01:00
bd63194f4b fix(core): update 2018-12-09 16:26:28 +01:00
2763fdef5f 3.1.12 2018-12-09 15:53:39 +01:00
bbedde01b9 fix(core): update 2018-12-09 15:53:38 +01:00
f26606f757 3.1.11 2018-12-09 15:22:20 +01:00
99b03aa796 fix(core): update 2018-12-09 15:22:20 +01:00
f30dd3da65 3.1.10 2018-12-09 14:59:51 +01:00
d4decddb4b fix(core): update 2018-12-09 14:59:51 +01:00
5c2880da1a 3.1.9 2018-12-09 14:53:44 +01:00
bfffc5b130 3.1.8 2018-12-09 14:39:25 +01:00
8900a13c6b fix(core): update 2018-12-09 14:39:24 +01:00
d42acf737f 3.1.7 2018-12-09 02:51:04 +01:00
77e3b2912d fix(core): update 2018-12-09 02:51:03 +01:00
103e470eb4 3.1.6 2018-12-09 02:50:00 +01:00
74c1324e55 fix(core): update 2018-12-09 02:50:00 +01:00
a1876963a8 3.1.5 2018-11-28 21:06:12 +01:00
5d88e25c99 fix(dependencies): update 2018-11-28 21:06:12 +01:00
b3c47546e2 3.1.4 2018-11-26 18:01:55 +01:00
6316e81958 fix(core): update 2018-11-26 18:01:54 +01:00
ff10afbee4 3.1.3 2018-11-24 15:12:55 +01:00
9dbfa77084 fix(ci): remove npmts build dependency 2018-11-24 15:12:55 +01:00
46dbd61d89 3.1.2 2018-11-24 15:10:56 +01:00
713df1867a fix(core): update 2018-11-24 15:10:55 +01:00
23886c1ed3 3.1.1 2018-11-24 15:08:08 +01:00
0c46b627be fix(core): update 2018-11-24 15:08:07 +01:00
622ccd8dd9 3.1.0 2018-11-24 15:00:19 +01:00
0079addfc5 feat(logging): use smartlog 2018-11-24 15:00:19 +01:00
8604c63d37 3.0.59 2018-09-22 15:18:21 +02:00
db0b38bd7b fix(cli): update cli files to be in line with gitzone cli template 2018-09-22 15:18:21 +02:00
edde87b6be 3.0.58 2018-09-22 14:36:26 +02:00
5085d664cb fix(fix request package usage): update 2018-09-22 14:36:25 +02:00
5d468fc840 3.0.57 2018-09-22 14:13:26 +02:00
e2ac6cdcc9 fix(dependencies): update 2018-09-22 14:13:25 +02:00
fcd04415be 3.0.56 2018-07-16 00:04:24 +02:00
1fd1899099 fix(ci): update to latest standards 2018-07-16 00:04:24 +02:00
7df7f882d1 3.0.55 2018-07-16 00:02:30 +02:00
348b4d60fd fix(security): snyk 2018-07-16 00:02:29 +02:00
74 changed files with 7862 additions and 3844 deletions

View 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

View 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

21
.gitignore vendored
View File

@@ -1,7 +1,20 @@
dist/ .nogit/
node_modules/
# artifacts
coverage/ coverage/
public/ public/
config.json pages/
# installs
node_modules/
# caches
.yarn/ .yarn/
.npmci_cache .cache/
.rpt2_cache
# builds
dist/
dist_*/
# custom

View File

@@ -1,130 +0,0 @@
# gitzone standard
image: hosttoday/ht-docker-node:npmci
cache:
paths:
- .yarn/
key: "$CI_BUILD_STAGE"
stages:
- security
- test
- release
- metadata
# ====================
# security stage
# ====================
mirror:
stage: security
script:
- npmci git mirror
tags:
- docker
- notpriv
snyk:
stage: security
script:
- npmci command yarn global add snyk
- npmci command yarn install --ignore-scripts
- npmci command snyk test
tags:
- docker
- notpriv
# ====================
# test stage
# ====================
testLEGACY:
stage: test
script:
- npmci node install legacy
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
allow_failure: true
testLTS:
stage: test
script:
- npmci node install lts
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
testSTABLE:
stage: test
script:
- npmci node install stable
- npmci npm install
- npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/
tags:
- docker
- notpriv
release:
stage: release
script:
- npmci node install stable
- npmci npm publish
only:
- tags
tags:
- docker
- notpriv
# ====================
# metadata stage
# ====================
codequality:
stage: metadata
image: docker:stable
allow_failure: true
services:
- docker:stable-dind
script:
- export SP_VERSION=$(echo "$CI_SERVER_VERSION" | sed 's/^\([0-9]*\)\.\([0-9]*\).*/\1-\2-stable/')
- docker run
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
"registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
artifacts:
paths: [codeclimate.json]
tags:
- docker
- priv
trigger:
stage: metadata
script:
- npmci trigger
only:
- tags
tags:
- docker
- notpriv
pages:
image: hosttoday/ht-docker-node:npmci
stage: metadata
script:
- npmci command yarn global add npmpage
- npmci command npmpage
tags:
- docker
- notpriv
only:
- tags
artifacts:
expire_in: 1 week
paths:
- public

28
.snyk
View File

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

11
.vscode/launch.json vendored Normal file
View 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
View 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
View 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
View 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
View 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);

View File

View File

@@ -1,17 +1,22 @@
{ {
"npmts":{ "npmci": {
"mode":"default", "npmGlobalTools": [],
"coverageTreshold": "70", "npmAccessLevel": "public",
"cli": true "npmRegistryUrl": "registry.npmjs.org"
}, },
"npmci": { "npmdocker": {
"npmGlobalTools": [ "baseImage": "hosttoday/ht-docker-node:npmci",
"@gitzone/npmts" "command": "npmci test stable"
], },
"npmAccessLevel": "public" "gitzone": {
}, "projectType": "npm",
"npmdocker":{ "module": {
"baseImage":"hosttoday/ht-docker-node:npmci", "githost": "gitlab.com",
"command": "npmci test stable" "gitscope": "ship.zone",
"gitrepo": "npmci",
"description": "node and docker in gitlab ci on steroids",
"npmPackagename": "@ship.zone/npmci",
"license": "MIT"
} }
}
} }

2500
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,19 @@
{ {
"name": "@shipzone/npmci", "name": "@ship.zone/npmci",
"version": "3.0.54", "version": "4.1.29",
"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) && tsrun test/test.ts", "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,33 +26,52 @@
}, },
"homepage": "https://gitlab.com/gitzone/npmci#README", "homepage": "https://gitlab.com/gitzone/npmci#README",
"devDependencies": { "devDependencies": {
"@gitzone/tsrun": "^1.1.9", "@gitzone/tsbuild": "^2.1.66",
"@pushrocks/tapbundle": "^3.0.1" "@gitzone/tsrun": "^1.2.44",
"@gitzone/tstest": "^1.0.77",
"@push.rocks/tapbundle": "^5.0.15",
"@types/node": "^20.5.4"
}, },
"dependencies": { "dependencies": {
"@pushrocks/smartcli": "^3.0.2", "@api.global/typedrequest": "^3.0.1",
"@pushrocks/smartdelay": "^2.0.1", "@push.rocks/lik": "^6.0.5",
"@pushrocks/smartfile": "^6.0.3", "@push.rocks/npmextra": "^4.0.0",
"@pushrocks/smartpromise": "^2.0.5", "@push.rocks/projectinfo": "^5.0.2",
"@types/lodash": "^4.14.112", "@push.rocks/qenv": "^6.0.2",
"@types/shelljs": "^0.8.0", "@push.rocks/smartanalytics": "^2.0.15",
"@types/through2": "^2.0.33", "@push.rocks/smartcli": "^4.0.8",
"beautylog": "^6.1.10", "@push.rocks/smartdelay": "^3.0.5",
"cflare": "^1.0.5", "@push.rocks/smartenv": "^5.0.5",
"lik": "^2.0.5", "@push.rocks/smartfile": "^10.0.30",
"lodash": "^4.17.10", "@push.rocks/smartgit": "^3.0.1",
"npmextra": "^2.0.9", "@push.rocks/smartlog": "^3.0.3",
"projectinfo": "^3.0.4", "@push.rocks/smartlog-destination-local": "^9.0.0",
"request": "^2.87.0", "@push.rocks/smartobject": "^1.0.12",
"shelljs": "^0.8.2", "@push.rocks/smartpath": "^5.0.11",
"smartanalytics": "^2.0.9", "@push.rocks/smartpromise": "^4.0.2",
"smartparam": "^1.0.2", "@push.rocks/smartrequest": "^2.0.18",
"smartshell": "^1.0.19", "@push.rocks/smartshell": "^3.0.3",
"smartsocket": "^1.1.19", "@push.rocks/smartsocket": "^2.0.22",
"smartssh": "^1.2.2", "@push.rocks/smartssh": "^2.0.1",
"smartstring": "^2.0.28", "@push.rocks/smartstring": "^4.0.8",
"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"
}, },
"private": false "files": [
"ts/**/*",
"ts_web/**/*",
"dist/**/*",
"dist_*/**/*",
"dist_ts/**/*",
"dist_ts_web/**/*",
"assets/**/*",
"cli.js",
"npmextra.json",
"readme.md"
],
"browserslist": [
"last 1 chrome versions"
]
} }

5855
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,25 +1,26 @@
# 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)
[![npm](https://shipzone.gitlab.io/assets/repo-button-npm.svg)](https://www.npmjs.com/package/@shipzone/npmci) * [gitlab.com (source)](https://gitlab.com/shipzone/npmci)
[![git](https://shipzone.gitlab.io/assets/repo-button-git.svg)](https://GitLab.com/shipzone/npmci) * [github.com (source mirror)](https://github.com/shipzone/npmci)
[![git](https://shipzone.gitlab.io/assets/repo-button-mirror.svg)](https://github.com/shipzone/npmci) * [docs (typedoc)](https://shipzone.gitlab.io/npmci/)
[![docs](https://shipzone.gitlab.io/assets/repo-button-docs.svg)](https://shipzone.gitlab.io/npmci/)
## Status for master ## Status for master
[![build status](https://GitLab.com/shipzone/npmci/badges/master/build.svg)](https://GitLab.com/shipzone/npmci/commits/master) Status Category | Status Badge
[![coverage report](https://GitLab.com/shipzone/npmci/badges/master/coverage.svg)](https://GitLab.com/shipzone/npmci/commits/master) -- | --
[![npm downloads per month](https://img.shields.io/npm/dm/npmci.svg)](https://www.npmjs.com/package/@shipzone/npmci) GitLab Pipelines | [![pipeline status](https://gitlab.com/shipzone/npmci/badges/master/pipeline.svg)](https://lossless.cloud)
[![Dependency Status](https://david-dm.org/shipzone/npmci.svg)](https://david-dm.org/shipzone/npmci) GitLab Pipline Test Coverage | [![coverage report](https://gitlab.com/shipzone/npmci/badges/master/coverage.svg)](https://lossless.cloud)
[![bitHound Dependencies](https://www.bithound.io/github/shipzone/npmci/badges/dependencies.svg)](https://www.bithound.io/github/shipzone/npmci/master/dependencies/npm) npm | [![npm downloads per month](https://badgen.net/npm/dy/@shipzone/npmci)](https://lossless.cloud)
[![bitHound Code](https://www.bithound.io/github/shipzone/npmci/badges/code.svg)](https://www.bithound.io/github/shipzone/npmci) Snyk | [![Known Vulnerabilities](https://badgen.net/snyk/shipzone/npmci)](https://lossless.cloud)
[![TypeScript](https://img.shields.io/badge/TypeScript-2.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/) TypeScript Support | [![TypeScript](https://badgen.net/badge/TypeScript/>=%203.x/blue?icon=typescript)](https://lossless.cloud)
[![node](https://img.shields.io/badge/node->=%206.x.x-blue.svg)](https://nodejs.org/dist/latest-v6.x/docs/api/) node Support | [![node](https://img.shields.io/badge/node->=%2010.x.x-blue.svg)](https://nodejs.org/dist/latest-v10.x/docs/api/)
[![JavaScript Style Guide](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com/) Code Style | [![Code Style](https://badgen.net/badge/style/prettier/purple)](https://lossless.cloud)
PackagePhobia (total standalone install weight) | [![PackagePhobia](https://badgen.net/packagephobia/install/@shipzone/npmci)](https://lossless.cloud)
PackagePhobia (package size on registry) | [![PackagePhobia](https://badgen.net/packagephobia/publish/@shipzone/npmci)](https://lossless.cloud)
BundlePhobia (total size when bundled) | [![BundlePhobia](https://badgen.net/bundlephobia/minzip/@shipzone/npmci)](https://lossless.cloud)
## Usage ## Usage
@@ -29,9 +30,9 @@ npmci is designed to work in docker CI environments. The following docker images
Docker Hub: Docker Hub:
* [hosttoday/ht-docker-node:npmci](https://hub.docker.com/r/hosttoday/ht-docker-node/) - [hosttoday/ht-docker-node:npmci](https://hub.docker.com/r/hosttoday/ht-docker-node/)
has LTS node version and npmci preinstalled. has LTS node version and npmci preinstalled.
* [hosttoday/ht-docker-dbase](https://hub.docker.com/r/hosttoday/ht-docker-dbase/) - [hosttoday/ht-docker-dbase](https://hub.docker.com/r/hosttoday/ht-docker-dbase/)
based on docker:git, can be used to build docker images in conjunction with docker:dind 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: npmci can be called from commandline and handle a lot of tasks durug ci:
@@ -71,7 +72,7 @@ npmci publish npm # will look vor $NPMCI_TOKEN_NPM env var and push any module i
npmci publish docker npmci publish docker
# trigger webhooks # trigger webhooks
npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name npmci trigger # will look for NPMCI_TRIGGER_1 to NPMCI_TRIGGER_100 in form domain|id|token|ref|name
``` ```
## Configuration ## Configuration
@@ -98,9 +99,12 @@ For further information read the linked docs at the top of this README.
Use TypeScript for best in class instellisense. Use TypeScript for best in class instellisense.
For further information read the linked docs at the top of this README. ## Contribution
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh) 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). :)
> | By using this npm module you agree to our [privacy policy](https://lossless.gmbH/privacy.html)
[![repo-footer](https://shipzone.gitlab.io/assets/repo-footer.svg)](https://push.rocks) 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)

View File

@@ -0,0 +1,2 @@
FROM mygroup/myrepo:sometag2
RUN apt-get update

26
test/test.cloudly.ts Normal file
View File

@@ -0,0 +1,26 @@
process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';
import { tap, expect } from '@push.rocks/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();

View File

@@ -1,8 +1,9 @@
import { tap, expect } from '@pushrocks/tapbundle'; import { tap, expect } from '@push.rocks/tapbundle';
import * as path from 'path'; import * as path from 'path';
import * as smartpath from '@push.rocks/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,83 @@ 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 import type * as npmciTypes from '../ts/index.js';
import '../ts/index'; const npmci = await import('../ts/index.js');
import npmciModDocker = require('../ts/mod_docker/index');
import npmciModNpm = require('../ts/mod_npm/index');
import npmciModNode = require('../ts/mod_node/index');
import npmciModSsh = require('../ts/mod_ssh/index');
import npmciEnv = require('../ts/npmci.env');
// ====== // ======
// Docker // Docker
// ====== // ======
let dockerfile1: npmciModDocker.Dockerfile; let dockerfile1: npmciTypes.Dockerfile;
let dockerfile2: npmciModDocker.Dockerfile; let dockerfile2: npmciTypes.Dockerfile;
let sortableArray: npmciModDocker.Dockerfile[]; let sortableArray: npmciTypes.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 }); await npmciInstance.start();
expect(dockerfile1.version).to.equal('latest'); dockerfile1 = new npmci.Dockerfile(npmciInstance.dockerManager, {
return expect(dockerfile2.version).to.equal('sometag1'); filePath: './Dockerfile',
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() await npmciInstance.start();
.then(async (readDockerfilesArrayArg: npmciModDocker.Dockerfile[]) => { return npmci.Dockerfile.readDockerfiles(npmciInstance.dockerManager).then(
async (readDockerfilesArrayArg: npmciTypes.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: npmciTypes.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'] await npmciInstance.start();
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'] await npmciInstance.start();
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'] await npmciInstance.start();
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'] await npmciInstance.start();
return npmciInstance.dockerManager.handleCli({
_: ['docker', 'login'],
}); });
}); });
@@ -86,8 +100,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 +110,16 @@ 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.start();
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
View File

@@ -0,0 +1,8 @@
/**
* autocreated commitinfo by @pushrocks/commitinfo
*/
export const commitinfo = {
name: '@ship.zone/npmci',
version: '4.1.29',
description: 'node and docker in gitlab ci on steroids'
}

View 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,
});
}
}

View File

@@ -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 () => {
await npmciInstance.start();
};

View File

@@ -0,0 +1,67 @@
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 dockerImageTag = await this.npmciRef.npmciConfig.kvStorage.readKey('latestPushedDockerTag');
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');
}
}

View File

@@ -0,0 +1 @@
export * from '../npmci.plugins.js';

190
ts/manager.docker/index.ts Normal file
View 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.smartobject.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;
}
}

View File

@@ -0,0 +1,336 @@
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,
});
await this.npmciDockerManagerRef.npmciRef.npmciConfig.kvStorage.writeKey('latestPushedDockerTag', this.pushTag)
}
/**
* 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;
}
}

View 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}!`);
}
}

View File

@@ -0,0 +1,28 @@
import { logger } from '../npmci.logging.js';
import * as plugins from './mod.plugins.js';
import { DockerRegistry } from './mod.classes.dockerregistry.js';
export class RegistryStorage {
objectMap = new plugins.lik.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!');
}
}

View 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';

View File

@@ -0,0 +1 @@
export * from '../npmci.plugins.js';

71
ts/manager.git/index.ts Normal file
View 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);
}
};
}

View File

@@ -0,0 +1 @@
export * from '../npmci.plugins.js';

View 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
View 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.smartobject.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.smartobject.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');
}
}

View File

@@ -0,0 +1 @@
export * from '../npmci.plugins.js';

View File

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

View File

@@ -1 +1 @@
export * from '../npmci.plugins'; export * from '../npmci.plugins.js';

View File

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

View File

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

View File

@@ -1,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 = '';

View File

@@ -1 +1 @@
export * from '../npmci.plugins'; export * from '../npmci.plugins.js';

View File

@@ -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);
};

View File

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

View File

@@ -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}!`);
}
}

View File

@@ -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!');
}
}

View File

@@ -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.smartpromise.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;
};

View File

@@ -1 +0,0 @@
export * from '../npmci.plugins';

View File

@@ -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);
}
};

View File

@@ -1 +0,0 @@
export * from '../npmci.plugins';

View File

@@ -1,70 +0,0 @@
import * as plugins from '../npmci.plugins';
import * as paths from '../npmci.paths';
import * as npmciConfig from '../npmci.config';
import { bash, bashNoError, nvmAvailable } from '../npmci.bash';
/**
* handle cli input
* @param argvArg
*/
export let handleCli = async argvArg => {
if (argvArg._.length >= 3) {
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 = '10';
} else if (versionArg === 'lts') {
version = '8';
} else if (versionArg === 'legacy') {
version = '9';
} 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');
await bash(`npm config set cache ${paths.NpmciCacheDir} --global `);
// lets look for further config
await npmciConfig.getConfig().then(async configArg => {
plugins.beautylog.log('Now checking for needed global npm tools...');
for (let npmTool of configArg.npmGlobalTools) {
plugins.beautylog.info(`Checking for global "${npmTool}"`);
let whichOutput: string = await bashNoError(`which ${npmTool}`);
let toolAvailable: boolean = !(/not\sfound/.test(whichOutput) || whichOutput === '');
if (toolAvailable) {
plugins.beautylog.log(`Tool ${npmTool} is available`);
} else {
plugins.beautylog.info(`globally installing ${npmTool} from npm`);
await bash(`npm install ${npmTool} -q -g`);
}
}
plugins.beautylog.success('all global npm tools specified in npmextra.json are now available!');
});
};

View File

@@ -1,100 +0,0 @@
import * as plugins from './mod.plugins';
import * as configModule from '../npmci.config';
import { bash, bashNoError, nvmAvailable } from '../npmci.bash';
/**
* handle cli input
* @param argvArg
*/
export let handleCli = async argvArg => {
if (argvArg._.length >= 2) {
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}`;
}
// -> preparing
plugins.beautylog.log(`now preparing environment:`);
prepare();
await bash(`npm -v`);
// -> build it
await bash(`npm install`);
await bash(`npm run build`);
plugins.beautylog.success(`Nice!!! The build for the publication was successfull!`);
plugins.beautylog.log(`Lets clean up so we don't publish any packages that don't belong to us:`);
// -> clean up before we publish stuff
await bashNoError(`rm -r ./.npmci_cache`);
await bash(`rm -r ./node_modules`);
plugins.beautylog.success(`Cleaned up!:`);
// -> publish it
plugins.beautylog.log(`now invoking npm to publish the package!`);
await bash(`npm publish ${npmAccessCliString}`);
plugins.beautylog.success(`Package was successfully published!`);
};
let install = async (): Promise<void> => {
plugins.beautylog.info('now installing dependencies:');
await bash('npm install');
};
export let test = async (): Promise<void> => {
plugins.beautylog.info('now starting tests:');
await bash('npm test');
};

View File

@@ -1 +0,0 @@
export * from '../npmci.plugins';

24
ts/mod_precheck/index.ts Normal file
View 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);
}
};

View File

@@ -0,0 +1 @@
export * from '../npmci.plugins.js';

View File

@@ -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 !== '##';
}; };
@@ -30,31 +31,31 @@ let notUndefined = (stringArg: string) => {
*/ */
export let prepare = async () => { export let prepare = async () => {
sshInstance = new plugins.smartssh.SshInstance(); // init ssh instance sshInstance = new plugins.smartssh.SshInstance(); // init ssh instance
plugins.smartparam.forEachMinimatch(process.env, 'NPMCI_SSHKEY_*', evaluateSshEnv); plugins.smartobject.forEachMinimatch(process.env, 'NPMCI_SSHKEY_*', evaluateSshEnv);
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];
} }

View File

@@ -1 +1 @@
export * from '../npmci.plugins'; export * from '../npmci.plugins.js';

View File

@@ -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.smartobject.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',
},
]
);
}; };

View File

@@ -1 +1 @@
export * from '../npmci.plugins'; export * from '../npmci.plugins.js';

View File

@@ -1,35 +1,34 @@
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 smartpromise from '@pushrocks/smartpromise';
/** /**
* wether nvm is available or not * wether nvm is available or not
*/ */
export let nvmAvailable = smartpromise.defer<boolean>(); export let nvmAvailable = plugins.smartpromise.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);
@@ -68,24 +67,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
View 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',
});
}
public async start() {
this.cloudlyConnector = new CloudlyConnector(this);
this.npmciEnv = new NpmciEnv(this);
this.npmciInfo = new NpmciInfo(this);
await this.npmciInfo.printToConsole();
this.npmciCli = new NpmciCli(this);
this.npmciConfig = new NpmciConfig(this);
await this.npmciConfig.init();
// 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);
this.npmciCli.startParse();
}
}

View 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();
};
}

View File

@@ -0,0 +1,78 @@
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;
}
public async init() {
this.npmciNpmextra = new plugins.npmextra.Npmextra(paths.cwd);
this.kvStorage = new plugins.npmextra.KeyValueStore(
'userHomeDir',
`${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: await this.npmciQenv.getEnvVarOnDemand('NPMCI_URL_CLOUDLY'),
};
this.configObject = this.npmciNpmextra.dataFor<INpmciOptions>('npmci', this.configObject);
}
public getConfig(): INpmciOptions {
return this.configObject;
}
}

View 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);
}
}

View 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 async printToConsole() {
await logger.log('info', `npmci version: ${this.projectInfo.version}`);
}
}

View File

@@ -1,123 +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';
const npmciSmartcli = new plugins.smartcli.Smartcli();
npmciSmartcli.addVersion(npmciInfo.version);
// clean
npmciSmartcli.addCommand('clean').subscribe(
async argv => {
let modClean = await npmciMods.modClean.load();
await modClean.clean();
},
err => {
console.log(err);
process.exit(1);
}
);
// cloudflare
npmciSmartcli.addCommand('cloudflare').subscribe(
async argvArg => {
let modPurge = await npmciMods.modCloudflare.load();
await modPurge.handleCli(argvArg);
},
err => {
console.log(err);
}
);
// command
npmciSmartcli.addCommand('command').subscribe(
async argv => {
let modCommand = await npmciMods.modCommand.load();
await modCommand.command();
},
err => {
console.log(err);
process.exit(1);
}
);
// command
npmciSmartcli.addCommand('git').subscribe(
async argvArg => {
let modGit = await npmciMods.modGit.load();
await modGit.handleCli(argvArg);
},
err => {
console.log(err);
process.exit(1);
}
);
// build
npmciSmartcli.addCommand('docker').subscribe(
async argvArg => {
let modDocker = await npmciMods.modDocker.load();
await modDocker.handleCli(argvArg);
},
err => {
console.log(err);
process.exit(1);
}
);
// node
npmciSmartcli.addCommand('node').subscribe(
async argvArg => {
let modNode = await npmciMods.modNode.load();
await modNode.handleCli(argvArg);
},
err => {
console.log(err);
process.exit(1);
}
);
// npm
npmciSmartcli.addCommand('npm').subscribe(
async argvArg => {
let modNpm = await npmciMods.modNpm.load();
await modNpm.handleCli(argvArg);
},
err => {
console.log(err);
}
);
// trigger
npmciSmartcli.addCommand('ssh').subscribe(
async argvArg => {
let modSsh = await npmciMods.modSsh.load();
await modSsh.handleCli(argvArg);
},
err => {
console.log(err);
process.exit(1);
}
);
// trigger
npmciSmartcli.addCommand('trigger').subscribe(
async argv => {
let modTrigger = await npmciMods.modTrigger.load();
await modTrigger.trigger();
},
err => {
console.log(err);
process.exit(1);
}
);
npmciSmartcli.startParse();

View File

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

View File

@@ -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
View 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());

View File

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

View File

@@ -1,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...');
});
};

View File

@@ -1,9 +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 let NpmciCacheDir = plugins.path.join(cwd, './.npmci_cache'); );
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');

View File

@@ -1,18 +1,67 @@
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 let request = require('request'); // @apiglobal
export import smartcli = require('@pushrocks/smartcli'); import * as typedrequest from '@api.global/typedrequest';
export import smartdelay = require('@pushrocks/smartdelay');
export import smartfile = require('@pushrocks/smartfile'); export { typedrequest };
export import shelljs = require('shelljs');
export import smartparam = require('smartparam'); // @servezone
export import smartpromise = require('@pushrocks/smartpromise'); import * as servezoneInterfaces from '@servezone/interfaces';
export import smartshell = require('smartshell');
export import smartsocket = require('smartsocket'); export { servezoneInterfaces };
export import smartsystem = require('smartsystem');
export import smartssh = require('smartssh'); // @push.rocks
export import smartstring = require('smartstring'); import * as lik from '@push.rocks/lik';
export import through2 = require('through2'); import * as npmextra from '@push.rocks/npmextra';
import * as projectinfo from '@push.rocks/projectinfo';
import * as qenv from '@push.rocks/qenv';
import * as smartanalytics from '@push.rocks/smartanalytics';
import * as smartdelay from '@push.rocks/smartdelay';
import * as smartfile from '@push.rocks/smartfile';
import * as smartcli from '@push.rocks/smartcli';
import * as smartgit from '@push.rocks/smartgit';
import * as smartlog from '@push.rocks/smartlog';
import * as smartlogDestinationLocal from '@push.rocks/smartlog-destination-local';
import * as smartobject from '@push.rocks/smartobject';
import * as smartpath from '@push.rocks/smartpath';
import * as smartpromise from '@push.rocks/smartpromise';
import * as smartrequest from '@push.rocks/smartrequest';
import * as smartshell from '@push.rocks/smartshell';
import * as smartsocket from '@push.rocks/smartsocket';
import * as smartssh from '@push.rocks/smartssh';
import * as smartstring from '@push.rocks/smartstring';
export {
lik,
npmextra,
projectinfo,
qenv,
smartanalytics,
smartdelay,
smartfile,
smartgit,
smartcli,
smartlog,
smartlogDestinationLocal,
smartobject,
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
View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"experimentalDecorators": true,
"useDefineForClassFields": false,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "nodenext",
"esModuleInterop": true
}
}

View File

@@ -1,3 +0,0 @@
{
"extends": "tslint-config-standard"
}