@pablozaiden/installer 0.0.0-development
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 +330 -0
- package/index.ts +3 -0
- package/install.sh +396 -0
- package/package.json +37 -0
- package/src/contract.ts +170 -0
- package/src/manifest.ts +214 -0
- package/src/update.ts +502 -0
package/README.md
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# @pablozaiden/installer
|
|
2
|
+
|
|
3
|
+
Reusable installer, updater, and release tooling for GitHub-hosted Bun binaries.
|
|
4
|
+
|
|
5
|
+
This package factors out the shared behavior used by projects like `pablozaiden/link` and `pablozaiden/ralpher`:
|
|
6
|
+
|
|
7
|
+
- a generic one-line shell installer that can target a GitHub repository,
|
|
8
|
+
- a TypeScript updater library for installed CLI binaries,
|
|
9
|
+
- a reusable GitHub Actions workflow for release binary assets,
|
|
10
|
+
- an npm publishing workflow for this TypeScript-only package.
|
|
11
|
+
|
|
12
|
+
## Install this package
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
bun add @pablozaiden/installer
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The package exports TypeScript source directly, following the same style as `@pablozaiden/terminatui`.
|
|
19
|
+
|
|
20
|
+
## Binary asset contract
|
|
21
|
+
|
|
22
|
+
All tools use the same release asset naming convention:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
<assetPrefix>-<tag>-<os>-<arch>
|
|
26
|
+
<assetPrefix>-<tag>-<os>-<arch>.sha256
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Supported targets are:
|
|
30
|
+
|
|
31
|
+
| OS | Architectures |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `linux` | `x64`, `arm64` |
|
|
34
|
+
| `darwin` | `x64`, `arm64` |
|
|
35
|
+
|
|
36
|
+
Tags may be provided as `1.2.3` or `v1.2.3`; release assets are always resolved with the `v` tag form published by GitHub releases.
|
|
37
|
+
|
|
38
|
+
## Generic one-line installer
|
|
39
|
+
|
|
40
|
+
Use the installer directly from this repository:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl -fsSL https://raw.githubusercontent.com/pablozaiden/installer/main/install.sh | sh -s -- pablozaiden/link
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The target repository should publish an installer manifest at either:
|
|
47
|
+
|
|
48
|
+
- `.github/installer.json`
|
|
49
|
+
- `.installer.json`
|
|
50
|
+
|
|
51
|
+
The installer:
|
|
52
|
+
|
|
53
|
+
1. Detects Linux/macOS and x64/arm64.
|
|
54
|
+
2. Loads the target repository's manifest.
|
|
55
|
+
3. Fetches the latest GitHub release.
|
|
56
|
+
4. Downloads each configured binary asset.
|
|
57
|
+
5. Verifies `.sha256` checksums by default.
|
|
58
|
+
6. Installs binaries into `$HOME/.local/bin` unless overridden.
|
|
59
|
+
7. Prints PATH guidance if the install directory is not on `PATH`.
|
|
60
|
+
|
|
61
|
+
### Manifest schema
|
|
62
|
+
|
|
63
|
+
Single-binary example for Link:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"schemaVersion": 1,
|
|
68
|
+
"repo": "pablozaiden/link",
|
|
69
|
+
"installDir": "$HOME/.local/bin",
|
|
70
|
+
"binaries": [
|
|
71
|
+
{
|
|
72
|
+
"name": "link-cli",
|
|
73
|
+
"assetPrefix": "link-cli",
|
|
74
|
+
"postInstallMessage": "Run 'link-cli web' to start Link."
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"checksums": {
|
|
78
|
+
"required": true,
|
|
79
|
+
"extension": ".sha256"
|
|
80
|
+
},
|
|
81
|
+
"platforms": {
|
|
82
|
+
"linux": ["x64", "arm64"],
|
|
83
|
+
"darwin": ["x64", "arm64"]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Multi-binary example for Ralpher:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"schemaVersion": 1,
|
|
93
|
+
"repo": "pablozaiden/ralpher",
|
|
94
|
+
"installDir": "$HOME/.local/bin",
|
|
95
|
+
"binaries": [
|
|
96
|
+
{
|
|
97
|
+
"name": "ralpher",
|
|
98
|
+
"assetPrefix": "ralpher",
|
|
99
|
+
"postInstallMessage": "Run 'ralpher' to start the local server."
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
"name": "ralpher-cli",
|
|
103
|
+
"assetPrefix": "ralpher-cli",
|
|
104
|
+
"postInstallMessage": "Run 'ralpher-cli --help' to use the API client."
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"checksums": {
|
|
108
|
+
"required": false,
|
|
109
|
+
"extension": ".sha256"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`checksums.required` should be `true` for new projects. Use `false` only while migrating existing projects that do not yet publish checksum assets.
|
|
115
|
+
The shell installer supports manifest `schemaVersion: 1` and fails before reading other manifest fields if a future schema version is provided.
|
|
116
|
+
|
|
117
|
+
### Installer fallback options
|
|
118
|
+
|
|
119
|
+
For projects without a manifest, pass binaries explicitly:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
curl -fsSL https://raw.githubusercontent.com/pablozaiden/installer/main/install.sh \
|
|
123
|
+
| sh -s -- pablozaiden/link --binary link-cli
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Useful options:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
--ref <ref> Repository ref to read manifests from
|
|
130
|
+
--binary <name> Binary name when no manifest is available
|
|
131
|
+
--asset-prefix <prefix> Asset prefix for the most recent --binary
|
|
132
|
+
--install-dir <dir> Install directory
|
|
133
|
+
--checksum required|optional|none
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`--checksum none` disables checksum downloads and verification entirely. `optional` attempts checksum verification when the checksum asset exists, while `required` fails if the checksum cannot be downloaded or verified.
|
|
137
|
+
|
|
138
|
+
## TypeScript updater library
|
|
139
|
+
|
|
140
|
+
Use `runUpdateCommand` from an installed binary's `update` command.
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import { runUpdateCommand } from "@pablozaiden/installer";
|
|
144
|
+
import { LINK_VERSION } from "./version";
|
|
145
|
+
|
|
146
|
+
export async function runCliCommand(command: { kind: string; checkOnly?: boolean; version?: string }) {
|
|
147
|
+
if (command.kind === "update") {
|
|
148
|
+
return await runUpdateCommand(
|
|
149
|
+
{
|
|
150
|
+
checkOnly: command.checkOnly ?? false,
|
|
151
|
+
version: command.version,
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
repository: "pablozaiden/link",
|
|
155
|
+
binaryName: "link-cli",
|
|
156
|
+
currentVersion: LINK_VERSION,
|
|
157
|
+
productName: "Link",
|
|
158
|
+
checksum: { required: true },
|
|
159
|
+
},
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
For a CLI with a companion binary installed beside it:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
import { runUpdateCommand } from "@pablozaiden/installer";
|
|
169
|
+
import { RALPHER_VERSION } from "./version";
|
|
170
|
+
|
|
171
|
+
await runUpdateCommand(
|
|
172
|
+
{
|
|
173
|
+
checkOnly: false,
|
|
174
|
+
version: undefined,
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
repository: "pablozaiden/ralpher",
|
|
178
|
+
binaryName: "ralpher-cli",
|
|
179
|
+
currentVersion: RALPHER_VERSION,
|
|
180
|
+
productName: "Ralpher",
|
|
181
|
+
checksum: { required: false },
|
|
182
|
+
companionBinaries: [
|
|
183
|
+
{
|
|
184
|
+
binaryName: "ralpher",
|
|
185
|
+
assetPrefix: "ralpher",
|
|
186
|
+
required: false
|
|
187
|
+
}
|
|
188
|
+
],
|
|
189
|
+
},
|
|
190
|
+
);
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
The updater supports:
|
|
194
|
+
|
|
195
|
+
- latest release checks,
|
|
196
|
+
- explicit version installs,
|
|
197
|
+
- semver comparison including prereleases,
|
|
198
|
+
- GitHub release metadata validation,
|
|
199
|
+
- Linux/macOS x64/arm64 target resolution,
|
|
200
|
+
- checksum verification before replacement,
|
|
201
|
+
- source-mode rejection when running from `bun`,
|
|
202
|
+
- staged temp-file replacement with executable permission preservation,
|
|
203
|
+
- companion binary updates that are committed together with the primary binary and rolled back on replacement failure.
|
|
204
|
+
|
|
205
|
+
Exported helpers include:
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
import {
|
|
209
|
+
buildReleaseAssetName,
|
|
210
|
+
compareReleaseVersions,
|
|
211
|
+
normalizeReleaseTag,
|
|
212
|
+
normalizeReleaseVersion,
|
|
213
|
+
parseInstallerManifestJson,
|
|
214
|
+
resolveReleasePlatform,
|
|
215
|
+
runUpdateCommand,
|
|
216
|
+
} from "@pablozaiden/installer";
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## Reusable binary release workflow
|
|
220
|
+
|
|
221
|
+
In a consuming repository, add a workflow like:
|
|
222
|
+
|
|
223
|
+
```yaml
|
|
224
|
+
name: Build and Release Binaries
|
|
225
|
+
|
|
226
|
+
on:
|
|
227
|
+
release:
|
|
228
|
+
types: [published]
|
|
229
|
+
|
|
230
|
+
jobs:
|
|
231
|
+
binaries:
|
|
232
|
+
uses: pablozaiden/installer/.github/workflows/reusable-binary-release.yml@main
|
|
233
|
+
permissions:
|
|
234
|
+
contents: write
|
|
235
|
+
with:
|
|
236
|
+
prebuild_command: bun run build
|
|
237
|
+
binaries: |
|
|
238
|
+
[
|
|
239
|
+
{
|
|
240
|
+
"name": "link-cli",
|
|
241
|
+
"asset_prefix": "link-cli",
|
|
242
|
+
"build_command": "bun run build-binary.ts --target=$BUN_TARGET --outfile=$ASSET_PATH",
|
|
243
|
+
"output_path": "$ASSET_PATH"
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
For a project with multiple binaries:
|
|
249
|
+
|
|
250
|
+
```yaml
|
|
251
|
+
jobs:
|
|
252
|
+
binaries:
|
|
253
|
+
uses: pablozaiden/installer/.github/workflows/reusable-binary-release.yml@main
|
|
254
|
+
permissions:
|
|
255
|
+
contents: write
|
|
256
|
+
with:
|
|
257
|
+
prebuild_command: bun run build
|
|
258
|
+
binaries: |
|
|
259
|
+
[
|
|
260
|
+
{
|
|
261
|
+
"name": "ralpher",
|
|
262
|
+
"asset_prefix": "ralpher",
|
|
263
|
+
"build_command": "cd apps/server && bun src/build.ts --target=$BUN_TARGET",
|
|
264
|
+
"output_path": "apps/server/dist/ralpher-$RELEASE_TARGET"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
"name": "ralpher-cli",
|
|
268
|
+
"asset_prefix": "ralpher-cli",
|
|
269
|
+
"build_command": "cd apps/cli && bun src/build.ts --target=$BUN_TARGET",
|
|
270
|
+
"output_path": "apps/cli/dist/ralpher-cli-$RELEASE_TARGET"
|
|
271
|
+
}
|
|
272
|
+
]
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
The workflow:
|
|
276
|
+
|
|
277
|
+
- runs on GitHub release publication,
|
|
278
|
+
- builds `linux-x64`, `linux-arm64`, `darwin-x64`, and `darwin-arm64`,
|
|
279
|
+
- exports `TAG`, `VERSION`, `RELEASE_TARGET`, `BUN_TARGET`, `BINARY_NAME`, `ASSET_PREFIX`, and `ASSET_PATH` to each build command,
|
|
280
|
+
- stages release assets using the shared naming convention,
|
|
281
|
+
- generates `.sha256` files by default,
|
|
282
|
+
- uploads matrix artifacts first, then publishes GitHub release assets only after all matrix builds succeed.
|
|
283
|
+
|
|
284
|
+
## Publishing this package to npm
|
|
285
|
+
|
|
286
|
+
This repository includes `.github/workflows/release-npm-package.yml`.
|
|
287
|
+
|
|
288
|
+
On a published GitHub release, it:
|
|
289
|
+
|
|
290
|
+
1. Derives the npm version from the release tag.
|
|
291
|
+
2. Updates `package.json`.
|
|
292
|
+
3. Verifies the version.
|
|
293
|
+
4. Runs `bun install --frozen-lockfile`.
|
|
294
|
+
5. Runs `bun run build`.
|
|
295
|
+
6. Runs `bun test`.
|
|
296
|
+
7. Publishes `@pablozaiden/installer` with npm provenance.
|
|
297
|
+
|
|
298
|
+
Manual `workflow_dispatch` publishes with the `unstable` tag.
|
|
299
|
+
|
|
300
|
+
## Migration guide: Link
|
|
301
|
+
|
|
302
|
+
1. Add `.github/installer.json` using the single-binary manifest above.
|
|
303
|
+
2. Replace `src/server/update.ts` logic with a thin wrapper around `runUpdateCommand`.
|
|
304
|
+
3. Keep Link's command parser and `LINK_VERSION`; pass them into the updater config.
|
|
305
|
+
4. Replace `.github/workflows/binary-release.yml` with a caller workflow that uses `reusable-binary-release.yml`.
|
|
306
|
+
5. Keep checksum publication enabled.
|
|
307
|
+
6. Optionally update the README one-liner to point at `pablozaiden/installer`.
|
|
308
|
+
|
|
309
|
+
## Migration guide: Ralpher
|
|
310
|
+
|
|
311
|
+
1. Add `.github/installer.json` using the multi-binary manifest above.
|
|
312
|
+
2. Decide whether to publish checksums immediately. If not, use `checksums.required: false` temporarily.
|
|
313
|
+
3. Replace `src/cli/update.ts` logic with `runUpdateCommand` configured with `binaryName: "ralpher-cli"` and `companionBinaries: [{ binaryName: "ralpher" }]`.
|
|
314
|
+
4. Replace `.github/workflows/binary-release.yml` with a caller workflow that builds both server and CLI binaries.
|
|
315
|
+
5. Once checksum assets are published, switch installer/updater checksum policy to required.
|
|
316
|
+
6. Optionally update the README one-liner to point at `pablozaiden/installer`.
|
|
317
|
+
|
|
318
|
+
## Development
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
bun install
|
|
322
|
+
bun run build
|
|
323
|
+
bun test
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Shell syntax for the installer is covered by tests and can be checked directly:
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
sh -n install.sh
|
|
330
|
+
```
|
package/index.ts
ADDED