Automate Grok Bot releases (#583)

* Automate Grok Bot releases

* Refresh Grok Bot to apt 0.66.0 and harden upstream.sh

Bump both architectures to Cursor apt 0.66.0 with matching SHA256s,
introduce a versioned _pool URL helper, and filter Packages stanzas by
Package: grok-bot so sync stays correct if the index grows.

* grok-bot: bump to 0.68.1, drop manual hold, validate pool filename

Bump both architectures to Cursor apt 0.68.1 with the SHA256s from the
amd64/arm64 Packages indexes (verified against the downloaded debs).

Drop grok-bot from the manual holds list in docs/upstream-sources.md and
have upstream.sh check that the newest stanza's Filename is the versioned
pool path the PKGBUILD downloads from. Both additions come from #848.
This commit is contained in:
Timothy Wright authored and GitHub committed 2026-10-08 15:50:44 -04:00
1 parent 678d7400ed
commit cb3909f052
5 files changed
+94 -57

No files matched your search

+1 -1
View File
@@ -219,7 +219,7 @@ in `origin` and has no effect on release selection.
## Existing manual holds
`grok-bot`, `libfprint-git`, `libretro-cap32-git`, `libretro-database-git`, `libretro-fbneo-git`, `libretro-uae-git`, `libretro-vice-git`, `quickshell-git`, `supergfxctl`.
`libfprint-git`, `libretro-cap32-git`, `libretro-database-git`, `libretro-fbneo-git`, `libretro-uae-git`, `libretro-vice-git`, `quickshell-git`, `supergfxctl`.
These packages were already excluded from automatic AUR updates. The migration preserves that policy.
+1 -1
View File
@@ -1,6 +1,6 @@
{
"source": "local",
"sync": false,
"release_ring": "fast",
"origin": {
"aur": "grok-bot",
"commit": "05eb78fca06b482affda28b26223cbf249d4bbcd"
+84
View File
@@ -0,0 +1,84 @@
#!/bin/bash
# Cursor publishes Grok Bot from its own Debian repository, one index per
# architecture. Each index carries the version and the SHA256, so an update
# is two small HTTP requests instead of downloading the debs, and the pool
# URL is keyed by version. bin/sync-upstream can rewrite pkgver and the
# checksums; it cannot rewrite a commit id embedded in the old
# downloads.cursor.com/grokbot/stable/<commit>/ URL.
set -euo pipefail
BASE_URL="https://downloads.cursor.com/aptrepo"
declare -A DEB_ARCHES=([x86_64]=amd64 [aarch64]=arm64)
# Print "<version> <sha256>" for the newest grok-bot stanza. Newest is
# vercmp's opinion, which is the one bin/sync-upstream and pacman both use;
# sort -V disagrees with it over versions like 1.0a. The winner's Filename
# must be the versioned pool path the PKGBUILD downloads from.
newest_release() {
local index="$1" debarch="$2"
local version sha256 filename best_version="" best_sha256="" best_filename=""
while read -r version sha256 filename; do
[[ -n "$version" && -n "$sha256" ]] || continue
if [[ -z "$best_version" ]] || [[ "$(vercmp "$version" "$best_version")" -gt 0 ]]; then
best_version="$version"
best_sha256="$sha256"
best_filename="$filename"
fi
done < <(awk '
{ sub(/\r$/, "") }
/^Package:/ { package = $2 }
/^Version:/ { version = $2 }
/^SHA256:/ { sha256 = $2 }
/^Filename:/ { filename = $2 }
/^$/ {
if (package == "grok-bot" && version && sha256) print version, sha256, filename
package = version = sha256 = filename = ""
}
END {
if (package == "grok-bot" && version && sha256) print version, sha256, filename
}
' <<<"$index")
[[ -n "$best_version" ]] || return 1
local expected="pool/grok-bot/g/gr/grok-bot_${best_version}_${debarch}.deb"
if [[ "$best_filename" != "$expected" ]]; then
echo "Unexpected Grok Bot $best_version $debarch Filename: '${best_filename}' (expected $expected)" >&2
return 1
fi
echo "$best_version $best_sha256"
}
versions=()
declare -A checksums=()
for arch in "${!DEB_ARCHES[@]}"; do
index=$(curl -fsSL "$BASE_URL/dists/grok-bot/main/binary-${DEB_ARCHES[$arch]}/Packages")
read -r version sha256 <<<"$(newest_release "$index" "${DEB_ARCHES[$arch]}")"
if [[ -z "${version:-}" || -z "${sha256:-}" ]]; then
echo "No usable Grok Bot release found for $arch" >&2
exit 1
fi
versions+=("$version")
checksums[$arch]="$sha256"
done
# A release can land one architecture at a time. Wait until both agree so one
# pkgver always describes both artifacts.
for version in "${versions[@]}"; do
if [[ "$version" != "${versions[0]}" ]]; then
echo "Upstream architectures are mid-release (${versions[*]}); skipping" >&2
echo '{}'
exit 0
fi
done
jq -n \
--arg pkgver "${versions[0]}" \
--arg x86_64 "${checksums[x86_64]}" \
--arg aarch64 "${checksums[aarch64]}" \
'{pkgver: $pkgver, sha256sums: {x86_64: [$x86_64], aarch64: [$aarch64]}}'
+8 -6
View File
@@ -2,9 +2,8 @@
# Contributor: Omarchy
pkgname=grok-bot
pkgver=0.47.0
pkgver=0.68.1
pkgrel=1
_commit=c1e7d7a46549956d25f53e9c0b9f59666e03aa3a
pkgdesc='Grok Bot desktop agent'
arch=('x86_64' 'aarch64')
url='https://x.ai/bot'
@@ -30,20 +29,23 @@ install=grok-bot.install
_deb_x86_64="grok-bot_${pkgver}_amd64.deb"
_deb_aarch64="grok-bot_${pkgver}_arm64.deb"
# Versioned pool paths — Packages indexes carry SHA256 so upstream.sh
# can bump pkgver without embedding a Cursor commit id.
_pool="https://downloads.cursor.com/aptrepo/pool/grok-bot/g/gr"
source=(
'grok-bot.sh'
'grok-bot.desktop'
)
source_x86_64=(
"${_deb_x86_64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/x64/${_deb_x86_64}"
"${_deb_x86_64}::${_pool}/${_deb_x86_64}"
)
source_aarch64=(
"${_deb_aarch64}::https://downloads.cursor.com/grokbot/stable/${_commit}/linux/arm64/${_deb_aarch64}"
"${_deb_aarch64}::${_pool}/${_deb_aarch64}"
)
sha256sums=('6dfa6c305941afa6cbaefbeaae06d05ab5a88f31630005d25a819a160c20c7a3'
'3e2a2461ea58d17ac1777616be9ba660f7cb9ceefa9292016e36c55758bf78dd')
sha256sums_x86_64=('11ca0f51a535b97af51a352adf9c0f9ecd2e1b0430a69ae9451b688a7a065808')
sha256sums_aarch64=('836f8d19d3826c6573c31ac45c7a9b797abc73381ae0d2b1e7a8dae5410e7e46')
sha256sums_x86_64=('b2be8106d2b3eae07d983d5f1ca77b657accde666dc440db2a409421ecff3359')
sha256sums_aarch64=('3f85fbe2ba3c1d122aa16f8be672076bc19146e07e9d431f37a93b85fa75a93f')
noextract=("${_deb_x86_64}" "${_deb_aarch64}")
package() {
-49
View File
@@ -1,49 +0,0 @@
#!/usr/bin/env bash
# Resolve current Grok Bot stable from Cursor's update feed and pin PKGBUILD.
# Linux has no latest alias (linux-x64 feed returns 204). The darwin-arm64
# sand feed publishes version + commit; the Linux .deb lives at the same commit.
# Darwin can ship first — HEAD-check the Linux URL and fail loudly if 404.
set -euo pipefail
PKGBUILD_PATH="${1:-PKGBUILD}"
[[ -f "${PKGBUILD_PATH}" ]] || { echo "Error: PKGBUILD not found at '${PKGBUILD_PATH}'" >&2; exit 1; }
FEED='https://api2.cursor.sh/updates/api/update/darwin-arm64/sand/0.0.0/00000000-0000-0000-0000-000000000000/stable'
json="$(curl -fsSL -H 'cache-control: no-cache' "${FEED}")"
ver="$(jq -er '.name // .version' <<<"${json}")"
feed_url="$(jq -er '.url' <<<"${json}")"
commit="$(sed -nE 's@.*/(grokbot|sand)/stable/([0-9a-f]{40})/.*@\2@p' <<<"${feed_url}")"
[[ -n "${ver}" && -n "${commit}" ]] || {
echo "Error: could not parse version/commit from feed: ${json}" >&2
exit 1
}
deb_url="https://downloads.cursor.com/grokbot/stable/${commit}/linux/x64/Grok_Bot_${ver}.deb"
code="$(curl -fsSIL -o /dev/null -w '%{http_code}' "${deb_url}")"
[[ "${code}" == "200" ]] || {
echo "Error: Linux deb not fetchable (${code}): ${deb_url}" >&2
exit 1
}
tmp="$(mktemp)"
trap 'rm -f "${tmp}"' EXIT
curl -fL --retry 3 -o "${tmp}" "${deb_url}"
sum="$(sha256sum "${tmp}" | awk '{print $1}')"
current_ver="$(sed -nE 's/^pkgver=([^[:space:]#]+).*/\1/p' "${PKGBUILD_PATH}" | head -n1)"
sed -i -E \
-e "s/^_commit=.*/_commit=${commit}/" \
-e "s/^pkgver=.*/pkgver=${ver}/" \
-e "0,/^[[:space:]]*'[0-9a-f]{64}'/s// '${sum}'/" \
"${PKGBUILD_PATH}"
if [[ "${ver}" != "${current_ver}" ]]; then
sed -i -E 's/^pkgrel=.*/pkgrel=1/' "${PKGBUILD_PATH}"
fi
echo "${ver} ${commit}"
echo "${deb_url}"
echo "${sum}"