@soft-artel/ci 1.3.15 → 1.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/incrementBuild.d.ts +3 -0
- package/incrementBuild.d.ts.map +1 -0
- package/incrementBuild.js +44 -0
- package/incrementBuild.js.map +1 -0
- package/k8s/App.d.ts +22 -0
- package/k8s/App.d.ts.map +1 -0
- package/k8s/App.js +150 -0
- package/k8s/App.js.map +1 -0
- package/k8s/DockerImage.d.ts +15 -0
- package/k8s/DockerImage.d.ts.map +1 -0
- package/k8s/DockerImage.js +112 -0
- package/k8s/DockerImage.js.map +1 -0
- package/k8s/Node.d.ts +17 -0
- package/k8s/Node.d.ts.map +1 -0
- package/k8s/Node.js +103 -0
- package/k8s/Node.js.map +1 -0
- package/k8s-build.d.ts +3 -0
- package/k8s-build.d.ts.map +1 -0
- package/k8s-build.js +125 -0
- package/k8s-build.js.map +1 -0
- package/k8s-deploy.d.ts +3 -0
- package/k8s-deploy.d.ts.map +1 -0
- package/k8s-deploy.js +124 -0
- package/k8s-deploy.js.map +1 -0
- package/libs/Exception.d.ts +5 -0
- package/libs/Exception.d.ts.map +1 -0
- package/libs/Exception.js +13 -0
- package/libs/Exception.js.map +1 -0
- package/libs/Git.d.ts +44 -0
- package/libs/Git.d.ts.map +1 -0
- package/libs/Git.js +161 -0
- package/libs/Git.js.map +1 -0
- package/libs/Gitlab.d.ts +12 -0
- package/libs/Gitlab.d.ts.map +1 -0
- package/libs/Gitlab.js +78 -0
- package/libs/Gitlab.js.map +1 -0
- package/libs/Jira.d.ts +31 -0
- package/libs/Jira.d.ts.map +1 -0
- package/libs/Jira.js +157 -0
- package/libs/Jira.js.map +1 -0
- package/libs/Project.d.ts +39 -0
- package/libs/Project.d.ts.map +1 -0
- package/libs/Project.js +177 -0
- package/libs/Project.js.map +1 -0
- package/libs/Reporter.d.ts +34 -0
- package/libs/Reporter.d.ts.map +1 -0
- package/libs/Reporter.js +131 -0
- package/libs/Reporter.js.map +1 -0
- package/libs/Shell.d.ts +39 -0
- package/libs/Shell.d.ts.map +1 -0
- package/libs/Shell.js +107 -0
- package/libs/Shell.js.map +1 -0
- package/libs/helpers.d.ts +29 -0
- package/libs/helpers.d.ts.map +1 -0
- package/libs/helpers.js +101 -0
- package/libs/helpers.js.map +1 -0
- package/libs/prototype.d.ts +9 -0
- package/libs/prototype.d.ts.map +1 -0
- package/libs/prototype.js +186 -0
- package/libs/prototype.js.map +1 -0
- package/package.json +4 -3
- package/xcode.d.ts +3 -0
- package/xcode.d.ts.map +1 -0
- package/xcode.js +163 -0
- package/xcode.js.map +1 -0
- package/.env +0 -21
- package/.eslintcache +0 -1
- package/.eslintignore +0 -4
- package/.eslintrc +0 -246
- package/.gitlab-ci.yml +0 -12
- package/_publish.sh +0 -24
- package/k8s/App.ts +0 -200
- package/k8s/DockerImage.ts +0 -147
- package/k8s/Node.ts +0 -119
- package/k8s-build.ts +0 -175
- package/k8s-deploy.ts +0 -174
- package/libs/Exception.ts +0 -19
- package/libs/Git.ts +0 -199
- package/libs/Gitlab.ts +0 -86
- package/libs/Jira.ts +0 -239
- package/libs/Project.ts +0 -215
- package/libs/Reporter.ts +0 -181
- package/libs/Shell.ts +0 -119
- package/libs/helpers.ts +0 -114
- package/libs/prototype.ts +0 -313
- package/tsconfig.json +0 -24
- package/upd_pkg.ts +0 -21
- package/xcode.ts +0 -226
package/k8s/App.ts
DELETED
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import '../libs/prototype';
|
|
2
|
-
|
|
3
|
-
import Mustache from 'mustache';
|
|
4
|
-
import yaml from 'js-yaml';
|
|
5
|
-
import { promises as asyncFs } from 'fs';
|
|
6
|
-
|
|
7
|
-
import Shell from '../libs/Shell';
|
|
8
|
-
import { log } from '../libs/helpers';
|
|
9
|
-
import { Project } from '../libs/Project';
|
|
10
|
-
import { Exception } from '../libs/Exception';
|
|
11
|
-
import { DockerImage } from './DockerImage';
|
|
12
|
-
|
|
13
|
-
// ================================================================================================
|
|
14
|
-
|
|
15
|
-
export interface Config {
|
|
16
|
-
|
|
17
|
-
appFile: string;
|
|
18
|
-
|
|
19
|
-
sharedPaths?: string[];
|
|
20
|
-
ignorePaths?: string[];
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// ================================================================================================
|
|
25
|
-
|
|
26
|
-
export class App{
|
|
27
|
-
|
|
28
|
-
group = '';
|
|
29
|
-
app = '';
|
|
30
|
-
|
|
31
|
-
name = '';
|
|
32
|
-
path = '';
|
|
33
|
-
|
|
34
|
-
$pathComp: string[] = [ './' ];
|
|
35
|
-
|
|
36
|
-
// ----------
|
|
37
|
-
|
|
38
|
-
constructor(path: string = ''){
|
|
39
|
-
const pathComp = path.split('/');
|
|
40
|
-
|
|
41
|
-
if(pathComp.length > 1){
|
|
42
|
-
|
|
43
|
-
this.group = pathComp[0];
|
|
44
|
-
this.app = pathComp[1];
|
|
45
|
-
this.name = `${this.group}-${this.app}`;
|
|
46
|
-
this.path = path;
|
|
47
|
-
|
|
48
|
-
this.$pathComp.push(`./${ this.group }/`);
|
|
49
|
-
this.$pathComp.push(`./${ this.path }/`);
|
|
50
|
-
|
|
51
|
-
}else{
|
|
52
|
-
this.app = path;
|
|
53
|
-
this.name = path;
|
|
54
|
-
this.path = '';
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ----------
|
|
59
|
-
|
|
60
|
-
async writeManifest(prj: Project, image: DockerImage){
|
|
61
|
-
|
|
62
|
-
const k8s_tpl_fileName = 'k8s_tpl.yaml';
|
|
63
|
-
const k8s_spec_fileName = 'k8s_spec.json';
|
|
64
|
-
|
|
65
|
-
// 1. Находим шаблон манифеста для app и специфицации ресурсов
|
|
66
|
-
|
|
67
|
-
let k8s_tpl = '';
|
|
68
|
-
const k8s_spec: Record<string, any> = {};
|
|
69
|
-
|
|
70
|
-
for (const path of this.$pathComp) {
|
|
71
|
-
|
|
72
|
-
const k8s_tplFile = await Shell.cat(path + k8s_tpl_fileName, {silent: log.debug, ignoreError:true });
|
|
73
|
-
k8s_tpl = k8s_tplFile && k8s_tplFile !== '' ? k8s_tplFile : k8s_tpl;
|
|
74
|
-
|
|
75
|
-
const k8s_specFile = await Shell.cat(path + k8s_spec_fileName, {silent: log.debug, ignoreError:true });
|
|
76
|
-
if(k8s_specFile && k8s_specFile !== ''){
|
|
77
|
-
try {
|
|
78
|
-
const sObj = JSON.parse(k8s_specFile) as Record<string, any>;
|
|
79
|
-
k8s_spec.mergeFrom(sObj, true);
|
|
80
|
-
} catch(e){
|
|
81
|
-
log.error(e);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if(k8s_tpl.length < 10){
|
|
87
|
-
throw new Exception(`No K8s template [${k8s_tpl_fileName}] found for app:${ this.name }`, this.$pathComp);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
log.dbg(`${this.name} k8s specs`, k8s_spec);
|
|
91
|
-
|
|
92
|
-
// 4.2. Ходим по стейджам, формируем и сохраняем манифесты
|
|
93
|
-
|
|
94
|
-
for (const stage of prj.$stages) {
|
|
95
|
-
|
|
96
|
-
const k8s_data: Record<string, any> = {};
|
|
97
|
-
|
|
98
|
-
k8s_data.stage = stage;
|
|
99
|
-
k8s_data.app = this;
|
|
100
|
-
k8s_data.image = image;
|
|
101
|
-
k8s_data.prj = prj;
|
|
102
|
-
k8s_data.spec = k8s_spec[ stage ] || {};
|
|
103
|
-
|
|
104
|
-
if(!k8s_data.spec.replicas){
|
|
105
|
-
k8s_data.spec.replicas = 1;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// k8s_data.spec.volumeMounts = k8s_data.spec.volumes;
|
|
109
|
-
const manifest = Mustache.render(k8s_tpl, k8s_data);
|
|
110
|
-
|
|
111
|
-
yaml.loadAll(manifest); // Test yaml
|
|
112
|
-
|
|
113
|
-
await Shell.mkdir(`${ prj.rootPath}/_k8s/${stage}`, {ignoreError: false});
|
|
114
|
-
await asyncFs.writeFile(`${ prj.rootPath}/_k8s/${stage}/${this.name}.yml`, manifest);
|
|
115
|
-
|
|
116
|
-
log.dbg(`[${stage}] ${this.name} writed -> ${ prj.rootPath}/_k8s/${stage}/${this.name}.yml `);
|
|
117
|
-
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// ================================================================================================
|
|
124
|
-
|
|
125
|
-
export async function getApps(prj: Project, config: Config, updatedPaths: string[], maxdepth: number = 3, ignore: string[] = ['*/_*', '*/\.*', '*/node_modules*']): Promise<{ apps: Record<string, App>; updated: string[] | undefined }>{
|
|
126
|
-
|
|
127
|
-
Shell.cd(prj.rootPath);
|
|
128
|
-
const appsPaths = await Shell.find(prj.rootPath, config.appFile, maxdepth, ignore);
|
|
129
|
-
|
|
130
|
-
const ignorePaths = [ ...config.ignorePaths || [], ...config.sharedPaths || [] ];
|
|
131
|
-
|
|
132
|
-
const apps: Record<string, App> = {};
|
|
133
|
-
const watchPaths: Record<string, string> = {};
|
|
134
|
-
|
|
135
|
-
for(const file of appsPaths.sort()) {
|
|
136
|
-
const path = file.replace(prj.rootPath+'/', '').replace('/' + config.appFile, '');
|
|
137
|
-
|
|
138
|
-
let skip = false;
|
|
139
|
-
for(const i_path of ignorePaths){
|
|
140
|
-
if(path.includes(i_path)){
|
|
141
|
-
skip = true;
|
|
142
|
-
break;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
if(path === '' || skip){
|
|
146
|
-
continue;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const app = new App(path);
|
|
150
|
-
|
|
151
|
-
if(app.name === config.appFile){
|
|
152
|
-
app.name = prj.name;
|
|
153
|
-
app.app = prj.name;
|
|
154
|
-
app.group = '';
|
|
155
|
-
app.path = '';
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
apps[ app.name ] = app;
|
|
159
|
-
watchPaths[ app.path ] = app.name;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
log.dbg(`Find apps by ${config.appFile}`, Object.keys(apps).sort());
|
|
163
|
-
|
|
164
|
-
const sharedPaths = config.sharedPaths || [];
|
|
165
|
-
|
|
166
|
-
sharedPaths.push('package.json');
|
|
167
|
-
sharedPaths.push('k8s_spec.json');
|
|
168
|
-
sharedPaths.push('k8s_tpl.yaml');
|
|
169
|
-
sharedPaths.push('dockerfile');
|
|
170
|
-
|
|
171
|
-
const watchPathsArr = Object.keys(watchPaths);
|
|
172
|
-
|
|
173
|
-
let appsChanged: Record<string, App> = {};
|
|
174
|
-
|
|
175
|
-
for (const file of updatedPaths) {
|
|
176
|
-
|
|
177
|
-
let allApps = false;
|
|
178
|
-
for(const i_path of sharedPaths){
|
|
179
|
-
if(file.includes(i_path)){
|
|
180
|
-
allApps = true;
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
if(allApps){
|
|
185
|
-
appsChanged = apps;
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
for(const testPath of watchPathsArr){
|
|
190
|
-
const appName = watchPaths[ testPath ];
|
|
191
|
-
if((RegExp(testPath).exec(file)) && apps[ appName ] && appsChanged[ appName ] === undefined){
|
|
192
|
-
appsChanged[ appName ] = apps[ appName ];
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const changed = Object.keys(appsChanged);
|
|
198
|
-
return { apps, updated: changed.length > 0 ? changed : undefined };
|
|
199
|
-
|
|
200
|
-
}
|
package/k8s/DockerImage.ts
DELETED
|
@@ -1,147 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
|
|
3
|
-
import { log, md5, resolvePath } from '../libs/helpers';
|
|
4
|
-
import Shell from '../libs/Shell';
|
|
5
|
-
|
|
6
|
-
const ENV = process.env;
|
|
7
|
-
|
|
8
|
-
// ========================================================
|
|
9
|
-
|
|
10
|
-
type DockerImagePrebuildAction = (img: DockerImage) => void;
|
|
11
|
-
const PREBUILD: Record<string, DockerImagePrebuildAction> = {};
|
|
12
|
-
|
|
13
|
-
export class DockerImage{
|
|
14
|
-
|
|
15
|
-
path = '';
|
|
16
|
-
key = '';
|
|
17
|
-
|
|
18
|
-
srcImage = '';
|
|
19
|
-
|
|
20
|
-
tag = '';
|
|
21
|
-
fullTag = '';
|
|
22
|
-
|
|
23
|
-
$prebuild_typed?: DockerImagePrebuildAction = undefined;
|
|
24
|
-
|
|
25
|
-
// -----------
|
|
26
|
-
|
|
27
|
-
constructor(path: string, ver: string, build: number){
|
|
28
|
-
this.path = resolvePath(path);
|
|
29
|
-
|
|
30
|
-
const dockerfile = fs.readFileSync(this.path + '/dockerfile', 'utf8');
|
|
31
|
-
this.key = md5(dockerfile);
|
|
32
|
-
|
|
33
|
-
const dockerImage = /FROM (.+)/.exec(dockerfile);
|
|
34
|
-
if(!dockerImage || dockerImage.length < 2){
|
|
35
|
-
throw new Error(`Wrong dockerfile format:\n${dockerfile}`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
this.srcImage = dockerImage[1];
|
|
39
|
-
|
|
40
|
-
const dockerName = /#[ ]?IMAGE NAME (.+)/.exec(dockerfile);
|
|
41
|
-
const name = dockerName && dockerName.length > 1 ? dockerName[1] : ENV.CI_PROJECT_NAME || this.key;
|
|
42
|
-
|
|
43
|
-
// api-v1.2:#321
|
|
44
|
-
this.tag = `${name}-v${ver}:${build}`;
|
|
45
|
-
this.fullTag = `${ ENV.CI_REGISTRY_IMAGE }/${ this.tag }`;
|
|
46
|
-
|
|
47
|
-
const dockerType = /#[ ]?IMAGE TYPE (.+)/.exec(dockerfile);
|
|
48
|
-
const type = dockerType && dockerType.length > 1 ? dockerType[1].toLowerCase() : this.srcImage.split(':')[0].toLowerCase();
|
|
49
|
-
|
|
50
|
-
this.$prebuild_typed = PREBUILD[ type ];
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// -----------
|
|
54
|
-
|
|
55
|
-
async prebuild(){
|
|
56
|
-
if(!this.$prebuild_typed){
|
|
57
|
-
throw new Error(`No prebuild action for ${ this.tag }`);
|
|
58
|
-
}
|
|
59
|
-
await this.$prebuild_typed(this);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async build(){
|
|
63
|
-
Shell.cd(this.path);
|
|
64
|
-
log.info(`Build docker image: ${ this.tag }`);
|
|
65
|
-
|
|
66
|
-
await Shell.exec(`docker build --platform amd64 -t ${ this.fullTag } -f ${ this.path }/dockerfile ${ this.path }/.`);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async push(){
|
|
70
|
-
await Shell.execRepeat(`docker login -u ${ ENV.CI_REGISTRY_USER } -p ${ ENV.CI_REGISTRY_PASSWORD } ${ ENV.CI_REGISTRY }`);
|
|
71
|
-
|
|
72
|
-
log.info(`Push docker image: ${ this.tag } to registry`);
|
|
73
|
-
await Shell.execRepeat(`docker push ${ this.fullTag }`);
|
|
74
|
-
|
|
75
|
-
log.dbg(`Clear local docker image: ${ this.tag }`);
|
|
76
|
-
await Shell.exec(`docker rmi -f ${ this.fullTag }`);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ========================================================
|
|
81
|
-
|
|
82
|
-
PREBUILD.nginx = async (img: DockerImage) => {
|
|
83
|
-
Shell.cd(img.path);
|
|
84
|
-
|
|
85
|
-
const mounts = { '/etc/nginx':`${ img.path }/nginx` };
|
|
86
|
-
|
|
87
|
-
log.info(`Test nginx configs`);
|
|
88
|
-
await run(img.srcImage, 'nginx -t', mounts);
|
|
89
|
-
await run('yandex/gixy', 'yandex/gixy /etc/nginx/nginx.conf', mounts);
|
|
90
|
-
|
|
91
|
-
log.info(`Nginx config file:`)
|
|
92
|
-
log.info( await Shell.cat(`${ img.path }/nginx/nginx.conf`) )
|
|
93
|
-
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// ------------
|
|
97
|
-
|
|
98
|
-
PREBUILD.gateway = async (img: DockerImage) => {
|
|
99
|
-
Shell.cd(img.path);
|
|
100
|
-
|
|
101
|
-
const mounts = { '/etc/nginx':`${ img.path }/nginx`, '/etc/certs':`${ img.path }/certs` };
|
|
102
|
-
|
|
103
|
-
log.info(`Test gateway nginx configs`);
|
|
104
|
-
await run(img.srcImage, 'nginx -t', mounts);
|
|
105
|
-
await run('yandex/gixy', 'yandex/gixy /etc/nginx/nginx.conf', mounts);
|
|
106
|
-
|
|
107
|
-
log.info(`Nginx config file:`);
|
|
108
|
-
log.info(await Shell.cat(`${ img.path }/nginx/nginx.conf`))
|
|
109
|
-
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// ------------
|
|
113
|
-
|
|
114
|
-
PREBUILD.spa = async (img: DockerImage) => {
|
|
115
|
-
Shell.cd(img.path);
|
|
116
|
-
await PREBUILD.nginx(img);
|
|
117
|
-
log.info(`Test and Distrib WEB SPA sources`);
|
|
118
|
-
|
|
119
|
-
// ? надо ли собирать веб внутри контейнера?!
|
|
120
|
-
// const mounts = { '/etc/nginx':`${ img.path }/nginx` }
|
|
121
|
-
// await run( img.srcImage, 'nginx -t', mounts );
|
|
122
|
-
|
|
123
|
-
await Shell.exec(`npm run distrib`);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// ------------
|
|
127
|
-
|
|
128
|
-
PREBUILD.node = async (img: DockerImage) => {
|
|
129
|
-
Shell.cd(img.path);
|
|
130
|
-
log.info(`Test and Distrib Node sources`);
|
|
131
|
-
await Shell.exec(`npm run distrib`);
|
|
132
|
-
};
|
|
133
|
-
|
|
134
|
-
// ========================================================
|
|
135
|
-
|
|
136
|
-
async function run(srcImage: string, cmd: string, mnt?: Record<string, string>){
|
|
137
|
-
let extCmd = `docker run --rm`;
|
|
138
|
-
|
|
139
|
-
for (const path in mnt) {
|
|
140
|
-
if(mnt.hasOwnProperty(path)) {
|
|
141
|
-
extCmd += ` -v ${mnt[path]}:${path}`;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
extCmd += ` ${ srcImage } ${ cmd }`;
|
|
146
|
-
await Shell.exec(`${ extCmd }`);
|
|
147
|
-
}
|
package/k8s/Node.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import '../libs/prototype';
|
|
2
|
-
|
|
3
|
-
import yaml from 'js-yaml';
|
|
4
|
-
|
|
5
|
-
import Shell, { ExecOptions } from '../libs/Shell';
|
|
6
|
-
import { log, resolvePath } from '../libs/helpers';
|
|
7
|
-
import { Stage } from '../libs/Project';
|
|
8
|
-
import { Exception } from '../libs/Exception';
|
|
9
|
-
import { Reporter } from '../libs/Reporter';
|
|
10
|
-
|
|
11
|
-
const ENV = process.env;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
// ================================================================================================
|
|
15
|
-
|
|
16
|
-
export class Node{
|
|
17
|
-
|
|
18
|
-
configFile = '';
|
|
19
|
-
namespace = '';
|
|
20
|
-
|
|
21
|
-
// ----------
|
|
22
|
-
|
|
23
|
-
constructor(stage: Stage){
|
|
24
|
-
this.namespace = stage;
|
|
25
|
-
|
|
26
|
-
const configKey = `K8S_${ stage.toUpperCase() }_CONFIG`;
|
|
27
|
-
let configFile = ENV[ configKey ];
|
|
28
|
-
|
|
29
|
-
if(stage !== 'prod' && !configFile){
|
|
30
|
-
configFile = ENV.K8S_STAGES_CONFIG;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if(!configFile){
|
|
34
|
-
throw new Exception(`K8s config file not found: ${ configKey }`);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
this.configFile = resolvePath(configFile) ;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ----------
|
|
41
|
-
|
|
42
|
-
async applyObject(manifestObj: Record<string, any>){
|
|
43
|
-
const manifestYaml = yaml.dump(manifestObj);
|
|
44
|
-
await this.exec(`apply -f -\n${ manifestYaml }`, {silent: false}, 'cat <<EOF | ');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// ----------
|
|
48
|
-
|
|
49
|
-
async apply(manifestFile: string, appName: string): Promise<{valid: boolean; msg: string}>{
|
|
50
|
-
|
|
51
|
-
let status: string;
|
|
52
|
-
|
|
53
|
-
try{
|
|
54
|
-
await this.exec(`apply -f ${ manifestFile } --dry-run=server --validate`);
|
|
55
|
-
status = (await Shell.exec(`cat ${ manifestFile } | grep 'image:'`)).replace('image: ', '').replace(ENV.CI_REGISTRY_IMAGE+'/', '').trim();
|
|
56
|
-
}catch(e){
|
|
57
|
-
log.error(e);
|
|
58
|
-
log.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
|
59
|
-
log.error(`VALIDATE FAIL: ${appName} at ${manifestFile}`);
|
|
60
|
-
log.error(e.message);
|
|
61
|
-
log.error(`${ await Shell.cat(manifestFile) }`);
|
|
62
|
-
log.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
|
63
|
-
|
|
64
|
-
return { valid:false, msg: e.message };
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
try{
|
|
68
|
-
status = await this.exec(`apply -f ${ manifestFile }`);
|
|
69
|
-
await this.exec(`rollout status deploy/${ appName } --watch=true --timeout=300s`);
|
|
70
|
-
|
|
71
|
-
log.info('+++++++++++++++++++++++++++++');
|
|
72
|
-
log.info(`DEPLOYED: ${appName}`);
|
|
73
|
-
log.info(await this.exec(`get pods --no-headers -l app=${appName} -o wide`, { ignoreError:true, silent:true }));
|
|
74
|
-
log.info('+++++++++++++++++++++++++++++');
|
|
75
|
-
|
|
76
|
-
return { valid:true, msg: status };
|
|
77
|
-
|
|
78
|
-
} catch(error){
|
|
79
|
-
log.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
|
80
|
-
log.error(`DEPLOY FAIL: ${appName}`);
|
|
81
|
-
log.error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
|
82
|
-
log.error(await this.exec(`get pods --no-headers -l app=${appName} -o wide`, { ignoreError:true, silent:true }));
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// ----------
|
|
89
|
-
|
|
90
|
-
async status(reporter: Reporter | undefined = undefined, appsOnly: boolean = true): Promise<string[]>{
|
|
91
|
-
|
|
92
|
-
const cmd = `get pods -o=jsonpath='{range .items[*]}{"\\n"}{"<b>"}{.metadata.labels.app}{"</b> "}{range .spec.containers[*]}{.image}{end}{" "}{.metadata.labels.pod-template-hash}{" "}{.status.phase}{end}'`;
|
|
93
|
-
const statusArr = (await this.exec(cmd)).split('\n');
|
|
94
|
-
|
|
95
|
-
const result: string[] = [];
|
|
96
|
-
for (const row of statusArr) {
|
|
97
|
-
if(row.length < 4 || (appsOnly && (RegExp((ENV.CI_REGISTRY_IMAGE || '')).exec(row)) === null)){
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
result.push(row.replace(ENV.CI_REGISTRY_IMAGE+'/', ''));
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
log.info(`K8S Node: ${ this.namespace.toUpperCase() }`, result);
|
|
104
|
-
|
|
105
|
-
if(reporter){
|
|
106
|
-
const msg = `\n<b>${ this.namespace.toUpperCase() }</b> Pods:\n-----------------\n ` + result.join('\n-----------------\n ');
|
|
107
|
-
await reporter.send(msg, '');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return result;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// ----------
|
|
114
|
-
|
|
115
|
-
async exec(cmd: string, opt: ExecOptions | undefined = undefined, cmdPrefix = ''): Promise<string>{
|
|
116
|
-
return Shell.exec(`${cmdPrefix}kubectl --kubeconfig ${ this.configFile } -n ${ this.namespace } ${ cmd }`, opt);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
}
|
package/k8s-build.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import './libs/prototype';
|
|
3
|
-
|
|
4
|
-
import {program, OptionValues} from 'commander';
|
|
5
|
-
|
|
6
|
-
import Shell from './libs/Shell';
|
|
7
|
-
import { Jira } from './libs/Jira';
|
|
8
|
-
import Git from './libs/Git';
|
|
9
|
-
import { Project } from './libs/Project';
|
|
10
|
-
import { Reporter } from './libs/Reporter';
|
|
11
|
-
import { log, checkEnvVars } from './libs/helpers';
|
|
12
|
-
import { DockerImage } from './k8s/DockerImage';
|
|
13
|
-
import { Config, getApps } from './k8s/App';
|
|
14
|
-
|
|
15
|
-
const ENV = process.env;
|
|
16
|
-
|
|
17
|
-
// ========================================================
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
async function main() {
|
|
21
|
-
|
|
22
|
-
program
|
|
23
|
-
.option('--path <project dir>', 'Path to project directory [default - current]')
|
|
24
|
-
|
|
25
|
-
.option('--no-prebuild', 'Skip prebuild phase')
|
|
26
|
-
|
|
27
|
-
.option('--no-changelog', 'Skip create gitlog')
|
|
28
|
-
.option('--no-gittag', 'Skip create and push new git tag')
|
|
29
|
-
.action(
|
|
30
|
-
async () => {
|
|
31
|
-
|
|
32
|
-
let reporter: Reporter | undefined;
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
|
|
36
|
-
// ------------------
|
|
37
|
-
// Инициализируемся
|
|
38
|
-
checkEnvVars(['CI_STAGES', 'REPORTER']);
|
|
39
|
-
|
|
40
|
-
const opts = program.opts() || {};
|
|
41
|
-
const prj = new Project(opts.path);
|
|
42
|
-
|
|
43
|
-
const reporterOpts = JSON.parse(ENV.REPORTER!);
|
|
44
|
-
reporterOpts.postTitle = opts.scheme;
|
|
45
|
-
|
|
46
|
-
const pkg = JSON.parse(await Shell.cat(prj.rootPath +'/package.json') || 'no package.json file!');
|
|
47
|
-
const pkgBuild = Number(pkg.version.split('.')[2]);
|
|
48
|
-
|
|
49
|
-
prj.build = prj.build < pkgBuild ? pkgBuild : prj.build;
|
|
50
|
-
prj.version = `${ pkg.version.split('.').splice(0, 2).join('.') }.${ prj.build }`;
|
|
51
|
-
|
|
52
|
-
if(!pkg.ci){
|
|
53
|
-
throw new Error('No ci config in package.json file!');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
reporter = new Reporter(prj, reporterOpts);
|
|
57
|
-
|
|
58
|
-
const config: Config = pkg.ci;
|
|
59
|
-
|
|
60
|
-
// Запускаем команду
|
|
61
|
-
await run(prj, reporter, opts, config);
|
|
62
|
-
|
|
63
|
-
} catch(e){
|
|
64
|
-
|
|
65
|
-
log.error(e);
|
|
66
|
-
|
|
67
|
-
if(reporter){
|
|
68
|
-
try {
|
|
69
|
-
await reporter.fail(e);
|
|
70
|
-
} catch(e2){
|
|
71
|
-
log.error(e2);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
);
|
|
80
|
-
|
|
81
|
-
await program.parseAsync(process.argv);
|
|
82
|
-
}
|
|
83
|
-
main();
|
|
84
|
-
|
|
85
|
-
// ============================================
|
|
86
|
-
|
|
87
|
-
async function run(prj: Project, reporter: Reporter, opts: OptionValues, config: Config) {
|
|
88
|
-
|
|
89
|
-
// ------------------
|
|
90
|
-
// Инициализируемся
|
|
91
|
-
|
|
92
|
-
const release = opts.changelog ? await Jira.resolve(prj) : { tasks:[], bugs:[], changelog:''};
|
|
93
|
-
|
|
94
|
-
// --build: Build and push docker image to registry
|
|
95
|
-
Shell.cd(prj.rootPath);
|
|
96
|
-
|
|
97
|
-
// -----------------------------
|
|
98
|
-
// 1. Start
|
|
99
|
-
prj.incrementBuild();
|
|
100
|
-
await reporter.startBuild();
|
|
101
|
-
log.info(`1. build ${ prj.stage }`);
|
|
102
|
-
|
|
103
|
-
// -----------------------------
|
|
104
|
-
// 2. Chek updated apps
|
|
105
|
-
await reporter.send(` + Load apps and check updated`);
|
|
106
|
-
log.info(`2. Load apps and check updated`);
|
|
107
|
-
|
|
108
|
-
const updateFiles = await Git.getDiffFiles();
|
|
109
|
-
log.info(`\n\nUPDATED FILES:\n$`, updateFiles);
|
|
110
|
-
|
|
111
|
-
const { apps, updated } = await getApps(prj, config, updateFiles);
|
|
112
|
-
|
|
113
|
-
if(!updated){
|
|
114
|
-
log.info('SKIP BUILD: NO Apps to update!');
|
|
115
|
-
await reporter.send(`⏩ SKIP - no apps to update\n ${ updateFiles.join('\n ')}`, ' ');
|
|
116
|
-
process.exit(0);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
await reporter.send(` ~ <b>${ updated.join('</b>\n ~ <b>') }</b>`);
|
|
120
|
-
|
|
121
|
-
// -----------------------------
|
|
122
|
-
// 4. write k8s manifests!
|
|
123
|
-
await reporter.send(` + Write K8s manifests`);
|
|
124
|
-
log.info(`3. Write K8s manifests`);
|
|
125
|
-
|
|
126
|
-
const image = new DockerImage(prj.rootPath, prj.shortVersion, prj.build);
|
|
127
|
-
log.dbg(`DockerImage`, image);
|
|
128
|
-
|
|
129
|
-
for (const appName of updated) {
|
|
130
|
-
await apps[ appName ]?.writeManifest(prj, image);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// -----------------------------
|
|
134
|
-
// 5. Build
|
|
135
|
-
if(opts.prebuild){
|
|
136
|
-
await reporter.send(` + Test and distrib`);
|
|
137
|
-
log.dbg(`4. Pre build`);
|
|
138
|
-
await image.prebuild();
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
await reporter.send(` + Build docker image: ${ image.tag }`);
|
|
142
|
-
log.dbg(`5. Build`);
|
|
143
|
-
await image.build();
|
|
144
|
-
|
|
145
|
-
await reporter.send(` + Push docker image to registry`);
|
|
146
|
-
log.dbg(`6. Docker push`);
|
|
147
|
-
await image.push();
|
|
148
|
-
|
|
149
|
-
// -----------------------------
|
|
150
|
-
// 5. Save new build to GitLab CI Variable
|
|
151
|
-
|
|
152
|
-
await reporter.send(` + Save current build: ${ prj.build }`);
|
|
153
|
-
log.dbg(`7. Put current build:${ prj.build } to GitLab`);
|
|
154
|
-
await prj.saveGitLabBuild();
|
|
155
|
-
|
|
156
|
-
// -----------------------
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if(opts.changelog){
|
|
160
|
-
await prj.updateChangeLog(release.changelog);
|
|
161
|
-
await reporter.send(` + Update <a href=\"${ prj.url }/-/blob/${ ENV.CI_COMMIT_REF_NAME || 'dev' }/CHANGELOG.md\">changelog</a>.`);
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
await Git.setOrigin();
|
|
165
|
-
await Shell.exec(`git add -A`, { ignoreError: true, silent: false });
|
|
166
|
-
await Shell.exec(`git commit -a -m "v${ prj.version }"`, { ignoreError: true, silent: false });
|
|
167
|
-
await Git.push(ENV.CI_COMMIT_REF_NAME || 'dev');
|
|
168
|
-
|
|
169
|
-
if(opts.gittag){
|
|
170
|
-
await reporter.send(` + Git tag new version`);
|
|
171
|
-
await Git.makeTag(prj.version);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
await reporter.send(`\n✅ <b>${ reporter.title }</b> builded!`, ' ');
|
|
175
|
-
}
|