@soft-artel/ci 1.3.15 → 1.3.16
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/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 +160 -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 +1 -1
- package/upd_pkg.d.ts +3 -0
- package/upd_pkg.d.ts.map +1 -0
- package/upd_pkg.js +28 -0
- package/upd_pkg.js.map +1 -0
- 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-deploy.ts
DELETED
|
@@ -1,174 +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, Stage } from './libs/Project';
|
|
10
|
-
import { Reporter } from './libs/Reporter';
|
|
11
|
-
import { log, checkEnvVars } from './libs/helpers';
|
|
12
|
-
import { DockerImage } from './k8s/DockerImage';
|
|
13
|
-
import { Node } from './k8s/Node';
|
|
14
|
-
import { App, Config, getApps } from './k8s/App';
|
|
15
|
-
|
|
16
|
-
const ENV = process.env;
|
|
17
|
-
|
|
18
|
-
// ========================================================
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
async function main() {
|
|
22
|
-
|
|
23
|
-
program
|
|
24
|
-
.option('--path <project dir>', 'Path to project directory [default - current]')
|
|
25
|
-
.option('--stage <stage>', 'Deploy manifests to K8s <stage>')
|
|
26
|
-
|
|
27
|
-
.option('--no-changelog', 'Skip create gitlog')
|
|
28
|
-
.option('--no-gitpush', 'Skip pushing to stage branch after deploy')
|
|
29
|
-
|
|
30
|
-
.option('--debug', 'Output extra debugging info')
|
|
31
|
-
.action(
|
|
32
|
-
async () => {
|
|
33
|
-
|
|
34
|
-
let reporter: Reporter | undefined;
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
|
|
38
|
-
// ------------------
|
|
39
|
-
// Инициализируемся
|
|
40
|
-
checkEnvVars(['CI_STAGES', 'REPORTER']);
|
|
41
|
-
|
|
42
|
-
const opts = program.opts() || {};
|
|
43
|
-
const prj = new Project(opts.path);
|
|
44
|
-
|
|
45
|
-
const reporterOpts = JSON.parse(ENV.REPORTER!);
|
|
46
|
-
reporterOpts.postTitle = opts.scheme;
|
|
47
|
-
|
|
48
|
-
const pkg = JSON.parse(await Shell.cat(prj.rootPath +'/package.json') || 'no package.json file!');
|
|
49
|
-
const pkgBuild = Number(pkg.version.split('.')[2]);
|
|
50
|
-
|
|
51
|
-
prj.build = prj.build < pkgBuild ? pkgBuild : prj.build;
|
|
52
|
-
prj.version = `${ pkg.version.split('.').splice(0, 2).join('.') }.${ prj.build }`;
|
|
53
|
-
|
|
54
|
-
if(!pkg.ci){
|
|
55
|
-
throw new Error('No ci config in package.json file!');
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
reporter = new Reporter(prj, reporterOpts);
|
|
59
|
-
|
|
60
|
-
const config: Config = pkg.ci;
|
|
61
|
-
|
|
62
|
-
// Запускаем команду
|
|
63
|
-
await run(prj, reporter, opts, config);
|
|
64
|
-
|
|
65
|
-
} catch(e){
|
|
66
|
-
|
|
67
|
-
log.error(e);
|
|
68
|
-
|
|
69
|
-
if(reporter){
|
|
70
|
-
try {
|
|
71
|
-
await reporter.fail(e);
|
|
72
|
-
} catch(e2){
|
|
73
|
-
log.error(e2);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
process.exit(1);
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
await program.parseAsync(process.argv);
|
|
84
|
-
}
|
|
85
|
-
main();
|
|
86
|
-
|
|
87
|
-
// ============================================
|
|
88
|
-
|
|
89
|
-
async function run(prj: Project, reporter: Reporter, opts: OptionValues) {
|
|
90
|
-
|
|
91
|
-
// ------------------
|
|
92
|
-
// Инициализируемся
|
|
93
|
-
|
|
94
|
-
const release = opts.changelog ? await Jira.resolve(prj) : { tasks:[], bugs:[], changelog:''};
|
|
95
|
-
|
|
96
|
-
// 1. Меняем стейдж на новый, потому что деплоим в него!
|
|
97
|
-
const stage = opts.stage;
|
|
98
|
-
|
|
99
|
-
prj.stage = stage;
|
|
100
|
-
await reporter.startDeploy(stage);
|
|
101
|
-
|
|
102
|
-
const node = new Node(stage);
|
|
103
|
-
|
|
104
|
-
// 2. Получаем путь
|
|
105
|
-
const k8s_dir = `${ prj.rootPath }/_k8s/${stage}/`;
|
|
106
|
-
Shell.cd(k8s_dir);
|
|
107
|
-
|
|
108
|
-
// 3. Обходим ВСЕ файлы - те что не поменялись не применятся
|
|
109
|
-
const deployedApps: Record<string, string> = {};
|
|
110
|
-
const k8s_files = await Shell.ls(k8s_dir);
|
|
111
|
-
|
|
112
|
-
try{
|
|
113
|
-
|
|
114
|
-
// Деплоим все(!) аппы - те что не поменялись не применятся
|
|
115
|
-
for (const k8s_file of k8s_files) {
|
|
116
|
-
|
|
117
|
-
const appName = k8s_file.replace('.yml', '');
|
|
118
|
-
const status = await node.apply(`${ k8s_dir }/${k8s_file}`, appName);
|
|
119
|
-
|
|
120
|
-
let msg = '';
|
|
121
|
-
if(status.valid){
|
|
122
|
-
deployedApps[ appName ] = status.msg;
|
|
123
|
-
msg = ` + <b>${appName}</b>`;
|
|
124
|
-
await reporter.send(msg);
|
|
125
|
-
} else {
|
|
126
|
-
msg = ` ❌ <b>${appName}</b> yaml is invalid!\n${ status.msg }`;
|
|
127
|
-
await reporter.send(msg);
|
|
128
|
-
throw new Error(`FAIL: Deployment app: ${appName}`);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
await node.status(reporter);
|
|
134
|
-
|
|
135
|
-
} catch(error){
|
|
136
|
-
|
|
137
|
-
// Деплой сфейлился - надо откатыватся
|
|
138
|
-
if(Object.keys(deployedApps).length > 0){
|
|
139
|
-
|
|
140
|
-
log.error('FAIL: Deployments to rollout', Object.keys(deployedApps));
|
|
141
|
-
await reporter.send(` 🚫 <b>APPLAY FAIL</b>: Rollout all deployed apps`);
|
|
142
|
-
|
|
143
|
-
for (const appName of Object.keys(deployedApps)) {
|
|
144
|
-
await node.exec(`rollout undo deployment/${ appName }`);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
await node.status(reporter);
|
|
150
|
-
throw error;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// deploy succsess, push changes to stage brunch
|
|
154
|
-
if(opts.gitpush){
|
|
155
|
-
await Git.push( stage );
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
await reporter.send(` + Save ${ prj.stage} -> ${ prj.version} to GitLab`);
|
|
159
|
-
await prj.saveGitLabStagesVersions();
|
|
160
|
-
|
|
161
|
-
if(opts.changelog){
|
|
162
|
-
await reporter.send(` + Resolved tasks:${ release.tasks.length }, bugs: ${ release.bugs.length }`);
|
|
163
|
-
|
|
164
|
-
const bugsDeployed = await Jira.moveBugsAsDeployed(release.bugs);
|
|
165
|
-
if(bugsDeployed.length > 0){
|
|
166
|
-
await reporter.send(` + Deployed ${ bugsDeployed.length } bugs.`);
|
|
167
|
-
} else {
|
|
168
|
-
await reporter.send(` - Deploy bugs. [SKIPED]`);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
await reporter.release(release.changelog);
|
|
173
|
-
|
|
174
|
-
}
|
package/libs/Exception.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
export class Exception extends Error {
|
|
2
|
-
params?: Record<string, any>;
|
|
3
|
-
|
|
4
|
-
// -------------
|
|
5
|
-
|
|
6
|
-
constructor(
|
|
7
|
-
message: string,
|
|
8
|
-
params?: Record<string, any>) {
|
|
9
|
-
super();
|
|
10
|
-
|
|
11
|
-
this.message = message;
|
|
12
|
-
this.params = params;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @see https://github.com/Microsoft/TypeScript-wiki/blob/master/Breaking-Changes.md#extending-built-ins-like-error-array-and-map-may-no-longer-work
|
|
16
|
-
*/
|
|
17
|
-
Object.setPrototypeOf(this, Exception.prototype);
|
|
18
|
-
}
|
|
19
|
-
}
|
package/libs/Git.ts
DELETED
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import Shell from './Shell';
|
|
2
|
-
|
|
3
|
-
const ENV = process.env;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// Can be redifined in ENV
|
|
7
|
-
// ------------------------
|
|
8
|
-
|
|
9
|
-
const GITLAB_PASS = ENV.GITLAB_PASS;
|
|
10
|
-
|
|
11
|
-
// ===========================================
|
|
12
|
-
|
|
13
|
-
class Commit{
|
|
14
|
-
|
|
15
|
-
date = new Date(ENV.CI_COMMIT_TIMESTAMP || 0 * 1);
|
|
16
|
-
sha = ENV.CI_COMMIT_SHA || '';
|
|
17
|
-
msg = ENV.CI_COMMIT_MESSAGE || '';
|
|
18
|
-
name = ENV.GITLAB_USER_NAME || '';
|
|
19
|
-
email = ENV.CI_COMMIT_AUTHOR || '';
|
|
20
|
-
|
|
21
|
-
constructor(row: string, delimetr: string){
|
|
22
|
-
if(!row || !delimetr){
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const cols = row.split(delimetr);
|
|
27
|
-
|
|
28
|
-
this.date = new Date(Date.parse(cols[3]));
|
|
29
|
-
this.sha = cols[0];
|
|
30
|
-
this.email = cols[2];
|
|
31
|
-
this.name = cols[1];
|
|
32
|
-
this.msg = cols[4];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
get issuesKeys(){
|
|
36
|
-
const matchedIssues = this.msg.match(/[A-Z0-9]+-\d+/g);
|
|
37
|
-
return !matchedIssues || matchedIssues.length === 0 ? [] : matchedIssues;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// ----------------------
|
|
44
|
-
|
|
45
|
-
async function setOrigin(opts: { url?: string; jobId?: number} = {}){
|
|
46
|
-
if(!opts.jobId && !ENV.CI_JOB_ID){
|
|
47
|
-
// setOrigin ONLY in GitLab CI Jobs runner, as they are detached!
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
let url = opts.url || ENV.CI_PROJECT_URL || '';
|
|
52
|
-
|
|
53
|
-
url = url.replace('https://', `https://'gitlab':${ GITLAB_PASS }@`);
|
|
54
|
-
await Shell.exec(`git remote set-url --push origin ${ url }.git`);
|
|
55
|
-
await Shell.exec(`git remote set-url origin ${ url }.git`);
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// -----------------------------------------
|
|
60
|
-
|
|
61
|
-
async function push(branch: string){
|
|
62
|
-
await Shell.exec(`git pull --ff origin ${ branch }`);
|
|
63
|
-
await Shell.execRepeat(`git push origin HEAD:${ branch }`);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// ----------------------
|
|
67
|
-
|
|
68
|
-
async function makeTag(version: string){
|
|
69
|
-
const tag = `v${version}`;
|
|
70
|
-
await Shell.exec(`git tag --force "${ tag }"`);
|
|
71
|
-
await Shell.execRepeat(`git push --force origin ${ tag }`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// ----------------------
|
|
75
|
-
|
|
76
|
-
async function getTags(limit = 1000, mask = /v[\d]+\.[\d]+\.[\d]+$/){
|
|
77
|
-
await Shell.exec(`git fetch -t`, { ignoreError: true });
|
|
78
|
-
|
|
79
|
-
const tagsStr = await Shell.exec('git tag | sort --version-sort', {silent: true, ignoreError:true});
|
|
80
|
-
|
|
81
|
-
let list = tagsStr.split('\n').filter((f)=>f.length > 2);
|
|
82
|
-
list = list.length > 0 ? list.reverse() : [tagsStr];
|
|
83
|
-
|
|
84
|
-
const tags = [];
|
|
85
|
-
|
|
86
|
-
let i = 1;
|
|
87
|
-
for (const tag of list) {
|
|
88
|
-
if(tag === '' || mask && (mask.exec(tag))=== null){
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
tags.push(tag);
|
|
92
|
-
i++;
|
|
93
|
-
if(i >= limit){
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return tags;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// -----------------------------------------
|
|
102
|
-
|
|
103
|
-
async function lastTag(){
|
|
104
|
-
const list = await getTags(1);
|
|
105
|
-
if(list && Array.isArray(list) && list.length > 0){
|
|
106
|
-
return list[0];
|
|
107
|
-
}
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
// -----------------------------------------
|
|
112
|
-
|
|
113
|
-
async function existTag(version: string){
|
|
114
|
-
const list = await getTags(100);
|
|
115
|
-
|
|
116
|
-
if(list && Array.isArray(list) && list.includes(`v${ version }`)){
|
|
117
|
-
return `v${ version }`;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
return undefined;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// -----------------------------------------
|
|
124
|
-
|
|
125
|
-
async function getCommitsAndIssues(opt: { onlyJira?: boolean; limit?: number; fromTag: string; toTag: string}){
|
|
126
|
-
|
|
127
|
-
opt.onlyJira = opt.onlyJira ?? true;
|
|
128
|
-
opt.limit = opt.limit ?? 10;
|
|
129
|
-
|
|
130
|
-
const result: { commits: Record<string, any>; issues: Record<string, any> } = { commits: {}, issues: {} };
|
|
131
|
-
|
|
132
|
-
const d = '#!|!#';
|
|
133
|
-
|
|
134
|
-
const from = opt.fromTag;
|
|
135
|
-
const to = opt.toTag || '';
|
|
136
|
-
|
|
137
|
-
const par = `${from}..${ from !== '' && to === '' ? 'HEAD' : to }`;
|
|
138
|
-
|
|
139
|
-
const commits = await Shell.exec(`git log ${ par !== '..' ? par : '' } --pretty='format:%H${d}%cN${d}%cE${d}%ci${d}%s' --max-count=${ opt.limit }`, { silent: true });
|
|
140
|
-
|
|
141
|
-
if(!commits || commits.includes(d) === false){
|
|
142
|
-
return result;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
let arr = commits.split('\n');
|
|
146
|
-
if(arr.length === 0){
|
|
147
|
-
arr = [commits];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
for (const row of arr) {
|
|
151
|
-
|
|
152
|
-
const commit = new Commit(row, d);
|
|
153
|
-
const issuesKeys = commit.issuesKeys;
|
|
154
|
-
|
|
155
|
-
if(opt.onlyJira && issuesKeys.length === 0){
|
|
156
|
-
continue;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
result.commits[ commit.sha ] = commit;
|
|
160
|
-
|
|
161
|
-
for (const key of issuesKeys) {
|
|
162
|
-
const issue = result.issues[ key ] || [];
|
|
163
|
-
issue.push(commit.sha);
|
|
164
|
-
result.issues[ key ] = issue;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
return result;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// -----------------------------------------
|
|
172
|
-
|
|
173
|
-
async function getDiffFiles(fromTag?: string, opt = { silent: true, ignoreError: true }){
|
|
174
|
-
|
|
175
|
-
const from = fromTag || await lastTag();
|
|
176
|
-
const diffCmd = from && from !== '' ? `git diff --name-only HEAD ${ from }` : "find . -not -path '*/_*' -not -path '*/\.*' -not -path '*/node_modules*' -type d -maxdepth 2";
|
|
177
|
-
const diffStr = await Shell.exec(diffCmd, opt) || '';
|
|
178
|
-
|
|
179
|
-
let arr = diffStr.split('\n');
|
|
180
|
-
if(arr.length === 0){
|
|
181
|
-
arr = [diffStr];
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
return arr.filter((f)=>f !== '').sort();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// ------------------------
|
|
188
|
-
|
|
189
|
-
export default {
|
|
190
|
-
Commit,
|
|
191
|
-
setOrigin,
|
|
192
|
-
push,
|
|
193
|
-
makeTag,
|
|
194
|
-
lastTag,
|
|
195
|
-
existTag,
|
|
196
|
-
getTags,
|
|
197
|
-
getCommitsAndIssues,
|
|
198
|
-
getDiffFiles,
|
|
199
|
-
};
|
package/libs/Gitlab.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
|
|
3
|
-
import { Exception } from '../libs/Exception';
|
|
4
|
-
import { checkVarsExisting } from '../libs/helpers';
|
|
5
|
-
|
|
6
|
-
// ------------------------
|
|
7
|
-
|
|
8
|
-
class Gitlab {
|
|
9
|
-
|
|
10
|
-
privateToken: string;
|
|
11
|
-
configVarName: string;
|
|
12
|
-
projectId: number;
|
|
13
|
-
url: string;
|
|
14
|
-
|
|
15
|
-
constructor(privateToken: string, projectId: number, configGitlabUrl = 'https://gitlab.soft-artel.com', configVarName = 'CONFIG') {
|
|
16
|
-
this.privateToken = privateToken;
|
|
17
|
-
this.projectId = projectId;
|
|
18
|
-
this.configVarName = configVarName;
|
|
19
|
-
|
|
20
|
-
this.url = `${ configGitlabUrl }/api/v4/projects/${ this.projectId }/variables/${ configVarName }`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async downloadConfig() {
|
|
24
|
-
|
|
25
|
-
try{
|
|
26
|
-
const resp = await axios({
|
|
27
|
-
method:'GET', timeout: 600, url: this.url, headers:{ 'PRIVATE-TOKEN': this.privateToken },
|
|
28
|
-
});
|
|
29
|
-
return JSON.parse(resp.data.value);
|
|
30
|
-
} catch(e){
|
|
31
|
-
|
|
32
|
-
const errTitle = `CONFIG ERR: GitLab project [id:${ this.projectId }] has not`;
|
|
33
|
-
|
|
34
|
-
if(e.response && (e.response.status === 401 || e.response.status === 403)){
|
|
35
|
-
const err = new Exception(`${ errTitle } access, HTTP-401`);
|
|
36
|
-
err.params = e.config;
|
|
37
|
-
throw err;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if(e.response && e.response.status === 404){
|
|
41
|
-
const err = new Exception(`${ errTitle } CI VARIABLE: '${ this.configVarName }'`);
|
|
42
|
-
err.params = e.config;
|
|
43
|
-
throw err;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
e.request = '...';
|
|
47
|
-
e.connection = '...';
|
|
48
|
-
|
|
49
|
-
throw e;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
async uploadConfig(config: Record<string, any>) {
|
|
54
|
-
const resp = await axios({
|
|
55
|
-
method:'PUT', timeout: 600, url: this.url,
|
|
56
|
-
headers:{ 'PRIVATE-TOKEN': this.privateToken },
|
|
57
|
-
data:{ value: JSON.stringify(config, null, 3) },
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
if(resp.status !== 200){
|
|
61
|
-
// eslint-disable-next-line no-console
|
|
62
|
-
console.error(resp);
|
|
63
|
-
throw new Error('CONFIG ERR: GitLab update VAR - HTTP'+resp.status);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Export and check
|
|
69
|
-
|
|
70
|
-
const ENV = process.env;
|
|
71
|
-
|
|
72
|
-
const privateToken = ENV.GITLAB_PASS;
|
|
73
|
-
const projectId = ENV.CI_PROJECT_ID;
|
|
74
|
-
|
|
75
|
-
checkVarsExisting([{
|
|
76
|
-
field: privateToken,
|
|
77
|
-
exceptionMessage: 'GITLAB_PASS must be provided',
|
|
78
|
-
}, {
|
|
79
|
-
field: projectId,
|
|
80
|
-
exceptionMessage: 'CI_PROJECT_ID must be provided',
|
|
81
|
-
}]);
|
|
82
|
-
|
|
83
|
-
const configGitlabUrl = ENV.CONFIG_GITLAB_URL;
|
|
84
|
-
const configVarName = ENV.CONFIG_VAR_NAME;
|
|
85
|
-
|
|
86
|
-
export default new Gitlab(privateToken!, Number(projectId), configGitlabUrl, configVarName);
|
package/libs/Jira.ts
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import axios from 'axios';
|
|
2
|
-
|
|
3
|
-
import { log, stripTags } from './helpers';
|
|
4
|
-
import git from './Git';
|
|
5
|
-
import { Project } from './Project';
|
|
6
|
-
|
|
7
|
-
const ENV = process.env;
|
|
8
|
-
|
|
9
|
-
// Can be redefined in ENV
|
|
10
|
-
// ------------------------
|
|
11
|
-
|
|
12
|
-
const RELEASE_BO_URL = ENV.RELEASE_BO_URL || 'https://bo.soft-artel.com/ci/jira';
|
|
13
|
-
const RELEASE_BO_TOKEN = ENV.RELEASE_BO_TOKEN || ENV.GITLAB_PASS;
|
|
14
|
-
|
|
15
|
-
const RELEASE_JIRA_URL = ENV.RELEASE_JIRA_URL || 'https://jira.soft-artel.com';
|
|
16
|
-
|
|
17
|
-
export interface ReleaseInfo{
|
|
18
|
-
components: string[];
|
|
19
|
-
bugs: Issue[];
|
|
20
|
-
tasks: Issue[];
|
|
21
|
-
changelog: string;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// ===========================================
|
|
25
|
-
|
|
26
|
-
async function resolve(prj: Project, head = true): Promise<ReleaseInfo>{
|
|
27
|
-
|
|
28
|
-
if(RELEASE_BO_TOKEN === undefined){
|
|
29
|
-
throw new Error('NO RELEASE_BO_TOKEN!');
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const release: ReleaseInfo = {
|
|
33
|
-
components: [], bugs:[], tasks:[], changelog: 'No issues found in git commits!',
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
// 1. Получаем информацию из гита - по тому какие коммиты были
|
|
37
|
-
|
|
38
|
-
const fromTag = prj.prevVersion ? await git.existTag(prj.prevVersion) : await git.lastTag();
|
|
39
|
-
const toTag = head ? undefined : `v${prj.version}`;
|
|
40
|
-
|
|
41
|
-
const gitLog = await git.getCommitsAndIssues({
|
|
42
|
-
fromTag: fromTag ?? '', toTag: toTag ?? '', onlyJira: true, limit: 1000,
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
const issuesKeys = Object.keys(gitLog.issues);
|
|
46
|
-
|
|
47
|
-
if(issuesKeys.length === 0){
|
|
48
|
-
// если никто не комитил с ключами - выходим!!!
|
|
49
|
-
log.info('No issues found in git log!');
|
|
50
|
-
return release;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// 2. Резолвим задачи - получаем названия и компоненты
|
|
54
|
-
|
|
55
|
-
try{
|
|
56
|
-
|
|
57
|
-
const resp = await axios({
|
|
58
|
-
method:'POST',
|
|
59
|
-
url: `${ RELEASE_BO_URL }/resolve`,
|
|
60
|
-
headers:{ 'PRIVATE-TOKEN': RELEASE_BO_TOKEN },
|
|
61
|
-
data: { issues: issuesKeys },
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
if(resp?.data?.data?.bugs && Array.isArray(resp.data.data.bugs)){
|
|
65
|
-
for (const fields of resp.data.data.bugs) {
|
|
66
|
-
const issue = new Issue(fields);
|
|
67
|
-
if(issue.key !== ''){
|
|
68
|
-
release.bugs.push(issue);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if(resp?.data?.data?.tasks && Array.isArray(resp.data.data.tasks)){
|
|
74
|
-
for (const fields of resp.data.data.tasks) {
|
|
75
|
-
const issue = new Issue(fields);
|
|
76
|
-
if(issue.key !== ''){
|
|
77
|
-
release.tasks.push(issue);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if(resp?.data?.data?.components){
|
|
83
|
-
release.components = Object.values<string>(resp.data.data.components).sort();
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
} catch(err){
|
|
87
|
-
err.request = '...';
|
|
88
|
-
err.connection = '...';
|
|
89
|
-
err.message = 'JIRA RESOLVE ERR: ' + err.message;
|
|
90
|
-
|
|
91
|
-
throw err;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
// 3. Формируем ченж лог
|
|
96
|
-
|
|
97
|
-
log.info('\n\n===============');
|
|
98
|
-
log.info('RELEASE:', prj.group, prj.name, 'v'+prj.version, ' pev:'+fromTag);
|
|
99
|
-
|
|
100
|
-
// let changelog = `🎉 ${ prj.group.toUpperCase() }: <b>${ prj.name.toUpperCase() } v${ prj.version }</b> [ ${ stage.toUpperCase() } ] \n\n`
|
|
101
|
-
|
|
102
|
-
let msg = '';
|
|
103
|
-
|
|
104
|
-
if(release.components.length > 0){
|
|
105
|
-
msg += '<b>Components:</b>\n';
|
|
106
|
-
for (const comp of release.components) {
|
|
107
|
-
msg += `- ${ comp }\n`;
|
|
108
|
-
}
|
|
109
|
-
msg += '\n';
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if(release.tasks.length > 0){
|
|
113
|
-
msg += '<b>Done:</b>\n';
|
|
114
|
-
for (const issue of release.tasks) {
|
|
115
|
-
msg += `- 🛠 <b><a href="${ RELEASE_JIRA_URL }/browse/${ issue.key }">${ issue.key }</a></b>: ${issue.summary}\n`;
|
|
116
|
-
}
|
|
117
|
-
msg += '\n';
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if(release.bugs.length > 0){
|
|
121
|
-
msg += '<b>BugFixes:</b>\n';
|
|
122
|
-
for (const issue of release.bugs) {
|
|
123
|
-
msg += `- 🐞 <b><a href="${ RELEASE_JIRA_URL }/browse/${ issue.key }">${ issue.key }</a></b>: ${issue.summary}\n`;
|
|
124
|
-
}
|
|
125
|
-
msg += '\n';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
release.changelog = msg;
|
|
129
|
-
|
|
130
|
-
log.info('changelog', msg);
|
|
131
|
-
log.info('text', stripTags(msg));
|
|
132
|
-
|
|
133
|
-
return release;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// ------------------------
|
|
137
|
-
|
|
138
|
-
export class Issue{
|
|
139
|
-
|
|
140
|
-
key = '';
|
|
141
|
-
updated = new Date();
|
|
142
|
-
|
|
143
|
-
type = '';
|
|
144
|
-
status = '';
|
|
145
|
-
summary = '';
|
|
146
|
-
assignee = { name: '', email: '', login: '' };
|
|
147
|
-
components: string[] = [];
|
|
148
|
-
|
|
149
|
-
constructor(fields: Record<string, any>){
|
|
150
|
-
this.key = fields.key;
|
|
151
|
-
this.updated = new Date(Date.parse(fields.updated));
|
|
152
|
-
this.type = fields.type;
|
|
153
|
-
this.status = fields.status;
|
|
154
|
-
this.summary = fields.summary;
|
|
155
|
-
if(fields.assignee && typeof fields.assignee === 'object'){
|
|
156
|
-
this.assignee.name = fields.assignee.name;
|
|
157
|
-
this.assignee.email = fields.assignee.email;
|
|
158
|
-
this.assignee.login = fields.assignee.login;
|
|
159
|
-
}
|
|
160
|
-
this.components = Array.isArray(fields.components) ? fields.components : [];
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// --------------------
|
|
165
|
-
|
|
166
|
-
async function moveBugsAsDeployed(bugs: { key: string }[]){
|
|
167
|
-
|
|
168
|
-
if(RELEASE_BO_TOKEN === undefined){
|
|
169
|
-
throw new Error('NO RELEASE_BO_TOKEN!');
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
const issuesKeys = [];
|
|
173
|
-
|
|
174
|
-
for (const bug of bugs) {
|
|
175
|
-
issuesKeys.push(bug.key);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
if(issuesKeys.length === 0){
|
|
179
|
-
return [];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const resp = await axios({
|
|
183
|
-
method:'POST',
|
|
184
|
-
url: `${ RELEASE_BO_URL }/deployed`,
|
|
185
|
-
headers:{ 'PRIVATE-TOKEN': RELEASE_BO_TOKEN },
|
|
186
|
-
data: { issues: issuesKeys },
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
if(resp?.data?.data?.deployed && Array.isArray(resp.data.data.deployed)){
|
|
190
|
-
return resp.data.data.deployed;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
return [];
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
// ------------------------
|
|
198
|
-
|
|
199
|
-
export const Jira = {
|
|
200
|
-
resolve,
|
|
201
|
-
moveBugsAsDeployed,
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// let msg = `## **${ prj.version }**
|
|
206
|
-
// ${ new Date().toLocaleString('ru-RU', {
|
|
207
|
-
// weekday: 'long',
|
|
208
|
-
// year: 'numeric',
|
|
209
|
-
// month: 'short',
|
|
210
|
-
// day: 'numeric',
|
|
211
|
-
// timeZone: 'Europe/Moscow',
|
|
212
|
-
// hour12: false,
|
|
213
|
-
// hour: 'numeric',
|
|
214
|
-
// minute: 'numeric',
|
|
215
|
-
// }) }`
|
|
216
|
-
|
|
217
|
-
// if( release.components.length > 0 ){
|
|
218
|
-
// msg += '**Components:**\n'
|
|
219
|
-
// for (const comp of release.components) {
|
|
220
|
-
// msg += `- **${ comp }**\n`
|
|
221
|
-
// }
|
|
222
|
-
// msg += '\n\n'
|
|
223
|
-
// }
|
|
224
|
-
|
|
225
|
-
// if( release.tasks.length > 0 ){
|
|
226
|
-
// msg += '**Done:**\n'
|
|
227
|
-
// for (const issue of release.tasks) {
|
|
228
|
-
// msg += `- 🛠 **[${ issue.key }](${ RELEASE_JIRA_URL }/browse/${ issue.key })**: ${issue.summary}, _by [${ issue.assignee.name }](${ RELEASE_JIRA_URL }/issues/?jql=assignee%20in%20(${issue.assignee.login}))_\n`
|
|
229
|
-
// }
|
|
230
|
-
// msg += '\n\n'
|
|
231
|
-
// }
|
|
232
|
-
|
|
233
|
-
// if( release.bugs.length > 0 ){
|
|
234
|
-
// msg += '**BugFixes:**\n'
|
|
235
|
-
// for (const issue of release.bugs) {
|
|
236
|
-
// msg += `- 🐞 **[${ issue.key }](${ RELEASE_JIRA_URL }/browse/${ issue.key })**: ${issue.summary}, _by [${ issue.assignee.name }](${ RELEASE_JIRA_URL }/issues/?jql=assignee%20in%20(${issue.assignee.login}))_\n`
|
|
237
|
-
// }
|
|
238
|
-
// msg += '\n'
|
|
239
|
-
// }
|