@opentermsarchive/engine 2.5.0 → 2.6.0
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/package.json +1 -1
- package/scripts/dataset/publish/github/index.js +36 -0
- package/scripts/dataset/publish/gitlab/index.js +133 -0
- package/scripts/dataset/publish/index.js +11 -32
- package/src/index.js +9 -13
- package/src/reporter/factory.js +13 -0
- package/src/reporter/{github.js → github/index.js} +14 -2
- package/src/reporter/{github.test.js → github/index.test.js} +1 -1
- package/src/reporter/{labels.test.js → github/labels.test.js} +1 -1
- package/src/reporter/gitlab/index.js +386 -0
- package/src/reporter/gitlab/index.test.js +527 -0
- package/src/reporter/gitlab/labels.json +77 -0
- package/src/reporter/gitlab/labels.test.js +30 -0
- package/src/reporter/index.js +54 -16
- package/src/reporter/index.test.js +63 -0
- /package/src/reporter/{labels.json → github/labels.json} +0 -0
package/package.json
CHANGED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fsApi from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import url from 'url';
|
|
4
|
+
|
|
5
|
+
import config from 'config';
|
|
6
|
+
import { Octokit } from 'octokit';
|
|
7
|
+
|
|
8
|
+
import * as readme from '../../assets/README.template.js';
|
|
9
|
+
|
|
10
|
+
export default async function publish({ archivePath, releaseDate, stats }) {
|
|
11
|
+
const octokit = new Octokit({ auth: process.env.OTA_ENGINE_GITHUB_TOKEN });
|
|
12
|
+
|
|
13
|
+
const [ owner, repo ] = url.parse(config.get('@opentermsarchive/engine.dataset.versionsRepositoryURL')).pathname.split('/').filter(component => component);
|
|
14
|
+
|
|
15
|
+
const tagName = `${path.basename(archivePath, path.extname(archivePath))}`; // use archive filename as Git tag
|
|
16
|
+
|
|
17
|
+
const { data: { upload_url: uploadUrl, html_url: releaseUrl } } = await octokit.rest.repos.createRelease({
|
|
18
|
+
owner,
|
|
19
|
+
repo,
|
|
20
|
+
tag_name: tagName,
|
|
21
|
+
name: readme.title({ releaseDate }),
|
|
22
|
+
body: readme.body(stats),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await octokit.rest.repos.uploadReleaseAsset({
|
|
26
|
+
data: fsApi.readFileSync(archivePath),
|
|
27
|
+
headers: {
|
|
28
|
+
'content-type': 'application/zip',
|
|
29
|
+
'content-length': fsApi.statSync(archivePath).size,
|
|
30
|
+
},
|
|
31
|
+
name: path.basename(archivePath),
|
|
32
|
+
url: uploadUrl,
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
return releaseUrl;
|
|
36
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import fsApi from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
|
|
4
|
+
import config from 'config';
|
|
5
|
+
import dotenv from 'dotenv';
|
|
6
|
+
import FormData from 'form-data';
|
|
7
|
+
import nodeFetch from 'node-fetch';
|
|
8
|
+
|
|
9
|
+
import GitLab from '../../../../src/reporter/gitlab/index.js';
|
|
10
|
+
import * as readme from '../../assets/README.template.js';
|
|
11
|
+
import logger from '../../logger/index.js';
|
|
12
|
+
|
|
13
|
+
dotenv.config();
|
|
14
|
+
|
|
15
|
+
export default async function publish({
|
|
16
|
+
archivePath,
|
|
17
|
+
releaseDate,
|
|
18
|
+
stats,
|
|
19
|
+
}) {
|
|
20
|
+
let projectId = null;
|
|
21
|
+
const gitlabAPIUrl = config.get('@opentermsarchive/engine.dataset.apiBaseURL');
|
|
22
|
+
|
|
23
|
+
const [ owner, repo ] = new URL(config.get('@opentermsarchive/engine.dataset.versionsRepositoryURL'))
|
|
24
|
+
.pathname
|
|
25
|
+
.split('/')
|
|
26
|
+
.filter(Boolean);
|
|
27
|
+
const commonParams = { owner, repo };
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const repositoryPath = `${commonParams.owner}/${commonParams.repo}`;
|
|
31
|
+
|
|
32
|
+
const options = GitLab.baseOptionsHttpReq(process.env.OTA_ENGINE_GITLAB_RELEASES_TOKEN);
|
|
33
|
+
|
|
34
|
+
options.method = 'GET';
|
|
35
|
+
options.headers = {
|
|
36
|
+
'Content-Type': 'application/json',
|
|
37
|
+
...options.headers,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const response = await nodeFetch(
|
|
41
|
+
`${gitlabAPIUrl}/projects/${encodeURIComponent(repositoryPath)}`,
|
|
42
|
+
options,
|
|
43
|
+
);
|
|
44
|
+
const res = await response.json();
|
|
45
|
+
|
|
46
|
+
projectId = res.id;
|
|
47
|
+
} catch (error) {
|
|
48
|
+
logger.error(`Error while obtaining projectId: ${error}`);
|
|
49
|
+
projectId = null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const tagName = `${path.basename(archivePath, path.extname(archivePath))}`; // use archive filename as Git tag
|
|
53
|
+
|
|
54
|
+
try {
|
|
55
|
+
let options = GitLab.baseOptionsHttpReq(process.env.OTA_ENGINE_GITLAB_RELEASES_TOKEN);
|
|
56
|
+
|
|
57
|
+
options.method = 'POST';
|
|
58
|
+
options.body = {
|
|
59
|
+
ref: 'main',
|
|
60
|
+
tag_name: tagName,
|
|
61
|
+
name: readme.title({ releaseDate }),
|
|
62
|
+
description: readme.body(stats),
|
|
63
|
+
};
|
|
64
|
+
options.headers = {
|
|
65
|
+
'Content-Type': 'application/json',
|
|
66
|
+
...options.headers,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
options.body = JSON.stringify(options.body);
|
|
70
|
+
|
|
71
|
+
const releaseResponse = await nodeFetch(
|
|
72
|
+
`${gitlabAPIUrl}/projects/${projectId}/releases`,
|
|
73
|
+
options,
|
|
74
|
+
);
|
|
75
|
+
const releaseRes = await releaseResponse.json();
|
|
76
|
+
|
|
77
|
+
const releaseId = releaseRes.commit.id;
|
|
78
|
+
|
|
79
|
+
logger.info(`Created release with releaseId: ${releaseId}`);
|
|
80
|
+
|
|
81
|
+
// Upload the package
|
|
82
|
+
options = GitLab.baseOptionsHttpReq(process.env.OTA_ENGINE_GITLAB_RELEASES_TOKEN);
|
|
83
|
+
options.method = 'PUT';
|
|
84
|
+
options.body = fsApi.createReadStream(archivePath);
|
|
85
|
+
|
|
86
|
+
// restrict characters to the ones allowed by GitLab APIs
|
|
87
|
+
const packageName = config.get('@opentermsarchive/engine.dataset.title').replace(/[^a-zA-Z0-9.\-_]/g, '-');
|
|
88
|
+
const packageVersion = tagName.replace(/[^a-zA-Z0-9.\-_]/g, '-');
|
|
89
|
+
const packageFileName = archivePath.replace(/[^a-zA-Z0-9.\-_/]/g, '-');
|
|
90
|
+
|
|
91
|
+
logger.debug(`packageName: ${packageName}, packageVersion: ${packageVersion} packageFileName: ${packageFileName}`);
|
|
92
|
+
|
|
93
|
+
const packageResponse = await nodeFetch(
|
|
94
|
+
`${gitlabAPIUrl}/projects/${projectId}/packages/generic/${packageName}/${packageVersion}/${packageFileName}?status=default&select=package_file`,
|
|
95
|
+
options,
|
|
96
|
+
);
|
|
97
|
+
const packageRes = await packageResponse.json();
|
|
98
|
+
|
|
99
|
+
const packageFilesId = packageRes.id;
|
|
100
|
+
|
|
101
|
+
logger.debug(`package file id: ${packageFilesId}`);
|
|
102
|
+
|
|
103
|
+
// use the package id to build the download url for the release
|
|
104
|
+
const publishedPackageUrl = `${config.get('@opentermsarchive/engine.dataset.versionsRepositoryURL')}/-/package_files/${packageFilesId}/download`;
|
|
105
|
+
|
|
106
|
+
// Create the release and link the package
|
|
107
|
+
const formData = new FormData();
|
|
108
|
+
|
|
109
|
+
formData.append('name', archivePath);
|
|
110
|
+
formData.append('url', publishedPackageUrl);
|
|
111
|
+
formData.append('file', fsApi.createReadStream(archivePath), { filename: path.basename(archivePath) });
|
|
112
|
+
|
|
113
|
+
options = GitLab.baseOptionsHttpReq(process.env.OTA_ENGINE_GITLAB_RELEASES_TOKEN);
|
|
114
|
+
options.method = 'POST';
|
|
115
|
+
options.headers = {
|
|
116
|
+
...formData.getHeaders(),
|
|
117
|
+
...options.headers,
|
|
118
|
+
};
|
|
119
|
+
options.body = formData;
|
|
120
|
+
|
|
121
|
+
const uploadResponse = await nodeFetch(
|
|
122
|
+
`${gitlabAPIUrl}/projects/${projectId}/releases/${tagName}/assets/links`,
|
|
123
|
+
options,
|
|
124
|
+
);
|
|
125
|
+
const uploadRes = await uploadResponse.json();
|
|
126
|
+
const releaseUrl = uploadRes.direct_asset_url;
|
|
127
|
+
|
|
128
|
+
return releaseUrl;
|
|
129
|
+
} catch (error) {
|
|
130
|
+
logger.error('Failed to create release or upload ZIP file:', error);
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -1,36 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import url from 'url';
|
|
1
|
+
import publishGitHub from './github/index.js';
|
|
2
|
+
import publishGitLab from './gitlab/index.js';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export default function publishRelease({ archivePath, releaseDate, stats }) {
|
|
5
|
+
// If both GitHub and GitLab tokens are defined, GitHub takes precedence
|
|
6
|
+
if (process.env.OTA_ENGINE_GITHUB_TOKEN) {
|
|
7
|
+
return publishGitHub({ archivePath, releaseDate, stats });
|
|
8
|
+
}
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
if (process.env.OTA_ENGINE_GITLAB_TOKEN) {
|
|
11
|
+
return publishGitLab({ archivePath, releaseDate, stats });
|
|
12
|
+
}
|
|
9
13
|
|
|
10
|
-
|
|
11
|
-
const octokit = new Octokit({ auth: process.env.OTA_ENGINE_GITHUB_TOKEN });
|
|
12
|
-
|
|
13
|
-
const [ owner, repo ] = url.parse(config.get('@opentermsarchive/engine.dataset.versionsRepositoryURL')).pathname.split('/').filter(component => component);
|
|
14
|
-
|
|
15
|
-
const tagName = `${path.basename(archivePath, path.extname(archivePath))}`; // use archive filename as Git tag
|
|
16
|
-
|
|
17
|
-
const { data: { upload_url: uploadUrl, html_url: releaseUrl } } = await octokit.rest.repos.createRelease({
|
|
18
|
-
owner,
|
|
19
|
-
repo,
|
|
20
|
-
tag_name: tagName,
|
|
21
|
-
name: readme.title({ releaseDate }),
|
|
22
|
-
body: readme.body(stats),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
await octokit.rest.repos.uploadReleaseAsset({
|
|
26
|
-
data: fsApi.readFileSync(archivePath),
|
|
27
|
-
headers: {
|
|
28
|
-
'content-type': 'application/zip',
|
|
29
|
-
'content-length': fsApi.statSync(archivePath).size,
|
|
30
|
-
},
|
|
31
|
-
name: path.basename(archivePath),
|
|
32
|
-
url: uploadUrl,
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
return releaseUrl;
|
|
14
|
+
throw new Error('No GitHub nor GitLab token found in environment variables (OTA_ENGINE_GITHUB_TOKEN or OTA_ENGINE_GITLAB_TOKEN). Cannot publish the dataset without authentication.');
|
|
36
15
|
}
|
package/src/index.js
CHANGED
|
@@ -55,21 +55,17 @@ export default async function track({ services, types, extractOnly, schedule })
|
|
|
55
55
|
logger.warn('Environment variable "OTA_ENGINE_SENDINBLUE_API_KEY" was not found; the Notifier module will be ignored');
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
if (process.env.OTA_ENGINE_GITHUB_TOKEN) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
logger.error('Cannot instantiate the Reporter module; it will be ignored:', error);
|
|
67
|
-
}
|
|
68
|
-
} else {
|
|
69
|
-
logger.warn('Configuration key "reporter.githubIssues.repositories.declarations" was not found; issues on the declarations repository cannot be created');
|
|
58
|
+
if (process.env.OTA_ENGINE_GITHUB_TOKEN || process.env.OTA_ENGINE_GITLAB_TOKEN) {
|
|
59
|
+
try {
|
|
60
|
+
const reporter = new Reporter(config.get('@opentermsarchive/engine.reporter'));
|
|
61
|
+
|
|
62
|
+
await reporter.initialize();
|
|
63
|
+
archivist.attach(reporter);
|
|
64
|
+
} catch (error) {
|
|
65
|
+
logger.error('Cannot instantiate the Reporter module; it will be ignored:', error);
|
|
70
66
|
}
|
|
71
67
|
} else {
|
|
72
|
-
logger.warn('Environment variable
|
|
68
|
+
logger.warn('Environment variable with token for GitHub or GitLab was not found; the Reporter module will be ignored');
|
|
73
69
|
}
|
|
74
70
|
|
|
75
71
|
if (!schedule) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import GitHub from './github/index.js';
|
|
2
|
+
import GitLab from './gitlab/index.js';
|
|
3
|
+
|
|
4
|
+
export function createReporter(config) {
|
|
5
|
+
switch (config.type) {
|
|
6
|
+
case 'github':
|
|
7
|
+
return new GitHub(config.repositories.declarations);
|
|
8
|
+
case 'gitlab':
|
|
9
|
+
return new GitLab(config.repositories.declarations, config.baseURL, config.apiBaseURL);
|
|
10
|
+
default:
|
|
11
|
+
throw new Error(`Unsupported reporter type: ${config.type}`);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -2,7 +2,7 @@ import { createRequire } from 'module';
|
|
|
2
2
|
|
|
3
3
|
import { Octokit } from 'octokit';
|
|
4
4
|
|
|
5
|
-
import logger from '
|
|
5
|
+
import logger from '../../logger/index.js';
|
|
6
6
|
|
|
7
7
|
const require = createRequire(import.meta.url);
|
|
8
8
|
|
|
@@ -14,7 +14,7 @@ export default class GitHub {
|
|
|
14
14
|
static ISSUE_STATE_ALL = 'all';
|
|
15
15
|
|
|
16
16
|
constructor(repository) {
|
|
17
|
-
const { version } = require('
|
|
17
|
+
const { version } = require('../../../package.json');
|
|
18
18
|
|
|
19
19
|
this.octokit = new Octokit({
|
|
20
20
|
auth: process.env.OTA_ENGINE_GITHUB_TOKEN,
|
|
@@ -198,4 +198,16 @@ export default class GitHub {
|
|
|
198
198
|
logger.error(`Failed to update issue "${title}": ${error.stack}`);
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
|
+
|
|
202
|
+
generateDeclarationURL(serviceName) {
|
|
203
|
+
return `https://github.com/${this.commonParams.owner}/${this.commonParams.repo}/blob/main/declarations/${encodeURIComponent(serviceName)}.json`;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
generateVersionURL(serviceName, termsType) {
|
|
207
|
+
return `https://github.com/${this.commonParams.owner}/${this.commonParams.repo}/blob/main/${encodeURIComponent(serviceName)}/${encodeURIComponent(termsType)}.md`;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
generateSnapshotsBaseUrl(serviceName, termsType) {
|
|
211
|
+
return `https://github.com/${this.commonParams.owner}/${this.commonParams.repo}/blob/main/${encodeURIComponent(serviceName)}/${encodeURIComponent(termsType)}`;
|
|
212
|
+
}
|
|
201
213
|
}
|