diff --git a/.gitea/workflows/tag-release.yml b/.gitea/workflows/tag-release.yml new file mode 100644 index 0000000..80d0c1d --- /dev/null +++ b/.gitea/workflows/tag-release.yml @@ -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 diff --git a/.gitea/workflows/update.yml b/.gitea/workflows/update.yml index 3efd39f..4c49cb3 100644 --- a/.gitea/workflows/update.yml +++ b/.gitea/workflows/update.yml @@ -10,6 +10,8 @@ jobs: steps: - uses: actions/checkout@v4 - name: Bump PKGBUILD if a new version is out + env: + GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }} run: | set -euo pipefail sudo apt-get update -qq @@ -17,9 +19,9 @@ jobs: 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 | head -1) ./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 @@ -28,15 +30,95 @@ jobs: echo "No bump (still $after)" exit 0 fi + if [[ -z "${GITEA_TOKEN:-}" ]]; then + 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 commit -m "pkgbuild: Bump grok-bot-bin to ${after}" - git tag "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 + # Do not tag here and do not push protected master. Open a bump PR; + # 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 diff --git a/README.md b/README.md index dec5bc2..474516b 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Not affiliated with Cursor / SpaceXAI. The app binary is unchanged; this only re ## 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. +This tree packages **0.39.0** (`pkgver` / `pkgrel=1` in `PKGBUILD`). `makepkg -si` from git tip builds that version even before a release tag exists. ```bash git clone https://git.s1d3sw1ped.com/s1d3sw1ped/grok-bot-bin.git @@ -30,11 +30,11 @@ makepkg -si ## Install from a release package -`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`. +`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 -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.36.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.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. @@ -53,42 +53,44 @@ Exact `Server=` URL may change once the first repo DB lands; `makepkg -si` works ## Updating -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`. +Stay-current path when Cursor's linux-x64 Grok Bot feed moves. `PKGBUILD` is currently **0.39.0** (pkgrel 1). One updater: `./scripts/update.sh`. ### 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. +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`. -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. +`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. -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`. +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. -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`”. +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`. -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`. +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, or you are landing a bump on `develop`: +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`. Then commit, tag, and push (or open a PR into `develop`): +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`. Or tag yourself after merge: ```bash git add PKGBUILD .SRCINFO git commit -m "pkgbuild: Bump grok-bot-bin to " -git push origin HEAD:develop # or open a PR into develop -# After it should cut a release: -git tag "v" # e.g. v0.36.0 +git push origin "HEAD:chore/bump-" # then open a PR into master +# After merge, tag-release.yml creates v. To tag yourself: +git tag "v" # e.g. v0.39.0 git push origin "v" makepkg -si # install from this tree without waiting for the release asset ```