@ghship/cli 1.0.2 → 1.0.4
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 +7 -3
- package/checksums.json +6 -6
- package/package.json +9 -2
- package/run.cjs +32 -10
- package/bin/darwin-amd64/ghship +0 -0
- package/bin/darwin-arm64/ghship +0 -0
- package/bin/linux-amd64/ghship +0 -0
- package/bin/linux-arm64/ghship +0 -0
- package/bin/windows-amd64/ghship.exe +0 -0
- package/bin/windows-arm64/ghship.exe +0 -0
package/README.md
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# GHShip npm distribution
|
|
2
2
|
|
|
3
|
-
Go CLI and home AI skill plus per-project integration.
|
|
4
|
-
|
|
3
|
+
Go CLI and home AI skill plus per-project integration. npm installs the native
|
|
4
|
+
binary package matching the Node.js operating system and architecture for
|
|
5
|
+
macOS/Linux/Windows × x64/arm64, with no postinstall downloads. Optional
|
|
6
|
+
dependencies must be enabled and the matching package must be available from the
|
|
7
|
+
configured registry. An emulated Node.js runtime selects its own architecture.
|
|
5
8
|
|
|
6
9
|
After publication: `npx @ghship/cli@latest install` installs the home skill, same-version
|
|
7
10
|
persistent CLI, then enters project initialization. `--user-only` stops after user
|
|
@@ -18,7 +21,8 @@ expiry when GitHub returns it, otherwise unknown. Tokens never belong in project
|
|
|
18
21
|
|
|
19
22
|
For a downloaded npm tarball, use:
|
|
20
23
|
`npm exec --package /absolute/ghship.tgz -- ghship install --package-source /absolute/ghship.tgz`.
|
|
21
|
-
|
|
24
|
+
The configured registry must provide the same-version platform package. Add
|
|
25
|
+
`--user-only` to install shared tools without initializing a project.
|
|
22
26
|
Registry commands require the selected version to be published.
|
|
23
27
|
|
|
24
28
|
Detailed Chinese tutorial and AI skill: https://github.com/ghship/cli
|
package/checksums.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
2
|
+
"darwin-arm64": "bdce86aa2ebb4bca9ee4e149cce2b29d51557dfeee7f732b2dcd6d1458f125a6",
|
|
3
|
+
"darwin-x64": "c0b71ad5b0d9e338cb9836b8572e9caacbad1a710965df0af88665d68dc100da",
|
|
4
|
+
"linux-arm64": "b3607bc943a8b01a5e8a164a21026766442cd1a7fae14b2703afcfdd1afa97f3",
|
|
5
|
+
"linux-x64": "2ba3458d178f81abc11478fa92128e76fcc61567b9abc4a8d1931fcaa6363f02",
|
|
6
|
+
"win32-arm64": "68a9bb61d9f1ee7147f2bc7eacc2c377fd25f2016b4d911b818db3d8666e2f4c",
|
|
7
|
+
"win32-x64": "dc1d6ebf166634222f919668f1b7803c2bf1c2c6d6df2d460c95b7bb48f2d85d"
|
|
8
8
|
}
|
package/package.json
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ghship/cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
4
4
|
"description": "Go CLI and AI skill for native GitHub delivery pipelines",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ghship": "run.cjs"
|
|
7
7
|
},
|
|
8
8
|
"files": [
|
|
9
9
|
"run.cjs",
|
|
10
|
-
"bin",
|
|
11
10
|
"README.md",
|
|
12
11
|
"checksums.json"
|
|
13
12
|
],
|
|
13
|
+
"optionalDependencies": {
|
|
14
|
+
"@ghship/cli-darwin-x64": "1.0.4",
|
|
15
|
+
"@ghship/cli-darwin-arm64": "1.0.4",
|
|
16
|
+
"@ghship/cli-linux-x64": "1.0.4",
|
|
17
|
+
"@ghship/cli-linux-arm64": "1.0.4",
|
|
18
|
+
"@ghship/cli-win32-x64": "1.0.4",
|
|
19
|
+
"@ghship/cli-win32-arm64": "1.0.4"
|
|
20
|
+
},
|
|
14
21
|
"engines": {
|
|
15
22
|
"node": ">=18"
|
|
16
23
|
},
|
package/run.cjs
CHANGED
|
@@ -4,11 +4,31 @@ const fs = require('node:fs');
|
|
|
4
4
|
const os = require('node:os');
|
|
5
5
|
const crypto = require('node:crypto');
|
|
6
6
|
const { spawn, spawnSync } = require('node:child_process');
|
|
7
|
-
function
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (
|
|
11
|
-
|
|
7
|
+
function singlePack(value,name) {
|
|
8
|
+
let record;
|
|
9
|
+
if(Array.isArray(value)) {if(value.length!==1)throw new Error('Unexpected npm pack result');record=value[0];}
|
|
10
|
+
else if(value&&typeof value==='object'&&Object.keys(value).length===1&&Object.hasOwn(value,name))record=value[name];
|
|
11
|
+
if(!record||typeof record!=='object'||record.name!==name||typeof record.version!=='string')throw new Error('Unexpected npm pack result');
|
|
12
|
+
return record;
|
|
13
|
+
}
|
|
14
|
+
function platformInfo(platform = process.platform, arch = process.arch) {
|
|
15
|
+
if (!['darwin','linux','win32'].includes(platform) || !['x64','arm64'].includes(arch)) throw new Error(`Unsupported platform: ${platform}/${arch}`);
|
|
16
|
+
return {target:`${platform}-${arch}`,name:`@ghship/cli-${platform}-${arch}`,binary:platform==='win32'?'ghship.exe':'ghship'};
|
|
17
|
+
}
|
|
18
|
+
function binaryPath(platform = process.platform, arch = process.arch, root = __dirname) {
|
|
19
|
+
const info=platformInfo(platform,arch);
|
|
20
|
+
const meta=JSON.parse(fs.readFileSync(path.join(root,'package.json'),'utf8'));
|
|
21
|
+
let manifest;try {manifest=require.resolve(`${info.name}/package.json`,{paths:[root]});}
|
|
22
|
+
catch (_) {throw new Error(`Platform package ${info.name}@${meta.version} is missing; enable optional dependencies and reinstall @ghship/cli@${meta.version}`);}
|
|
23
|
+
const allowed=[path.join(root,'node_modules',info.name),path.join(path.dirname(path.dirname(root)),info.name)];
|
|
24
|
+
if(!allowed.some(dir=>path.resolve(path.dirname(manifest))===path.resolve(dir)))throw new Error('Platform package is outside the installation; preserved');
|
|
25
|
+
noLinks(manifest);
|
|
26
|
+
const platformMeta=JSON.parse(fs.readFileSync(manifest,'utf8'));
|
|
27
|
+
if(platformMeta.name!==info.name||platformMeta.version!==meta.version||!platformMeta.os?.includes(platform)||!platformMeta.cpu?.includes(arch))throw new Error('Platform package does not match CLI version or platform; preserved');
|
|
28
|
+
const executable=path.join(path.dirname(manifest),'bin',info.binary);noLinks(executable);
|
|
29
|
+
const checks=JSON.parse(fs.readFileSync(path.join(root,'checksums.json'),'utf8'));
|
|
30
|
+
if(!checks[info.target]||hashFile(executable)!==checks[info.target])throw new Error('Platform binary missing or checksum mismatch; preserved');
|
|
31
|
+
return executable;
|
|
12
32
|
}
|
|
13
33
|
function npmCommand() {
|
|
14
34
|
if (process.env.npm_execpath && fs.existsSync(process.env.npm_execpath)) return [process.execPath, [process.env.npm_execpath]];
|
|
@@ -53,8 +73,10 @@ function observePackage(root,meta,existing,replacingVerifiedReceipt=false) {
|
|
|
53
73
|
const directory=path.join(root,meta.name); noLinks(directory);
|
|
54
74
|
const metadata=JSON.parse(fs.readFileSync(path.join(directory,'package.json'),'utf8'));
|
|
55
75
|
if(metadata.name!==meta.name||metadata.version!==existing.version||metadata.bin?.ghship!=='run.cjs')throw new Error('Unrecognized global package; preserved');
|
|
56
|
-
const
|
|
57
|
-
const
|
|
76
|
+
const info=platformInfo();const legacyOS={darwin:'darwin',linux:'linux',win32:'windows'}[process.platform];const legacyArch={x64:'amd64',arm64:'arm64'}[process.arch];
|
|
77
|
+
const legacy=path.join(directory,'bin',`${legacyOS}-${legacyArch}`,info.binary);
|
|
78
|
+
const installedBinary=fs.existsSync(legacy)?legacy:binaryPath(process.platform,process.arch,directory);noLinks(installedBinary);
|
|
79
|
+
const observed={root,name:meta.name,version:metadata.version,launcher:hashFile(path.join(directory,'run.cjs')),binary:hashFile(installedBinary)};
|
|
58
80
|
const current=observed.version===meta.version&&observed.launcher===hashFile(path.join(__dirname,'run.cjs'))&&observed.binary===hashFile(binaryPath());
|
|
59
81
|
const receipt=packageReceipt(root);noLinks(receipt);
|
|
60
82
|
let recorded=null;try{recorded=JSON.parse(fs.readFileSync(receipt,'utf8'));}catch(error){if(error.code!=='ENOENT')throw new Error('Invalid installation receipt; preserved');}
|
|
@@ -73,7 +95,7 @@ function lifecycle(executable,args) {
|
|
|
73
95
|
const action=args[0], meta=require('./package.json'); let source=`${meta.name}@${meta.version}`;
|
|
74
96
|
const passed=args.slice(1); const sourceIndex=passed.indexOf('--package-source');
|
|
75
97
|
if(sourceIndex>=0) {if(!passed[sourceIndex+1])throw new Error('--package-source requires a local tarball');source=path.resolve(passed[sourceIndex+1]);passed.splice(sourceIndex,2);
|
|
76
|
-
const packed=JSON.parse(npm(['pack',source,'--dry-run','--json'],true));if(packed.
|
|
98
|
+
const packed=singlePack(JSON.parse(npm(['pack',source,'--dry-run','--json'],true)),meta.name);if(packed.version!==meta.version)throw new Error('Local package source must match this exact package and version');
|
|
77
99
|
}
|
|
78
100
|
const lifecycleArgs=[];const initArgs=[];let userOnly=false;
|
|
79
101
|
const initValues=new Set(['--project','--repo','--author','--reviewer','--admin','--acceptance-pr']);
|
|
@@ -115,7 +137,7 @@ function lifecycle(executable,args) {
|
|
|
115
137
|
const verified=JSON.parse(npm(['list','-g',meta.name,'--depth=0','--json'],true));
|
|
116
138
|
if(!verified.dependencies||verified.dependencies[meta.name]?.version!==meta.version)throw new Error('Installed CLI version does not match skill; installation incomplete');
|
|
117
139
|
const persisted=observePackage(root,meta,verified.dependencies[meta.name],!!observation);if(!persisted.current)throw new Error('Persistent CLI content does not match this package');
|
|
118
|
-
const runtimeVersion=go(path.join(root,meta.name
|
|
140
|
+
const runtimeVersion=go(binaryPath(process.platform,process.arch,path.join(root,meta.name)),['version'],true);
|
|
119
141
|
if(runtimeVersion.code!==0||runtimeVersion.stdout.trim()!==meta.version)throw new Error('Persistent CLI cannot run the expected version');
|
|
120
142
|
saveReceipt(root,persisted.observed);
|
|
121
143
|
if(action==='update'||userOnly){console.log(JSON.stringify({userInstalled:true,version:meta.version,projectInitialized:false}));return 0;}
|
|
@@ -123,7 +145,7 @@ function lifecycle(executable,args) {
|
|
|
123
145
|
let result;try{result=JSON.parse(init.stdout);}catch(_){result={ready:false,missing:['Initialization failed before producing a result'],next:['ghship init --json']};}
|
|
124
146
|
result.userInstalled=true;result.version=meta.version;console.log(JSON.stringify(result));return init.code;
|
|
125
147
|
}
|
|
126
|
-
module.exports = {binaryPath};
|
|
148
|
+
module.exports = {binaryPath,platformInfo,singlePack};
|
|
127
149
|
if(require.main===module) {
|
|
128
150
|
try {
|
|
129
151
|
const executable=binaryPath();if(!fs.existsSync(executable))throw new Error('Package missing Go binary; reinstall the package');
|
package/bin/darwin-amd64/ghship
DELETED
|
Binary file
|
package/bin/darwin-arm64/ghship
DELETED
|
Binary file
|
package/bin/linux-amd64/ghship
DELETED
|
Binary file
|
package/bin/linux-arm64/ghship
DELETED
|
Binary file
|
|
Binary file
|
|
Binary file
|