feat: asked claude sonnet 4.6 to rework as github workflow instead of on my machine

This commit is contained in:
2026-04-30 09:59:35 +02:00
parent 475ffc8445
commit 0a04b994ae
6 changed files with 587 additions and 60 deletions
+284
View File
@@ -0,0 +1,284 @@
# AGENTS.md — webkit2gtk-automator
This file provides guidance for agentic coding agents working in this repository.
---
## Project Overview
This project is a Bash/Docker automation daemon that:
1. Polls the AUR RPC API for new `webkit2gtk` releases
2. Builds the package using `makepkg` inside an Arch Linux container
3. Publishes the resulting `.pkg.tar.zst` artifact to GitHub Releases
4. Generates and pushes an updated `webkit2gtk-bin` PKGBUILD to the AUR
The entire codebase is Bash scripts orchestrated via Docker Compose. There is no application framework, no package manager (npm/pip/cargo), and no test suite.
---
## Repository Structure
```
webkit2gtk-automator/
├── .env.example # Template for required environment variables
├── .gitignore
├── Dockerfile # Arch Linux image with build dependencies
├── docker-compose.yml # Defines the "builder" service
├── README.md
└── scripts/
├── entrypoint.sh # Container entrypoint; polling loop
├── check-update.sh # AUR API poll; triggers build + publish if new version
├── build.sh # Runs makepkg; collects .pkg.tar.zst artifacts
└── publish.sh # Uploads to GitHub Releases; pushes PKGBUILD to AUR
```
Runtime-generated (gitignored):
- `state/last_version` — tracks last published version
- `state/artifacts/` — holds built `.pkg.tar.zst` files
- `webkit2gtk/` — AUR source package clone
- `webkit2gtk-bin/` — AUR binary package clone
---
## Environment Setup
Copy `.env.example` to `.env` and fill in all required values before starting:
```bash
cp .env.example .env
# Edit .env with your GITHUB_TOKEN, AUR SSH key path, GPG key, etc.
```
All scripts validate required variables at startup using the pattern:
```bash
: "${GITHUB_TOKEN:?GITHUB_TOKEN is not set}"
```
Missing variables cause an immediate exit with a descriptive error.
---
## Build / Run Commands
| Purpose | Command |
|---|---|
| Start the daemon (detached) | `docker compose up -d` |
| Start and rebuild the image | `docker compose up -d --build` |
| Watch live logs | `docker compose logs -f` |
| Stop the daemon | `docker compose down` |
| Force a rebuild on next poll | `rm state/last_version && docker compose restart` |
---
## Running a Single Script
There is no test runner. To manually invoke a single script inside the container:
```bash
# Run check-update.sh (polls AUR and triggers build+publish if needed)
docker compose run --rm builder bash -c "source /workspace/.env && /workspace/scripts/check-update.sh"
# Run build.sh directly
docker compose run --rm builder bash -c "source /workspace/.env && /workspace/scripts/build.sh"
# Run publish.sh directly
docker compose run --rm builder bash -c "source /workspace/.env && /workspace/scripts/publish.sh"
```
To test publish without recompiling, pre-place an artifact in `state/artifacts/`:
```bash
# build.sh detects existing artifact and skips makepkg
cp some-existing.pkg.tar.zst state/artifacts/
docker compose run --rm builder bash -c "source /workspace/.env && /workspace/scripts/publish.sh"
```
---
## No Test Suite
There are no unit tests, integration tests, or test commands. Manual invocation of
individual scripts (see above) is the primary validation mechanism.
---
## Code Style Guidelines
### Shebang and Strict Mode
Every script **must** begin with:
```bash
#!/usr/bin/env bash
set -euo pipefail
```
- `set -e` — exit immediately on any non-zero return code
- `set -u` — treat unset variables as errors
- `set -o pipefail` — propagate errors through pipelines
### Variable Naming
| Scope | Convention | Example |
|---|---|---|
| All variables (env or local) | `UPPER_SNAKE_CASE` | `PKG_VERSION`, `BUILD_DIR` |
| Functions | `snake_case` | `log`, `die`, `check_deps` |
| Script files | `kebab-case.sh` | `check-update.sh`, `build.sh` |
### Quoting
Always double-quote variable expansions. Use `${VAR}` brace syntax:
```bash
# Correct
cp "${SRC_FILE}" "${DEST_DIR}/"
echo "Version: ${PKG_VERSION}"
# Wrong — never do this
cp $SRC_FILE $DEST_DIR/
```
### Sourcing Files
Use `source` (not the POSIX `.` shorthand):
```bash
# Correct
source /workspace/.env
# Avoid
. /workspace/.env
```
To auto-export all variables from a sourced file:
```bash
set -a
source /workspace/.env
set +a
```
### Logging
Every script defines a `log()` function with a consistent timestamp prefix:
```bash
log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] [script-name] $*"; }
```
Use `log` for all informational output. Use `log "ERROR: ..." >&2` (or `die`) for errors.
### Arrays
Use Bash arrays when collecting multiple items:
```bash
packages=()
packages+=("${pkg_file}")
```
---
## Error Handling Conventions
### Required Variable Checks
Use Bash parameter expansion to validate required env vars:
```bash
: "${GITHUB_TOKEN:?GITHUB_TOKEN is not set}"
: "${AUR_SSH_KEY:?AUR_SSH_KEY is not set}"
```
### `die()` Helper
Define and use a `die()` function for fatal errors:
```bash
die() {
log "ERROR: $*" >&2
exit 1
}
# Usage
[[ -f "${pkg_file}" ]] || die "Expected artifact not found: ${pkg_file}"
```
### Explicit Guard Blocks
Prefer explicit `if/else` over bare command calls for critical steps:
```bash
if "${SCRIPT_DIR}/build.sh"; then
log "Build succeeded"
else
log "ERROR: Build failed, aborting"
exit 1
fi
```
### Null/Empty API Response Checks
Always validate outputs from `curl | jq` pipelines:
```bash
aur_version=$(curl -s "${AUR_API_URL}" | jq -r '.results[0].Version')
if [[ -z "${aur_version}" || "${aur_version}" == "null" ]]; then
log "ERROR: Failed to parse version from AUR response"
exit 1
fi
```
### Graceful No-Op
For idempotent operations (e.g., git commit), allow the no-op case:
```bash
git commit -m "Update to ${FULL_VERSION}" || {
log "Nothing to commit, already at ${FULL_VERSION}"
exit 0
}
```
---
## External Tool Dependencies
These CLI tools are invoked directly by the scripts. They must be present in the container:
| Tool | Purpose |
|---|---|
| `curl` | HTTP requests to AUR RPC API |
| `jq` | JSON parsing of AUR API responses |
| `makepkg` | Arch Linux package build tool |
| `gh` | GitHub CLI — creating releases and uploading assets |
| `git` | Cloning/pulling AUR repos, committing, pushing |
| `gpg` | Verifying PGP signatures on source tarballs |
| `sha256sum` | Computing checksums for the artifact |
| `bsdtar` | Extracting the `.pkg.tar.zst` in the generated PKGBUILD |
| `sudo` | Dropping privileges from root to `builduser` for `makepkg` |
| `ssh` | AUR authentication via SSH key |
All of these are installed in the `Dockerfile`. If adding a new dependency, add it there.
---
## Dockerfile and docker-compose.yml
- The base image is Arch Linux. Keep it updated with `pacman -Syu` in the `Dockerfile`.
- The container runs as root but drops to a `builduser` account for `makepkg` (which
refuses to run as root).
- Secrets (`.env`, SSH keys, GPG keys) are mounted at runtime via volume mounts defined
in `docker-compose.yml`. Never bake secrets into the image.
---
## ShellCheck
ShellCheck is the recommended linter for Bash scripts. It is not formally enforced (no
`.shellcheckrc` or CI step), but inline directives are already used in the codebase
(e.g., `# shellcheck source=/dev/null`). When editing scripts, run ShellCheck locally:
```bash
shellcheck scripts/*.sh
```
Fix all warnings before committing. Use inline directives sparingly and only with a
comment explaining why the suppression is necessary.
---
## Adding a New Script
1. Create the file as `scripts/kebab-case-name.sh`
2. Start with `#!/usr/bin/env bash` and `set -euo pipefail`
3. Define a `log()` function matching the pattern above
4. Validate all required env vars with `: "${VAR:?...}"`
5. Define a `die()` helper for fatal errors
6. Make it executable: `chmod +x scripts/kebab-case-name.sh`
7. If it needs to run inside the container, invoke it via `docker compose run --rm builder`