argsbarg 5.1.1 → 5.1.2

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/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [5.1.2] - 2026-07-04
11
+
12
+ ### Changed
13
+
14
+ - **Private GitHub release installs** — release formulae use `GitHubPrivateReleaseDownloadStrategy` (GitHub API + `GitHub::API.credentials` / `HOMEBREW_GITHUB_API_TOKEN`); `just install-production` and `just test-release` export the token (with `gh auth token` fallback). Documented in `docs/distribution-homebrew.md`.
15
+
10
16
  ## [5.1.1] - 2026-07-04
11
17
 
12
18
  ### Fixed
@@ -595,7 +601,8 @@ const cli = { ... } satisfies CliProgram; // or : CliProgram
595
601
  - Migrate schemas: rename every `children` property to **`commands`**; move positional definitions to **`CliPositional`** objects on `positionals` and strip `positional` / `argMin` / `argMax` from flag definitions under `options` (flags only carry `name`, `description`, `kind`, and optional `shortName`).
596
602
  - Imports: use `CliPositional` where needed; replace `CliOptionDef` with `CliOption` or `CliPositional` as appropriate.
597
603
 
598
- [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v5.1.1...HEAD
604
+ [Unreleased]: https://github.com/bdombro/bun-argsbarg/compare/v5.1.2...HEAD
605
+ [5.1.2]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.2
599
606
  [5.1.1]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.1
600
607
  [5.1.0]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.1.0
601
608
  [5.0.3]: https://github.com/bdombro/bun-argsbarg/releases/tag/v5.0.3
package/docs/configure.md CHANGED
@@ -14,6 +14,8 @@ brew install <tap>/<key>
14
14
 
15
15
  Upgrade with `brew upgrade <key>`. Shell completions are installed by Homebrew during `brew install`. Users must configure their shell per [Homebrew Shell Completion](https://docs.brew.sh/Shell-Completion).
16
16
 
17
+ Private GitHub release assets require `HOMEBREW_GITHUB_API_TOKEN` at install time — see [distribution-homebrew.md](distribution-homebrew.md#end-user-install).
18
+
17
19
  **Uninstall the binary:** remove agent artifacts first (while the CLI is still on PATH), then `brew uninstall`:
18
20
 
19
21
  ```bash
@@ -20,6 +20,16 @@ brew install <tap>/{key}
20
20
  {key} configure # when app config is required
21
21
  ```
22
22
 
23
+ For **private or internal GitHub repos**, release formulae attach `HOMEBREW_GITHUB_API_TOKEN` when downloading the binary. Export a PAT with `repo` scope (or rely on `gh auth login` — `just install-production` and `just test-release` fall back to `gh auth token`):
24
+
25
+ ```bash
26
+ export HOMEBREW_GITHUB_API_TOKEN="$(gh auth token)"
27
+ brew tap <org>/<repo> git@github.com:<org>/<repo>.git
28
+ brew install <tap>/{key}
29
+ ```
30
+
31
+ Local dev installs (`just install-local`) use a `file://` staging URL and do not need the token.
32
+
23
33
  ### Developer install
24
34
 
25
35
  ```bash
@@ -56,6 +66,15 @@ def post_install
56
66
  end
57
67
  ```
58
68
 
69
+ Release formulae generated by `scripts/formula-shared.ts` embed a `GitHubPrivateReleaseDownloadStrategy` that resolves the release asset through the GitHub API at download time and authenticates with `GitHub::API.credentials` (backed by `HOMEBREW_GITHUB_API_TOKEN`, `gh auth`, or other Homebrew GitHub credential sources):
70
+
71
+ ```ruby
72
+ url "https://github.com/<org>/<repo>/releases/download/vX.Y.Z/{key}",
73
+ using: GitHubPrivateReleaseDownloadStrategy
74
+ ```
75
+
76
+ Local dev formulae (`just install-local`) use a plain `file://` URL and do not need the token.
77
+
59
78
  Completions require users to configure their shell per [Homebrew Shell Completion](https://docs.brew.sh/Shell-Completion).
60
79
 
61
80
  **Why configure is separate from `post_install`:** the wizard is interactive (TTY + prompts for secrets). Formula `post_install` runs non-interactively during `brew install` and in CI (`brew test`). Apps with `appConfig` print a one-line configure hint in formula `caveats` instead.
@@ -43,7 +43,7 @@ Production CLIs with several JSON commands tend to use **codegen** so types, han
43
43
 
44
44
  ## Recommended pipeline (copy per repo)
45
45
 
46
- No shared npm package — each app copies the same **contract**. Reference implementations: **sqsp-qa-tools**, **idp-trees**, **sqsp-i18n-tools** (see each repo’s `docs/architecture.md` for which commands use which schema root).
46
+ No shared npm package — each app copies the same **contract**. Reference implementations: **sqsp-qa-manager**, **idp-trees**, **poc-sqsp-i18n-tools** (see each repo’s `docs/architecture.md` for which commands use which schema root).
47
47
 
48
48
  ```mermaid
49
49
  flowchart LR
@@ -59,8 +59,8 @@ Requires [Homebrew](https://brew.sh) and a compiled binary at `dist/full-example
59
59
  just build
60
60
  just install-local # first-time dev formula (`just install` is an alias)
61
61
  just reinstall-local # fast binary swap during development
62
- just install-production # uninstall local dev, install from GitHub tap
63
- just test-release
62
+ just install-production # uninstall local dev, install from GitHub tap (needs HOMEBREW_GITHUB_API_TOKEN for private repos)
63
+ just test-release # same token requirement when formula uses a GitHub release URL
64
64
  ```
65
65
 
66
66
  Undo a local dev install:
@@ -8,6 +8,8 @@ cli_key := `bun scripts/print-identity.ts key`
8
8
  tap_org := `bun scripts/print-identity.ts tapOrg`
9
9
  tap_repo := `bun scripts/print-identity.ts tapRepo`
10
10
  tap := `bun scripts/print-identity.ts tap`
11
+ release_repo := `bun scripts/print-identity.ts releaseRepo`
12
+ tap_git_url := "git@github.com:" + release_repo + ".git"
11
13
  brew_prefix := `brew --prefix`
12
14
  tap_parent := brew_prefix + "/Library/Taps/" + tap_org
13
15
  tap_path := tap_parent + "/homebrew-" + tap_repo
@@ -59,12 +61,15 @@ install-local: build
59
61
  @echo ""
60
62
  @echo "Next: {{cli_key}} configure"
61
63
 
62
- # Remove local dev install, then install from GitHub tap
64
+ # Remove local dev install, then install from GitHub tap (private release assets need HOMEBREW_GITHUB_API_TOKEN)
63
65
  install-production: uninstall
64
- brew tap {{tap}}
65
- brew install --formula {{tap}}/{{cli_key}}
66
- @echo ""
67
- @echo "Next: {{cli_key}} configure"
66
+ #!/usr/bin/env bash
67
+ set -eu -o pipefail
68
+ source scripts/ensure-brew-github-token.sh
69
+ brew tap {{release_repo}} {{tap_git_url}}
70
+ brew install --formula {{release_repo}}/{{cli_key}}
71
+ echo ""
72
+ echo "Next: {{cli_key}} configure"
68
73
 
69
74
  # Alias for backward compatibility
70
75
  reinstall: reinstall-local
@@ -96,10 +101,13 @@ test: check
96
101
 
97
102
  # Install release formula from tap and run formula test
98
103
  test-release:
99
- @brew untap {{tap}} 2>/dev/null || true
104
+ #!/usr/bin/env bash
105
+ set -eu -o pipefail
106
+ source scripts/ensure-brew-github-token.sh
107
+ brew untap {{tap}} 2>/dev/null || true
100
108
  mkdir -p {{tap_parent}}
101
109
  ln -sfn '{{justfile_directory()}}' {{tap_path}}
102
- @brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
110
+ brew uninstall --formula {{tap}}/{{cli_key}} 2>/dev/null || true
103
111
  brew install --formula {{tap}}/{{cli_key}}
104
112
  brew test {{cli_key}}
105
113
 
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+ # Ensure HOMEBREW_GITHUB_API_TOKEN is set for private GitHub release downloads.
3
+ : "${HOMEBREW_GITHUB_API_TOKEN:=$(gh auth token 2>/dev/null || true)}"
4
+ if [[ -z "${HOMEBREW_GITHUB_API_TOKEN}" ]]; then
5
+ echo "HOMEBREW_GITHUB_API_TOKEN is required to download private GitHub release assets." >&2
6
+ echo "Export a GitHub PAT with repo scope, or run: gh auth login" >&2
7
+ exit 1
8
+ fi
9
+ export HOMEBREW_GITHUB_API_TOKEN
@@ -30,8 +30,51 @@ export const formulaTestRuby = `test do
30
30
 
31
31
  export interface FormulaCoords {
32
32
  url: string;
33
+ urlStanza: string;
33
34
  version: string;
34
35
  sha256: string;
36
+ /** When true, embed {@link githubPrivateReleaseDownloadStrategyRuby} in the formula class. */
37
+ privateRelease?: boolean;
38
+ }
39
+
40
+ /** Resolves private GitHub release assets via the API at download time. */
41
+ export const githubPrivateReleaseDownloadStrategyRuby = ` class GitHubPrivateReleaseDownloadStrategy < CurlDownloadStrategy
42
+ def initialize(url, name, version, **meta)
43
+ super
44
+ pattern = %r{https://github\\.com/([^/]+)/([^/]+)/releases/download/([^/]+)/(\\S+)}
45
+ match = url.match(pattern)
46
+ raise CurlDownloadStrategyError, "Invalid GitHub release URL: #{url}" unless match
47
+ @owner, @repo, @tag, @filename = match.captures
48
+ end
49
+
50
+ private
51
+
52
+ def _fetch(url:, resolved_url: resolved_download_url, timeout:)
53
+ curl_download resolved_download_url,
54
+ "--header", "Accept: application/octet-stream",
55
+ "--header", "Authorization: Bearer #{GitHub::API.credentials}",
56
+ to: temporary_path
57
+ end
58
+
59
+ def resolved_download_url
60
+ @resolved_download_url ||= begin
61
+ asset = GitHub.get_release(@owner, @repo, @tag).fetch("assets")
62
+ .find { |a| a["name"] == @filename }
63
+ raise CurlDownloadStrategyError, "Release asset not found: #{@filename}" unless asset
64
+ asset.fetch("url")
65
+ end
66
+ end
67
+ end`;
68
+
69
+ /** Homebrew `url` for local dev staging paths. */
70
+ export function devUrlStanza(url: string): string {
71
+ return `url "${url}"`;
72
+ }
73
+
74
+ /** Homebrew `url` for GitHub release assets (uses {@link githubPrivateReleaseDownloadStrategyRuby}). */
75
+ export function releaseUrlStanza(url: string): string {
76
+ return `url "${url}",
77
+ using: GitHubPrivateReleaseDownloadStrategy`;
35
78
  }
36
79
 
37
80
  export function releaseFormulaUrl(version: string): string {
@@ -39,10 +82,11 @@ export function releaseFormulaUrl(version: string): string {
39
82
  }
40
83
 
41
84
  export function renderFormula(coords: FormulaCoords): string {
85
+ const strategy = coords.privateRelease ? `${githubPrivateReleaseDownloadStrategyRuby}\n\n ` : "";
42
86
  return `class ${className} < Formula
43
- desc "${desc}"
87
+ ${strategy}desc "${desc}"
44
88
  homepage "${homepage}"
45
- url "${coords.url}"
89
+ ${coords.urlStanza}
46
90
  version "${coords.version}"
47
91
  sha256 "${coords.sha256}"
48
92
  {dependsOnBlock}
@@ -58,16 +102,21 @@ end
58
102
  }
59
103
 
60
104
  export function renderReleaseFormula(version: string, sha256: string): string {
105
+ const url = releaseFormulaUrl(version);
61
106
  return renderFormula({
62
- url: releaseFormulaUrl(version),
107
+ url,
108
+ urlStanza: releaseUrlStanza(url),
63
109
  version,
64
110
  sha256,
111
+ privateRelease: true,
65
112
  });
66
113
  }
67
114
 
68
115
  export function renderDevFormula(stagingPath: string, version: string, sha256: string): string {
116
+ const url = `file://${stagingPath}`;
69
117
  return renderFormula({
70
- url: `file://${stagingPath}`,
118
+ url,
119
+ urlStanza: devUrlStanza(url),
71
120
  version,
72
121
  sha256,
73
122
  });
@@ -5,7 +5,7 @@ import { createIdentity } from "./create-identity.ts";
5
5
 
6
6
  const field = process.argv[2];
7
7
  if (!field) {
8
- console.error("Usage: bun scripts/print-identity.ts <key|className|tap|tapOrg|tapRepo|envPrefix>");
8
+ console.error("Usage: bun scripts/print-identity.ts <key|className|tap|tapOrg|tapRepo|releaseRepo|envPrefix>");
9
9
  process.exit(1);
10
10
  }
11
11
 
@@ -17,6 +17,7 @@ const values: Record<string, string> = {
17
17
  tapOrg: tapOrg ?? "",
18
18
  tapRepo: tapRepo ?? "",
19
19
  envPrefix: createIdentity.envPrefix,
20
+ releaseRepo: createIdentity.releaseRepo,
20
21
  };
21
22
 
22
23
  const value = values[field];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "argsbarg",
3
- "version": "5.1.1",
3
+ "version": "5.1.2",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "bun": ">=1.3"