@soft-artel/ci 2.3.87 → 2.3.89

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.
Files changed (80) hide show
  1. package/Project.d.ts +57 -0
  2. package/Project.d.ts.map +1 -0
  3. package/Project.js +173 -0
  4. package/Project.js.map +1 -0
  5. package/commands/incrementBuild.d.ts +3 -0
  6. package/commands/incrementBuild.d.ts.map +1 -0
  7. package/commands/incrementBuild.js +34 -0
  8. package/commands/incrementBuild.js.map +1 -0
  9. package/commands/k8s-build.d.ts +30 -0
  10. package/commands/k8s-build.d.ts.map +1 -0
  11. package/commands/k8s-build.js +291 -0
  12. package/commands/k8s-build.js.map +1 -0
  13. package/commands/k8s-deploy.d.ts +11 -0
  14. package/commands/k8s-deploy.d.ts.map +1 -0
  15. package/commands/k8s-deploy.js +145 -0
  16. package/commands/k8s-deploy.js.map +1 -0
  17. package/commands/xcode.d.ts +3 -0
  18. package/commands/xcode.d.ts.map +1 -0
  19. package/commands/xcode.js +128 -0
  20. package/commands/xcode.js.map +1 -0
  21. package/package.json +3 -3
  22. package/services/Git.d.ts +46 -0
  23. package/services/Git.d.ts.map +1 -0
  24. package/services/Git.js +138 -0
  25. package/services/Git.js.map +1 -0
  26. package/services/Gitlab.d.ts +14 -0
  27. package/services/Gitlab.d.ts.map +1 -0
  28. package/services/Gitlab.js +101 -0
  29. package/services/Gitlab.js.map +1 -0
  30. package/services/Jira.d.ts +32 -0
  31. package/services/Jira.d.ts.map +1 -0
  32. package/services/Jira.js +136 -0
  33. package/services/Jira.js.map +1 -0
  34. package/services/Reporter.d.ts +43 -0
  35. package/services/Reporter.d.ts.map +1 -0
  36. package/services/Reporter.js +134 -0
  37. package/services/Reporter.js.map +1 -0
  38. package/utils/Exception.d.ts +5 -0
  39. package/utils/Exception.d.ts.map +1 -0
  40. package/utils/Exception.js +14 -0
  41. package/utils/Exception.js.map +1 -0
  42. package/utils/Logger.d.ts +11 -0
  43. package/utils/Logger.d.ts.map +1 -0
  44. package/utils/Logger.js +62 -0
  45. package/utils/Logger.js.map +1 -0
  46. package/utils/Shell.d.ts +39 -0
  47. package/utils/Shell.d.ts.map +1 -0
  48. package/utils/Shell.js +89 -0
  49. package/utils/Shell.js.map +1 -0
  50. package/utils/helpers.d.ts +16 -0
  51. package/utils/helpers.d.ts.map +1 -0
  52. package/utils/helpers.js +109 -0
  53. package/utils/helpers.js.map +1 -0
  54. package/utils/prototype.d.ts +9 -0
  55. package/utils/prototype.d.ts.map +1 -0
  56. package/utils/prototype.js +186 -0
  57. package/utils/prototype.js.map +1 -0
  58. package/.env +0 -21
  59. package/.eslintcache +0 -1
  60. package/.eslintignore +0 -4
  61. package/.eslintrc +0 -246
  62. package/.gitlab-ci.yml +0 -12
  63. package/README.md +0 -33
  64. package/_publish.sh +0 -11
  65. package/src/Project.ts +0 -286
  66. package/src/commands/incrementBuild.ts +0 -46
  67. package/src/commands/k8s-build.ts +0 -441
  68. package/src/commands/k8s-deploy.ts +0 -215
  69. package/src/commands/xcode.ts +0 -192
  70. package/src/services/Git.ts +0 -203
  71. package/src/services/Gitlab.ts +0 -129
  72. package/src/services/Jira.ts +0 -228
  73. package/src/services/Reporter.ts +0 -230
  74. package/src/utils/Exception.ts +0 -19
  75. package/src/utils/Logger.ts +0 -85
  76. package/src/utils/Shell.ts +0 -120
  77. package/src/utils/helpers.ts +0 -126
  78. package/src/utils/prototype.ts +0 -313
  79. package/test.ts +0 -0
  80. package/tsconfig.json +0 -25
@@ -1,192 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import {program, OptionValues} from 'commander';
4
-
5
- import Shell, { ExecOptions } from '../utils/Shell';
6
- import Git from '../services/Git';
7
- import { Jira } from '../services/Jira';
8
- import { log } from '../utils/Logger';
9
- import { stripTags, resolvePath, asyncSleep } from '../utils/helpers';
10
- import { Config, Project, RunCommandHandler } from '../Project';
11
- import { Reporter } from '../services/Reporter';
12
-
13
-
14
- const ENV = process.env;
15
-
16
-
17
- // ============================================
18
- // Command flow
19
-
20
- const runHandler: RunCommandHandler = async ( prj: Project, reporter: Reporter, opts: OptionValues, config: Config ) => {
21
-
22
-
23
- // ------------------
24
- // Проверяем что есть изменения
25
- const changedFiles = await Git.getDiffFiles();
26
-
27
- if(changedFiles.length === 0 && !opts.sudo){
28
- log.info('SKIP BUILD: NO changedFiles found in repo');
29
- process.exit(0);
30
- } else {
31
- log.info('START BUILD!');
32
- log.info( changedFiles.join('\n') );
33
- }
34
-
35
- // ------------------
36
- // Инициализируемся
37
- const secrets = JSON.parse(ENV.SECRETS!);
38
- const scheme = opts.scheme || 'iOS';
39
-
40
- const bundleID = await Shell.exec(`xcodebuild -showBuildSettings -scheme ${ scheme } | grep PRODUCT_BUNDLE_IDENTIFIER | tr -d 'PRODUCT_BUNDLE_IDENTIFIER = '`, { silent: true });
41
-
42
- reporter.$message_footer_changes_from = prj.version;
43
- reporter.$message_footer_changes_to = ENV.CI_COMMIT_REF_NAME || 'dev';
44
-
45
- // 1. BUILD ------------------------
46
- prj.incrementBuild();
47
- await reporter.startBuild();
48
-
49
- await fastlane('increment_build_number', { build_number: prj.build });
50
-
51
- log.info('unlock_keychain');
52
-
53
- await fastlane('unlock_keychain', {
54
- path: resolvePath(secrets.keychain.path),
55
- password: secrets.keychain.password || opts.sudo,
56
- set_default: true,
57
- },
58
- { silent: true });
59
-
60
- await reporter.append(` + Build & archive xcode project.`);
61
- await fastlane('build_app', {
62
- scheme,
63
- configuration: 'Release',
64
- silent: false,
65
- export_method: 'app-store',
66
- xcargs: '-allowProvisioningUpdates',
67
- include_bitcode: true,
68
- }, { verbose: '' });
69
-
70
-
71
- // 2. RELEASE INFO ------------------------
72
-
73
- const release = await Jira.resolve(prj);
74
- await reporter.append(` + Resolved tasks:${ release.tasks.length }, bugs: ${ release.bugs.length }`);
75
-
76
- await Git.setOrigin();
77
-
78
- await Shell.exec(`git reset --hard HEAD`, { silent: false });
79
- await prj.updateChangeLog(release.changelog);
80
-
81
- await Shell.exec(`git commit -a -m "v${ prj.version }"`, { ignoreError: true, silent:false });
82
- await Git.push(ENV.CI_COMMIT_REF_NAME || 'dev');
83
- await reporter.append(` + Update <a href="${ prj.url }/-/blob/${ ENV.CI_COMMIT_REF_NAME || 'dev' }/CHANGELOG.md">changelog</a>.`);
84
-
85
- await reporter.append(` + Git tag new version`);
86
- await Git.makeTag(prj.version);
87
-
88
- await reporter.append(` + Save build: ${ prj.build} to GitLab`);
89
- await prj.saveGitLabBuild();
90
-
91
-
92
- // 3. DEPLOY ARCHIVE ------------------------
93
- await reporter.appendDeploy('testfight');
94
- await reporter.append(` + Upload to Testfilght.`);
95
- await fastlane('upload_to_testflight', {
96
- api_key_path: ENV.TESTFLIGHT || `${ prj.rootPath }/testflight.json`,
97
- changelog: stripTags(release.changelog),
98
- }, { attempts: 3, verbose: '' });
99
-
100
- // 4. UPLOAD DSYMS ------------------------
101
-
102
- if(secrets.bugsnag[ scheme ]){
103
-
104
- await reporter.append(` + Download DSYMs.`);
105
-
106
- await asyncSleep(60);
107
-
108
- await fastlane('download_dsyms', {
109
- api_key_path: ENV.TESTFLIGHT || `${ prj.rootPath }/testflight.json`,
110
- version: prj.shortVersion,
111
- build_number: prj.build,
112
- app_identifier: bundleID,
113
- wait_for_dsym_processing: true,
114
- output_directory: prj.rootPath,
115
- }, {
116
- attempts: 10, sleep: 120, silent: false, ignoreError: true,
117
- });
118
-
119
- await reporter.append(` + Upload DSYMs to BugSnag.`);
120
- const cmd = `bugsnag-dsym-upload --api-key ${ secrets.bugsnag[ scheme ] } --project-root ./ ${ prj.rootPath }/${bundleID}-${prj.shortVersion}-${prj.build}.dSYM.zip`;
121
- await Shell.execRepeat(cmd, 10, 120, { silent: false, ignoreError: true });
122
-
123
- } else {
124
- await reporter.append(` - Upload DSYMs to BugSnag. [SKIPED]`);
125
- }
126
-
127
- // 5. RELEASE ------------------------
128
-
129
- await reporter.append(` + Resolved tasks:${ release.tasks.length }, bugs: ${ release.bugs.length }`);
130
-
131
- const bugsDeployed = await Jira.moveBugsAsDeployed(release.bugs);
132
- if(bugsDeployed.length > 0){
133
- await reporter.append(` + Deployed ${ bugsDeployed.length } bugs.`);
134
- } else {
135
- await reporter.append(` - Deploy bugs. [SKIPED]`);
136
- }
137
-
138
- await reporter.append(` + Save ${ prj.stage} -> ${ prj.version} to GitLab`);
139
- await prj.saveGitLabStagesVersions();
140
-
141
- // FINISH!
142
- await reporter.succses(release);
143
-
144
-
145
- }
146
-
147
- // ========================================================
148
- // Command
149
-
150
- async function main() {
151
-
152
- program
153
- .option('--path <xcode project dir>', 'Path to Xcode project directory [default - current]')
154
- .option('--scheme <Build scheme>', 'Xcode scheme to build and deploy')
155
- .option('--sudo <password>', 'Sudo password for local run build')
156
- .option('--debug', 'Output extra debugging info')
157
- .option('--debug', 'Output extra debugging info')
158
- .action( async () => { await Project.run( program.opts() || {}, runHandler, [ 'SECRETS' ] ) });
159
-
160
- await program.parseAsync(process.argv);
161
- }
162
- main();
163
-
164
-
165
- // ========================================================
166
- // HELPERS
167
-
168
- function fastlane(action: string, pars: Record<string, any> = {}, { silent = false, attempts = 1, sleep = 60, ignoreError = false, verbose = '--verbose' } = {}) {
169
-
170
- let params = '';
171
- for (const key of Object.keys(pars)) {
172
-
173
- switch (typeof pars[key]) {
174
- case 'object':
175
- params += ` ${ key }:"${ JSON.stringify(pars[key]) }"`;
176
- break;
177
-
178
- case 'string':
179
- params += ` ${ key }:"${ pars[key] }"`;
180
- break;
181
- case 'number':
182
- params += ` ${ key }:${ pars[key] }`;
183
- break;
184
-
185
- default:
186
- params += ` ${ key } `;
187
- }
188
- }
189
-
190
- return Shell.execRepeat(`fastlane run ${ action } ${ params } ${ verbose }`, attempts, sleep, { silent, ignoreError });
191
- }
192
-
@@ -1,203 +0,0 @@
1
- import Shell from '../utils/Shell';
2
-
3
- const ENV = process.env;
4
-
5
- // ===========================================
6
-
7
- class Commit{
8
-
9
- date = new Date(ENV.CI_COMMIT_TIMESTAMP || 0 * 1);
10
- sha = ENV.CI_COMMIT_SHA || '';
11
- msg = ENV.CI_COMMIT_MESSAGE || '';
12
- name = ENV.GITLAB_USER_NAME || '';
13
- email = ENV.CI_COMMIT_AUTHOR || '';
14
-
15
- constructor(row: string, delimetr: string){
16
- if(!row || !delimetr){
17
- return;
18
- }
19
-
20
- const cols = row.split(delimetr);
21
-
22
- this.date = new Date(Date.parse(cols[3]));
23
- this.sha = cols[0];
24
- this.email = cols[2];
25
- this.name = cols[1];
26
- this.msg = cols[4];
27
- }
28
-
29
- get issuesKeys(){
30
- const matchedIssues = this.msg.match(/[A-Z0-9]+-\d+/g);
31
- return !matchedIssues || matchedIssues.length === 0 ? [] : matchedIssues;
32
- }
33
-
34
- }
35
-
36
-
37
- // ----------------------
38
-
39
- async function setOrigin(opts: { url?: string; jobId?: number} = {}){
40
- if(!opts.jobId && !ENV.CI_JOB_ID){
41
- // setOrigin ONLY in GitLab CI Jobs runner, as they are detached!
42
- return;
43
- }
44
-
45
- let url = opts.url || ENV.CI_PROJECT_URL || '';
46
-
47
- url = url.replace('https://', `https://gitlab:${ ENV.GITLAB_PASS }@`);
48
- await Shell.exec(`git remote set-url --push origin ${ url }.git`);
49
- await Shell.exec(`git remote set-url origin ${ url }.git`);
50
-
51
- }
52
-
53
- // -----------------------------------------
54
-
55
- async function push(branch: string){
56
- await Shell.exec(`git pull --ff --allow-unrelated-histories origin ${ branch }`);
57
- await Shell.execRepeat(`git push origin HEAD:${ branch }`);
58
- }
59
-
60
- // ----------------------
61
-
62
- async function makeTag(version: string){
63
- const tag = `v${version}`;
64
- await Shell.exec(`git tag --force "${ tag }"`);
65
- await Shell.execRepeat(`git push --force origin ${ tag }`);
66
- }
67
-
68
- // ----------------------
69
-
70
- async function getTags(limit = 1000, mask = /v[\d]+\.[\d]+\.[\d]+$/){
71
- await Shell.exec(`git fetch -t`, { ignoreError: true });
72
-
73
- const tagsStr = await Shell.exec('git tag | sort --version-sort', {silent: true, ignoreError:true});
74
-
75
- let list = tagsStr.split('\n').filter((f)=>f.length > 2);
76
- list = list.length > 0 ? list.reverse() : [tagsStr];
77
-
78
- const tags = [];
79
-
80
- let i = 1;
81
- for (const tag of list) {
82
- if(tag === '' || mask && (mask.exec(tag))=== null){
83
- continue;
84
- }
85
- tags.push(tag);
86
- i++;
87
- if(i >= limit){
88
- break;
89
- }
90
- }
91
-
92
- return tags;
93
- }
94
-
95
- // ----------------------
96
-
97
- async function getBrunch():Promise<string | undefined>{
98
- const brunch = await Shell.exec(`git rev-parse --abbrev-ref HEAD`, { ignoreError: true });
99
- return brunch.length > 3 ? brunch : undefined
100
- }
101
-
102
-
103
-
104
- // -----------------------------------------
105
-
106
- async function lastTag(){
107
- const list = await getTags(1);
108
- if(list && Array.isArray(list) && list.length > 0){
109
- return list[0];
110
- }
111
- return undefined;
112
- }
113
-
114
- // -----------------------------------------
115
-
116
- async function existTag(version: string){
117
- const list = await getTags(100);
118
-
119
- if(list && Array.isArray(list) && list.includes(`v${ version }`)){
120
- return `v${ version }`;
121
- }
122
-
123
- return undefined;
124
- }
125
-
126
- // -----------------------------------------
127
-
128
- async function getCommitsAndIssues(opt: { onlyJira?: boolean; limit?: number; fromTag: string; toTag: string}){
129
-
130
- opt.onlyJira = opt.onlyJira ?? true;
131
- opt.limit = opt.limit ?? 10;
132
-
133
- const result: { commits: Record<string, any>; issues: Record<string, any> } = { commits: {}, issues: {} };
134
-
135
- const d = '#!|!#';
136
-
137
- const from = opt.fromTag;
138
- const to = opt.toTag || '';
139
-
140
- const par = `${from}..${ from !== '' && to === '' ? 'HEAD' : to }`;
141
-
142
- 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 });
143
-
144
- if(!commits || commits.includes(d) === false){
145
- return result;
146
- }
147
-
148
- let arr = commits.split('\n');
149
- if(arr.length === 0){
150
- arr = [commits];
151
- }
152
-
153
- for (const row of arr) {
154
-
155
- const commit = new Commit(row, d);
156
- const issuesKeys = commit.issuesKeys;
157
-
158
- if(opt.onlyJira && issuesKeys.length === 0){
159
- continue;
160
- }
161
-
162
- result.commits[ commit.sha ] = commit;
163
-
164
- for (const key of issuesKeys) {
165
- const issue = result.issues[ key ] || [];
166
- issue.push(commit.sha);
167
- result.issues[ key ] = issue;
168
- }
169
- }
170
-
171
- return result;
172
- }
173
-
174
- // -----------------------------------------
175
-
176
- async function getDiffFiles(fromTag?: string, opt = { silent: true, ignoreError: true }){
177
-
178
- const from = fromTag || await lastTag();
179
- const diffCmd = from && from !== '' ? `git diff --name-only HEAD ${ from }` : "find . -not -path '*/_*' -not -path '*/\.*' -not -path '*/node_modules*' -type d -maxdepth 2";
180
- const diffStr = await Shell.exec(diffCmd, opt) || '';
181
-
182
- let arr = diffStr.split('\n');
183
- if(arr.length === 0){
184
- arr = [diffStr];
185
- }
186
-
187
- return arr.filter((f)=>f !== '').sort();
188
- }
189
-
190
- // ------------------------
191
-
192
- export default {
193
- Commit,
194
- setOrigin,
195
- push,
196
- makeTag,
197
- lastTag,
198
- existTag,
199
- getTags,
200
- getBrunch,
201
- getCommitsAndIssues,
202
- getDiffFiles,
203
- };
@@ -1,129 +0,0 @@
1
- import axios from 'axios';
2
-
3
- import { Exception } from '../utils/Exception';
4
- import { checkVarsExisting } from '../utils/helpers';
5
- import { Project } from '../Project';
6
- import { log } from '../utils/Logger';
7
-
8
- // ------------------------
9
-
10
- class Gitlab {
11
-
12
- privateToken: string;
13
- configVarName: string;
14
- projectId: number;
15
- url: string;
16
-
17
- constructor(privateToken: string, projectId: number, configGitlabUrl = 'https://gitlab.soft-artel.com', configVarName = 'CONFIG') {
18
- this.privateToken = privateToken;
19
- this.projectId = projectId;
20
- this.configVarName = configVarName;
21
-
22
- this.url = `${ configGitlabUrl }/api/v4/projects/${ this.projectId }/variables/${ configVarName }`;
23
- }
24
-
25
- async downloadConfig() {
26
-
27
- try{
28
- const resp = await axios({
29
- method:'GET', timeout: 600, url: this.url, headers:{ 'PRIVATE-TOKEN': this.privateToken },
30
- });
31
- return JSON.parse(resp.data.value);
32
- } catch(e){
33
-
34
- const errTitle = `CONFIG ERR: GitLab project [id:${ this.projectId }] has not`;
35
-
36
- if(e.response && (e.response.status === 401 || e.response.status === 403)){
37
- const err = new Exception(`${ errTitle } access, HTTP-401`);
38
- err.params = e.config;
39
- throw err;
40
- }
41
-
42
- if(e.response && e.response.status === 404){
43
- const err = new Exception(`${ errTitle } CI VARIABLE: '${ this.configVarName }'`);
44
- err.params = e.config;
45
- throw err;
46
- }
47
-
48
- e.request = '...';
49
- e.connection = '...';
50
-
51
- throw e;
52
- }
53
- }
54
-
55
- async uploadConfig(config: Record<string, any>) {
56
- const resp = await axios({
57
- method:'PUT', timeout: 600, url: this.url,
58
- headers:{ 'PRIVATE-TOKEN': this.privateToken },
59
- data:{ value: JSON.stringify(config, null, 3) },
60
- });
61
-
62
- if(resp.status !== 200){
63
- // eslint-disable-next-line no-console
64
- console.error(resp);
65
- throw new Error('CONFIG ERR: GitLab update VAR - HTTP'+resp.status);
66
- }
67
- }
68
-
69
-
70
- async saveVariable(prj: Project, name: string, value: any) {
71
-
72
- try{
73
- const resp = await axios({
74
- method:'PUT',
75
- timeout: 6000,
76
- url: `${ ENV.CONFIG_GITLAB_URL || 'https://gitlab.soft-artel.com' }/api/v4/projects/${ prj.id }/variables/${ name }`,
77
- headers:{ 'PRIVATE-TOKEN': ENV.GITLAB_API_TOKEN || '' },
78
- data:{
79
- value,
80
- },
81
- });
82
-
83
- log.dbg(resp.data);
84
- return JSON.parse(resp.data.value);
85
-
86
- } catch(e){
87
-
88
- const errTitle = `GitLab project [${ prj.id }] has not`;
89
-
90
- if(e.response && (e.response.status === 401 || e.response.status === 403)){
91
- const err = new Exception(`${ errTitle } access, HTTP-401`);
92
- err.params = e.config;
93
- throw err;
94
- }
95
-
96
- if(e.response && e.response.status === 404){
97
- const err = new Exception(`${ errTitle } CI VARIABLE: ${ name }`);
98
- err.params = e.config;
99
- throw err;
100
- }
101
-
102
- e.request = '...';
103
- e.connection = '...';
104
-
105
- throw e;
106
- }
107
-
108
- }
109
- }
110
-
111
- // Export and check
112
-
113
- const ENV = process.env;
114
-
115
- const privateToken = ENV.GITLAB_PASS;
116
- const projectId = ENV.CI_PROJECT_ID;
117
-
118
- checkVarsExisting([{
119
- field: privateToken,
120
- exceptionMessage: 'GITLAB_PASS must be provided',
121
- }, {
122
- field: projectId,
123
- exceptionMessage: 'CI_PROJECT_ID must be provided',
124
- }]);
125
-
126
- const configGitlabUrl = ENV.CONFIG_GITLAB_URL;
127
- const configVarName = ENV.CONFIG_VAR_NAME;
128
-
129
- export default new Gitlab(privateToken!, Number(projectId), configGitlabUrl, configVarName);