c8ctl-plugin-nano 1.0.0 → 1.1.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/README.md +42 -12
- package/c8ctl-plugin.js +127 -4
- package/nanobpmn-binary.json +4 -4
- package/package.json +6 -6
- package/platforms.mjs +8 -6
package/README.md
CHANGED
|
@@ -124,6 +124,27 @@ Persistent settings are stored in `<state home>/config.json`:
|
|
|
124
124
|
|
|
125
125
|
Show the effective configuration and all on-disk locations with `c8ctl nano config`.
|
|
126
126
|
|
|
127
|
+
## Updating to a new release (`update`)
|
|
128
|
+
|
|
129
|
+
The plugin and the bundled server binary (delivered via the matching platform
|
|
130
|
+
package) ship together on npm as `c8ctl-plugin-nano`. To pull a new nanobpmn
|
|
131
|
+
release onto a machine that already has nano installed:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
c8ctl nano update # check npm for a newer release and install it
|
|
135
|
+
c8ctl nano update --check # only report whether an update is available
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`update` compares the installed plugin version against the latest published on
|
|
139
|
+
npm. When a newer release exists it reinstalls the package globally
|
|
140
|
+
(`npm install -g c8ctl-plugin-nano@latest`), which brings the new server binary
|
|
141
|
+
with it. It only ever drives npm — it never touches the private upstream source —
|
|
142
|
+
so it works for any npm-installed user. After updating, restart any running
|
|
143
|
+
cluster (`c8ctl nano restart`) so it picks up the new binary.
|
|
144
|
+
|
|
145
|
+
If the plugin is running from a local checkout rather than a global npm install,
|
|
146
|
+
`update` prints the manual command instead of reinstalling in place.
|
|
147
|
+
|
|
127
148
|
## Checking status
|
|
128
149
|
|
|
129
150
|
`c8ctl nano status` queries each node's always-on `GET /v2/topology`, which is the
|
|
@@ -261,8 +282,9 @@ The plugin needs a built `nanobpmn` server binary. Resolution order:
|
|
|
261
282
|
1. `--binary <path>`
|
|
262
283
|
2. configured path (`c8ctl nano set bin <path>`)
|
|
263
284
|
3. `NANOBPMN_BINARY=<path>`
|
|
264
|
-
4. the matching **platform package** (
|
|
265
|
-
automatically as an `optionalDependency` when you install the plugin
|
|
285
|
+
4. the matching **platform package** (`@nanobpm/c8ctl-plugin-nano-<os>-<arch>`),
|
|
286
|
+
installed automatically as an `optionalDependency` when you install the plugin
|
|
287
|
+
from npm
|
|
266
288
|
5. `release` build under the nanobpmn repo
|
|
267
289
|
6. `debug` build under the nanobpmn repo
|
|
268
290
|
|
|
@@ -426,15 +448,16 @@ publishes to npm, and creates a GitHub Release.
|
|
|
426
448
|
### Platform packages
|
|
427
449
|
|
|
428
450
|
The server binary is shipped as a set of platform-specific npm packages, one per
|
|
429
|
-
target, gated by npm's `os`/`cpu` fields
|
|
451
|
+
target, gated by npm's `os`/`cpu` fields. They are **scoped under `@nanobpm`** (a
|
|
452
|
+
scope we own) so the names can never be squatted or npm-security-held:
|
|
430
453
|
|
|
431
|
-
| package
|
|
432
|
-
|
|
433
|
-
|
|
|
434
|
-
|
|
|
435
|
-
|
|
|
436
|
-
|
|
|
437
|
-
|
|
|
454
|
+
| package | os | cpu |
|
|
455
|
+
|--------------------------------------------|--------|-------|
|
|
456
|
+
| `@nanobpm/c8ctl-plugin-nano-darwin-arm64` | darwin | arm64 |
|
|
457
|
+
| `@nanobpm/c8ctl-plugin-nano-darwin-x64` | darwin | x64 |
|
|
458
|
+
| `@nanobpm/c8ctl-plugin-nano-linux-x64` | linux | x64 |
|
|
459
|
+
| `@nanobpm/c8ctl-plugin-nano-linux-arm64` | linux | arm64 |
|
|
460
|
+
| `@nanobpm/c8ctl-plugin-nano-win32-x64` | win32 | x64 |
|
|
438
461
|
|
|
439
462
|
The root `c8ctl-plugin-nano` lists all five as `optionalDependencies` (pinned to
|
|
440
463
|
the exact release version, injected into the published tarball at release time).
|
|
@@ -487,7 +510,14 @@ with provenance (`NPM_CONFIG_PROVENANCE: true`, requires this repo to be public)
|
|
|
487
510
|
Trusted Publishing is per-package and requires the package to already exist, so:
|
|
488
511
|
|
|
489
512
|
1. **Bootstrap** the first release with a granular-automation `NPM_TOKEN` secret —
|
|
490
|
-
it is used automatically and creates all six packages.
|
|
513
|
+
it is used automatically and creates all six packages. The token must have
|
|
514
|
+
**publish rights to the `@nanobpm` scope** (the platform packages are scoped).
|
|
491
515
|
2. On npmjs.com, add a **Trusted Publisher** (this repo + `release.yml`) for the
|
|
492
|
-
root package and each of the five platform
|
|
516
|
+
root package and each of the five `@nanobpm/c8ctl-plugin-nano-*` platform
|
|
517
|
+
packages.
|
|
493
518
|
3. Remove the `NPM_TOKEN` secret; subsequent releases authenticate via OIDC.
|
|
519
|
+
|
|
520
|
+
> Note: because the platform packages are **scoped** (`@nanobpm/…`), they sidestep
|
|
521
|
+
> the unscoped-name squatting/`0.0.1-security` hold that previously blocked
|
|
522
|
+
> `c8ctl-plugin-nano-win32-x64`. If you ever add a new platform, its scoped name is
|
|
523
|
+
> yours to publish immediately.
|
package/c8ctl-plugin.js
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* c8ctl nano restart [<nodes>] ...
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
-
import { spawn } from 'node:child_process';
|
|
28
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
29
29
|
import {
|
|
30
30
|
existsSync,
|
|
31
31
|
mkdirSync,
|
|
@@ -63,8 +63,9 @@ function readBundledBinaryInfo() {
|
|
|
63
63
|
|
|
64
64
|
/**
|
|
65
65
|
* Locate the nanobpmn binary shipped by the matching platform package
|
|
66
|
-
* (an optionalDependency such as c8ctl-plugin-nano-darwin-arm64).
|
|
67
|
-
* absolute path, or undefined if the package isn't installed for
|
|
66
|
+
* (an optionalDependency such as @nanobpm/c8ctl-plugin-nano-darwin-arm64).
|
|
67
|
+
* Returns the absolute path, or undefined if the package isn't installed for
|
|
68
|
+
* this host.
|
|
68
69
|
*/
|
|
69
70
|
function findPlatformPackageBinary() {
|
|
70
71
|
const p = platformForHost();
|
|
@@ -257,7 +258,7 @@ function findBinary(flags) {
|
|
|
257
258
|
// Argument parsing
|
|
258
259
|
// ---------------------------------------------------------------------------
|
|
259
260
|
|
|
260
|
-
const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'config'];
|
|
261
|
+
const VALID_SUBCOMMANDS = ['start', 'stop', 'status', 'logs', 'log', 'restart', 'pause', 'resume', 'clean', 'set', 'config', 'update'];
|
|
261
262
|
|
|
262
263
|
/**
|
|
263
264
|
* Parse positional args + flags into a normalized request.
|
|
@@ -288,6 +289,7 @@ function parseRequest(args, flags) {
|
|
|
288
289
|
force: Boolean(flags?.force),
|
|
289
290
|
capture: Boolean(flags?.capture),
|
|
290
291
|
workspace: Boolean(flags?.workspace),
|
|
292
|
+
check: Boolean(flags?.check),
|
|
291
293
|
binary: flags?.binary,
|
|
292
294
|
};
|
|
293
295
|
}
|
|
@@ -1106,6 +1108,119 @@ function showConfig() {
|
|
|
1106
1108
|
console.log(' Change with: c8ctl nano set bin <path> | c8ctl nano set model-dir <path>');
|
|
1107
1109
|
}
|
|
1108
1110
|
|
|
1111
|
+
// ---------------------------------------------------------------------------
|
|
1112
|
+
// update — pull a new nanobpmn release onto a machine with an existing install.
|
|
1113
|
+
// The plugin (and the bundled server binary, shipped via the matching platform
|
|
1114
|
+
// package) is distributed on npm as c8ctl-plugin-nano, so a release is pulled by
|
|
1115
|
+
// reinstalling the package globally. We only ever drive npm here — never touch
|
|
1116
|
+
// the private upstream source — so this works for any npm-installed user.
|
|
1117
|
+
// ---------------------------------------------------------------------------
|
|
1118
|
+
|
|
1119
|
+
/** This plugin package's identity, read from its own package.json. */
|
|
1120
|
+
function pluginPackage() {
|
|
1121
|
+
try {
|
|
1122
|
+
const pkg = JSON.parse(readFileSync(join(pluginDir, 'package.json'), 'utf8'));
|
|
1123
|
+
return { name: pkg.name || 'c8ctl-plugin-nano', version: pkg.version || null };
|
|
1124
|
+
} catch {
|
|
1125
|
+
return { name: 'c8ctl-plugin-nano', version: null };
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* Numeric semver comparison (major.minor.patch), ignoring any pre-release/build
|
|
1131
|
+
* suffix. Returns -1 if a<b, 0 if equal, 1 if a>b.
|
|
1132
|
+
*/
|
|
1133
|
+
function compareSemver(a, b) {
|
|
1134
|
+
const norm = (v) =>
|
|
1135
|
+
String(v)
|
|
1136
|
+
.replace(/^v/, '')
|
|
1137
|
+
.split(/[-+]/)[0]
|
|
1138
|
+
.split('.')
|
|
1139
|
+
.map((n) => Number.parseInt(n, 10) || 0);
|
|
1140
|
+
const av = norm(a);
|
|
1141
|
+
const bv = norm(b);
|
|
1142
|
+
for (let i = 0; i < 3; i++) {
|
|
1143
|
+
const x = av[i] || 0;
|
|
1144
|
+
const y = bv[i] || 0;
|
|
1145
|
+
if (x !== y) return x < y ? -1 : 1;
|
|
1146
|
+
}
|
|
1147
|
+
return 0;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
/** Latest published version of `name` per the npm registry (throws on failure). */
|
|
1151
|
+
function npmLatestVersion(name) {
|
|
1152
|
+
const res = spawnSync('npm', ['view', name, 'version'], { encoding: 'utf8' });
|
|
1153
|
+
if (res.error) throw new Error(res.error.message);
|
|
1154
|
+
if (res.status !== 0) {
|
|
1155
|
+
throw new Error((res.stderr || '').trim() || `npm view exited ${res.status}`);
|
|
1156
|
+
}
|
|
1157
|
+
return res.stdout.trim();
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/** True when this plugin lives under npm's global node_modules (so `-g` updates it). */
|
|
1161
|
+
function isGlobalInstall() {
|
|
1162
|
+
const res = spawnSync('npm', ['root', '-g'], { encoding: 'utf8' });
|
|
1163
|
+
if (res.status !== 0) return false;
|
|
1164
|
+
const root = res.stdout.trim();
|
|
1165
|
+
return Boolean(root) && pluginDir.startsWith(root);
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
function updatePlugin(req) {
|
|
1169
|
+
const { name, version: current } = pluginPackage();
|
|
1170
|
+
const bundled = readBundledBinaryInfo();
|
|
1171
|
+
const nanoNote = bundled ? ` (bundled nano ${bundled.version})` : '';
|
|
1172
|
+
const manual = ` npm install -g ${name}@latest`;
|
|
1173
|
+
|
|
1174
|
+
console.log(`Installed: ${name} v${current ?? '?'}${nanoNote}`);
|
|
1175
|
+
|
|
1176
|
+
let latest;
|
|
1177
|
+
try {
|
|
1178
|
+
latest = npmLatestVersion(name);
|
|
1179
|
+
} catch (err) {
|
|
1180
|
+
console.log(`Could not check npm for updates: ${err.message}`);
|
|
1181
|
+
console.log('Pull the latest release manually with:');
|
|
1182
|
+
console.log(manual);
|
|
1183
|
+
return;
|
|
1184
|
+
}
|
|
1185
|
+
console.log(`Latest: ${name} v${latest} (npm)`);
|
|
1186
|
+
console.log('');
|
|
1187
|
+
|
|
1188
|
+
if (current && compareSemver(current, latest) >= 0) {
|
|
1189
|
+
console.log('Already on the latest release — nothing to do.');
|
|
1190
|
+
return;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
console.log(`Update available: v${current ?? '?'} -> v${latest}`);
|
|
1194
|
+
|
|
1195
|
+
if (req.check) {
|
|
1196
|
+
console.log('Run `c8ctl nano update` to pull it (or manually):');
|
|
1197
|
+
console.log(manual);
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
if (!isGlobalInstall()) {
|
|
1202
|
+
console.log('This plugin is not a global npm install, so it cannot self-update in place.');
|
|
1203
|
+
console.log('Pull the latest release with:');
|
|
1204
|
+
console.log(manual);
|
|
1205
|
+
console.log('(or, for a local checkout, `git pull` then reload the plugin).');
|
|
1206
|
+
return;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
console.log(`Pulling ${name}@${latest} via npm...`);
|
|
1210
|
+
console.log('');
|
|
1211
|
+
const res = spawnSync('npm', ['install', '-g', `${name}@${latest}`], { stdio: 'inherit' });
|
|
1212
|
+
if (res.error) throw new Error(res.error.message);
|
|
1213
|
+
if (res.status !== 0) {
|
|
1214
|
+
throw new Error(
|
|
1215
|
+
`npm install -g ${name}@${latest} failed (exit ${res.status}). ` +
|
|
1216
|
+
`You may need elevated permissions: sudo ${manual.trim()}`,
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1219
|
+
console.log('');
|
|
1220
|
+
console.log(`Updated to v${latest}. Restart any running cluster to use the new binary:`);
|
|
1221
|
+
console.log(' c8ctl nano restart');
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1109
1224
|
// ---------------------------------------------------------------------------
|
|
1110
1225
|
// processos — manage a single local ProcessOS instance (the optimization-plane
|
|
1111
1226
|
// server that analyses a running Nano BPM engine). Unlike nano, the ProcessOS
|
|
@@ -1662,6 +1777,8 @@ export const metadata = {
|
|
|
1662
1777
|
{ command: 'c8ctl nano set bin <path>', description: 'Set the nanobpmn server binary path' },
|
|
1663
1778
|
{ command: 'c8ctl nano set model-dir <path>', description: 'Set the workspace dir (models + workers)' },
|
|
1664
1779
|
{ command: 'c8ctl nano config', description: 'Show current plugin configuration and paths' },
|
|
1780
|
+
{ command: 'c8ctl nano update', description: 'Pull the latest published nano release (re-installs via npm)' },
|
|
1781
|
+
{ command: 'c8ctl nano update --check', description: 'Check whether a newer nano release is available' },
|
|
1665
1782
|
],
|
|
1666
1783
|
},
|
|
1667
1784
|
processos: {
|
|
@@ -1695,6 +1812,7 @@ export const commands = {
|
|
|
1695
1812
|
purge: { type: 'boolean', description: 'stop: also delete per-node engine data' },
|
|
1696
1813
|
force: { type: 'boolean', description: 'start: stop any existing cluster first' },
|
|
1697
1814
|
workspace: { type: 'boolean', description: 'clean: also delete the workspace (models + workers)' },
|
|
1815
|
+
check: { type: 'boolean', description: 'update: only report whether a new release is available; do not install' },
|
|
1698
1816
|
binary: { type: 'string', description: 'Path to the nanobpmn server binary' },
|
|
1699
1817
|
},
|
|
1700
1818
|
handler: async (args, flags) => {
|
|
@@ -1740,6 +1858,9 @@ export const commands = {
|
|
|
1740
1858
|
case 'config':
|
|
1741
1859
|
showConfig();
|
|
1742
1860
|
break;
|
|
1861
|
+
case 'update':
|
|
1862
|
+
updatePlugin(req);
|
|
1863
|
+
break;
|
|
1743
1864
|
}
|
|
1744
1865
|
} catch (error) {
|
|
1745
1866
|
logger.error(`nano ${req.subcommand} failed: ${error instanceof Error ? error.message : error}`);
|
|
@@ -1812,6 +1933,7 @@ function printUsage() {
|
|
|
1812
1933
|
console.log(' c8ctl nano clean [--workspace]');
|
|
1813
1934
|
console.log(' c8ctl nano set <bin|model-dir> <path>');
|
|
1814
1935
|
console.log(' c8ctl nano config');
|
|
1936
|
+
console.log(' c8ctl nano update [--check]');
|
|
1815
1937
|
console.log('');
|
|
1816
1938
|
console.log('Subcommands:');
|
|
1817
1939
|
console.log(' start Spawn an N-node local cluster wired to talk to each other on localhost');
|
|
@@ -1824,6 +1946,7 @@ function printUsage() {
|
|
|
1824
1946
|
console.log(' clean Wipe journal/data + logs on disk (keeps models/workers)');
|
|
1825
1947
|
console.log(' set Persist a setting: "bin <path>" or "model-dir <path>"');
|
|
1826
1948
|
console.log(' config Show current configuration and on-disk locations');
|
|
1949
|
+
console.log(' update Pull the latest published nano release (--check to only report)');
|
|
1827
1950
|
console.log('');
|
|
1828
1951
|
console.log('Options:');
|
|
1829
1952
|
console.log(' <nodes> Number of nodes to start (default 1)');
|
package/nanobpmn-binary.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
3
|
-
"commit": "
|
|
4
|
-
"updated": "2026-06-
|
|
5
|
-
}
|
|
2
|
+
"version": "0.0.2",
|
|
3
|
+
"commit": "44ad803",
|
|
4
|
+
"updated": "2026-06-30T06:04:34Z"
|
|
5
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "c8ctl-plugin-nano",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "c8ctl plugin to start, inspect, and stop a local Nano BPM (nanobpmn) cluster",
|
|
6
6
|
"main": "c8ctl-plugin.js",
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"semantic-release": "^25.0.3"
|
|
50
50
|
},
|
|
51
51
|
"optionalDependencies": {
|
|
52
|
-
"c8ctl-plugin-nano-darwin-arm64": "1.
|
|
53
|
-
"c8ctl-plugin-nano-darwin-x64": "1.
|
|
54
|
-
"c8ctl-plugin-nano-linux-x64": "1.
|
|
55
|
-
"c8ctl-plugin-nano-linux-arm64": "1.
|
|
56
|
-
"c8ctl-plugin-nano-win32-x64": "1.
|
|
52
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-arm64": "1.1.0",
|
|
53
|
+
"@nanobpm/c8ctl-plugin-nano-darwin-x64": "1.1.0",
|
|
54
|
+
"@nanobpm/c8ctl-plugin-nano-linux-x64": "1.1.0",
|
|
55
|
+
"@nanobpm/c8ctl-plugin-nano-linux-arm64": "1.1.0",
|
|
56
|
+
"@nanobpm/c8ctl-plugin-nano-win32-x64": "1.1.0"
|
|
57
57
|
}
|
|
58
58
|
}
|
package/platforms.mjs
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
* Single source of truth for the platform-specific binary packages.
|
|
3
3
|
*
|
|
4
4
|
* Each entry maps a Node platform/arch pair to:
|
|
5
|
-
* - pkg: the npm package name that carries the binary for that platform
|
|
5
|
+
* - pkg: the npm package name that carries the binary for that platform.
|
|
6
|
+
* Scoped under @nanobpm (a scope we own) so the names can never be
|
|
7
|
+
* squatted or npm-security-held the way an unscoped name can.
|
|
6
8
|
* - os: the npm "os" field value (process.platform)
|
|
7
9
|
* - cpu: the npm "cpu" field value (process.arch)
|
|
8
10
|
* - triple: the Rust target triple (informational; used by the Nano BPM CI)
|
|
@@ -19,7 +21,7 @@ export const BIN_BASENAME = 'nanobpm-gateway-rest-server';
|
|
|
19
21
|
|
|
20
22
|
export const PLATFORMS = [
|
|
21
23
|
{
|
|
22
|
-
pkg: 'c8ctl-plugin-nano-darwin-arm64',
|
|
24
|
+
pkg: '@nanobpm/c8ctl-plugin-nano-darwin-arm64',
|
|
23
25
|
os: 'darwin',
|
|
24
26
|
cpu: 'arm64',
|
|
25
27
|
triple: 'aarch64-apple-darwin',
|
|
@@ -27,7 +29,7 @@ export const PLATFORMS = [
|
|
|
27
29
|
bin: BIN_BASENAME,
|
|
28
30
|
},
|
|
29
31
|
{
|
|
30
|
-
pkg: 'c8ctl-plugin-nano-darwin-x64',
|
|
32
|
+
pkg: '@nanobpm/c8ctl-plugin-nano-darwin-x64',
|
|
31
33
|
os: 'darwin',
|
|
32
34
|
cpu: 'x64',
|
|
33
35
|
triple: 'x86_64-apple-darwin',
|
|
@@ -35,7 +37,7 @@ export const PLATFORMS = [
|
|
|
35
37
|
bin: BIN_BASENAME,
|
|
36
38
|
},
|
|
37
39
|
{
|
|
38
|
-
pkg: 'c8ctl-plugin-nano-linux-x64',
|
|
40
|
+
pkg: '@nanobpm/c8ctl-plugin-nano-linux-x64',
|
|
39
41
|
os: 'linux',
|
|
40
42
|
cpu: 'x64',
|
|
41
43
|
triple: 'x86_64-unknown-linux-gnu',
|
|
@@ -43,7 +45,7 @@ export const PLATFORMS = [
|
|
|
43
45
|
bin: BIN_BASENAME,
|
|
44
46
|
},
|
|
45
47
|
{
|
|
46
|
-
pkg: 'c8ctl-plugin-nano-linux-arm64',
|
|
48
|
+
pkg: '@nanobpm/c8ctl-plugin-nano-linux-arm64',
|
|
47
49
|
os: 'linux',
|
|
48
50
|
cpu: 'arm64',
|
|
49
51
|
triple: 'aarch64-unknown-linux-gnu',
|
|
@@ -51,7 +53,7 @@ export const PLATFORMS = [
|
|
|
51
53
|
bin: BIN_BASENAME,
|
|
52
54
|
},
|
|
53
55
|
{
|
|
54
|
-
pkg: 'c8ctl-plugin-nano-win32-x64',
|
|
56
|
+
pkg: '@nanobpm/c8ctl-plugin-nano-win32-x64',
|
|
55
57
|
os: 'win32',
|
|
56
58
|
cpu: 'x64',
|
|
57
59
|
triple: 'x86_64-pc-windows-msvc',
|