Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7787fc52a1 | |||
| 464a9558df | |||
| 6bc0ad9de4 | |||
| 807ebc6513 | |||
| a98cc6cabc | |||
| 45c6c4da73 | |||
| 1b51bbddca | |||
| f93409a2ac | |||
| 1001abba40 | |||
| 56b6c046ef | |||
| a9697913da | |||
| 7d361549e1 | |||
| 049b00de10 | |||
| eb83529a0d | |||
| ae6d65637e | |||
| f6f3520415 | |||
| 4fc0fa9eaf | |||
| e1da61d7b7 | |||
| fe03fed004 | |||
| 1faa355d6e | |||
| 49a15ebb2d | |||
| 6b180acd39 | |||
| b93fe47e90 | |||
| 34ded1b6ae | |||
| e65d3131ba | |||
| 6184de4bd3 | |||
| 4b2bc70766 |
@@ -1,6 +1,6 @@
|
|||||||
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.35.0
|
pkgver = 0.44.0
|
||||||
pkgrel = 1
|
pkgrel = 1
|
||||||
url = https://cursor.com/download/bot
|
url = https://cursor.com/download/bot
|
||||||
arch = x86_64
|
arch = x86_64
|
||||||
@@ -19,6 +19,7 @@ pkgbase = grok-bot-bin
|
|||||||
depends = xdg-utils
|
depends = xdg-utils
|
||||||
optdepends = libappindicator-gtk3: tray icon support
|
optdepends = libappindicator-gtk3: tray icon support
|
||||||
optdepends = curl: auto-update check on launch
|
optdepends = curl: auto-update check on launch
|
||||||
|
optdepends = polkit: graphical password prompt for desktop auto-update (pkexec)
|
||||||
provides = grok-bot
|
provides = grok-bot
|
||||||
provides = sand
|
provides = sand
|
||||||
conflicts = grok-bot
|
conflicts = grok-bot
|
||||||
@@ -26,10 +27,14 @@ pkgbase = grok-bot-bin
|
|||||||
replaces = sand
|
replaces = sand
|
||||||
options = !strip
|
options = !strip
|
||||||
options = !debug
|
options = !debug
|
||||||
source = https://downloads.cursor.com/grokbot/stable/1c5a6ceb364c4dd53f0069f72cc4239220ed471e/linux/x64/grok-bot_0.35.0_amd64.deb
|
source = https://downloads.cursor.com/grokbot/stable/12dcfa973ef51585fd1b35df6839fc9d1d7fd6aa/linux/x64/grok-bot_0.44.0_amd64.deb
|
||||||
source = grok-bot-launch.sh
|
source = grok-bot-launch.sh
|
||||||
noextract = grok-bot_0.35.0_amd64.deb
|
source = pkexec-pacman-u
|
||||||
sha256sums = ed254e819d0f0419a1df9771009363074f65f80d8175d2ee0fc62900087ebd99
|
source = com.s1d3sw1ped.grok-bot-bin.policy
|
||||||
sha256sums = 886c8b55eb44d2f7812be50dcc1571907dc2d7e755171e67e916f497634f09eb
|
noextract = grok-bot_0.44.0_amd64.deb
|
||||||
|
sha256sums = dded18b2d3d44b1c32d6b9f63446d2b27bca68b3de7a2aa028ce7956e9694164
|
||||||
|
sha256sums = 36e1c522f7a3920a850a6235263d82ad5990611612979447c1e9eff92548ac1e
|
||||||
|
sha256sums = e92ea4534d864d7f302a082a8717a52af9675195af41092d18f15094f74fed45
|
||||||
|
sha256sums = a9533dfe4d31332ac1505d2e582eff27771dd0107108a5f6289d0d3839431a74
|
||||||
|
|
||||||
pkgname = grok-bot-bin
|
pkgname = grok-bot-bin
|
||||||
|
|||||||
@@ -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}"
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
name: Tag release after merge
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['master']
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tag:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
- name: Create v$pkgver tag if missing
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
if [[ "${GITHUB_REF:-}" != "refs/heads/master" ]]; then
|
||||||
|
echo "error: refusing to tag from ${GITHUB_REF:-unset}; only master" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
pkgver=$(sed -n 's/^pkgver=//p' PKGBUILD | head -1)
|
||||||
|
if [[ -z "$pkgver" ]]; then
|
||||||
|
echo "error: could not read pkgver from PKGBUILD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ ! "$pkgver" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][0-9A-Za-z]+)*$ ]]; then
|
||||||
|
echo "error: PKGBUILD pkgver looks wrong: $pkgver" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -z "${GITHUB_SHA:-}" ]]; then
|
||||||
|
echo "error: GITHUB_SHA is empty; cannot tag v${pkgver}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
tag="v${pkgver}"
|
||||||
|
existing=$(git ls-remote --tags origin "refs/tags/${tag}")
|
||||||
|
if [[ -n "$existing" ]]; then
|
||||||
|
echo "Tag ${tag} already exists; nothing to do"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ -z "${GITEA_TOKEN:-}" ]]; then
|
||||||
|
echo "error: GITEA_TOKEN is empty; cannot push tag ${tag}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git tag "${tag}" "${GITHUB_SHA}"
|
||||||
|
if git push origin "refs/tags/${tag}"; then
|
||||||
|
echo "Pushed tag ${tag} -> ${GITHUB_SHA}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
existing=$(git ls-remote --tags origin "refs/tags/${tag}")
|
||||||
|
if [[ -n "$existing" ]]; then
|
||||||
|
echo "Tag ${tag} appeared concurrently; nothing to do"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "error: could not push tag ${tag} for ${GITHUB_SHA}." >&2
|
||||||
|
echo "error: Manual path: git tag ${tag} && git push origin ${tag} so build.yml can attach the release asset." >&2
|
||||||
|
exit 1
|
||||||
+104
-9
@@ -1,7 +1,7 @@
|
|||||||
name: Check for new release
|
name: Check for new release
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '17 6 * * *'
|
- cron: '17 * * * *'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -10,20 +10,115 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Bump PKGBUILD if a new version is out
|
- name: Bump PKGBUILD if a new version is out
|
||||||
|
env:
|
||||||
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||||||
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
|
||||||
before=$(sed -n 's/^pkgver=//p' PKGBUILD)
|
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 | head -1)
|
||||||
./scripts/update.sh
|
./scripts/update.sh
|
||||||
after=$(sed -n 's/^pkgver=//p' PKGBUILD)
|
after=$(sed -n 's/^pkgver=//p' PKGBUILD | head -1)
|
||||||
|
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'
|
if [[ -z "${GITEA_TOKEN:-}" ]]; then
|
||||||
git config user.email 's1d3sw1ped_bot@git.s1d3sw1ped.com'
|
echo "error: GITEA_TOKEN is empty; cannot open or reuse bump PR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||||
|
echo "error: GITHUB_REPOSITORY is empty; cannot open or reuse bump PR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
git config user.name 'eva'
|
||||||
|
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}"
|
# Do not tag here and do not push protected master. Open a bump PR;
|
||||||
git push origin "HEAD:${GITHUB_REF_NAME}" "v${after}"
|
# tag-release.yml creates v$pkgver after merge so build.yml can run.
|
||||||
|
branch="chore/bump-${after}"
|
||||||
|
git fetch origin "refs/heads/${branch}:refs/remotes/origin/${branch}" || \
|
||||||
|
echo "note: ${branch} not on origin yet (creating)"
|
||||||
|
if ! git push --force-with-lease origin "HEAD:refs/heads/${branch}"; then
|
||||||
|
echo "error: could not push ${branch} (pkgver ${after})." >&2
|
||||||
|
echo "error: Manual path: commit PKGBUILD+.SRCINFO, open a PR to master, merge, then let tag-release.yml create v${after} (or push that tag yourself)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
api="${GITHUB_API_URL:-https://git.s1d3sw1ped.com/api/v1}"
|
||||||
|
repo="${GITHUB_REPOSITORY}"
|
||||||
|
title="pkgbuild: Bump grok-bot-bin to ${after}"
|
||||||
|
body=$(printf '%s\n' \
|
||||||
|
"Automated PKGBUILD bump from Cursor's linux-x64 feed (${before} → ${after})." \
|
||||||
|
"" \
|
||||||
|
"This job does not create a git tag. After this PR merges to master, tag-release.yml should create \`v${after}\` so build.yml can attach the \`.pkg.tar.zst\`.")
|
||||||
|
find_pr() {
|
||||||
|
local prs
|
||||||
|
if ! prs=$(curl -fsS -H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
"${api}/repos/${repo}/pulls?state=open&limit=50"); then
|
||||||
|
echo "error: could not list open pull requests for ${repo}" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if ! jq -e 'type == "array"' >/dev/null <<<"$prs"; then
|
||||||
|
echo "error: unexpected pulls list response for ${repo}" >&2
|
||||||
|
printf '%s\n' "$prs" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
jq -r --arg h "$branch" \
|
||||||
|
'[.[] | select(.base.ref == "master" and (.head.ref == $h or ((.head.label // "") | endswith(":" + $h)))) | (.html_url // .url)] | .[0] // empty' \
|
||||||
|
<<<"$prs"
|
||||||
|
}
|
||||||
|
existing=$(find_pr) || {
|
||||||
|
echo "error: could not look up existing PR for ${branch} → master" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if [[ -n "$existing" ]]; then
|
||||||
|
echo "Reusing existing PR: ${existing}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
payload=$(jq -n \
|
||||||
|
--arg title "$title" \
|
||||||
|
--arg body "$body" \
|
||||||
|
--arg head "$branch" \
|
||||||
|
--arg base "master" \
|
||||||
|
'{title:$title, body:$body, head:$head, base:$base}')
|
||||||
|
tmp=$(mktemp)
|
||||||
|
trap 'rm -f "$tmp"' EXIT
|
||||||
|
set +e
|
||||||
|
code=$(curl -sS -o "$tmp" -w '%{http_code}' -X POST \
|
||||||
|
-H "Authorization: token ${GITEA_TOKEN}" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d "$payload" \
|
||||||
|
"${api}/repos/${repo}/pulls")
|
||||||
|
curl_ec=$?
|
||||||
|
set -e
|
||||||
|
if [[ $curl_ec -ne 0 ]]; then
|
||||||
|
echo "error: curl failed creating PR ${branch} → master (exit ${curl_ec})" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if [[ "$code" == "201" ]]; then
|
||||||
|
pr_url=$(jq -r '.html_url // .url // empty' "$tmp")
|
||||||
|
echo "Opened PR: ${pr_url:-created (${branch} → master)}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
if [[ "$code" == "409" || "$code" == "422" ]]; then
|
||||||
|
existing=$(find_pr) || {
|
||||||
|
echo "error: PR create returned HTTP ${code} but looking up existing PR failed" >&2
|
||||||
|
cat "$tmp" >&2 || true
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
if [[ -n "$existing" ]]; then
|
||||||
|
echo "Reusing existing PR: ${existing}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "error: could not open or reuse PR ${branch} → master (HTTP ${code})" >&2
|
||||||
|
cat "$tmp" >&2 || true
|
||||||
|
exit 1
|
||||||
|
|||||||
@@ -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 ≤ ~70–75 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.
|
||||||
|
|
||||||
@@ -8,8 +8,8 @@
|
|||||||
# 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.35.0
|
pkgver=0.44.0
|
||||||
_commit=1c5a6ceb364c4dd53f0069f72cc4239220ed471e
|
_commit=12dcfa973ef51585fd1b35df6839fc9d1d7fd6aa
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Grok Bot desktop agent (official .deb repackaged)"
|
pkgdesc="Grok Bot desktop agent (official .deb repackaged)"
|
||||||
arch=('x86_64')
|
arch=('x86_64')
|
||||||
@@ -32,6 +32,7 @@ depends=(
|
|||||||
optdepends=(
|
optdepends=(
|
||||||
'libappindicator-gtk3: tray icon support'
|
'libappindicator-gtk3: tray icon support'
|
||||||
'curl: auto-update check on launch'
|
'curl: auto-update check on launch'
|
||||||
|
'polkit: graphical password prompt for desktop auto-update (pkexec)'
|
||||||
)
|
)
|
||||||
provides=('grok-bot' 'sand')
|
provides=('grok-bot' 'sand')
|
||||||
conflicts=('grok-bot' 'sand')
|
conflicts=('grok-bot' 'sand')
|
||||||
@@ -40,11 +41,15 @@ options=('!strip' '!debug')
|
|||||||
source=(
|
source=(
|
||||||
"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"
|
||||||
"grok-bot-launch.sh"
|
"grok-bot-launch.sh"
|
||||||
|
"pkexec-pacman-u"
|
||||||
|
"com.s1d3sw1ped.grok-bot-bin.policy"
|
||||||
)
|
)
|
||||||
noextract=("grok-bot_${pkgver}_amd64.deb")
|
noextract=("grok-bot_${pkgver}_amd64.deb")
|
||||||
sha256sums=(
|
sha256sums=(
|
||||||
'ed254e819d0f0419a1df9771009363074f65f80d8175d2ee0fc62900087ebd99'
|
'dded18b2d3d44b1c32d6b9f63446d2b27bca68b3de7a2aa028ce7956e9694164'
|
||||||
'886c8b55eb44d2f7812be50dcc1571907dc2d7e755171e67e916f497634f09eb'
|
'36e1c522f7a3920a850a6235263d82ad5990611612979447c1e9eff92548ac1e'
|
||||||
|
'e92ea4534d864d7f302a082a8717a52af9675195af41092d18f15094f74fed45'
|
||||||
|
'a9533dfe4d31332ac1505d2e582eff27771dd0107108a5f6289d0d3839431a74'
|
||||||
)
|
)
|
||||||
|
|
||||||
package() {
|
package() {
|
||||||
@@ -56,6 +61,19 @@ 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"
|
||||||
|
|
||||||
|
# pkexec helper + polkit action (auth_admin, not NOPASSWD) for desktop auto-update.
|
||||||
|
install -Dm755 "$srcdir/pkexec-pacman-u" "$pkgdir/usr/lib/grok-bot-bin/pkexec-pacman-u"
|
||||||
|
install -Dm644 "$srcdir/com.s1d3sw1ped.grok-bot-bin.policy" \
|
||||||
|
"$pkgdir/usr/share/polkit-1/actions/com.s1d3sw1ped.grok-bot-bin.policy"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|||||||
@@ -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.39.0** (`pkgver` / `pkgrel=2` 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 the bump is tagged (see Updating). After `v0.39.0` is tagged, CI (`build.yml`) attaches `grok-bot-bin-0.39.0-1-x86_64.pkg.tar.zst`. Until a new tag's asset exists, use `makepkg -si` for git-tip `pkgver`.
|
||||||
|
|
||||||
```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.39.0/grok-bot-bin-0.39.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.39.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,55 @@ 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.39.0** (pkgrel 2). 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` as eva.
|
||||||
|
3. Pushes branch `chore/bump-$pkgver` (force-with-lease if that version is re-run). It does **not** push `master` or create a tag.
|
||||||
|
4. Opens a PR into `master` via the Gitea API (or reuses an open PR from that head). Title: `pkgbuild: Bump grok-bot-bin to $pkgver`.
|
||||||
|
|
||||||
|
`master` and tags stay protected; the bump job must not push those refs. A no-op is only “already at this `pkgver`” (exit 0). Branch push or PR create/reuse failures fail the job.
|
||||||
|
|
||||||
|
After that PR merges, `.gitea/workflows/tag-release.yml` (push to `master`, or `workflow_dispatch`) reads `pkgver` from `PKGBUILD`. If tag `v$pkgver` is missing, it creates and pushes it for the master commit; if the tag already exists, it is a no-op. Pushing only that tag does not re-run the PKGBUILD bump.
|
||||||
|
|
||||||
|
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. An upstream bump resets `pkgrel` to 1, so 0.39.0 → tag `v0.39.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.
|
||||||
|
|
||||||
|
Scheduled jobs run on the default branch (`master`). Bump PRs target `master` so merge can tag. Product PRs still land on `develop` (see CONTRIBUTING).
|
||||||
|
|
||||||
|
### Manual force path
|
||||||
|
|
||||||
|
When you do not want to wait for cron:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# requires curl, python3, sha256sum; jq optional
|
||||||
|
./scripts/update.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
If the feed is newer, that rewrites `PKGBUILD` and `.SRCINFO`. Commit and open a PR into `master` (same as the scheduled job); after merge, `tag-release.yml` creates `v<pkgver>`. Or tag yourself after merge:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add PKGBUILD .SRCINFO
|
||||||
|
git commit -m "pkgbuild: Bump grok-bot-bin to <pkgver>"
|
||||||
|
git push origin "HEAD:chore/bump-<pkgver>" # then open a PR into master
|
||||||
|
# After merge, tag-release.yml creates v<pkgver>. To tag yourself:
|
||||||
|
git tag "v<pkgver>" # e.g. v0.39.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.
|
- Auto-update privilege order: `sudo -n` (passwordless, e.g. lab NOPASSWD) → `pkexec` / polkit when launched from the desktop (no TTY, `DISPLAY` or `WAYLAND_DISPLAY` set) → interactive `sudo` when stdin is a TTY. Cancel or deny still launches the installed binary. Passwordless sudo is **not** the default.
|
||||||
|
- Desktop / CachyOS: `polkit` (provides `pkexec`) and a session polkit authentication agent (usually already running with KDE / GNOME / Hyprland / etc.) are required for the graphical password prompt. The package installs `/usr/lib/grok-bot-bin/pkexec-pacman-u` and `com.s1d3sw1ped.grok-bot-bin.update` (`auth_admin`, not NOPASSWD). `polkit` is an optdepend.
|
||||||
|
- 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.
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE policyconfig PUBLIC
|
||||||
|
"-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN"
|
||||||
|
"http://www.freedesktop.org/standards/PolicyKit/1/policyconfig.dtd">
|
||||||
|
<policyconfig>
|
||||||
|
<vendor>s1d3sw1ped</vendor>
|
||||||
|
<vendor_url>https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin</vendor_url>
|
||||||
|
<action id="com.s1d3sw1ped.grok-bot-bin.update">
|
||||||
|
<description>Install a grok-bot-bin package update</description>
|
||||||
|
<message>Authentication is required to update Grok Bot</message>
|
||||||
|
<defaults>
|
||||||
|
<allow_any>no</allow_any>
|
||||||
|
<allow_inactive>no</allow_inactive>
|
||||||
|
<allow_active>auth_admin</allow_active>
|
||||||
|
</defaults>
|
||||||
|
<annotate key="org.freedesktop.policykit.exec.path">/usr/lib/grok-bot-bin/pkexec-pacman-u</annotate>
|
||||||
|
</action>
|
||||||
|
</policyconfig>
|
||||||
+38
-7
@@ -5,6 +5,43 @@ set -u
|
|||||||
|
|
||||||
REAL_DIR="/opt/Grok Bot"
|
REAL_DIR="/opt/Grok Bot"
|
||||||
API_URL='https://git.s1d3sw1ped.com/api/v1/repos/s1d3sw1ped/grok-bot-bin/releases?limit=1'
|
API_URL='https://git.s1d3sw1ped.com/api/v1/repos/s1d3sw1ped/grok-bot-bin/releases?limit=1'
|
||||||
|
PKEXEC_HELPER=/usr/lib/grok-bot-bin/pkexec-pacman-u
|
||||||
|
|
||||||
|
# Privilege order for pacman -U:
|
||||||
|
# 1. sudo -n (NOPASSWD, e.g. lab CT113)
|
||||||
|
# 2. pkexec (graphical polkit; desktop Exec=grok-bot has no TTY)
|
||||||
|
# 3. interactive sudo (terminal TTY)
|
||||||
|
# Never default to passwordless sudo. Cancel/deny still launches the installed binary.
|
||||||
|
_install_update_pkg() {
|
||||||
|
local pkg=$1
|
||||||
|
|
||||||
|
if sudo -n true 2>/dev/null; then
|
||||||
|
if sudo -n pacman -U --noconfirm "$pkg"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "grok-bot: pacman -U failed; launching installed version" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -t 0 ]] && command -v pkexec >/dev/null 2>&1 && [[ -x "$PKEXEC_HELPER" ]] \
|
||||||
|
&& [[ -n "${DISPLAY:-}${WAYLAND_DISPLAY:-}" ]]; then
|
||||||
|
if pkexec --disable-internal-agent "$PKEXEC_HELPER" "$pkg"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
echo "grok-bot: polkit auth failed or cancelled; launching installed version" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -t 0 ]]; then
|
||||||
|
if sudo pacman -U --noconfirm "$pkg"; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "grok-bot: need sudo or polkit 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
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
_maybe_update() {
|
_maybe_update() {
|
||||||
[[ "${GROK_BOT_NO_UPDATE:-}" == "1" ]] && return 0
|
[[ "${GROK_BOT_NO_UPDATE:-}" == "1" ]] && return 0
|
||||||
@@ -50,13 +87,7 @@ _maybe_update() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Prefer passwordless sudo; fall back to interactive sudo. Fail soft either way.
|
_install_update_pkg "$pkg" || return 0
|
||||||
if ! sudo -n pacman -U --noconfirm "$pkg" 2>/dev/null; then
|
|
||||||
if ! sudo pacman -U --noconfirm "$pkg"; then
|
|
||||||
echo "grok-bot: pacman -U failed; launching installed version" >&2
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_maybe_update || true
|
_maybe_update || true
|
||||||
|
|||||||
Executable
+39
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Root helper for grok-bot-bin GUI auto-update. Invoked via pkexec only.
|
||||||
|
# Runs pacman -U on a local grok-bot-bin package — not a generic pacman wrapper.
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $# -ne 1 ]]; then
|
||||||
|
echo "pkexec-pacman-u: usage: pkexec-pacman-u /path/to/grok-bot-bin-*-x86_64.pkg.tar.zst" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
pkg=$1
|
||||||
|
if [[ "$pkg" != /* || "$pkg" == *..* ]]; then
|
||||||
|
echo "pkexec-pacman-u: refusing path: $pkg" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
base=$(basename -- "$pkg")
|
||||||
|
if [[ ! "$base" =~ ^grok-bot-bin-.+-x86_64\.pkg\.tar\.zst$ ]]; then
|
||||||
|
echo "pkexec-pacman-u: refusing package name: $base" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "$pkg" || ! -r "$pkg" ]]; then
|
||||||
|
echo "pkexec-pacman-u: package not found or unreadable: $pkg" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Filename is not enough; require the package metadata name.
|
||||||
|
info=$(/usr/bin/pacman -Qp -- "$pkg" 2>/dev/null) || {
|
||||||
|
echo "pkexec-pacman-u: not a pacman package: $pkg" >&2
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
name=${info%% *}
|
||||||
|
if [[ "$name" != grok-bot-bin ]]; then
|
||||||
|
echo "pkexec-pacman-u: refusing package $name" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec /usr/bin/pacman -U --noconfirm -- "$pkg"
|
||||||
+143
-23
@@ -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,9 +79,34 @@ 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"
|
||||||
|
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)
|
deb_sha=$(sha256sum "$tmp" | cut -d' ' -f1)
|
||||||
shim_sha=$(sha256sum grok-bot-launch.sh | cut -d' ' -f1)
|
shim_sha=$(sha256sum grok-bot-launch.sh | cut -d' ' -f1)
|
||||||
|
pkexec_sha=$(sha256sum pkexec-pacman-u | cut -d' ' -f1)
|
||||||
|
policy_sha=$(sha256sum com.s1d3sw1ped.grok-bot-bin.policy | cut -d' ' -f1)
|
||||||
|
for label in deb_sha:$deb_sha shim_sha:$shim_sha pkexec_sha:$pkexec_sha policy_sha:$policy_sha; do
|
||||||
|
name=${label%%:*}
|
||||||
|
val=${label#*:}
|
||||||
|
if [[ ! "$val" =~ ^[0-9a-f]{64}$ ]]; then
|
||||||
|
echo "error: sha256sum failed ($name=$val)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
# Reset pkgrel on upstream version bumps.
|
# Reset pkgrel on upstream version bumps.
|
||||||
sed -i \
|
sed -i \
|
||||||
@@ -33,41 +115,79 @@ sed -i \
|
|||||||
-e "s/^pkgrel=.*/pkgrel=1/" \
|
-e "s/^pkgrel=.*/pkgrel=1/" \
|
||||||
PKGBUILD
|
PKGBUILD
|
||||||
|
|
||||||
python3 - "$deb_sha" "$shim_sha" <<'PY'
|
newver=$(sed -n 's/^pkgver=//p' PKGBUILD | head -1)
|
||||||
|
newcommit=$(sed -n 's/^_commit=//p' PKGBUILD | head -1)
|
||||||
|
newrel=$(sed -n 's/^pkgrel=//p' PKGBUILD | head -1)
|
||||||
|
if [[ "$newver" != "$version" || "$newcommit" != "$commit" || "$newrel" != "1" ]]; then
|
||||||
|
echo "error: PKGBUILD rewrite did not stick (pkgver=$newver _commit=$newcommit pkgrel=$newrel)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
python3 - "$deb_sha" "$shim_sha" "$pkexec_sha" "$policy_sha" <<'PY2'
|
||||||
import pathlib, re, sys
|
import pathlib, re, sys
|
||||||
deb_sha, shim_sha = sys.argv[1], sys.argv[2]
|
deb_sha, shim_sha, pkexec_sha, policy_sha = sys.argv[1:5]
|
||||||
p = pathlib.Path("PKGBUILD")
|
p = pathlib.Path("PKGBUILD")
|
||||||
text = p.read_text()
|
text = p.read_text()
|
||||||
block = f"sha256sums=(\n '{deb_sha}'\n '{shim_sha}'\n)"
|
block = (
|
||||||
|
"sha256sums=(\n"
|
||||||
|
f" '{deb_sha}'\n"
|
||||||
|
f" '{shim_sha}'\n"
|
||||||
|
f" '{pkexec_sha}'\n"
|
||||||
|
f" '{policy_sha}'\n"
|
||||||
|
")"
|
||||||
|
)
|
||||||
text2, n = re.subn(r"sha256sums=\([^\)]*\)", block, text, count=1, flags=re.S)
|
text2, n = re.subn(r"sha256sums=\([^\)]*\)", block, text, count=1, flags=re.S)
|
||||||
if n != 1:
|
if n != 1:
|
||||||
raise SystemExit(f"sha256sums replace failed (n={n})")
|
raise SystemExit(f"sha256sums replace failed (n={n})")
|
||||||
p.write_text(text2)
|
p.write_text(text2)
|
||||||
PY
|
PY2
|
||||||
|
|
||||||
python3 - "$version" "$commit" "$deb_sha" "$shim_sha" <<'PY'
|
python3 - "$version" "$commit" "$deb_sha" "$shim_sha" "$pkexec_sha" "$policy_sha" <<'PY2'
|
||||||
import pathlib, re, sys
|
import pathlib, sys
|
||||||
version, commit, deb_sha, shim_sha = sys.argv[1:5]
|
version, commit, deb_sha, shim_sha, pkexec_sha, policy_sha = sys.argv[1:7]
|
||||||
p = pathlib.Path(".SRCINFO")
|
p = pathlib.Path(".SRCINFO")
|
||||||
|
if not p.is_file():
|
||||||
|
raise SystemExit(".SRCINFO missing")
|
||||||
|
shas = [deb_sha, shim_sha, pkexec_sha, policy_sha]
|
||||||
lines = []
|
lines = []
|
||||||
saw_sha = False
|
saw_sha = False
|
||||||
|
saw_pkgver = saw_pkgrel = saw_source = saw_noextract = False
|
||||||
for line in p.read_text().splitlines(True):
|
for line in p.read_text().splitlines(True):
|
||||||
if line.startswith("\tpkgver ="):
|
if line.startswith("\tpkgver ="):
|
||||||
lines.append(f"\tpkgver = {version}\n"); continue
|
lines.append(f"\tpkgver = {version}\n"); saw_pkgver = True; continue
|
||||||
if line.startswith("\tpkgrel ="):
|
if line.startswith("\tpkgrel ="):
|
||||||
lines.append("\tpkgrel = 1\n"); continue
|
lines.append("\tpkgrel = 1\n"); saw_pkgrel = True; continue
|
||||||
if line.startswith("\tsource = https://downloads.cursor.com/grokbot/stable/"):
|
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"); continue
|
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_"):
|
if line.startswith("\tnoextract = grok-bot_"):
|
||||||
lines.append(f"\tnoextract = grok-bot_{version}_amd64.deb\n"); continue
|
lines.append(f"\tnoextract = grok-bot_{version}_amd64.deb\n")
|
||||||
|
saw_noextract = True
|
||||||
|
continue
|
||||||
if line.startswith("\tsha256sums ="):
|
if line.startswith("\tsha256sums ="):
|
||||||
if not saw_sha:
|
if not saw_sha:
|
||||||
lines.append(f"\tsha256sums = {deb_sha}\n")
|
for s in shas:
|
||||||
lines.append(f"\tsha256sums = {shim_sha}\n")
|
lines.append(f"\tsha256sums = {s}\n")
|
||||||
saw_sha = True
|
saw_sha = True
|
||||||
continue
|
continue
|
||||||
lines.append(line)
|
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)}")
|
||||||
|
# Ensure four sha lines present
|
||||||
|
sha_lines = [l for l in lines if l.startswith("\tsha256sums =")]
|
||||||
|
if len(sha_lines) != 4:
|
||||||
|
raise SystemExit(f".SRCINFO expected 4 sha256sums lines, got {len(sha_lines)}")
|
||||||
p.write_text("".join(lines))
|
p.write_text("".join(lines))
|
||||||
PY
|
PY2
|
||||||
|
|
||||||
echo "Updated PKGBUILD and .SRCINFO to ${version} deb_sha=${deb_sha} shim_sha=${shim_sha}"
|
echo "Updated PKGBUILD and .SRCINFO to ${version} deb_sha=${deb_sha} shim_sha=${shim_sha} pkexec_sha=${pkexec_sha} policy_sha=${policy_sha}"
|
||||||
|
|||||||
Reference in New Issue
Block a user