UNPKG

4.1 kBJavaScriptView Raw
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15'use strict';
16
17const crypto = require('crypto');
18const semver = require('semver');
19
20/**
21 * Checks that a change log file takes into account
22 * the signature of a public API (tracks API breakage)
23 * and that the version number in package.json is in sync
24 * with the contents of the changelog.
25 * @private
26 * @class
27 * @memberof module:concerto
28 */
29class VersionChecker {
30
31 /**
32 * @param {string} changelog - the text of a changelog file
33 * @param {string} publicApi - the text of a public API description
34 * @param {string} packageJson - the text of a package.json file
35 * @returns {boolean} true if the version check passes
36 * @throws {Error} if there is an issue with the version check
37 */
38 static check(changelog, publicApi, packageJson) {
39 const changelogLines = changelog.split('\n');
40 const digest = VersionChecker.getDigest(publicApi);
41 let result = false;
42
43 for (let n = 0; n < changelogLines.length; n++) {
44 const line = changelogLines[n];
45
46 if (!line.startsWith('#')) {
47 // find the first instance of 'Version'
48 const versionIndex = line.indexOf('Version');
49 if (versionIndex >= 0) {
50 // find the version number
51 const openBraceIndex = line.indexOf('{', versionIndex);
52
53 if (openBraceIndex < 0) {
54 throw new Error('Invalid changelog, failed to find { in line ' + line);
55 }
56
57 const version = line.substring(versionIndex + 'Version'.length, openBraceIndex).trim();
58
59 // check the version in package.json is up to date
60 const packageObj = JSON.parse(packageJson);
61
62 if (!semver.lte(version, packageObj.version)) {
63 throw new Error(`The version in the changelog file "${version}" is not less than or equal to the version in package.json "${packageObj.version}".`);
64 }
65
66 // get MD5
67 const closeBraceIndex = line.indexOf('}', openBraceIndex);
68
69 if (closeBraceIndex < 0) {
70 throw new Error('Invalid changelog, failed to find } in line ' + line);
71 }
72
73 const md5 = line.substring(openBraceIndex + 1, closeBraceIndex).trim();
74
75 if (digest !== md5) {
76 throw new Error('Computed public API digest did not match the digest in the changelog for the most recent version. ' +
77 'Increment the version number and add a new entry to the changelog (explaining your public API change) using the digest ' + digest +
78 '. Run \'git diff api.txt\' to understand the pubic API changes.');
79 }
80
81 // we're done here...
82 result = true;
83 break;
84 }
85 }
86
87 }
88 if (!result) {
89 throw new Error('Did not find any version in changelog');
90 }
91 else {
92 console.log('SUCCESS: validated public API against package.json and changelog.txt.');
93 }
94
95 return true;
96 }
97
98 /**
99 * Gets the digest (hash) for an input string
100 * @param {string} data - the data to hash
101 * @returns {string} the hash in hex format
102 */
103 static getDigest(data) {
104 return crypto.createHash('md5').update(data).digest('hex');
105 }
106}
107
108module.exports = VersionChecker;