diff --git a/.github/workflows/aur-publish.yml b/.github/workflows/aur-publish.yml new file mode 100644 index 00000000..9bc222b9 --- /dev/null +++ b/.github/workflows/aur-publish.yml @@ -0,0 +1,102 @@ +name: aur-publish + +# Publish the `mcpp-bin` and `mcpp` AUR packages after a release. +# +# Triggers on COMPLETION of the `release` workflow (not on `release: +# published`): release.yml creates the GitHub Release in its first job but +# uploads the aarch64 / macOS / Windows assets in LATER jobs, so the aarch64 +# .sha256 that mcpp-bin needs only exists once the whole workflow finishes. +# +# Requires one repository secret: +# AUR_SSH_PRIVATE_KEY — private key whose public half is registered on the +# AUR account that owns mcpp / mcpp-bin. +# See scripts/aur/README.md → "Automated publishing" for the full setup. +on: + workflow_run: + workflows: [release] + types: [completed] + workflow_dispatch: + inputs: + version: + description: "Version to publish (default: [package].version in mcpp.toml)" + required: false + +concurrency: + group: aur-publish + cancel-in-progress: false + +jobs: + publish: + runs-on: ubuntu-latest + # On the workflow_run trigger, only proceed if the release actually + # succeeded (skip failed/cancelled release runs). + if: >- + github.event_name == 'workflow_dispatch' || + github.event.workflow_run.conclusion == 'success' + steps: + - name: Checkout released commit + uses: actions/checkout@v4 + with: + # workflow_run: the exact commit the release was built from. + # workflow_dispatch: default ref (HEAD of the branch). + ref: ${{ github.event.workflow_run.head_sha || github.ref }} + + - name: Refresh both PKGBUILDs to the release version + id: refresh + env: + # CI runs as root; force update.sh's template .SRCINFO path. + MCPP_AUR_NO_MAKEPKG: "1" + run: | + VER="${{ github.event.inputs.version }}" + if [ -z "$VER" ]; then + # mcpp.toml at the released commit carries the right version. + VER=$(grep -m1 -E '^\s*version\s*=' mcpp.toml | sed -E 's/.*"([^"]+)".*/\1/') + fi + echo "version=$VER" >> "$GITHUB_OUTPUT" + ./scripts/aur/update.sh "$VER" + + - name: Configure AUR SSH + run: | + install -dm700 ~/.ssh + printf '%s\n' "${{ secrets.AUR_SSH_PRIVATE_KEY }}" > ~/.ssh/aur + chmod 600 ~/.ssh/aur + ssh-keyscan -t rsa,ed25519 aur.archlinux.org >> ~/.ssh/known_hosts 2>/dev/null + cat > ~/.ssh/config <<'EOF' + Host aur.archlinux.org + User aur + IdentityFile ~/.ssh/aur + IdentitiesOnly yes + EOF + + - name: Push to the AUR + env: + VER: ${{ steps.refresh.outputs.version }} + run: | + set -eu + git config --global user.name "mcpp-ci" + git config --global user.email "x.d2learn.org@gmail.com" + + publish() { # $1 = package name (= dir under scripts/aur/) + pkg="$1"; src="scripts/aur/${pkg}"; work="/tmp/aur-${pkg}" + # Clone the existing AUR repo; if the package doesn't exist yet + # (first publish), start an empty repo — AUR creates it on push. + if git clone "ssh://aur@aur.archlinux.org/${pkg}.git" "$work" 2>/dev/null \ + && [ -e "$work/.git" ]; then :; else + rm -rf "$work"; mkdir -p "$work" + git -C "$work" init -q + git -C "$work" remote add origin "ssh://aur@aur.archlinux.org/${pkg}.git" + fi + # AUR repos contain only PKGBUILD, .SRCINFO and local sources. + cp "$src/PKGBUILD" "$src/.SRCINFO" "$src/mcpp.sh" "$work/" + git -C "$work" add -A + if git -C "$work" diff --cached --quiet; then + echo ":: ${pkg}: no changes, skipping" + return 0 + fi + git -C "$work" commit -q -m "${pkg} ${VER}" + git -C "$work" push origin HEAD:master + echo ":: ${pkg}: published ${VER}" + } + + publish mcpp-bin + publish mcpp diff --git a/scripts/aur/README.md b/scripts/aur/README.md new file mode 100644 index 00000000..48517774 --- /dev/null +++ b/scripts/aur/README.md @@ -0,0 +1,139 @@ +# AUR packaging + +Arch Linux packaging for mcpp. Two packages, same runtime layout: + +| Package | What it installs | Pick it when | +| --- | --- | --- | +| [`mcpp-bin`](mcpp-bin/) | the **prebuilt** release binary (what [`install.sh`](../../install.sh) downloads) | you just want mcpp, fast | +| [`mcpp`](mcpp/) | mcpp **built from source**, bootstrapped with `mcpp-bin` | you want a from-source build | + +```sh +yay -S mcpp-bin # prebuilt +yay -S mcpp # from source (pulls mcpp-bin as a build dep) +``` + +Both `provides`/`conflicts` each other, so only one can be installed at a time. +Supported architectures: `x86_64`, `aarch64`. + +## Layout & why the wrapper exists + +mcpp ships as a single self-contained tree. At runtime it **writes** into +`MCPP_HOME` — the registry sandbox, BMI/metadata caches, logs, and every +toolchain it downloads. That has to be per-user and writable, so it cannot live +under a root-owned system prefix. + +mcpp resolves `MCPP_HOME` from the running binary's *real* path +(`/proc/self/exe`, which resolves symlinks). A plain `/usr/bin/mcpp` symlink +would therefore make `MCPP_HOME` resolve into the read-only install dir and +every command would fail to write. So both packages split the tree: + +| Path | Contents | Mode | +| --- | --- | --- | +| `/opt/mcpp/bin/mcpp` | the mcpp binary | shared, read-only | +| `/opt/mcpp/registry/bin/xlings` | bundled xlings | shared, read-only | +| `/usr/bin/mcpp` | [`mcpp.sh`](mcpp-bin/mcpp.sh) launcher | on PATH | +| `~/.mcpp/` | registry sandbox, caches, toolchains | per-user, writable | + +`mcpp.sh` exports `MCPP_HOME=${MCPP_HOME:-$HOME/.mcpp}` and +`MCPP_VENDORED_XLINGS=${MCPP_VENDORED_XLINGS:-/opt/mcpp/registry/bin/xlings}`, +then execs the real binary. mcpp copies the vendored xlings into +`~/.mcpp/registry/bin/xlings` on first run. Both env vars defer to a value the +user already exported, so a custom home or xlings still works. + +First `mcpp build`/`mcpp run` bootstraps the sandbox (downloads ninja, patchelf +and the default toolchain into `~/.mcpp`) — expected, and only once per user. + +### How the `mcpp` source package builds + +mcpp is self-hosting. The `mcpp` PKGBUILD uses the installed `mcpp-bin` as the +bootstrap compiler and runs `mcpp build --target -linux-musl` — the same +path [`release.yml`](../../.github/workflows/release.yml) ships. mcpp downloads +its own pinned toolchain (it does **not** use the host gcc), so the build needs +network access, like the upstream release build. + +## Files + +``` +scripts/aur/ + README.md this file + update.sh bump BOTH packages to a release version + mcpp-bin/{PKGBUILD, .SRCINFO, mcpp.sh} + mcpp/{PKGBUILD, .SRCINFO, mcpp.sh} +``` + +`mcpp.sh` is identical in both dirs (each AUR repo must be self-contained); +`update.sh` keeps them in sync. + +## Releasing a new version + +After a GitHub release is published (and mirrored), bump both packages: + +```sh +scripts/aur/update.sh # uses [package].version from mcpp.toml +# or pin: scripts/aur/update.sh 0.0.66 +``` + +`update.sh` pulls the per-arch `.sha256` sidecars (for `mcpp-bin`) and hashes +the source archive (for `mcpp`), rewrites `pkgver` + checksums, resets +`pkgrel=1`, and regenerates both `.SRCINFO` files. + +### Test locally (on Arch) + +```sh +cd scripts/aur/mcpp-bin && makepkg -si # prebuilt +cd scripts/aur/mcpp && makepkg -si # from source (slow: builds mcpp) +mcpp --version +``` + +## Automated publishing (CI) + +[`.github/workflows/aur-publish.yml`](../../.github/workflows/aur-publish.yml) +publishes both packages automatically. It runs when the `release` workflow +**completes successfully** (not on `release: published` — the aarch64 asset the +`mcpp-bin` checksum needs is uploaded by a later release job), refreshes the +PKGBUILDs via `update.sh`, and pushes each package to its AUR git repo over SSH. + +> The AUR has no "watch upstream" feature — packages only update when their git +> repo is pushed. This workflow is that push. + +### One-time setup you need to do + +1. **AUR account** — sign in at with the account + that will own `mcpp` / `mcpp-bin`. + +2. **Generate a dedicated SSH key** (no passphrase, it's for CI): + + ```sh + ssh-keygen -t ed25519 -C "mcpp-aur-ci" -f aur_ci -N "" + ``` + +3. **Register the public key** on the AUR: *My Account → Edit → SSH Public Key* + → paste the contents of `aur_ci.pub` → Update. + +4. **Add the private key as a GitHub secret** (repo *Settings → Secrets and + variables → Actions → New repository secret*): + + - Name: `AUR_SSH_PRIVATE_KEY` + - Value: the full contents of `aur_ci` (the private key) + + Then delete the local `aur_ci` / `aur_ci.pub` files. + +That's the only secret required — AUR auth is SSH-key based, there is **no API +token**. The default `GITHUB_TOKEN` is *not* used (we push to the AUR, not to +GitHub). + +### First publish + +The first time, the package names must be free. The workflow auto-creates each +AUR repo on first push (AUR does this for a valid, available name). If you +prefer to claim them by hand first, push an initial commit manually: + +```sh +git clone ssh://aur@aur.archlinux.org/mcpp-bin.git +cp scripts/aur/mcpp-bin/{PKGBUILD,.SRCINFO,mcpp.sh} mcpp-bin/ && cd mcpp-bin +git add -A && git commit -m "initial mcpp-bin" && git push # repeat for mcpp +``` + +After that, every release publishes both packages with no manual step. You can +also run it on demand from the Actions tab (*aur-publish → Run workflow*, +optional version input). diff --git a/scripts/aur/mcpp-bin/.SRCINFO b/scripts/aur/mcpp-bin/.SRCINFO new file mode 100644 index 00000000..0550c682 --- /dev/null +++ b/scripts/aur/mcpp-bin/.SRCINFO @@ -0,0 +1,20 @@ +pkgbase = mcpp-bin + pkgdesc = Modern C++ build & package management tool (prebuilt binary) + pkgver = 0.0.65 + pkgrel = 1 + url = https://github.com/mcpp-community/mcpp + arch = x86_64 + arch = aarch64 + license = Apache-2.0 + depends = git + provides = mcpp + conflicts = mcpp + options = !strip + source = mcpp-0.0.65.sh::mcpp.sh + sha256sums = SKIP + source_x86_64 = mcpp-0.0.65-linux-x86_64.tar.gz::https://github.com/mcpp-community/mcpp/releases/download/v0.0.65/mcpp-0.0.65-linux-x86_64.tar.gz + sha256sums_x86_64 = 0d1d16aae05e4d7c59a00a2621abc4b99421b9821d2145c139fabf95fcf93409 + source_aarch64 = mcpp-0.0.65-linux-aarch64.tar.gz::https://github.com/mcpp-community/mcpp/releases/download/v0.0.65/mcpp-0.0.65-linux-aarch64.tar.gz + sha256sums_aarch64 = 20dd7a8be657bf2e32dcffcf10b758e34fe740fcdb1ceb374822d5ee25cb4a52 + +pkgname = mcpp-bin diff --git a/scripts/aur/mcpp-bin/PKGBUILD b/scripts/aur/mcpp-bin/PKGBUILD new file mode 100644 index 00000000..954c8c72 --- /dev/null +++ b/scripts/aur/mcpp-bin/PKGBUILD @@ -0,0 +1,47 @@ +# Maintainer: mcpp-community +# +# mcpp-bin — prebuilt release binaries from GitHub, the same artifacts the +# upstream `install.sh` one-liner downloads. See scripts/aur/README.md for +# how this is published to the AUR and how to bump it (scripts/aur/update.sh). + +pkgname=mcpp-bin +pkgver=0.0.65 +pkgrel=1 +pkgdesc="Modern C++ build & package management tool (prebuilt binary)" +arch=('x86_64' 'aarch64') +url="https://github.com/mcpp-community/mcpp" +license=('Apache-2.0') +# mcpp/xlings are statically linked; git is used for package-index sync. +depends=('git') +provides=('mcpp') +conflicts=('mcpp') +# Prebuilt upstream binaries — do not strip/repackage them. +options=('!strip') + +_relbase="https://github.com/mcpp-community/mcpp/releases/download/v${pkgver}" + +source_x86_64=("mcpp-${pkgver}-linux-x86_64.tar.gz::${_relbase}/mcpp-${pkgver}-linux-x86_64.tar.gz") +source_aarch64=("mcpp-${pkgver}-linux-aarch64.tar.gz::${_relbase}/mcpp-${pkgver}-linux-aarch64.tar.gz") +# Shared, arch-independent files (versioned to invalidate makepkg's cache on bump). +source=("mcpp-${pkgver}.sh::mcpp.sh") + +sha256sums=('SKIP') +sha256sums_x86_64=('0d1d16aae05e4d7c59a00a2621abc4b99421b9821d2145c139fabf95fcf93409') +sha256sums_aarch64=('20dd7a8be657bf2e32dcffcf10b758e34fe740fcdb1ceb374822d5ee25cb4a52') + +package() { + local _src="${srcdir}/mcpp-${pkgver}-linux-${CARCH}" + + # Self-contained tree, read-only and shared by all users, under /opt. + # Ship only the two binaries the runtime needs: + # bin/mcpp — the static mcpp executable + # registry/bin/xlings — bundled xlings, seeded per-user via the wrapper + install -Dm755 "${_src}/bin/mcpp" "${pkgdir}/opt/mcpp/bin/mcpp" + install -Dm755 "${_src}/registry/bin/xlings" "${pkgdir}/opt/mcpp/registry/bin/xlings" + + # Per-user launcher on PATH (sets MCPP_HOME / MCPP_VENDORED_XLINGS). + install -Dm755 "${srcdir}/mcpp-${pkgver}.sh" "${pkgdir}/usr/bin/mcpp" + + install -Dm644 "${_src}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" + install -Dm644 "${_src}/README.md" "${pkgdir}/usr/share/doc/${pkgname}/README.md" +} diff --git a/scripts/aur/mcpp-bin/mcpp.sh b/scripts/aur/mcpp-bin/mcpp.sh new file mode 100755 index 00000000..87cbde91 --- /dev/null +++ b/scripts/aur/mcpp-bin/mcpp.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# mcpp launcher (Arch / AUR mcpp-bin package). +# +# The AUR package installs mcpp's self-contained tree read-only under +# /opt/mcpp (shared by every user). But mcpp WRITES its registry sandbox, +# BMI/metadata caches, logs and downloaded toolchains into MCPP_HOME at +# runtime — that has to be a per-user, writable location, never /opt. +# +# mcpp resolves MCPP_HOME from the binary's real path (/proc/self/exe, which +# resolves symlinks), so a plain /usr/bin symlink would make MCPP_HOME land in +# the root-owned /opt tree and every command would fail to write. This wrapper +# fixes that by pinning the two env knobs the binary honors: +# +# MCPP_HOME — per-user home (default ~/.mcpp, same as install.sh) +# MCPP_VENDORED_XLINGS — the bundled xlings under /opt, which mcpp copies +# into $MCPP_HOME/registry/bin/xlings on first run +# +# Both respect a value the user already exported, so power users can still +# point mcpp at a custom home or xlings. +set -eu + +MCPP_OPT="/opt/mcpp" + +export MCPP_HOME="${MCPP_HOME:-$HOME/.mcpp}" +export MCPP_VENDORED_XLINGS="${MCPP_VENDORED_XLINGS:-$MCPP_OPT/registry/bin/xlings}" + +exec "$MCPP_OPT/bin/mcpp" "$@" diff --git a/scripts/aur/mcpp/.SRCINFO b/scripts/aur/mcpp/.SRCINFO new file mode 100644 index 00000000..3026abcb --- /dev/null +++ b/scripts/aur/mcpp/.SRCINFO @@ -0,0 +1,19 @@ +pkgbase = mcpp + pkgdesc = Modern C++ build & package management tool (built from source) + pkgver = 0.0.65 + pkgrel = 1 + url = https://github.com/mcpp-community/mcpp + arch = x86_64 + arch = aarch64 + license = Apache-2.0 + makedepends = mcpp-bin + makedepends = git + depends = git + conflicts = mcpp-bin + options = !strip + source = mcpp-0.0.65.tar.gz::https://github.com/mcpp-community/mcpp/archive/v0.0.65.tar.gz + source = mcpp.sh + sha256sums = 07f8233d3f18565c52607816a82c9facda3a7ed11c67d3772e42bd84cb54476a + sha256sums = SKIP + +pkgname = mcpp diff --git a/scripts/aur/mcpp/PKGBUILD b/scripts/aur/mcpp/PKGBUILD new file mode 100644 index 00000000..5e987e61 --- /dev/null +++ b/scripts/aur/mcpp/PKGBUILD @@ -0,0 +1,75 @@ +# Maintainer: mcpp-community +# +# mcpp — built from source, bootstrapped with the prebuilt `mcpp-bin`. +# mcpp is self-hosting: the mcpp-bin compiler builds this release's own +# source (the same `mcpp build --target -linux-musl` path release.yml +# ships). For the prebuilt-only package, install `mcpp-bin` instead. +# See scripts/aur/README.md. + +pkgname=mcpp +pkgver=0.0.65 +pkgrel=1 +pkgdesc="Modern C++ build & package management tool (built from source)" +arch=('x86_64' 'aarch64') +url="https://github.com/mcpp-community/mcpp" +license=('Apache-2.0') +# mcpp/xlings are statically linked; git is used for package-index sync. +depends=('git') +# mcpp-bin is the bootstrap compiler; it also supplies the bundled xlings we +# ship at runtime. git is needed for toolchain/index sync during the build. +makedepends=('mcpp-bin' 'git') +conflicts=('mcpp-bin') +# We strip the built ELF ourselves; don't let makepkg re-strip the vendored +# xlings binary (a prebuilt third-party artifact). +options=('!strip') + +source=("mcpp-${pkgver}.tar.gz::https://github.com/mcpp-community/mcpp/archive/v${pkgver}.tar.gz" + "mcpp.sh") +sha256sums=('07f8233d3f18565c52607816a82c9facda3a7ed11c67d3772e42bd84cb54476a' + 'SKIP') + +# mcpp downloads its own pinned toolchain (gcc/ninja/patchelf) into the build +# sandbox — it does not use the host gcc. This needs network access at build +# time, like the upstream release build. +build() { + cd "${srcdir}/mcpp-${pkgver}" + + case "$CARCH" in + x86_64) _target=x86_64-linux-musl ;; + aarch64) _target=aarch64-linux-musl ;; + *) echo "unsupported CARCH: $CARCH" >&2; return 1 ;; + esac + + # Bootstrap with mcpp-bin's real binary (not its /usr/bin wrapper, which + # would force MCPP_HOME into the user's home). Keep the build sandbox + # self-contained under $srcdir and reuse mcpp-bin's bundled xlings. + export MCPP_HOME="${srcdir}/.mcpp-home" + export MCPP_VENDORED_XLINGS="/opt/mcpp/registry/bin/xlings" + + /opt/mcpp/bin/mcpp build --target "$_target" + + _artifact=$(find "target/${_target}" -type f -name mcpp | head -1) + test -n "$_artifact" || { echo "build produced no mcpp binary" >&2; return 1; } + file "$_artifact" | grep -q 'statically linked' + # Debug info on a static ELF balloons it ~7×; strip with the native tool. + strip "$_artifact" + + # Stash artifact + the vendored xlings for package() (which has no /opt + # guarantees beyond makedepends being installed). + install -Dm755 "$_artifact" "${srcdir}/stage/bin/mcpp" + install -Dm755 /opt/mcpp/registry/bin/xlings "${srcdir}/stage/registry/bin/xlings" +} + +package() { + # Same /opt + wrapper layout as mcpp-bin (see scripts/aur/README.md for + # why the per-user wrapper exists instead of a /usr/bin symlink). + install -Dm755 "${srcdir}/stage/bin/mcpp" "${pkgdir}/opt/mcpp/bin/mcpp" + install -Dm755 "${srcdir}/stage/registry/bin/xlings" "${pkgdir}/opt/mcpp/registry/bin/xlings" + + install -Dm755 "${srcdir}/mcpp.sh" "${pkgdir}/usr/bin/mcpp" + + install -Dm644 "${srcdir}/mcpp-${pkgver}/LICENSE" \ + "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE" + install -Dm644 "${srcdir}/mcpp-${pkgver}/README.md" \ + "${pkgdir}/usr/share/doc/${pkgname}/README.md" +} diff --git a/scripts/aur/mcpp/mcpp.sh b/scripts/aur/mcpp/mcpp.sh new file mode 100755 index 00000000..87cbde91 --- /dev/null +++ b/scripts/aur/mcpp/mcpp.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# mcpp launcher (Arch / AUR mcpp-bin package). +# +# The AUR package installs mcpp's self-contained tree read-only under +# /opt/mcpp (shared by every user). But mcpp WRITES its registry sandbox, +# BMI/metadata caches, logs and downloaded toolchains into MCPP_HOME at +# runtime — that has to be a per-user, writable location, never /opt. +# +# mcpp resolves MCPP_HOME from the binary's real path (/proc/self/exe, which +# resolves symlinks), so a plain /usr/bin symlink would make MCPP_HOME land in +# the root-owned /opt tree and every command would fail to write. This wrapper +# fixes that by pinning the two env knobs the binary honors: +# +# MCPP_HOME — per-user home (default ~/.mcpp, same as install.sh) +# MCPP_VENDORED_XLINGS — the bundled xlings under /opt, which mcpp copies +# into $MCPP_HOME/registry/bin/xlings on first run +# +# Both respect a value the user already exported, so power users can still +# point mcpp at a custom home or xlings. +set -eu + +MCPP_OPT="/opt/mcpp" + +export MCPP_HOME="${MCPP_HOME:-$HOME/.mcpp}" +export MCPP_VENDORED_XLINGS="${MCPP_VENDORED_XLINGS:-$MCPP_OPT/registry/bin/xlings}" + +exec "$MCPP_OPT/bin/mcpp" "$@" diff --git a/scripts/aur/update.sh b/scripts/aur/update.sh new file mode 100755 index 00000000..67ef2a5e --- /dev/null +++ b/scripts/aur/update.sh @@ -0,0 +1,135 @@ +#!/usr/bin/env bash +# scripts/aur/update.sh — bump BOTH AUR packages to a release version. +# +# mcpp-bin/ prebuilt release binaries (per-arch tarball checksums) +# mcpp/ built from source via mcpp-bin (source-archive checksum) +# +# Pulls checksums straight from the GitHub release / archive, rewrites each +# PKGBUILD's pkgver + sums, resets pkgrel to 1, regenerates both .SRCINFO +# files, and keeps the shared mcpp.sh wrapper in sync across both dirs. +# Run after a release is published, then publish each package (see README.md). +# +# Usage: +# scripts/aur/update.sh [VERSION] # default: [package].version from mcpp.toml +set -euo pipefail + +cd "$(dirname "$0")" +REPO="mcpp-community/mcpp" +ARCHES=(linux-x86_64 linux-aarch64) + +# Resolve version: explicit arg, else mcpp.toml at repo root. +if [[ $# -ge 1 ]]; then + VER="$1" +else + VER=$(grep -m1 -E '^\s*version\s*=' ../../mcpp.toml | sed -E 's/.*"([^"]+)".*/\1/') +fi +[[ -n "$VER" ]] || { echo "error: could not determine version" >&2; exit 1; } +echo ":: targeting mcpp v${VER}" + +reldl="https://github.com/${REPO}/releases/download/v${VER}" +archive_url="https://github.com/${REPO}/archive/v${VER}.tar.gz" + +# --- prebuilt binary checksums (mcpp-bin) ---------------------------------- +declare -A SUMS +for plat in "${ARCHES[@]}"; do + url="${reldl}/mcpp-${VER}-${plat}.tar.gz.sha256" + echo ":: fetching ${url}" + line=$(curl -fsSL --connect-timeout 15 "$url") \ + || { echo "error: cannot fetch sha256 for ${plat} (is v${VER} released?)" >&2; exit 1; } + SUMS[$plat]=$(awk '{print $1}' <<<"$line") + [[ -n "${SUMS[$plat]}" ]] || { echo "error: empty sha256 for ${plat}" >&2; exit 1; } +done +x86=${SUMS[linux-x86_64]} +arm=${SUMS[linux-aarch64]} + +# --- source-archive checksum (mcpp) ---------------------------------------- +echo ":: hashing source archive ${archive_url}" +src=$(curl -fsSL --connect-timeout 30 "$archive_url" | sha256sum | awk '{print $1}') +[[ -n "$src" ]] || { echo "error: cannot hash source archive" >&2; exit 1; } + +# --- keep the wrapper in sync ---------------------------------------------- +cp -f mcpp-bin/mcpp.sh mcpp/mcpp.sh 2>/dev/null || true + +# --- rewrite mcpp-bin/PKGBUILD --------------------------------------------- +sed -i -E \ + -e "s/^pkgver=.*/pkgver=${VER}/" \ + -e "s/^pkgrel=.*/pkgrel=1/" \ + -e "s/^sha256sums_x86_64=\('[^']*'\)/sha256sums_x86_64=('${x86}')/" \ + -e "s/^sha256sums_aarch64=\('[^']*'\)/sha256sums_aarch64=('${arm}')/" \ + mcpp-bin/PKGBUILD + +# --- rewrite mcpp/PKGBUILD ------------------------------------------------- +sed -i -E \ + -e "s/^pkgver=.*/pkgver=${VER}/" \ + -e "s/^pkgrel=.*/pkgrel=1/" \ + -e "s/^sha256sums=\('[^']*'\)/sha256sums=('${src}')/" \ + mcpp/PKGBUILD + +# --- regenerate .SRCINFO files --------------------------------------------- +# Prefer makepkg's own generator on an Arch host; fall back to templates so +# this also works when bumping from a non-Arch machine (e.g. CI / dev box). +_srcinfo() { # $1 = package dir + # CI runs as root where makepkg refuses to run; MCPP_AUR_NO_MAKEPKG=1 + # forces the template path (byte-identical output, no makepkg needed). + if [[ -z "${MCPP_AUR_NO_MAKEPKG:-}" ]] && command -v makepkg >/dev/null 2>&1; then + ( cd "$1" && makepkg --printsrcinfo > .SRCINFO ) + return + fi + case "$1" in + mcpp-bin) + cat > mcpp-bin/.SRCINFO < mcpp/.SRCINFO <