15 Commits

Author SHA1 Message Date
eva ae6d65637e ci: Prefer job GITEA_TOKEN for package releases
Build Arch package / build (push) Successful in 31s
2026-09-03 16:04:51 +00:00
linus f6f3520415 ci: Replace deleted s1d3sw1ped_bot commit identity (#12)
update.yml commits as eva. Closes #11.
2026-09-03 01:44:48 -05:00
eva 4fc0fa9eaf ci: Replace deleted s1d3sw1ped_bot commit identity
Use eva for scheduled bump commits; push still via job token.
2026-09-03 06:43:41 +00:00
linus e1da61d7b7 scripts: Parse update feed with python3 if jq is missing (#10)
jq optional on stay-current path; fail closed on bad feed/download. Duplicate #9 closed.
2026-09-03 00:18:31 -05:00
ash fe03fed004 scripts: Parse update feed with python3 if jq is missing
Jumpboxes may lack jq; requiring it made the documented manual path
fail closed for the wrong reason. Keep python3 as the rewrite tool
and the feed parser fallback, and fail loudly when neither parser
nor curl/sha256sum is present. Reject tiny/non-deb downloads so a
failed fetch cannot look like a successful bump.
2026-09-03 05:17:04 +00:00
linus 1faa355d6e pkgbuild: Bump grok-bot-bin to 0.36.0 (#8)
pkgbuild: Bump grok-bot-bin to 0.36.0

Stay-current path: fail-closed update.sh/workflow, README Updating for cron + manual force. Closes #7.
2026-09-03 00:15:14 -05:00
ash 49a15ebb2d docs: Document stay-current bump path
Tell Justin how cron runs update.sh, commits, tags, and pushes, and how
to force the same bump by hand. Align the release install example with
PKGBUILD 0.36.0 (tag v0.36.0) and keep the makepkg path until CI
publishes the asset.
2026-09-03 05:13:25 +00:00
ash 6b180acd39 ci: Harden update workflow
Fail clearly when curl/jq/python3 are missing, when the feed cannot be
parsed, or when the PKGBUILD rewrite does not stick. A scheduled bump
still commits PKGBUILD+.SRCINFO, tags v$pkgver, and pushes; a no-op is
only an already-current pkgver.
2026-09-03 05:13:25 +00:00
ash b93fe47e90 pkgbuild: Bump grok-bot-bin to 0.36.0
Cursor's linux-x64 feed moved past 0.35.0 (pkgrel 2). Keep Justin on
the current official .deb: pkgver 0.36.0, pkgrel 1, commit
9465f3ae75550511296fabbb7a4b6fc8afe9e408.
2026-09-03 05:13:25 +00:00
s1d3sw1ped_bot 34ded1b6ae chore: Promote develop to master (CONTRIBUTING)
Land CONTRIBUTING.md on default master via develop tip.
2026-09-02 11:34:00 -05:00
s1d3sw1ped_bot e65d3131ba docs: Add CONTRIBUTING
Fixes #4
2026-09-02 11:33:28 -05:00
s1d3sw1ped_bot 6184de4bd3 README: Point pacman -U example at v0.35.0-2
Docs sync: align README with current install/CLI behavior.

Co-authored-by: s1d3sw1ped_bot <s1d3sw1ped+giteabot@gmail.com>
Co-committed-by: s1d3sw1ped_bot <s1d3sw1ped+giteabot@gmail.com>
2026-09-02 10:43:48 -05:00
s1d3sw1ped_bot 4b2bc70766 PKGBUILD: Point desktop Exec at update shim
Build Arch package / build (push) Successful in 27s
0.30 shipped Exec="/opt/Grok Bot/grok-bot", so the app menu skipped
/usr/bin/grok-bot and never auto-updated. Always rewrite the desktop
Exec to the PATH shim after unpacking the .deb so that cannot regress.
Bump pkgrel to 2; clearer sudo failure hint in the launch shim.
2026-09-02 15:21:20 +00:00
s1d3sw1ped_bot 7fea71c3ec pkgbuild: Fix sha256sums array after 0.35.0 bump
Build Arch package / build (push) Successful in 27s
update.sh replaced only the first sha256sums line and left orphan
hashes, so makepkg could not source PKGBUILD. Rewrite both deb and
launch-shim sums; reset pkgrel to 1 for the first 0.35.0 package.
2026-09-02 14:54:27 +00:00
s1d3sw1ped_bot c8fdd67e83 pkgbuild: Bump grok-bot-bin to 0.35.0 2026-09-02 06:17:46 +00:00
8 changed files with 282 additions and 41 deletions
+6 -6
View File
@@ -1,7 +1,7 @@
pkgbase = grok-bot-bin pkgbase = grok-bot-bin
pkgdesc = Grok Bot desktop agent (official .deb repackaged) pkgdesc = Grok Bot desktop agent (official .deb repackaged)
pkgver = 0.30.0 pkgver = 0.36.0
pkgrel = 2 pkgrel = 1
url = https://cursor.com/download/bot url = https://cursor.com/download/bot
arch = x86_64 arch = x86_64
license = LicenseRef-proprietary license = LicenseRef-proprietary
@@ -26,10 +26,10 @@ pkgbase = grok-bot-bin
replaces = sand replaces = sand
options = !strip options = !strip
options = !debug options = !debug
source = https://downloads.cursor.com/grokbot/stable/2385d097738b3719cc5ecd9281a107aa106215f1/linux/x64/grok-bot_0.30.0_amd64.deb source = https://downloads.cursor.com/grokbot/stable/9465f3ae75550511296fabbb7a4b6fc8afe9e408/linux/x64/grok-bot_0.36.0_amd64.deb
source = grok-bot-launch.sh source = grok-bot-launch.sh
noextract = grok-bot_0.30.0_amd64.deb noextract = grok-bot_0.36.0_amd64.deb
sha256sums = fb888b2204c8a51c71a9f5f9a2913ac10561f3ef6939c1245ecae4e837d4ada2 sha256sums = 948b4177667d9a03915c1aee497e7c5438705393da8083a6af0177288512d07e
sha256sums = 886c8b55eb44d2f7812be50dcc1571907dc2d7e755171e67e916f497634f09eb sha256sums = 1c5a3599db15816caa839fc9e088ba9798757e44fec89c066ef5f6f3c0972aee
pkgname = grok-bot-bin pkgname = grok-bot-bin
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
- name: Attach package to Gitea release - name: Attach package to Gitea release
if: startsWith(github.ref, 'refs/tags/') if: startsWith(github.ref, 'refs/tags/')
env: env:
GITEA_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
run: | run: |
set -euo pipefail set -euo pipefail
tag="${GITHUB_REF_NAME}" tag="${GITHUB_REF_NAME}"
+18 -5
View File
@@ -13,17 +13,30 @@ jobs:
run: | run: |
set -euo pipefail set -euo pipefail
sudo apt-get update -qq sudo apt-get update -qq
sudo apt-get install -y -qq jq curl sudo apt-get install -y -qq jq curl python3
for cmd in jq curl python3; do
command -v "$cmd" >/dev/null || { echo "error: missing $cmd" >&2; exit 1; }
done
before=$(sed -n 's/^pkgver=//p' PKGBUILD) before=$(sed -n 's/^pkgver=//p' PKGBUILD)
./scripts/update.sh ./scripts/update.sh
after=$(sed -n 's/^pkgver=//p' PKGBUILD) after=$(sed -n 's/^pkgver=//p' PKGBUILD)
if [[ -z "$after" ]]; then
echo "error: could not read pkgver after update.sh" >&2
exit 1
fi
if [[ "$before" == "$after" ]]; then if [[ "$before" == "$after" ]]; then
echo "No bump" echo "No bump (still $after)"
exit 0 exit 0
fi fi
git config user.name 's1d3sw1ped_bot' git config user.name 'eva'
git config user.email 's1d3sw1ped_bot@git.s1d3sw1ped.com' git config user.email 's1d3sw1ped+eva@gmail.com'
git add PKGBUILD .SRCINFO git add PKGBUILD .SRCINFO
git commit -m "pkgbuild: Bump grok-bot-bin to ${after}" git commit -m "pkgbuild: Bump grok-bot-bin to ${after}"
git tag "v${after}" git tag "v${after}"
git push origin "HEAD:${GITHUB_REF_NAME}" "v${after}" # Proven on this forge: run 1190 pushed master + tag v0.35.0.
# Still fail the job if push is denied rather than reporting a landed bump.
if ! git push origin "HEAD:${GITHUB_REF_NAME}" "v${after}"; then
echo "error: could not push commit/tag to ${GITHUB_REF_NAME} (v${after})." >&2
echo "error: Manual path: ./scripts/update.sh, commit, PR/merge, then tag v${after} and push the tag so build.yml can attach the release asset." >&2
exit 1
fi
+45
View File
@@ -0,0 +1,45 @@
# Contributing
## Propose changes
Open a pull request against `develop`. Keep the default branch for releases and
stable tips; land work on `develop` first.
Point at an existing issue when one fits. Prefer a short issue that states the
symptom or request before a large PR.
## Commits
Subject form:
```
area: Imperative summary
```
- **Area** is a real package, directory, or subsystem token (`ci:`, `docs:`,
Go package name). Not a lone filename.
- **Imperative** mood: Fix, Add, Remove — not "Fixed" or "This patch…".
- No trailing period. Aim ≤ ~7075 characters for the whole subject.
- Not conventional-commits (`feat:` / `fix:` / `chore:` as types).
Body explains **why**. Establish the problem, then say what you are doing.
One logical change per commit; split fix and cleanup.
## Pull requests
Title matches the primary commit subject.
- **What** changed
- **Why** (problem and impact)
- **Test** (concrete steps; "CI green" alone is weak)
## Issues and closing
Cite leftover issues by **full URL**. Gitea closes issues when `#N` appears in
merge text, so do not put `#N` in the merge message unless that issue is actually
done. Use `Fixes #N` / `Closes #N` only when the leftover work is finished.
## License
License TBD by owner.
+13 -5
View File
@@ -8,9 +8,9 @@
# https://downloads.cursor.com/grokbot/stable/<commit>/linux/x64/grok-bot_<pkgver>_amd64.deb # https://downloads.cursor.com/grokbot/stable/<commit>/linux/x64/grok-bot_<pkgver>_amd64.deb
pkgname=grok-bot-bin pkgname=grok-bot-bin
pkgver=0.30.0 pkgver=0.36.0
_commit=2385d097738b3719cc5ecd9281a107aa106215f1 _commit=9465f3ae75550511296fabbb7a4b6fc8afe9e408
pkgrel=2 pkgrel=1
pkgdesc="Grok Bot desktop agent (official .deb repackaged)" pkgdesc="Grok Bot desktop agent (official .deb repackaged)"
arch=('x86_64') arch=('x86_64')
url="https://cursor.com/download/bot" url="https://cursor.com/download/bot"
@@ -43,8 +43,8 @@ source=(
) )
noextract=("grok-bot_${pkgver}_amd64.deb") noextract=("grok-bot_${pkgver}_amd64.deb")
sha256sums=( sha256sums=(
'fb888b2204c8a51c71a9f5f9a2913ac10561f3ef6939c1245ecae4e837d4ada2' '948b4177667d9a03915c1aee497e7c5438705393da8083a6af0177288512d07e'
'886c8b55eb44d2f7812be50dcc1571907dc2d7e755171e67e916f497634f09eb' '1c5a3599db15816caa839fc9e088ba9798757e44fec89c066ef5f6f3c0972aee'
) )
package() { package() {
@@ -56,6 +56,14 @@ package() {
# Keep provides(sand) on PATH; both names run the same shim. # Keep provides(sand) on PATH; both names run the same shim.
ln -sf grok-bot "$pkgdir/usr/bin/sand" ln -sf grok-bot "$pkgdir/usr/bin/sand"
# Always point the menu entry at the PATH shim. Upstream .desktop has used
# Exec="/opt/Grok Bot/grok-bot" (0.30) which bypasses auto-update; rewrite
# every build so a future /opt regression cannot ship again.
if [[ -f "$pkgdir/usr/share/applications/grok-bot.desktop" ]]; then
sed -i 's|^Exec=.*|Exec=grok-bot %U|' \
"$pkgdir/usr/share/applications/grok-bot.desktop"
fi
# Path contains a space, so Chromium cannot use the SUID sandbox. # Path contains a space, so Chromium cannot use the SUID sandbox.
# Arch/CachyOS kernels have user namespaces; keep chrome-sandbox non-setuid. # Arch/CachyOS kernels have user namespaces; keep chrome-sandbox non-setuid.
if [[ -f "$pkgdir/opt/Grok Bot/chrome-sandbox" ]]; then if [[ -f "$pkgdir/opt/Grok Bot/chrome-sandbox" ]]; then
+47 -6
View File
@@ -6,6 +6,8 @@ Not affiliated with Cursor / SpaceXAI. The app binary is unchanged; this only re
## Install (build locally) ## Install (build locally)
This tree packages **0.36.0** (`pkgver` / `pkgrel=1` in `PKGBUILD`). `makepkg -si` from git tip builds that version even before a release tag exists.
```bash ```bash
git clone https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin.git git clone https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin.git
cd grok-bot-bin cd grok-bot-bin
@@ -28,11 +30,11 @@ makepkg -si
## Install from a release package ## Install from a release package
When CI has published a `.pkg.tar.zst` on the [Releases](https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin/releases) page: `pacman -U` installs whatever `.pkg.tar.zst` is attached on [Releases](https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin/releases), which lags git tip until someone **tags** the bump (see Updating). After `v0.36.0` is pushed, CI (`build.yml`) attaches `grok-bot-bin-0.36.0-1-x86_64.pkg.tar.zst`. Until that asset exists, use `makepkg -si` for 0.36.0; the newest published asset may still be `v0.35.0-2`.
```bash ```bash
curl -LO 'https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin/releases/download/v0.30.0/grok-bot-bin-0.30.0-1-x86_64.pkg.tar.zst' curl -LO 'https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin/releases/download/v0.36.0/grok-bot-bin-0.36.0-1-x86_64.pkg.tar.zst'
sudo pacman -U grok-bot-bin-0.30.0-1-x86_64.pkg.tar.zst sudo pacman -U grok-bot-bin-0.36.0-1-x86_64.pkg.tar.zst
``` ```
Download first, then `pacman -U` the local file (`LocalFileSigLevel = Optional`). Do not pass the remote URL straight to pacman if signatures are required. Download first, then `pacman -U` the local file (`LocalFileSigLevel = Optional`). Do not pass the remote URL straight to pacman if signatures are required.
@@ -51,12 +53,51 @@ Exact `Server=` URL may change once the first repo DB lands; `makepkg -si` works
## Updating ## Updating
`./scripts/update.sh` reads Cursor's linux-x64 update feed, downloads the matching `.deb`, and bumps `pkgver` / `_commit` / `sha256sums` in `PKGBUILD` and `.SRCINFO`. Stay-current path when Cursor's linux-x64 Grok Bot feed moves. `PKGBUILD` is currently **0.36.0** (pkgrel 1). One updater: `./scripts/update.sh`.
Scheduled Gitea Actions will do the same and build a release package. ### Scheduled bump (Gitea Actions)
`.gitea/workflows/update.yml` runs daily (`cron: '17 6 * * *'`) and on `workflow_dispatch`. It:
1. Runs `./scripts/update.sh` against the live Cursor linux-x64 feed.
2. If `pkgver` changed, commits `PKGBUILD` and `.SRCINFO`.
3. Tags `v$pkgver` (an upstream bump resets `pkgrel` to 1, so 0.36.0 → tag `v0.36.0`).
4. Pushes the branch and tag.
The tag triggers `.gitea/workflows/build.yml`, which builds the Arch package and attaches `grok-bot-bin-$pkgver-$pkgrel-x86_64.pkg.tar.zst` to the Gitea release.
Actions **can** push and tag on this forge. [Run 1190](https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin/actions/runs/1190) (schedule on `master`) bumped 0.30.0 → 0.35.0 and pushed `master` plus tag `v0.35.0`.
If the script cannot parse the feed, the `.deb` download fails, or `curl` / `python3` / `sha256sum` is missing, the job fails (it is not a silent “up to date”). `jq` is optional; without it the script parses the feed with `python3`. The workflow still `apt-get install`s `jq` for the run. A no-op is only “already at this `pkgver`”.
Scheduled jobs run on the default branch (`master`). Product PRs land on `develop`; promote or run the manual path below if `develop` is ahead of `master`.
### Manual force path
When you do not want to wait for cron, or you are landing a bump on `develop`:
```bash
# requires curl, python3, sha256sum; jq optional
./scripts/update.sh
```
If the feed is newer, that rewrites `PKGBUILD` and `.SRCINFO`. Then commit, tag, and push (or open a PR into `develop`):
```bash
git add PKGBUILD .SRCINFO
git commit -m "pkgbuild: Bump grok-bot-bin to <pkgver>"
git push origin HEAD:develop # or open a PR into develop
# After it should cut a release:
git tag "v<pkgver>" # e.g. v0.36.0
git push origin "v<pkgver>"
makepkg -si # install from this tree without waiting for the release asset
```
Install the new version with `makepkg -si`, or (once CI publishes the asset) `pacman -U` from Releases as in the example above.
## Notes ## Notes
- `/usr/bin/grok-bot` (and `sand`) is a launch shim: unless `GROK_BOT_NO_UPDATE=1`, it checks the latest Gitea release and may `pacman -U` a newer `.pkg.tar.zst` before exec'ing `/opt/Grok Bot/…`. Network/API failures still launch the installed binary. - `/usr/bin/grok-bot` (and `sand`) is a launch shim: unless `GROK_BOT_NO_UPDATE=1`, it checks the latest Gitea release and may `pacman -U` a newer `.pkg.tar.zst` before exec'ing `/opt/Grok Bot/…`. Network/API failures still launch the installed binary.
- Upstream Linux builds still have no in-app updater for the Electron app itself; `scripts/update.sh` bumps the PKGBUILD from Cursor's feed when packaging a new upstream version. - If the app menu still launches an old binary without updating, run `/usr/bin/grok-bot` once from a terminal, or `sudo pacman -U` the newer `.pkg.tar.zst` from Releases — the menu must call the PATH shim, not `/opt/Grok Bot/…`.
- Upstream Linux builds still have no in-app updater for the Electron app itself; `scripts/update.sh` (cron or manual) is the packaging bump from Cursor's feed.
- `chrome-sandbox` is left non-setuid because the install path contains a space; user namespaces cover sandboxing on CachyOS. - `chrome-sandbox` is left non-setuid because the install path contains a space; user namespaces cover sandboxing on CachyOS.
+1
View File
@@ -53,6 +53,7 @@ _maybe_update() {
# Prefer passwordless sudo; fall back to interactive sudo. Fail soft either way. # Prefer passwordless sudo; fall back to interactive sudo. Fail soft either way.
if ! sudo -n pacman -U --noconfirm "$pkg" 2>/dev/null; then if ! sudo -n pacman -U --noconfirm "$pkg" 2>/dev/null; then
if ! sudo pacman -U --noconfirm "$pkg"; then if ! sudo pacman -U --noconfirm "$pkg"; then
echo "grok-bot: need sudo to auto-update; run: sudo pacman -U <pkg> or launch /usr/bin/grok-bot from a terminal" >&2
echo "grok-bot: pacman -U failed; launching installed version" >&2 echo "grok-bot: pacman -U failed; launching installed version" >&2
return 0 return 0
fi fi
+151 -18
View File
@@ -1,16 +1,73 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# Bump PKGBUILD/.SRCINFO when Cursor publishes a newer linux-x64 Grok Bot. # Bump PKGBUILD/.SRCINFO when Cursor publishes a newer linux-x64 Grok Bot.
# Requires curl, sha256sum, python3. jq is optional (python3 parses the feed).
# Fail loudly; do not leave a half-applied bump that looks like "up to date".
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")/.." cd "$(dirname "$0")/.."
FEED='https://api2.cursor.sh/updates/api/update/linux-x64/sand/0.0.0/00000000-0000-0000-0000-000000000000/stable' need_cmd() { command -v "$1" >/dev/null 2>&1; }
resp=$(curl -fsSL "$FEED")
version=$(jq -r .version <<<"$resp")
commit=$(jq -r .url <<<"$resp" | sed -E 's#.*/stable/([^/]+)/.*#\1#')
current=$(sed -n 's/^pkgver=//p' PKGBUILD)
if [[ -z "$version" || "$version" == "null" || ! "$commit" =~ ^[0-9a-f]{40}$ ]]; then missing=()
echo "Could not parse update feed: $resp" >&2 need_cmd curl || missing+=(curl)
need_cmd sha256sum || missing+=(sha256sum)
need_cmd python3 || missing+=(python3)
if ((${#missing[@]})); then
echo "error: missing required tools: ${missing[*]}" >&2
exit 1
fi
if ! need_cmd jq; then
echo "note: jq not found; parsing update feed with python3" >&2
fi
FEED='https://api2.cursor.sh/updates/api/update/linux-x64/sand/0.0.0/00000000-0000-0000-0000-000000000000/stable'
echo "Fetching update feed..."
if ! resp=$(curl -fsSL --retry 3 --retry-delay 2 "$FEED"); then
echo "error: failed to fetch update feed: $FEED" >&2
exit 1
fi
if [[ -z "$resp" ]]; then
echo "error: empty update feed from $FEED" >&2
exit 1
fi
feed_field() {
local field="$1"
if need_cmd jq; then
jq -er --arg f "$field" '.[$f] | select(. != null and . != "")' <<<"$resp"
else
python3 -c '
import json, sys
d = json.loads(sys.stdin.read())
v = d.get(sys.argv[1])
if not isinstance(v, (str, int, float)) or v == "":
raise SystemExit(1)
print(v)
' "$field" <<<"$resp"
fi
}
if ! version=$(feed_field version); then
echo "error: could not parse .version from update feed: $resp" >&2
exit 1
fi
if ! url=$(feed_field url); then
echo "error: could not parse .url from update feed: $resp" >&2
exit 1
fi
commit=$(sed -E 's#.*/stable/([^/]+)/.*#\1#' <<<"$url")
current=$(sed -n 's/^pkgver=//p' PKGBUILD | head -1)
if [[ ! "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z]+)*$ ]]; then
echo "error: feed version looks wrong: $version" >&2
exit 1
fi
if [[ ! "$commit" =~ ^[0-9a-f]{40}$ ]]; then
echo "error: could not parse 40-char commit from feed url: $url" >&2
exit 1
fi
if [[ -z "$current" ]]; then
echo "error: could not read pkgver from PKGBUILD" >&2
exit 1 exit 1
fi fi
if [[ "$version" == "$current" ]]; then if [[ "$version" == "$current" ]]; then
@@ -22,21 +79,97 @@ echo "Bump $current -> $version (commit $commit)"
deb_url="https://downloads.cursor.com/grokbot/stable/${commit}/linux/x64/grok-bot_${version}_amd64.deb" deb_url="https://downloads.cursor.com/grokbot/stable/${commit}/linux/x64/grok-bot_${version}_amd64.deb"
tmp=$(mktemp) tmp=$(mktemp)
trap 'rm -f "$tmp"' EXIT trap 'rm -f "$tmp"' EXIT
curl -fsSL --retry 3 "$deb_url" -o "$tmp" echo "Downloading $deb_url"
sha=$(sha256sum "$tmp" | cut -d' ' -f1) if ! curl -fL --retry 3 --retry-delay 2 -o "$tmp" "$deb_url"; then
echo "error: failed to download deb: $deb_url" >&2
exit 1
fi
sz=$(wc -c <"$tmp")
if ((sz < 1000000)); then
echo "error: downloaded deb too small (${sz} bytes): $deb_url" >&2
exit 1
fi
magic=$(head -c 8 "$tmp" | tr -d '\0')
if [[ "$magic" != '!<arch>'* ]]; then
echo "error: download is not a .deb (missing ar magic): $deb_url" >&2
exit 1
fi
deb_sha=$(sha256sum "$tmp" | cut -d' ' -f1)
shim_sha=$(sha256sum grok-bot-launch.sh | cut -d' ' -f1)
if [[ ! "$deb_sha" =~ ^[0-9a-f]{64}$ || ! "$shim_sha" =~ ^[0-9a-f]{64}$ ]]; then
echo "error: sha256sum failed (deb=$deb_sha shim=$shim_sha)" >&2
exit 1
fi
# Reset pkgrel on upstream version bumps.
sed -i \ sed -i \
-e "s/^pkgver=.*/pkgver=${version}/" \ -e "s/^pkgver=.*/pkgver=${version}/" \
-e "s/^_commit=.*/_commit=${commit}/" \ -e "s/^_commit=.*/_commit=${commit}/" \
-e "s/^sha256sums=.*/sha256sums=('${sha}')/" \ -e "s/^pkgrel=.*/pkgrel=1/" \
PKGBUILD PKGBUILD
# Refresh .SRCINFO source URL + hashes without requiring makepkg. newver=$(sed -n 's/^pkgver=//p' PKGBUILD | head -1)
sed -i \ newcommit=$(sed -n 's/^_commit=//p' PKGBUILD | head -1)
-e "s/^\\tpkgver = .*/\\tpkgver = ${version}/" \ newrel=$(sed -n 's/^pkgrel=//p' PKGBUILD | head -1)
-e "s#^\\tsource = https://downloads.cursor.com/grokbot/stable/.*/linux/x64/grok-bot_.*_amd64.deb#\\tsource = https://downloads.cursor.com/grokbot/stable/${commit}/linux/x64/grok-bot_${version}_amd64.deb#" \ if [[ "$newver" != "$version" || "$newcommit" != "$commit" || "$newrel" != "1" ]]; then
-e "s/^\\tnoextract = grok-bot_.*_amd64.deb/\\tnoextract = grok-bot_${version}_amd64.deb/" \ echo "error: PKGBUILD rewrite did not stick (pkgver=$newver _commit=$newcommit pkgrel=$newrel)" >&2
-e "s/^\\tsha256sums = .*/\\tsha256sums = ${sha}/" \ exit 1
.SRCINFO fi
echo "Updated PKGBUILD and .SRCINFO to ${version} sha256=${sha}" python3 - "$deb_sha" "$shim_sha" <<'PY'
import pathlib, re, sys
deb_sha, shim_sha = sys.argv[1], sys.argv[2]
p = pathlib.Path("PKGBUILD")
text = p.read_text()
block = f"sha256sums=(\n '{deb_sha}'\n '{shim_sha}'\n)"
text2, n = re.subn(r"sha256sums=\([^\)]*\)", block, text, count=1, flags=re.S)
if n != 1:
raise SystemExit(f"sha256sums replace failed (n={n})")
p.write_text(text2)
PY
python3 - "$version" "$commit" "$deb_sha" "$shim_sha" <<'PY'
import pathlib, sys
version, commit, deb_sha, shim_sha = sys.argv[1:5]
p = pathlib.Path(".SRCINFO")
if not p.is_file():
raise SystemExit(".SRCINFO missing")
lines = []
saw_sha = False
saw_pkgver = saw_pkgrel = saw_source = saw_noextract = False
for line in p.read_text().splitlines(True):
if line.startswith("\tpkgver ="):
lines.append(f"\tpkgver = {version}\n"); saw_pkgver = True; continue
if line.startswith("\tpkgrel ="):
lines.append("\tpkgrel = 1\n"); saw_pkgrel = True; continue
if line.startswith("\tsource = https://downloads.cursor.com/grokbot/stable/"):
lines.append(
f"\tsource = https://downloads.cursor.com/grokbot/stable/{commit}/linux/x64/grok-bot_{version}_amd64.deb\n"
)
saw_source = True
continue
if line.startswith("\tnoextract = grok-bot_"):
lines.append(f"\tnoextract = grok-bot_{version}_amd64.deb\n")
saw_noextract = True
continue
if line.startswith("\tsha256sums ="):
if not saw_sha:
lines.append(f"\tsha256sums = {deb_sha}\n")
lines.append(f"\tsha256sums = {shim_sha}\n")
saw_sha = True
continue
lines.append(line)
missing = [n for n, ok in (
("pkgver", saw_pkgver),
("pkgrel", saw_pkgrel),
("source", saw_source),
("noextract", saw_noextract),
("sha256sums", saw_sha),
) if not ok]
if missing:
raise SystemExit(f".SRCINFO rewrite missed fields: {', '.join(missing)}")
p.write_text("".join(lines))
PY
echo "Updated PKGBUILD and .SRCINFO to ${version} deb_sha=${deb_sha} shim_sha=${shim_sha}"