@r1z4x/tezgah 1.9.0 → 1.9.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 +16 -1
- package/docs/environment.md +3 -3
- package/docs/operations.md +22 -7
- package/package.json +1 -1
- package/packaging/install.ps1 +36 -3
- package/packaging/install.sh +13 -3
- package/packaging/upgrade.sh +61 -7
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,19 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.9.2] - 2026-10-17
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **1.9.2 ships what 1.9.1 carried.** The v1.9.1 release run failed its own CI on the changelog's prose. So npm and Homebrew never received 1.9.1. This release carries the same changes.
|
|
14
|
+
|
|
15
|
+
## [1.9.1] - 2026-10-17
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **A token fetches a private repository's release.** GitHub answers `404` to `releases/download/...` from a session without one. So `brew install`, `upgrade.sh` and the `curl | sh` first install all broke when the repository went private. `upgrade.sh` and `install.sh` read `TEZGAH_GITHUB_TOKEN`, `GITHUB_TOKEN` or `GH_TOKEN`. With a token, they read the tarball through the REST asset endpoint. `install.ps1` sends the same header. The Homebrew formula names that endpoint and reads `HOMEBREW_GITHUB_API_TOKEN`, and its caveats say so. With no token, the public URLs stand and a failed fetch names the token to set. The bearer reaches curl on stdin (`-H @-`), so no other user's `ps` shows it. An install still on 1.9.0 has no token support: install the new release with the token set.
|
|
20
|
+
- **The formula's caveats keep their text.** Backticks in the template ran as commands in the release step's unquoted heredoc. The caveats lost the token scope and the failure line, and the step stayed green. The test now renders the template the way the step does.
|
|
21
|
+
|
|
9
22
|
## [1.9.0] - 2026-10-17
|
|
10
23
|
|
|
11
24
|
### Added
|
|
@@ -1206,7 +1219,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
1206
1219
|
the copy could not find `hooks/` and died on import. It now links into the
|
|
1207
1220
|
installed tree, and also installs the command as `tezgah`.
|
|
1208
1221
|
|
|
1209
|
-
[Unreleased]: https://github.com/r1z4x/tezgah/compare/v1.9.
|
|
1222
|
+
[Unreleased]: https://github.com/r1z4x/tezgah/compare/v1.9.2...HEAD
|
|
1223
|
+
[1.9.2]: https://github.com/r1z4x/tezgah/releases/tag/v1.9.2
|
|
1224
|
+
[1.9.1]: https://github.com/r1z4x/tezgah/releases/tag/v1.9.1
|
|
1210
1225
|
[1.9.0]: https://github.com/r1z4x/tezgah/releases/tag/v1.9.0
|
|
1211
1226
|
[1.8.3]: https://github.com/r1z4x/tezgah/releases/tag/v1.8.3
|
|
1212
1227
|
[1.8.2]: https://github.com/r1z4x/tezgah/releases/tag/v1.8.2
|
package/docs/environment.md
CHANGED
|
@@ -19,12 +19,12 @@ the kill switches are files, not variables, and live in
|
|
|
19
19
|
|
|
20
20
|
| Variable | Read by | Default | Effect |
|
|
21
21
|
|---|---|---|---|
|
|
22
|
-
| `TEZGAH_PREFIX` | `packaging/install.sh:
|
|
22
|
+
| `TEZGAH_PREFIX` | `packaging/install.sh:30`, `packaging/upgrade.sh`, `packaging/install.ps1`, `bin/tezgah-setup::default_prefix` | `$XDG_DATA_HOME/tezgah`, else `%LOCALAPPDATA%\tezgah` on Windows, else `~/.local/share/tezgah` | Where the artifact install unpacks its versions and the `current` link; `tezgah-setup` treats it as the install prefix. |
|
|
23
23
|
| `TEZGAH_VERSION` | `packaging/install.sh`, `packaging/upgrade.sh`, `packaging/install.ps1`, `packaging/build.sh:70` | the newest GitHub release; `build.sh` falls back to `VERSION`/the CHANGELOG | The version to install, or the version `build.sh` stamps when `--version` is not given. |
|
|
24
|
-
| `TEZGAH_REPO` | `packaging/install.sh:
|
|
24
|
+
| `TEZGAH_REPO` | `packaging/install.sh:13`, `packaging/upgrade.sh`, `packaging/install.ps1` | `r1z4x/tezgah` | The GitHub repository releases are fetched from. |
|
|
25
25
|
| `TEZGAH_UPDATE_URL` | `hooks/tezgah_update.py` | `https://github.com/<TEZGAH_REPO>/releases/latest` | Where the daily release check reads the newest tag: from the redirect, or from a JSON body's `tag_name`. Tests point it at a `file://` fixture. |
|
|
26
26
|
| `TEZGAH_UPDATE_CHECK` | `hooks/tezgah_update.py` | unset | `0` turns off the update chip and the daily check. The test suite sets it, so no test reaches the network. |
|
|
27
|
-
| `TEZGAH_DIST` | `packaging/upgrade.sh:
|
|
27
|
+
| `TEZGAH_DIST` | `packaging/upgrade.sh:105`, `packaging/install.ps1` | unset: the release URL | A directory holding `tezgah-<V>.tar.gz` and its `.sha256` (what `build.sh --out` writes) used instead of the release download; CI exercises the real fetch-verify-unpack path with it. |
|
|
28
28
|
| `TEZGAH_GH` | `packaging/upgrade.sh` | `gh` on PATH | The `gh` that checks the tarball's build provenance (`gh attestation verify`). A path that does not exist reads as no `gh`: the upgrade prints `provenance not checked` and goes on. Tests point it at a stand-in. |
|
|
29
29
|
| `TEZGAH_NO_DEPS` | `bin/tezgah-setup::main` | unset | Any value but empty or `0` is `--no-deps`: the optional tools (codegraph, orx, host CLIs) are not installed. |
|
|
30
30
|
| `TEZGAH_NO_SYMLINK` | `bin/tezgah-setup::symlinks_refused` | unset | Any value but empty or `0` writes the copy layout a machine without symlinks gets, on a machine that has them. |
|
package/docs/operations.md
CHANGED
|
@@ -58,8 +58,8 @@ built by `packaging/build.sh` from the tracked `MANIFEST` plus a generated
|
|
|
58
58
|
team can stay on one version and a rollback is one tree away: the older version is
|
|
59
59
|
never removed, and going back is
|
|
60
60
|
`ln -sfn <prefix>/<previous> <prefix>/current` (`packaging/upgrade.sh:9-11`,
|
|
61
|
-
`packaging/upgrade.sh:
|
|
62
|
-
`TEZGAH_PREFIX` or `$XDG_DATA_HOME` says otherwise (`packaging/upgrade.sh:
|
|
61
|
+
`packaging/upgrade.sh:176-196`). The prefix is `~/.local/share/tezgah` unless
|
|
62
|
+
`TEZGAH_PREFIX` or `$XDG_DATA_HOME` says otherwise (`packaging/upgrade.sh:94`),
|
|
63
63
|
and `bin/tezgah-setup --prefix DIR` wins over both (`bin/tezgah-setup::INSTALL_PREFIX`).
|
|
64
64
|
A farm link counts as tezgah's when it resolves into the checkout **or** into the
|
|
65
65
|
install root, which is what keeps an upgrade from orphaning the wiring
|
|
@@ -68,30 +68,45 @@ install root, which is what keeps an upgrade from orphaning the wiring
|
|
|
68
68
|
| Step | Command |
|
|
69
69
|
|---|---|
|
|
70
70
|
| first install, POSIX | `curl -fsSL https://raw.githubusercontent.com/r1z4x/tezgah/v<version>/packaging/install.sh \| sh -s -- --version <version>` |
|
|
71
|
-
| from a tarball you hold | unpack it, then `sh packaging/install.sh --version <version>` — it finds `upgrade.sh` beside itself (`packaging/install.sh:
|
|
71
|
+
| from a tarball you hold | unpack it, then `sh packaging/install.sh --version <version>` — it finds `upgrade.sh` beside itself (`packaging/install.sh:34-36`) |
|
|
72
72
|
| first install, Windows | `$env:TEZGAH_VERSION = '<version>'; irm https://raw.githubusercontent.com/r1z4x/tezgah/v<version>/packaging/install.ps1 \| iex` |
|
|
73
73
|
| upgrade | `tezgah update` (any channel), `bin/tezgah-setup --upgrade [VERSION]` from the installed tree, or `sh packaging/upgrade.sh --version X.Y.Z` |
|
|
74
74
|
|
|
75
75
|
`packaging/install.sh` is a bootstrap, never a second implementation: it runs
|
|
76
76
|
`packaging/upgrade.sh` — the one place a version is fetched, checksum-verified,
|
|
77
77
|
unpacked and made current — and then starts `bin/tezgah-setup --install` from the
|
|
78
|
-
tree that just became current (`packaging/install.sh:
|
|
78
|
+
tree that just became current (`packaging/install.sh:54-66`). `upgrade.sh`
|
|
79
79
|
compares the digest it fetched against the artifact before unpacking anything and
|
|
80
|
-
stops, printing both, on a mismatch (`packaging/upgrade.sh:
|
|
80
|
+
stops, printing both, on a mismatch (`packaging/upgrade.sh:148-152`). It then
|
|
81
81
|
checks the tarball's build provenance with `gh attestation verify` when `gh` is
|
|
82
82
|
on PATH. Without `gh` it prints `provenance not checked`, and a `gh` that cannot
|
|
83
83
|
answer is a warning: the checksum stays the gate.
|
|
84
84
|
`TEZGAH_DIST` points `upgrade.sh` and `install.ps1` at a directory holding
|
|
85
85
|
`tezgah-<version>.tar.gz` + `.sha256` instead of the release URL — the seam that
|
|
86
86
|
installs a locally built artifact with no published release, which is what CI
|
|
87
|
-
uses (`packaging/upgrade.sh:17-
|
|
87
|
+
uses (`packaging/upgrade.sh:17-24`, `packaging/upgrade.sh:105-111`).
|
|
88
|
+
|
|
89
|
+
**A private `TEZGAH_REPO` needs a token.** GitHub answers `404` to
|
|
90
|
+
`releases/download/...` from a session without one. Measured 2026-10-17: the token
|
|
91
|
+
in the URL and a plain bearer header answered the same. So a token in
|
|
92
|
+
`TEZGAH_GITHUB_TOKEN`, `GITHUB_TOKEN` or `GH_TOKEN` sends the fetch to the REST
|
|
93
|
+
asset endpoint instead. That endpoint wants `Accept: application/octet-stream` plus
|
|
94
|
+
`Authorization: Bearer`, and the script reads the asset's id out of the release
|
|
95
|
+
JSON of the tag. The bearer reaches curl on stdin (`-H @-`). No other user's `ps`
|
|
96
|
+
shows it as an argument. `packaging/install.sh` carries the same bearer for the
|
|
97
|
+
`raw.githubusercontent.com` bootstrap. `packaging/install.ps1` carries it for the
|
|
98
|
+
release JSON and the asset blobs. With no token, the public URLs stand and a failed
|
|
99
|
+
fetch names the token to set. The brew formula takes the same shape. It names the
|
|
100
|
+
asset endpoint and reads `HOMEBREW_GITHUB_API_TOKEN`. Homebrew leaves that variable
|
|
101
|
+
in the environment it reads a formula with, so the token resolves at evaluation.
|
|
102
|
+
Homebrew redacts it from the commands it logs.
|
|
88
103
|
|
|
89
104
|
Windows goes through `packaging/install.ps1`, which assumes no `sh`, no `python3`
|
|
90
105
|
and no symlink privilege: it unpacks with the `tar.exe` that Windows 10 1803+
|
|
91
106
|
ships, materialises `current` as a directory junction, copies the tree where a
|
|
92
107
|
junction is refused, and starts the installer with the first of `py -3`,
|
|
93
108
|
`python`, `python3` it finds, passing `--prefix` on (`packaging/install.ps1:12-23`,
|
|
94
|
-
`packaging/install.ps1:
|
|
109
|
+
`packaging/install.ps1:179-195`). The installer knows both shapes of `current`
|
|
95
110
|
(`bin/tezgah-setup::running_prefix`). A junction answers to
|
|
96
111
|
`os.path.isjunction`, or to its reparse tag below Python 3.12. A copy is the
|
|
97
112
|
running tree at `<prefix>/current` with no `.git`, whose `VERSION` names a
|
package/package.json
CHANGED
package/packaging/install.ps1
CHANGED
|
@@ -27,6 +27,11 @@
|
|
|
27
27
|
|
|
28
28
|
$env:TEZGAH_VERSION = '0.1.0'; irm https://raw.githubusercontent.com/r1z4x/tezgah/main/packaging/install.ps1 | iex
|
|
29
29
|
|
|
30
|
+
The tezgah repository is private, so that fetch and the release below need a
|
|
31
|
+
token with read access, in `TEZGAH_GITHUB_TOKEN`, `GITHUB_TOKEN` or `GH_TOKEN`:
|
|
32
|
+
|
|
33
|
+
$env:GITHUB_TOKEN = 'ghp_...'
|
|
34
|
+
|
|
30
35
|
.EXAMPLE
|
|
31
36
|
.\install.ps1 -Version 0.1.0 -Prefix D:\tezgah
|
|
32
37
|
#>
|
|
@@ -59,16 +64,29 @@ function Remove-Current([string]$Path) {
|
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
if ($env:TEZGAH_REPO) { $Repo = $env:TEZGAH_REPO }
|
|
67
|
+
# A private repository serves no release file to an anonymous session, so the
|
|
68
|
+
# token decides which URL is read: the REST asset endpoint with it, the plain
|
|
69
|
+
# download URL without. `releases/download/...` answers 404 to both a token in
|
|
70
|
+
# the URL and a bearer header (measured 2026-10-17), so the id comes first.
|
|
71
|
+
$Token = $env:TEZGAH_GITHUB_TOKEN
|
|
72
|
+
if (-not $Token) { $Token = $env:GITHUB_TOKEN }
|
|
73
|
+
if (-not $Token) { $Token = $env:GH_TOKEN }
|
|
74
|
+
$Headers = @{}
|
|
75
|
+
$AssetHeaders = @{ Accept = 'application/octet-stream' }
|
|
76
|
+
if ($Token) {
|
|
77
|
+
$Headers.Authorization = "Bearer $Token"
|
|
78
|
+
$AssetHeaders.Authorization = "Bearer $Token"
|
|
79
|
+
}
|
|
62
80
|
if (-not $Version) { $Version = $env:TEZGAH_VERSION }
|
|
63
81
|
if (-not $Prefix) { $Prefix = $env:TEZGAH_PREFIX }
|
|
64
82
|
if (-not $Prefix) { $Prefix = Join-Path $env:LOCALAPPDATA 'tezgah' } # Windows' data dir
|
|
65
83
|
$Prefix = Resolve-Full $Prefix
|
|
66
84
|
if (-not $Version) {
|
|
67
85
|
try {
|
|
68
|
-
$rel = Invoke-RestMethod "https://api.github.com/repos/$Repo/releases/latest"
|
|
86
|
+
$rel = Invoke-RestMethod "https://api.github.com/repos/$Repo/releases/latest" -Headers $Headers
|
|
69
87
|
$Version = "$($rel.tag_name)".TrimStart('v')
|
|
70
88
|
} catch {
|
|
71
|
-
throw "tezgah: cannot read the newest release of $Repo (no release yet, or no network): $_"
|
|
89
|
+
throw "tezgah: cannot read the newest release of $Repo (no release yet, or no network; a private repository needs TEZGAH_GITHUB_TOKEN, GITHUB_TOKEN or GH_TOKEN): $_"
|
|
72
90
|
}
|
|
73
91
|
}
|
|
74
92
|
if (-not $Version -or $Version -match '[\\/]' -or $Version -in @('.', '..')) {
|
|
@@ -86,13 +104,28 @@ try {
|
|
|
86
104
|
if ($env:TEZGAH_DIST) {
|
|
87
105
|
$archive = Join-Path (Resolve-Full $env:TEZGAH_DIST) $name
|
|
88
106
|
if (-not (Test-Path -LiteralPath $archive)) { throw "tezgah: no $archive" }
|
|
107
|
+
} elseif ($Token) {
|
|
108
|
+
$release = Invoke-RestMethod "https://api.github.com/repos/$Repo/releases/tags/v$Version" -Headers $Headers
|
|
109
|
+
$asset = $release.assets | Where-Object { $_.name -eq $name }
|
|
110
|
+
$sidecarAsset = $release.assets | Where-Object { $_.name -eq "$name.sha256" }
|
|
111
|
+
if (-not $asset -or -not $sidecarAsset) {
|
|
112
|
+
throw "tezgah: release v$Version of $Repo carries no $name"
|
|
113
|
+
}
|
|
114
|
+
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch { }
|
|
115
|
+
Invoke-WebRequest -UseBasicParsing -Headers $AssetHeaders `
|
|
116
|
+
"https://api.github.com/repos/$Repo/releases/assets/$($asset.id)" -OutFile $archive
|
|
89
117
|
} else {
|
|
90
118
|
$base = "https://github.com/$Repo/releases/download/v$Version"
|
|
91
119
|
try { [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 } catch { }
|
|
92
120
|
Invoke-WebRequest -UseBasicParsing "$base/$name" -OutFile $archive
|
|
93
121
|
}
|
|
94
122
|
$sidecar = "$archive.sha256"
|
|
95
|
-
if (
|
|
123
|
+
if ($env:TEZGAH_DIST) {
|
|
124
|
+
# already beside the archive
|
|
125
|
+
} elseif ($Token) {
|
|
126
|
+
Invoke-WebRequest -UseBasicParsing -Headers $AssetHeaders `
|
|
127
|
+
"https://api.github.com/repos/$Repo/releases/assets/$($sidecarAsset.id)" -OutFile $sidecar
|
|
128
|
+
} else {
|
|
96
129
|
Invoke-WebRequest -UseBasicParsing "$base/$name.sha256" -OutFile $sidecar
|
|
97
130
|
}
|
|
98
131
|
|
package/packaging/install.sh
CHANGED
|
@@ -6,10 +6,14 @@
|
|
|
6
6
|
# Runs packaging/upgrade.sh (the one place a version is fetched, verified,
|
|
7
7
|
# unpacked and made current), then the installer from the tree it made current.
|
|
8
8
|
# Needs sh and curl; tar and sha256sum are upgrade.sh's. Env, unlike its flags:
|
|
9
|
-
# TEZGAH_REPO, TEZGAH_DIST, TEZGAH_PREFIX, as in upgrade.sh
|
|
9
|
+
# TEZGAH_REPO, TEZGAH_DIST, TEZGAH_PREFIX, as in upgrade.sh, and the token below
|
|
10
|
+
# (a private TEZGAH_REPO serves no file without one).
|
|
10
11
|
set -eu
|
|
11
12
|
|
|
12
13
|
REPO=${TEZGAH_REPO:-r1z4x/tezgah}
|
|
14
|
+
# raw.githubusercontent.com answers 404 to a session without a token when the
|
|
15
|
+
# repository is private, and serves the same file to one that carries the bearer.
|
|
16
|
+
token=${TEZGAH_GITHUB_TOKEN:-${GITHUB_TOKEN:-${GH_TOKEN:-}}}
|
|
13
17
|
VERSION_ARG=
|
|
14
18
|
PREFIX_ARG=
|
|
15
19
|
REPLY_ARG=
|
|
@@ -37,8 +41,14 @@ else
|
|
|
37
41
|
[ -z "$VERSION_ARG" ] || ref=v$VERSION_ARG
|
|
38
42
|
work=$(mktemp -d "${TMPDIR:-/tmp}/tezgah-install.XXXXXX") || exit 1
|
|
39
43
|
up=$work/upgrade.sh
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
url="https://raw.githubusercontent.com/$REPO/$ref/packaging/upgrade.sh"
|
|
45
|
+
if [ -n "$token" ]; then
|
|
46
|
+
printf 'Authorization: Bearer %s\n' "$token" | curl -fsSL -H @- "$url" -o "$up" \
|
|
47
|
+
|| { echo "tezgah: cannot fetch packaging/upgrade.sh at $ref - if $REPO is private, set TEZGAH_GITHUB_TOKEN, GITHUB_TOKEN or GH_TOKEN" >&2; exit 1; }
|
|
48
|
+
else
|
|
49
|
+
curl -fsSL "$url" -o "$up" \
|
|
50
|
+
|| { echo "tezgah: cannot fetch packaging/upgrade.sh at $ref - if $REPO is private, set TEZGAH_GITHUB_TOKEN, GITHUB_TOKEN or GH_TOKEN" >&2; exit 1; }
|
|
51
|
+
fi
|
|
42
52
|
fi
|
|
43
53
|
|
|
44
54
|
set -- --prefix "$PREFIX" # explicit flags: a prefix may hold a space
|
package/packaging/upgrade.sh
CHANGED
|
@@ -12,13 +12,15 @@
|
|
|
12
12
|
# Callers: packaging/install.sh (a first install) and `tezgah-setup --upgrade`.
|
|
13
13
|
# Neither re-implements the fetch, the checksum or the flip.
|
|
14
14
|
#
|
|
15
|
-
# Needs: sh, curl, tar, and sha256sum or shasum. No python. Uses `gh` when it
|
|
15
|
+
# Needs: sh, curl, tar, awk, and sha256sum or shasum. No python. Uses `gh` when it
|
|
16
16
|
# is on PATH to check the release's build provenance; without it, says so.
|
|
17
17
|
# Env: TEZGAH_PREFIX, XDG_DATA_HOME, TEZGAH_VERSION, TEZGAH_REPO, TEZGAH_DIST
|
|
18
18
|
# (a directory holding tezgah-<V>.tar.gz + .sha256 - what build.sh --out
|
|
19
19
|
# writes; it swaps the release URL for that directory, one code path, and
|
|
20
20
|
# is how upgrade.sh is exercised without a published release), TEZGAH_GH
|
|
21
|
-
# (the gh to run for the provenance check; default `gh` on PATH)
|
|
21
|
+
# (the gh to run for the provenance check; default `gh` on PATH),
|
|
22
|
+
# TEZGAH_GITHUB_TOKEN / GITHUB_TOKEN / GH_TOKEN (the first one set is sent
|
|
23
|
+
# as the bearer a private $TEZGAH_REPO needs; with none, the public URLs).
|
|
22
24
|
set -eu
|
|
23
25
|
|
|
24
26
|
REPO=${TEZGAH_REPO:-r1z4x/tezgah}
|
|
@@ -39,10 +41,40 @@ die() {
|
|
|
39
41
|
exit 1
|
|
40
42
|
}
|
|
41
43
|
|
|
44
|
+
# A private repository answers 404 to `releases/download/...` from a session without
|
|
45
|
+
# a token (measured 2026-10-17, with the token as URL userinfo and as a header
|
|
46
|
+
# alike), while the REST asset endpoint returns the blob for `Accept:
|
|
47
|
+
# application/octet-stream` plus `Authorization: Bearer`. So the token decides which
|
|
48
|
+
# URL is read, and a public repository - no token - keeps exactly the URL it had.
|
|
49
|
+
token=${TEZGAH_GITHUB_TOKEN:-${GITHUB_TOKEN:-${GH_TOKEN:-}}}
|
|
50
|
+
|
|
51
|
+
# Every read goes through here, so the bearer cannot be forgotten on one call. It
|
|
52
|
+
# reaches curl on stdin (`-H @-`, curl 7.55+): an argument is in every user's `ps`.
|
|
53
|
+
get() { # get <url> [curl args...]
|
|
54
|
+
if [ -n "$token" ]; then
|
|
55
|
+
printf 'Authorization: Bearer %s\n' "$token" | curl -fsSL -H @- "$@"
|
|
56
|
+
else
|
|
57
|
+
curl -fsSL "$@"
|
|
58
|
+
fi
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# The id of asset `$2` in the JSON of one release (`$1`). An asset's id is written
|
|
62
|
+
# down in one place, its own `url` field, so the JSON is flattened, split at each
|
|
63
|
+
# `"url":` - one fragment per asset, from its url to the next one - and the id read
|
|
64
|
+
# from the fragment that names the file wanted. Empty, not an error, when the
|
|
65
|
+
# release carries no such asset; the caller says so.
|
|
66
|
+
asset_id() {
|
|
67
|
+
printf '%s\n' "$1" | tr -d '[:space:]' | awk -v want="\"name\":\"$2\"" '
|
|
68
|
+
{ n = split($0, o, "\"url\":")
|
|
69
|
+
for (i = 1; i <= n; i++)
|
|
70
|
+
if (index(o[i], want) && match(o[i], /"id":[0-9]+/))
|
|
71
|
+
{ print substr(o[i], RSTART + 5, RLENGTH - 5); exit } }'
|
|
72
|
+
}
|
|
73
|
+
|
|
42
74
|
# The newest release tag. The API answers `tag_name`; the raw redirect would
|
|
43
75
|
# too, but GitHub answers this without a rate-limit surprise on a repeat run.
|
|
44
76
|
latest_release() {
|
|
45
|
-
body=$(
|
|
77
|
+
body=$(get "https://api.github.com/repos/$REPO/releases/latest" 2>/dev/null) \
|
|
46
78
|
|| return 1
|
|
47
79
|
tag=$(printf '%s\n' "$body" \
|
|
48
80
|
| sed -n 's/.*"tag_name":[[:space:]]*"\([^"]*\)".*/\1/p' | head -n 1)
|
|
@@ -77,18 +109,40 @@ if [ -n "${TEZGAH_DIST:-}" ]; then
|
|
|
77
109
|
*) dist=$PWD/$TEZGAH_DIST ;;
|
|
78
110
|
esac
|
|
79
111
|
base="file://$dist"
|
|
112
|
+
assets=
|
|
113
|
+
elif [ -n "$token" ]; then
|
|
114
|
+
# The asset endpoint is addressed by id, and the release JSON is the only
|
|
115
|
+
# place that id is written down.
|
|
116
|
+
rel=$(get "https://api.github.com/repos/$REPO/releases/tags/v$VERSION") \
|
|
117
|
+
|| die "cannot read release v$VERSION of $REPO with the token in TEZGAH_GITHUB_TOKEN/GITHUB_TOKEN/GH_TOKEN"
|
|
118
|
+
id=$(asset_id "$rel" "tezgah-$VERSION.tar.gz")
|
|
119
|
+
id_sidecar=$(asset_id "$rel" "tezgah-$VERSION.tar.gz.sha256")
|
|
120
|
+
[ -n "$id" ] && [ -n "$id_sidecar" ] \
|
|
121
|
+
|| die "release v$VERSION of $REPO carries no tezgah-$VERSION.tar.gz"
|
|
122
|
+
base="https://api.github.com/repos/$REPO/releases/assets"
|
|
123
|
+
assets=$base
|
|
80
124
|
else
|
|
81
125
|
base="https://github.com/$REPO/releases/download/v$VERSION"
|
|
126
|
+
assets=
|
|
82
127
|
fi
|
|
83
128
|
|
|
84
129
|
work=$(mktemp -d "${TMPDIR:-/tmp}/tezgah-upgrade.XXXXXX") || die "cannot create a temp dir"
|
|
85
130
|
trap 'rm -rf "$work"' EXIT INT TERM
|
|
86
131
|
|
|
87
132
|
name=tezgah-$VERSION.tar.gz
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
133
|
+
if [ -n "$assets" ]; then
|
|
134
|
+
# Both files come from the same release, and neither blob is served without
|
|
135
|
+
# this Accept: the endpoint answers JSON metadata otherwise.
|
|
136
|
+
get -H "Accept: application/octet-stream" "$assets/$id" -o "$work/$name" \
|
|
137
|
+
|| die "cannot fetch $name from $assets/$id"
|
|
138
|
+
get -H "Accept: application/octet-stream" "$assets/$id_sidecar" -o "$work/$name.sha256" \
|
|
139
|
+
|| die "cannot fetch $name.sha256 from $assets/$id_sidecar"
|
|
140
|
+
else
|
|
141
|
+
get "$base/$name" -o "$work/$name" \
|
|
142
|
+
|| die "cannot fetch $name from $base - if $REPO is private, set TEZGAH_GITHUB_TOKEN, GITHUB_TOKEN or GH_TOKEN"
|
|
143
|
+
get "$base/$name.sha256" -o "$work/$name.sha256" \
|
|
144
|
+
|| die "cannot fetch $name.sha256 from $base - if $REPO is private, set TEZGAH_GITHUB_TOKEN, GITHUB_TOKEN or GH_TOKEN"
|
|
145
|
+
fi
|
|
92
146
|
|
|
93
147
|
want=$(sed -n '1s/[[:space:]].*//p' "$work/$name.sha256")
|
|
94
148
|
got=$(sha256_of "$work/$name")
|