Skip to content

Commit f254776

Browse files
stephenmichaelfbryanmacfarlane
authored andcommitted
Add third party notice and copy files to _build. (#161)
1 parent d681eb5 commit f254776

6 files changed

+864
-73
lines changed

ThirdPartyNotice.txt

+686
Large diffs are not rendered by default.

ThirdPartyNotices.txt

-69
This file was deleted.

generate-third-party-notice.js

+169
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
/**
2+
* Run from the root of the vsts-tasks repo.
3+
* Usage: `node generate-third-party-notice.js <task name>`
4+
*/
5+
const fs = require('fs');
6+
const os = require('os');
7+
const path = require('path');
8+
9+
const log = {
10+
info(message) {
11+
console.log(`[INFO] ${message}`);
12+
},
13+
warning(message) {
14+
console.log(`[WARNING] ${message}`);
15+
},
16+
error(message) {
17+
console.error(`[ERROR] ${message}`)
18+
}
19+
};
20+
21+
/** Log `label: ${value}` and pass the value through. */
22+
function trace(label, value) {
23+
log.info(`${label}: ${value}`);
24+
return value;
25+
}
26+
27+
/**
28+
* Read `packagePath`'s package.json and deserialize it.
29+
* @param packagePath Absolute path to the NPM package
30+
* @returns Package manifest information parsed from the package's package.json
31+
*/
32+
function readPackageJson(packagePath) {
33+
log.info(`Reading the package.json for ${packagePath} ...`);
34+
const contents = fs.readFileSync(path.join(packagePath, 'package.json'), { encoding: 'utf-8' });
35+
return JSON.parse(contents);
36+
}
37+
38+
/**
39+
* Get the name of the file containing the license for `packagePath`.
40+
* @param packagePath Absolute path to the NPM package
41+
* @returns Absolute path to the license file, or `null` if the license file can't be found
42+
*/
43+
function findLicense(packagePath) {
44+
log.info(`Finding the license for '${packagePath}'`);
45+
const children = fs.readdirSync(packagePath);
46+
const licenseNames = [
47+
'LICENSE',
48+
'LICENSE.md',
49+
'LICENSE.txt',
50+
'LICENSE-MIT.txt'
51+
].map(x => x.toLowerCase());
52+
const candidates = children.filter(x => licenseNames.includes(x.toLowerCase()));
53+
if (!candidates || candidates.length === 0) {
54+
log.warning(`Could not find a license for ${packagePath}`);
55+
return null;
56+
} else {
57+
//console.log(JSON.stringify(candidates));
58+
if (candidates.length > 1) {
59+
log.warning(`Found multiple license files for ${packagePath}: ${candidates.join(', ')}`);
60+
}
61+
return trace('Found license', path.join(packagePath, candidates[0]));
62+
}
63+
}
64+
65+
/**
66+
* Scan the contents of the 'node_modules' directory for license information.
67+
* @param modulesRoot NPM package installation directory to scan
68+
* @returns Iterable of objects: `name` x `url` x `licenseText`
69+
*/
70+
function* collectLicenseInfo(modulesRoot) {
71+
const packagePaths = fs.readdirSync(modulesRoot).map(x => path.join(modulesRoot, x));
72+
for (let absolutePath of packagePaths) {
73+
log.info(`Collecting license information from ${absolutePath} ...`);
74+
const name = (() => {
75+
const basename = path.basename(absolutePath);
76+
if (path.dirname(absolutePath).endsWith('@types')) {
77+
return `@types/${basename}`;
78+
} else {
79+
return basename;
80+
}
81+
})();
82+
83+
if (name === '.bin') {
84+
continue;
85+
}
86+
87+
if (name === '@types') {
88+
yield* collectLicenseInfo(absolutePath);
89+
continue;
90+
}
91+
92+
const manifest = readPackageJson(absolutePath);
93+
const license = findLicense(absolutePath);
94+
95+
let licenseText;
96+
if (license) {
97+
licenseText = fs.readFileSync(license, { encoding: 'utf-8' });
98+
} else {
99+
licenseText = 'No license text available.';
100+
}
101+
102+
yield {
103+
name: name,
104+
url: manifest.repository.url,
105+
licenseText: licenseText
106+
};
107+
}
108+
}
109+
110+
/** Generate the third party notice line-by-line. */
111+
function* thirdPartyNotice(libName, licenseInfo) {
112+
// Preamble
113+
yield '';
114+
yield 'THIRD-PARTY SOFTWARE NOTICES AND INFORMATION';
115+
yield 'Do Not Translate or Localize';
116+
yield '';
117+
yield `This Visual Studio Team Services extension (${libName}) is based on or incorporates material from the projects listed below (Third Party IP). The original copyright notice and the license under which Microsoft received such Third Party IP, are set forth below. Such licenses and notices are provided for informational purposes only. Microsoft licenses the Third Party IP to you under the licensing terms for the Visual Studio Team Services extension. Microsoft reserves all other rights not expressly granted under this agreement, whether by implication, estoppel or otherwise.`;
118+
yield '';
119+
120+
// Enumerated modules
121+
let num = 1;
122+
for (let item of licenseInfo) {
123+
if (item.url) {
124+
yield `${num}.\t${item.name} (${item.url})`;
125+
} else {
126+
yield `${num}.\t${item.name}`;
127+
}
128+
num += 1;
129+
}
130+
131+
yield '';
132+
yield '';
133+
134+
// Module licenses
135+
for (let item of licenseInfo) {
136+
yield `%% ${item.name} NOTICES, INFORMATION, AND LICENSE BEGIN HERE`;
137+
yield '=========================================';
138+
yield item.licenseText.trim();
139+
yield '=========================================';
140+
yield `END OF ${item.name} NOTICES, INFORMATION, AND LICENSE`;
141+
yield '';
142+
}
143+
}
144+
145+
function writeLines(writeStream, lines) {
146+
const writeLine = (line) => {
147+
writeStream.write(line);
148+
writeStream.write(os.EOL);
149+
};
150+
151+
for (let line of lines) {
152+
writeLine(line);
153+
}
154+
}
155+
156+
function main(args) {
157+
try {
158+
const nodeModuleDir = path.join(__dirname, 'node_modules');
159+
const licenseInfo = Array.from(collectLicenseInfo(nodeModuleDir));
160+
161+
const writeStream = fs.createWriteStream(path.join(__dirname, 'ThirdPartyNotice.txt'));
162+
writeLines(writeStream, thirdPartyNotice('vsts-task-lib', licenseInfo));
163+
writeStream.end();
164+
} catch (e) {
165+
log.error(e.message);
166+
}
167+
}
168+
169+
main(process.argv);

make.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,16 @@ target.build = function() {
2727
target.clean();
2828

2929
run('tsc --outDir ' + buildPath);
30-
cp(rp('dependencies/typings.json'), buildPath);
30+
3131
cp('-Rf', rp('api/opensource'), buildPath);
32+
33+
cp(rp('dependencies/typings.json'), buildPath);
34+
cp(rp('LICENSE'), buildPath);
3235
cp(rp('package.json'), buildPath);
36+
cp(rp('package-lock.json'), buildPath);
37+
cp(rp('ThirdPartyNotice.txt'), buildPath);
3338
cp(rp('README.md'), buildPath);
34-
cp(rp('LICENSE'), buildPath);
39+
3540
// just a bootstrap file to avoid /// in final js and .d.ts file
3641
rm(path.join(buildPath, 'index.*'));
3742
}

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vso-node-api",
33
"description": "Node client for Visual Studio Online/TFS REST APIs",
4-
"version": "6.3.2",
4+
"version": "6.3.3",
55
"main": "./WebApi.js",
66
"typings": "./WebApi.d.ts",
77
"scripts": {

0 commit comments

Comments
 (0)