Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 114 additions & 1 deletion .github/workflows/publish-aur.yml
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,11 +16,21 @@ on:
permissions:
contents: read

concurrency:
group: publish-aur
cancel-in-progress: false

env:
AUR_PACKAGE: create-awesome-python-app
AUR_RPC_URL: https://aur.archlinux.org/rpc/v5/info?arg=create-awesome-python-app
PYPI_PACKAGE: create-awesome-python-app

jobs:
aur:
name: Update AUR package
runs-on: ubuntu-latest
environment: pypi
timeout-minutes: 20
steps:
- name: Resolve version
id: version
Expand All@@ -33,6 +43,10 @@ jobs:
else
VERSION="${TAG_REF#create-awesome-python-app@}"
fi
if ! echo "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+([a-zA-Z0-9.-]+)?$'; then
echo "::error::Invalid AUR package version: $VERSION"
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: Checkout aur-package mirror repo
Expand All@@ -48,11 +62,27 @@ jobs:
NEW_VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
retry() {
local attempts="$1"
local delay="$2"
shift 2
for attempt in $(seq 1 "$attempts"); do
if "$@"; then
return 0
fi
if [ "$attempt" = "$attempts" ]; then
return 1
fi
echo "::warning::Attempt $attempt/$attempts failed: $*; retrying in ${delay}s" >&2
sleep "$delay"
done
}

# Reset pkgver and pkgrel; source URL already interpolates ${pkgver}.
sed -i "s/^pkgver=.*/pkgver=${NEW_VERSION}/" PKGBUILD
sed -i "s/^pkgrel=.*/pkgrel=1/" PKGBUILD

META=$(curl -sfL "https://pypi.org/pypi/create-awesome-python-app/${NEW_VERSION}/json")
META=$(retry 5 10 curl -sfL "https://pypi.org/pypi/${PYPI_PACKAGE}/${NEW_VERSION}/json")
SHA=$(echo "$META" | jq -r '.urls[] | select(.packagetype=="sdist") | .digests.sha256')
if [ -z "$SHA" ] || [ "$SHA" = "null" ]; then
echo "::error::Failed to resolve PyPI sdist sha256 for v${NEW_VERSION}" >&2
Expand All@@ -63,6 +93,45 @@ jobs:
echo "----- Updated PKGBUILD -----"
cat PKGBUILD

- name: Preflight AUR availability
env:
AUR_SSH_PRIVATE_KEY: ${{ secrets.AUR_SSH_PRIVATE_KEY }}
run: |
set -euo pipefail
retry() {
local attempts="$1"
local delay="$2"
shift 2
for attempt in $(seq 1 "$attempts"); do
if "$@"; then
return 0
fi
if [ "$attempt" = "$attempts" ]; then
return 1
fi
echo "::warning::Attempt $attempt/$attempts failed: $*; retrying in ${delay}s" >&2
sleep "$delay"
done
}

test -n "$AUR_SSH_PRIVATE_KEY" || {
echo "::error::AUR_SSH_PRIVATE_KEY is empty or unavailable in the pypi environment"
exit 1
}

retry 5 15 curl -fsSL "$AUR_RPC_URL" >/tmp/aur-rpc.json
python3 - <<'PY'
import json
from pathlib import Path

data = json.loads(Path("/tmp/aur-rpc.json").read_text())
print(f"AUR RPC resultcount={data.get('resultcount')}")
PY

mkdir -p ~/.ssh
retry 5 10 ssh-keyscan -T 30 -t rsa,ecdsa,ed25519 aur.archlinux.org >> ~/.ssh/known_hosts
retry 5 15 git ls-remote "https://aur.archlinux.org/${AUR_PACKAGE}.git" >/dev/null

- name: Publish to AUR
# Pushes to aur.archlinux.org via SSH. The action reads the
# updated PKGBUILD, regenerates .SRCINFO, and pushes.
Expand All@@ -79,6 +148,50 @@ jobs:
# avoid "Unknown key type" errors during keyscan.
ssh_keyscan_types: "rsa,ecdsa,ed25519"

- name: Verify AUR RPC after publish
env:
EXPECTED_VERSION: ${{ steps.version.outputs.version }}
run: |
set -euo pipefail
retry() {
local attempts="$1"
local delay="$2"
shift 2
for attempt in $(seq 1 "$attempts"); do
if "$@"; then
return 0
fi
if [ "$attempt" = "$attempts" ]; then
return 1
fi
echo "::warning::Attempt $attempt/$attempts failed: $*; retrying in ${delay}s" >&2
sleep "$delay"
done
}

retry 6 20 curl -fsSL "$AUR_RPC_URL" >/tmp/aur-rpc.json
AUR_VERSION=$(
python3 - <<'PY'
import json
from pathlib import Path

data = json.loads(Path("/tmp/aur-rpc.json").read_text())
results = data.get("results") or []
print(results[0]["Version"].split("-", 1)[0] if results else "")
PY
)
echo "AUR version: $AUR_VERSION"
echo "Expected version: $EXPECTED_VERSION"
if [ "$AUR_VERSION" != "$EXPECTED_VERSION" ]; then
echo "::warning::AUR RPC has not reflected ${EXPECTED_VERSION} yet (current: ${AUR_VERSION:-missing})"
fi
{
echo "## AUR publish verification"
echo
echo "- Expected version: \`$EXPECTED_VERSION\`"
echo "- AUR RPC version: \`${AUR_VERSION:-missing}\`"
} >> "$GITHUB_STEP_SUMMARY"

- name: Sync updated PKGBUILD to GitHub mirror
# Keep the aur-package GitHub mirror in sync with what's live
# on AUR. Only PKGBUILD needs to be committed here — .SRCINFO
Expand Down
20 changes: 20 additions & 0 deletions docs/DISTRIBUTION_SETUP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -92,6 +92,26 @@ Paste the **private** key as repo secret `AUR_SSH_PRIVATE_KEY`.
Fine-grained PAT with **Contents: Read and write** on `Create-Python-App/aur-package` only.
Store as `AUR_REPO_TOKEN`.

### AUR publish runbook

`publish-aur.yml` performs three reliability checks around the publish step:

1. Resolve the PyPI sdist SHA with retry before editing `PKGBUILD`
2. Preflight AUR RPC, `ssh-keyscan`, and `git ls-remote` with retry before pushing
3. Query AUR RPC after publish and write the observed version to the job summary

If the workflow fails before `Publish to AUR`, check the preflight log first:

- Empty `AUR_SSH_PRIVATE_KEY` means the secret is missing from the `pypi`
environment or the workflow did not get environment access.
- AUR RPC / `git ls-remote` failures are usually transient AUR availability
issues; rerun the job after a few minutes.
- PyPI metadata failures usually mean the release tag fired before PyPI finished
indexing the sdist; rerun once PyPI shows the version.

If `Publish to AUR` succeeds but the RPC summary still shows the previous
version, wait for AUR propagation and rerun the distribution smoke workflow.

## Homebrew (`HOMEBREW_TAP_TOKEN`)

**Prereqs**: [`Create-Python-App/homebrew-tap`](https://github.com/Create-Python-App/homebrew-tap)
Expand Down