| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491 |
- /* eslint-env es2017 */
- const child_process = require('child_process');
- const crypto = require('crypto');
- const http = require('http');
- const https = require('https');
- const fs = require('fs');
- const os = require('os');
- const path = require('path');
- let configuration = null;
- const load = () => {
- const file = path.join(__dirname, 'package.json');
- const content = fs.readFileSync(file, 'utf-8');
- configuration = JSON.parse(content);
- };
- const write = (message) => {
- if (process.stdout.write) {
- process.stdout.write(message + os.EOL);
- }
- };
- const rm = (...args) => {
- write('rm ' + path.join(...args));
- const dir = path.join(__dirname, ...args);
- fs.rmSync(dir, { recursive: true, force: true });
- };
- const mkdir = (...args) => {
- write('mkdir ' + path.join(...args));
- const dir = path.join(__dirname, ...args);
- fs.mkdirSync(dir, { recursive: true });
- return dir;
- };
- const exec = (command) => {
- try {
- child_process.execSync(command, { cwd: __dirname, stdio: [ 0,1,2 ] });
- } catch (error) {
- process.exit(1);
- }
- };
- const sleep = (delay) => {
- return new Promise((resolve) => {
- setTimeout(resolve, delay);
- });
- };
- const install = () => {
- const node_modules = path.join(__dirname, 'node_modules');
- if (!fs.existsSync(node_modules)) {
- const options = { cwd: __dirname, stdio: [ 0,1,2 ] };
- child_process.execSync('npm install', options);
- }
- };
- const clean = () => {
- rm('dist');
- rm('node_modules');
- rm('package-lock.json');
- };
- const reset = () => {
- clean();
- rm('third_party', 'env');
- rm('third_party', 'source');
- };
- const build = async (target) => {
- switch (target || read()) {
- case 'web': {
- write('build web');
- rm('dist', 'web');
- mkdir('dist', 'web');
- write('cp source/dir dist/dir');
- const source_dir = path.join(__dirname, 'source');
- const dist_dir = path.join(__dirname, 'dist', 'web');
- const extensions = new Set([ 'html', 'css', 'js', 'json', 'ico', 'png' ]);
- for (const file of fs.readdirSync(source_dir)) {
- if (extensions.has(file.split('.').pop())) {
- fs.copyFileSync(path.join(source_dir, file), path.join(dist_dir, file));
- }
- }
- rm('dist', 'web', 'app.js');
- rm('dist', 'web', 'electron.js');
- const manifestFile = path.join(__dirname, 'package.json');
- const contentFile = path.join(__dirname, 'dist', 'web', 'index.html');
- const manifest = JSON.parse(fs.readFileSync(manifestFile, 'utf-8'));
- let content = fs.readFileSync(contentFile, 'utf-8');
- content = content.replace(/(<meta\s*name="version"\s*content=")(.*)(">)/m, (match, p1, p2, p3) => {
- return p1 + manifest.version + p3;
- });
- content = content.replace(/(<meta\s*name="date"\s*content=")(.*)(">)/m, (match, p1, p2, p3) => {
- return p1 + manifest.date + p3;
- });
- fs.writeFileSync(contentFile, content, 'utf-8');
- break;
- }
- case 'electron': {
- write('build electron');
- install();
- exec('npx electron-builder install-app-deps');
- exec('npx electron-builder install-app-deps');
- exec('npx electron-builder --mac --universal --publish never -c.mac.identity=null');
- exec('npx electron-builder --win --x64 --arm64 --publish never');
- exec('npx electron-builder --linux appimage --x64 --publish never');
- exec('npx electron-builder --linux snap --x64 --publish never');
- break;
- }
- case 'python': {
- write('build python');
- exec('python package.py build version');
- exec('python -m pip install --user build wheel --quiet');
- exec('python -m build --no-isolation --wheel --outdir dist/pypi dist/pypi');
- if (read('install')) {
- exec('python -m pip install --force-reinstall dist/pypi/*.whl');
- }
- break;
- }
- default: {
- write('build');
- rm('dist');
- install();
- await build('web');
- await build('electron');
- await build('python');
- break;
- }
- }
- };
- const publish = async (target) => {
- const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
- const GITHUB_USER = process.env.GITHUB_USER;
- switch (target || read()) {
- case 'web': {
- write('publish web');
- build('web');
- rm('dist', 'gh-pages');
- const url = 'https://x-access-token:' + GITHUB_TOKEN + '@github.com/' + GITHUB_USER + '/netron.git';
- exec('git clone --depth=1 ' + url + ' --branch gh-pages ./dist/gh-pages 2>&1 > /dev/null');
- write('cp dist/web dist/gh-pages');
- const source_dir = path.join(__dirname, 'dist', 'web');
- const target_dir = path.join(__dirname, 'dist', 'gh-pages');
- for (const file of fs.readdirSync(target_dir).filter((file) => file !== '.git')) {
- fs.unlinkSync(path.join(target_dir, file));
- }
- for (const file of fs.readdirSync(source_dir)) {
- fs.copyFileSync(path.join(source_dir, file), path.join(target_dir, file));
- }
- exec('git -C dist/gh-pages add --all');
- exec('git -C dist/gh-pages commit --amend --no-edit');
- exec('git -C dist/gh-pages push --force origin gh-pages');
- break;
- }
- case 'electron': {
- write('publish electron');
- install();
- exec('npx electron-builder install-app-deps');
- exec('npx electron-builder --mac --universal --publish always');
- exec('npx electron-builder --win --x64 --arm64 --publish always');
- exec('npx electron-builder --linux appimage --x64 --publish always');
- exec('npx electron-builder --linux snap --x64 --publish always');
- break;
- }
- case 'python': {
- write('publish python');
- build('python');
- exec('python -m pip install --user twine');
- exec('python -m twine upload --non-interactive --skip-existing --verbose dist/pypi/*.whl');
- break;
- }
- case 'cask': {
- write('publish cask');
- const authorization = 'Authorization: token ' + GITHUB_TOKEN;
- exec('curl -s -H "' + authorization + '" -X "DELETE" https://api.github.com/repos/' + GITHUB_USER + '/homebrew-cask 2>&1 > /dev/null');
- await sleep(4000);
- exec('curl -s -H "' + authorization + '"' + " https://api.github.com/repos/Homebrew/homebrew-cask/forks -d '' 2>&1 > /dev/null");
- rm('dist', 'homebrew-cask');
- exec('git clone --depth=2 https://x-access-token:' + GITHUB_TOKEN + '@github.com/' + GITHUB_USER + '/homebrew-cask.git ./dist/homebrew-cask');
- const repository = 'https://github.com/' + configuration.repository;
- const url = repository + '/releases/download/v#{version}/' + configuration.productName + '-#{version}-mac.zip';
- const location = url.replace(/#{version}/g, configuration.version);
- const sha256 = crypto.createHash('sha256').update(await get(location)).digest('hex').toLowerCase();
- const file = path.join(mkdir('dist', 'homebrew-cask', 'Casks'), 'netron.rb');
- fs.writeFileSync(file, [
- 'cask "' + configuration.name + '" do',
- ' version "' + configuration.version + '"',
- ' sha256 "' + sha256 + '"',
- '',
- ' url "' + url + '"',
- ' name "' + configuration.productName + '"',
- ' desc "' + configuration.description + '"',
- ' homepage "' + repository + '"',
- '',
- ' auto_updates true',
- '',
- ' app "' + configuration.productName + '.app"',
- 'end',
- ''
- ].join('\n'));
- exec('git -C dist/homebrew-cask add --all');
- exec('git -C dist/homebrew-cask commit -m "Update ' + configuration.name + ' to ' + configuration.version + '"');
- exec('git -C dist/homebrew-cask push');
- exec('curl -H "' + authorization + '"' + ' https://api.github.com/repos/Homebrew/homebrew-cask/pulls -d "{\\"title\\":\\"Update ' + configuration.name + ' to ' + configuration.version + '\\",\\"base\\":\\"master\\",\\"head\\":\\"' + GITHUB_USER + ':master\\",\\"body\\":\\"Update version and sha256.\\"}" 2>&1 > /dev/null');
- rm('dist', 'homebrew-cask');
- break;
- }
- case 'winget': {
- write('publish winget');
- const authorization = 'Authorization: token ' + GITHUB_TOKEN;
- write('delete github winget-pkgs');
- exec('curl -s -H "' + authorization + '" -X "DELETE" https://api.github.com/repos/' + GITHUB_USER + '/winget-pkgs');
- await sleep(4000);
- write('create github winget-pkgs');
- exec('curl -s -H "' + authorization + '" https://api.github.com/repos/microsoft/winget-pkgs/forks -d ""');
- rm('dist', 'winget-pkgs');
- await sleep(4000);
- write('clone github winget-pkgs');
- exec('git clone --depth=2 https://x-access-token:' + GITHUB_TOKEN + '@github.com/' + GITHUB_USER + '/winget-pkgs.git dist/winget-pkgs');
- const name = configuration.name;
- const version = configuration.version;
- const product = configuration.productName;
- const publisher = configuration.author.name;
- const identifier = publisher.replace(' ', '') + '.' + product;
- const copyright = 'Copyright (c) ' + publisher;
- const repository = 'https://github.com/' + configuration.repository;
- const url = repository + '/releases/download/v' + version + '/' + product + '-Setup-' + version + '.exe';
- const extensions = configuration.build.fileAssociations.map((entry) => '- ' + entry.ext).sort().join('\n');
- write('download ' + url);
- const sha256 = crypto.createHash('sha256').update(await get(url)).digest('hex').toUpperCase();
- const paths = [ 'dist', 'winget-pkgs', 'manifests', publisher[0].toLowerCase(), publisher.replace(' ', ''), product ];
- // rm(...paths);
- // exec('git -C dist/winget-pkgs add --all');
- // exec('git -C dist/winget-pkgs commit -m "Remove ' + configuration.name + '"');
- paths.push(version);
- mkdir(...paths);
- write('create manifest');
- const manifestFile = path.join(__dirname, ...paths, identifier);
- fs.writeFileSync(manifestFile + '.yaml', [
- '# yaml-language-server: $schema=https://aka.ms/winget-manifest.version.1.2.0.schema.json',
- 'PackageIdentifier: ' + identifier,
- 'PackageVersion: ' + version,
- 'DefaultLocale: en-US',
- 'ManifestType: version',
- 'ManifestVersion: 1.2.0',
- ''
- ].join('\n'));
- fs.writeFileSync(manifestFile + '.installer.yaml', [
- '# yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.2.0.schema.json',
- 'PackageIdentifier: ' + identifier,
- 'PackageVersion: ' + version,
- 'Platform:',
- '- Windows.Desktop',
- 'InstallModes:',
- '- silent',
- '- silentWithProgress',
- 'Installers:',
- '- Architecture: x86',
- ' Scope: user',
- ' InstallerType: nullsoft',
- ' InstallerUrl: ' + url,
- ' InstallerSha256: ' + sha256,
- ' InstallerLocale: en-US',
- ' InstallerSwitches:',
- ' Custom: /NORESTART',
- ' UpgradeBehavior: install',
- '- Architecture: arm64',
- ' Scope: user',
- ' InstallerType: nullsoft',
- ' InstallerUrl: ' + url,
- ' InstallerSha256: ' + sha256,
- ' InstallerLocale: en-US',
- ' InstallerSwitches:',
- ' Custom: /NORESTART',
- ' UpgradeBehavior: install',
- 'FileExtensions:',
- extensions,
- 'ManifestType: installer',
- 'ManifestVersion: 1.2.0',
- ''
- ].join('\n'));
- fs.writeFileSync(manifestFile + '.locale.en-US.yaml', [
- '# yaml-language-server: $schema=https://aka.ms/winget-manifest.defaultLocale.1.2.0.schema.json',
- 'PackageIdentifier: ' + identifier,
- 'PackageVersion: ' + version,
- 'PackageName: ' + product,
- 'PackageLocale: en-US',
- 'PackageUrl: ' + repository,
- 'Publisher: ' + publisher,
- 'PublisherUrl: ' + repository,
- 'PublisherSupportUrl: ' + repository + '/issues',
- 'Author: ' + publisher,
- 'License: ' + configuration.license,
- 'Copyright: ' + copyright,
- 'CopyrightUrl: ' + repository + '/blob/main/LICENSE',
- 'ShortDescription: ' + configuration.description,
- 'Description: ' + configuration.description,
- 'Moniker: ' + name,
- 'Tags:',
- '- machine-learning',
- '- deep-learning',
- '- neural-network',
- 'ManifestType: defaultLocale',
- 'ManifestVersion: 1.2.0',
- ''
- ].join('\n'));
- write('commit manifest');
- exec('git -C dist/winget-pkgs add --all');
- exec('git -C dist/winget-pkgs commit -m "Update ' + configuration.name + ' to ' + configuration.version + '"');
- exec('git -C dist/winget-pkgs push');
- exec('curl -H "' + authorization + '" https://api.github.com/repos/microsoft/winget-pkgs/pulls -d "{\\"title\\":\\"Update ' + configuration.productName + ' to ' + configuration.version + '\\",\\"base\\":\\"master\\",\\"head\\":\\"' + GITHUB_USER + ':master\\",\\"body\\":\\"\\"}"');
- rm('dist', 'winget-pkgs');
- break;
- }
- default: {
- write('publish');
- rm('dist');
- install();
- await publish('web');
- await publish('electron');
- await publish('python');
- await publish('cask');
- await publish('winget');
- break;
- }
- }
- };
- const lint = () => {
- install();
- write('eslint');
- exec('npx eslint source/*.js test/*.js publish/*.js tools/*.js');
- write('pylint');
- exec('python -m pip install --upgrade --quiet pylint');
- exec('python -m pylint -sn --recursive=y source test publish tools');
- };
- const update = () => {
- const targets = process.argv.length > 3 ? process.argv.slice(3) : [
- 'armnn',
- 'bigdl',
- 'caffe',
- 'circle',
- 'cntk',
- 'coreml',
- 'dlc',
- 'dnn',
- 'mnn',
- 'mslite',
- 'megengine',
- 'nnabla',
- 'onnx',
- 'om',
- 'paddle',
- 'pytorch',
- 'rknn',
- 'sklearn',
- 'tf',
- 'uff',
- 'xmodel'
- ];
- for (const target of targets) {
- exec('tools/' + target + ' sync install schema metadata');
- }
- };
- const get = (url) => {
- return new Promise((resolve, reject) => {
- const httpModule = url.split(':').shift() === 'https' ? https : http;
- const request = httpModule.request(url, {}, (response) => {
- if (response.statusCode === 200) {
- const data = [];
- let position = 0;
- response.on('data', (chunk) => {
- data.push(chunk);
- position += chunk.length;
- process.stdout.write(' ' + position + ' bytes\r');
- });
- response.on('err', (err) => {
- reject(err);
- });
- response.on('end', () => {
- resolve(Buffer.concat(data));
- });
- } else if (response.statusCode === 302) {
- get(response.headers.location).then((data) => {
- resolve(data);
- }).catch((err) => {
- reject(err);
- });
- } else {
- const err = new Error("The web request failed with status code " + response.statusCode + " at '" + url + "'.");
- err.type = 'error';
- err.url = url;
- err.status = response.statusCode;
- reject(err);
- }
- });
- request.on("error", (err) => {
- reject(err);
- });
- request.end();
- });
- };
- const pull = () => {
- exec('git fetch --prune origin "refs/tags/*:refs/tags/*"');
- exec('git pull --prune --rebase');
- };
- const coverage = () => {
- rm('.nyc_output');
- rm('coverage');
- rm('dist', 'nyc');
- mkdir('dist', 'nyc');
- exec('cp package.json dist/nyc');
- exec('cp -R source dist/nyc');
- exec('nyc instrument --compact false source dist/nyc/source');
- exec('nyc --reporter=lcov --instrument npx electron ./dist/nyc');
- };
- const analyze = () => {
- if (!fs.existsSync('third_party/tools/codeql')) {
- exec('git clone --depth=1 https://github.com/github/codeql.git third_party/tools/codeql');
- }
- rm('dist', 'codeql');
- mkdir('dist', 'codeql', 'netron');
- exec('cp -r publish source test tools dist/codeql/netron/');
- exec('codeql database create dist/codeql/database --source-root dist/codeql/netron --language=javascript --threads=3');
- exec('codeql database analyze dist/codeql/database ./third_party/tools/codeql/javascript/ql/src/codeql-suites/javascript-security-and-quality.qls --format=csv --output=dist/codeql/results.csv --threads=3');
- exec('cat dist/codeql/results.csv');
- };
- const version = () => {
- const file = path.join(__dirname, 'package.json');
- let content = fs.readFileSync(file, 'utf-8');
- content = content.replace(/(\s*"version":\s")(\d\.\d\.\d)(",)/m, (match, p1, p2, p3) => {
- const version = Array.from((parseInt(p2.split('.').join(''), 10) + 1).toString()).join('.');
- return p1 + version + p3;
- });
- content = content.replace(/(\s*"date":\s")(.*)(",)/m, (match, p1, p2, p3) => {
- const date = new Date().toISOString().split('.').shift().split('T').join(' ');
- return p1 + date + p3;
- });
- fs.writeFileSync(file, content, 'utf-8');
- load();
- exec('git add package.json');
- exec('git commit -m "Update to ' + configuration.version + '"');
- exec('git tag v' + configuration.version);
- exec('git push');
- exec('git push --tags');
- };
- const args = process.argv.slice(2);
- const read = (match) => {
- if (args.length > 0 || (!match || args[0] === match)) {
- return args.shift();
- }
- return null;
- };
- const next = async () => {
- try {
- const task = read();
- switch (task) {
- case 'install': clean(); break;
- case 'clean': clean(); break;
- case 'reset': reset(); break;
- case 'build': await build(); break;
- case 'publish': await publish(); break;
- case 'version': version(); break;
- case 'lint': lint(); break;
- case 'update': update(); break;
- case 'pull': pull(); break;
- case 'analyze': analyze(); break;
- case 'coverage': coverage(); break;
- default: throw new Error("Unsupported task '" + task + "'.");
- }
- } catch (err) {
- write(err.message);
- }
- };
- load();
- next();
|