CLI: Add product and version information to the halotools binaries (#296)

This commit is contained in:
Michał Leszczyński
2024-01-06 21:23:03 +01:00
committed by GitHub
parent 9fd746362a
commit 65768baf65
15 changed files with 170 additions and 49 deletions

View File

@@ -91,15 +91,19 @@ jobs:
shell: bash
run: |
cd cli
node build/ci_scripts.js --platform linux --product cli
node_modules/.bin/pkg --compress GZip -t node18-linux-x64 -c package.json -o dist/halocli entry_cli.js
node build/ci_scripts.js --platform linux --product bridge
node_modules/.bin/pkg --compress GZip -t node18-linux-x64 -c package.json -o dist/halo-bridge entry_bridge.js
node build/ci_scripts.js --platform linux --product gateway
node_modules/.bin/pkg --compress GZip -t node18-linux-x64 -c package.json -o dist/halo-gateway entry_gateway.js
- name: Package HaLo CLI tool (Windows)
if: matrix.os == 'windows-latest'
shell: bash
run: |
cd cli
node win_fix_binary.js cli
node build/ci_scripts.js --platform windows --product cli
cat halotools_version.json
export PKG_PATCHED_BIN='1'
export PKG_CACHE_PATH='./.pkg-cache/'
export PKG_IGNORE_TAG='1'
@@ -109,7 +113,7 @@ jobs:
shell: bash
run: |
cd cli
node win_fix_binary.js bridge
node build/ci_scripts.js --platform windows --product bridge
export PKG_PATCHED_BIN='1'
export PKG_CACHE_PATH='./.pkg-cache/'
export PKG_IGNORE_TAG='1'
@@ -119,7 +123,7 @@ jobs:
shell: bash
run: |
cd cli
node win_fix_binary.js gateway
node build/ci_scripts.js --platform windows --product gateway
export PKG_PATCHED_BIN='1'
export PKG_CACHE_PATH='./.pkg-cache/'
export PKG_IGNORE_TAG='1'
@@ -129,8 +133,11 @@ jobs:
shell: bash
run: |
cd cli
node build/ci_scripts.js --platform macos --product cli
node_modules/.bin/pkg --compress GZip -t node18-macos-x64 -c package.json -o dist/halocli entry_cli.js
node build/ci_scripts.js --platform macos --product bridge
node_modules/.bin/pkg --compress GZip -t node18-macos-x64 -c package.json -o dist/halo-bridge entry_bridge.js
node build/ci_scripts.js --platform macos --product gateway
node_modules/.bin/pkg --compress GZip -t node18-macos-x64 -c package.json -o dist/halo-gateway entry_gateway.js
mv "macos_bridge_app" "dist/HaLo CLI Bridge Server.app"
mv "macos_pkgbuild_scripts" "dist/macos_pkgbuild_scripts"

View File

@@ -6,6 +6,7 @@
const {ArgumentParser} = require("argparse");
const {JSONParseAction} = require("./actions");
const {printVersionInfo} = require("./version");
const parser = new ArgumentParser({
description: 'HaLo - Command Line Tool for PC/SC'
@@ -16,6 +17,8 @@ const subparsers = parser.add_subparsers({help: 'command', dest: 'name'});
subparsers.add_parser("version", {help: "Get tag version."});
subparsers.add_parser("cli_version", {help: "Get halocli build version."});
if (process.env.__UNSAFE_ENABLE_TESTS === "1") {
let testParser = subparsers.add_parser("test", {help: "Run test suite against the tag. Please do not use this command."});
testParser.add_argument("--unsafe", {
@@ -379,6 +382,7 @@ function parseArgs() {
let args = parser.parse_args();
if (!args.name) {
printVersionInfo();
parser.print_help();
return null;
}

24
cli/build/ci_scripts.js Normal file
View File

@@ -0,0 +1,24 @@
const {ArgumentParser} = require("argparse");
const {doFixWinBinary} = require("./win_fix_binary");
const {parseGitHubRef, getProductInfo} = require("./version_helper");
const {writeFileSync} = require("fs");
async function runCIScripts() {
const parser = new ArgumentParser({
description: "GitHub Actions CI Entrypoint"
});
parser.add_argument("--platform", {required: true});
parser.add_argument("--product", {required: true});
let args = parser.parse_args();
if (args.platform.includes("windows")) {
await doFixWinBinary(args.product);
}
let productInfo = getProductInfo(args.product);
let versionInfo = parseGitHubRef();
writeFileSync('halotools_version.json', JSON.stringify({...productInfo, ...versionInfo}));
}
runCIScripts();

View File

@@ -0,0 +1,40 @@
function parseGitHubRef() {
let commitId = process.env.GITHUB_SHA;
let tagName = process.env.GITHUB_REF_NAME;
let version = null;
if (tagName && tagName.startsWith('halotools-v')) {
let vStr = tagName.split('-v')[1];
let vStr2 = vStr.split('.');
version = [parseInt(vStr2[0]), parseInt(vStr2[1]), parseInt(vStr2[2]), 0];
} else {
version = [0, 0, 0, 0];
}
return {
commitId,
tagName,
version
};
}
function getProductInfo(productType) {
let name, binName;
if (productType === "cli") {
name = 'HaLo CLI';
binName = 'halocli.exe';
} else if (productType === "bridge") {
name = 'HaLo Bridge Server';
binName = 'halo-bridge.exe';
} else if (productType === "gateway") {
name = 'HaLo Gateway Server';
binName = 'halo-gateway.exe';
} else {
throw Error("Unknown product type specified.");
}
return {name, binName};
}
module.exports = {parseGitHubRef, getProductInfo};

View File

@@ -4,8 +4,9 @@ const { readFileSync, writeFileSync } = require('fs');
// purposely not declared in package.json, the "pkg-fetch" will be
// implicitly installed by "pkg" dev dependency in correct version
const { need, system } = require('pkg-fetch');
const package_json = require('./package.json');
const package_json = require('../package.json');
const crypto = require("crypto");
const {parseGitHubRef, getProductInfo} = require("./version_helper");
const {
hostArch,
@@ -95,39 +96,16 @@ async function fixBinary(name, bin_name, version) {
fs.appendFileSync('node_modules\\pkg-fetch\\lib-es5\\expected.js', '\n/** PATCHED **/ if (process.env.PKG_PATCHED_BIN === "1") {exports.EXPECTED_HASHES[\'' + nodeHashKey + '\'] = \'' + fileHash + '\';}');
}
let name = null;
let binName = null;
async function doFixWinBinary(productType) {
let {name, binName} = getProductInfo(productType);
let {version} = parseGitHubRef();
console.log('Using version', version);
await fixBinary(name, binName, version);
if (process.argv.length < 3) {
throw Error("Binary type not specified in argv.");
} else if (process.argv[2] === "cli") {
name = 'HaLo CLI';
binName = 'halocli.exe';
} else if (process.argv[2] === "bridge") {
name = 'HaLo Bridge Server';
binName = 'halo-bridge.exe';
} else if (process.argv[2] === "gateway") {
name = 'HaLo Gateway Server';
binName = 'halo-gateway.exe';
} else {
throw Error("Unknown binary type specified.");
// run pkg with:
// $env:PKG_PATCHED_BIN = 1
// $env:PKG_CACHE_PATH = './.pkg-cache/'
// $env:PKG_IGNORE_TAG = 1
}
let tagName = process.env.GITHUB_REF_NAME;
let version = null;
if (tagName && tagName.startsWith('halotools-v')) {
let vStr = tagName.split('-v')[1];
let vStr2 = vStr.split('.');
version = [parseInt(vStr2[0]), parseInt(vStr2[1]), parseInt(vStr2[2]), 0];
} else {
version = [0, 0, 0, 0];
}
console.log('Using version', version);
fixBinary(name, binName, version);
// run pkg with:
// $env:PKG_PATCHED_BIN = 1
// $env:PKG_CACHE_PATH = './.pkg-cache/'
// $env:PKG_IGNORE_TAG = 1
module.exports = {doFixWinBinary};

View File

@@ -141,9 +141,9 @@ function runHalo(entryMode, args) {
console.error('Command execution failed.');
} else if (code !== "done") {
if (output === "color") {
console.error("NFC card or compatible PC/SC reader not found.");
console.error("HaLo tag or compatible PC/SC reader not found.");
} else {
console.log(JSON.stringify({"_error": "NFC card or compatible PC/SC reader not found."}));
console.log(JSON.stringify({"_error": "HaLo tag or compatible PC/SC reader not found."}));
}
}

View File

@@ -6,6 +6,7 @@
const {parseArgs} = require('./args_bridge.js');
const {runHalo} = require("./cli");
const {printVersionInfo} = require("./version");
let args = parseArgs();
@@ -13,4 +14,5 @@ if (!args) {
process.exit(0);
}
printVersionInfo();
runHalo("server", args);

View File

@@ -6,10 +6,20 @@
const {parseArgs} = require('./args_cli.js');
const {runHalo} = require("./cli");
const {printVersionInfo, getVersionInfo} = require("./version");
let args = parseArgs();
if (!args) {
if (args && args.name === "cli_version") {
if (args.output === "json") {
let versionInfo = getVersionInfo() ?? {};
console.log(JSON.stringify(versionInfo));
} else {
printVersionInfo();
}
}
if (!args || args.name === "cli_version") {
process.exit(0);
}

View File

@@ -5,14 +5,18 @@
*/
const crypto = require('crypto').webcrypto;
const {parseArgs} = require('./args_gateway.js');
const express = require("express");
const {WebSocketServer} = require("ws");
const {WebSocketServer} = require('ws');
const queryString = require('query-string');
const {dirname} = require("./util");
const nunjucks = require("nunjucks");
const {parse} = require("url");
const {parseArgs} = require('./args_gateway.js');
const {printVersionInfo, getBuildInfo} = require("./version");
const {dirname} = require("./util");
let buildInfo = getBuildInfo();
const REQUESTOR_SESS_LIMIT = 10 * 60 * 1000;
const MAX_SESSION_LIMIT = 1000;
@@ -92,7 +96,8 @@ function processRequestor(ws, req) {
ws.send(JSON.stringify({
"type": "welcome",
"sessionId": sessionId
"sessionId": sessionId,
"serverVersion": buildInfo
}));
}
@@ -222,4 +227,5 @@ function createServer(args) {
console.log('HaLo Gateway server is listening...');
}
printVersionInfo();
createServer(args);

View File

@@ -34,7 +34,8 @@
"outputPath": "dist",
"assets": [
"node_modules/@pokusew/pcsclite/build/Release/pcsclite.node",
"assets/**"
"assets/**",
"halotools_version.json"
]
},
"type": "commonjs",

30
cli/version.js Normal file
View File

@@ -0,0 +1,30 @@
const fs = require("fs");
const {dirname} = require("./util");
function getVersionInfo() {
if (fs.existsSync(dirname + '/halotools_version.json')) {
return JSON.parse(fs.readFileSync(dirname + '/halotools_version.json', 'utf-8'));
} else {
return null;
}
}
function getBuildInfo() {
let versionInfo = getVersionInfo();
return {
tagName: versionInfo ? versionInfo.tagName : 'SNAPSHOT',
commitId: versionInfo ? versionInfo.commitId : 'SNAPSHOT',
version: versionInfo ? versionInfo.version : [0, 0, 0, 0]
};
}
function printVersionInfo() {
let versionInfo = getVersionInfo();
if (versionInfo) {
console.log(versionInfo.name + ' (' + versionInfo.tagName + '; ' + versionInfo.commitId + ')');
}
}
module.exports = {getVersionInfo, printVersionInfo, getBuildInfo};

View File

@@ -10,6 +10,7 @@ const path = require("path");
const os = require("os");
const util = require("util");
const {execHaloCmdPCSC} = require("../api/desktop");
const {getBuildInfo} = require("./version");
let wss = null;
@@ -19,6 +20,8 @@ let currentState = null;
let jwtSigningKey = randomBuffer().toString('hex');
let userConsentOrigins = new Set();
let buildInfo = getBuildInfo();
function generateHandle() {
return randomBuffer().toString('base64');
}
@@ -324,7 +327,13 @@ function wsCreateServer(args, getReaderNames) {
sendToCurrentWs(ws, {
"event": "ws_connected",
"uid": null,
"data": {}
"data": {
"server_version": {
tag_name: buildInfo.tagName,
commit_id: buildInfo.commitId,
version: buildInfo.version
}
}
});
let readerNames = getReaderNames();

View File

@@ -82,7 +82,7 @@ Where the `event` key is a string representing the name of particular event.
Possible incoming events are the following:
* `ws_connected` - welcome event sent by the server;
* `ws_connected` - welcome event sent by the server, contains server's version information in `data.server_version`;
* `reader_added` - a new NFC reader was detected, the reader's name will be provided as `data.reader_name`;
* `reader_removed` - the existing NFC reader was disconnected, the reader's name will be provided as `data.reader_name`;
* `handle_added` - a reader has detected new HaLo tag (`data.reader_name` - reader's name, `data.handle` - random value, a handle to the connected tag);

View File

@@ -94,6 +94,7 @@ class HaloGateway {
let waitPromise = this.waitForWelcomePacket();
await this.ws.open();
let welcomeMsg = await waitPromise;
let serverVersion = welcomeMsg.serverVersion;
/**
* URL format in the QR Code:
@@ -116,7 +117,8 @@ class HaloGateway {
return {
execURL: execURL,
qrCode: qrCode
qrCode: qrCode,
serverVersion: serverVersion
};
}

View File

@@ -22,6 +22,11 @@
font-size: 10px;
color: gray;
}
#server-ver {
font-size: 10px;
color: gray;
}
</style>
</head>
<body>
@@ -48,8 +53,9 @@
<pre id="statusText" style="word-break: break-all; white-space: pre-wrap;"></pre>
<img id="qr" src="data:," alt>
<div class="qr-link-container">
<a href="about:blank" id="qr-link"></a>
<a href="about:blank" target="_blank" id="qr-link"></a>
</div>
<div id="server-ver"></div>
<script type="text/javascript">
// generate random message on load
@@ -79,6 +85,8 @@
document.getElementById('qr').src = pairInfo.qrCode;
document.getElementById('qr-link').href = pairInfo.execURL;
document.getElementById('qr-link').innerText = pairInfo.execURL;
document.getElementById('server-ver').innerText =
'Server version: ' + pairInfo.serverVersion.tagName + '; ' + pairInfo.serverVersion.commitId;
log('Please scan the QR code presented below with your smartphone.');
} catch (e) {
document.getElementById('pairSignBtn').disabled = false;