diff --git a/.github/workflows/sync-upstream.yml b/.github/workflows/sync-upstream.yml new file mode 100644 index 0000000..0083ec3 --- /dev/null +++ b/.github/workflows/sync-upstream.yml @@ -0,0 +1,95 @@ +name: Sync Upstream Releases + +on: + schedule: + # Every 6 hours, off the hour to dodge the scheduling backlog at :00 + - cron: '20 */6 * * *' + workflow_dispatch: + inputs: + packages: + description: 'Specific packages to update (space-separated, leave empty for all)' + required: false + default: '' + +jobs: + sync: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + persist-credentials: false + + # Runs in an Arch container for vercmp: whether a release is an upgrade has + # to be decided by the same comparator pacman will use on users' machines. + - name: Update packages from upstream release feeds + run: | + docker run --rm \ + -e PACKAGES="$PACKAGES" \ + -e HOST_UID="$(id -u)" \ + -e HOST_GID="$(id -g)" \ + -v "$PWD/bin:/workspace/bin:ro" \ + -v "$PWD/helpers:/workspace/helpers:ro" \ + -v "$PWD/pkgbuilds:/workspace/pkgbuilds" \ + -w /workspace \ + archlinux:base-devel bash -lc ' + set -euo pipefail + + pacman -Syu --noconfirm jq + + groupadd -g "$HOST_GID" runner + useradd -m -u "$HOST_UID" -g "$HOST_GID" runner + chown -R runner:runner /workspace/pkgbuilds + + if [[ -n "${PACKAGES:-}" ]]; then + read -r -a package_args <<< "$PACKAGES" + runuser -u runner -- ./bin/sync-upstream "${package_args[@]}" + else + runuser -u runner -- ./bin/sync-upstream + fi + ' + env: + PACKAGES: ${{ github.event.inputs.packages }} + + - name: Check for changes + id: changes + run: | + if [ -z "$(git status --porcelain)" ]; then + echo "has_changes=false" >> "$GITHUB_OUTPUT" + else + echo "has_changes=true" >> "$GITHUB_OUTPUT" + fi + + - name: Create Pull Request + if: steps.changes.outputs.has_changes == 'true' + uses: peter-evans/create-pull-request@v7 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: 'chore: sync upstream releases' + title: 'chore: sync upstream releases' + body: | + Automated update of packages that track an upstream vendor release + feed rather than the AUR. + + Each package reports its newest release through + `.omarchy/upstream.sh`. + branch: auto/sync-upstream + delete-branch: true + labels: automated + reviewers: ryanrhughes + + - name: Notify Basecamp on failure + if: failure() && env.BASECAMP_CHATBOT_URL != '' + env: + BASECAMP_CHATBOT_URL: ${{ secrets.BASECAMP_CHATBOT_URL }} + run: | + curl -s -o /dev/null \ + -H "Content-Type: application/json" \ + -d "$(jq -n --arg content \ + "πŸ”΄ Upstream sync failed
View run" \ + '{content: $content}')" \ + "$BASECAMP_CHATBOT_URL" diff --git a/README.md b/README.md index 5f1e891..50c03f0 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ The filesystem no longer encodes release policy. Instead: - all other packages reach `stable` by promoting tested edge artifacts with `bin/repo migrate` - AUR sync behavior is controlled by `source`, `sync`, `aur`, patches, and hooks in `.omarchy/` - packages can opt out of unscoped builds with `skip_build`; explicit `--package` builds remain available +- packages that follow a vendor release feed instead of the AUR carry an `.omarchy/upstream.sh` hook ## Prerequisites ### aarch64 Builds (Optional) @@ -248,6 +249,40 @@ bin/sync-aur yay v4l2-relayd # Sync specific packages AUR sync is metadata-driven. It preserves `.omarchy/`, replaces the package root with AUR contents, applies `.omarchy/patches/*.patch`, runs `.omarchy/post-sync.sh` when present, applies pkgrel metadata, removes AUR-only `.SRCINFO` and `.gitignore` files, and records `upstream_commit`. +### Sync Upstream Releases + +```bash +bin/sync-upstream # Update every package with an upstream hook +bin/sync-upstream openai-codex-desktop # Update specific packages +``` + +Some vendors publish a release feed of their own that is faster and more precise +than the AUR packaging of it. Those packages are `source: local` β€” Omarchy owns +the PKGBUILD β€” and provide `.omarchy/upstream.sh`, a hook that reports the newest +upstream release as JSON on stdout: + +```json +{ + "pkgver": "1.2.3", + "sha256sums": { "x86_64": [""], "aarch64": [""] } +} +``` + +Architecture keys become `sha256sums_` in the PKGBUILD; the key `any` means +the unsuffixed `sha256sums` array, and only the arrays a hook names are touched. +An empty object (`{}`) reports no update, which is how a hook waits out a release +that has landed for one architecture but not yet the other. + +When the reported version is newer than the checked-in one, `bin/sync-upstream` +rewrites `pkgver` and those checksum arrays and resets `pkgrel` to 1. A version +that is equal or older leaves the package alone, so a vendor rolling a release +back cannot walk the repository backwards. + +Hooks should read checksums from whatever manifest the vendor publishes rather +than downloading the artifacts β€” see `pkgbuilds/openai-codex-desktop/.omarchy/upstream.sh`, +which reads OpenAI's Debian package index and never fetches the 750 MB of debs +it describes. + ### Other ```bash @@ -260,6 +295,7 @@ bin/repo push # Upload local builds to the host and publi bin/add-package # Add an AUR/local package with metadata bin/package-worktree # Create upstream/patched/current scratch workspace bin/repo remove # Remove package +bin/sync-upstream # Update packages that track a vendor release feed bin/clean-docker # Clear Docker images/cache (forces fresh rebuild) ``` @@ -345,7 +381,8 @@ omarchy-pkgs/ β”‚ └── .omarchy/ β”‚ β”œβ”€β”€ package.json # Source/sync/release metadata β”‚ β”œβ”€β”€ patches/ # Omarchy patches reapplied after AUR sync -β”‚ └── post-sync.sh # Optional dynamic post-sync customization hook +β”‚ β”œβ”€β”€ post-sync.sh # Optional dynamic post-sync customization hook +β”‚ └── upstream.sh # Optional vendor release feed hook (non-AUR packages) β”œβ”€β”€ build/ β”œβ”€β”€ build-output/ # Unsigned packages (temporary) β”‚ β”œβ”€β”€ edge/ @@ -396,7 +433,7 @@ Minimal examples: Fields: -- `source`: `aur` or `local` +- `source`: `aur` or `local`. A `local` package can still follow an upstream release with an `.omarchy/upstream.sh` hook. - `sync`: optional for AUR packages; defaults to `true`. Set `false` for AUR-origin packages that Omarchy maintains manually. - `aur`: optional AUR package name when it differs from the local package directory, usually for split packages. - `release_ring`: optional. `fast` means the package is built directly for stable as well as edge. Packages without a ring build in edge and reach stable through tested artifact promotion (`bin/repo migrate`). @@ -539,6 +576,7 @@ The repository includes GitHub workflows and systemd services for automated rele #### GitHub Workflows 1. **sync-aur.yml** (Every 6 hours): Syncs AUR packages according to `.omarchy/package.json` and opens a PR when changes are found. +2. **sync-upstream.yml** (Every 6 hours): Runs `.omarchy/upstream.sh` for packages that track a vendor release feed and opens a PR when a newer version is out. #### Systemd Services diff --git a/bin/sync-upstream b/bin/sync-upstream new file mode 100755 index 0000000..93e6f0d --- /dev/null +++ b/bin/sync-upstream @@ -0,0 +1,390 @@ +#!/bin/bash +set -euo pipefail + +BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") +source "$BUILD_ROOT/helpers/message-helpers.sh" +source "$BUILD_ROOT/helpers/paths.sh" +source "$BUILD_ROOT/helpers/package-metadata.sh" + +TEMP_DIR=$(mktemp -d) +trap 'rm -rf "$TEMP_DIR"' EXIT + +SPECIFIC_PACKAGES=() + +usage() { + cat </.omarchy/upstream.sh, a hook +that reports the newest upstream release as JSON on stdout: + + { + "pkgver": "1.2.3", + "sha256sums": { "x86_64": [""], "aarch64": [""] } + } + +Architecture keys become sha256sums_ in the PKGBUILD; the key "any" means +the unsuffixed sha256sums array. An empty object ({}) reports no update. + +When the reported version is newer than the checked-in one, pkgver and the +listed checksum arrays are rewritten and pkgrel is reset to 1. + +Arguments: + PACKAGE One or more package names to update (optional) + +Examples: + $0 # Update every package with an upstream hook + $0 openai-codex-desktop # Update specific packages +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -h|--help) + usage + exit 0 + ;; + --*) + print_error "Unknown option: $1" + exit 1 + ;; + *) + SPECIFIC_PACKAGES+=("$1") + shift + ;; + esac +done + +if ! command -v vercmp >/dev/null 2>&1; then + print_error "vercmp not found: this needs pacman to decide whether a release is an upgrade" + exit 1 +fi + +print_header "Upstream Package Sync" + +UPDATED=0 +SKIPPED=0 +FAILED=0 +SPECIFIC_MODE=false + +get_pkgver() { + local package_dir="$1" + + grep -m1 '^pkgver=' "$package_dir/PKGBUILD" | cut -d= -f2- | tr -d "\"'" +} + +assert_single_assignment() { + local pkgbuild="$1" + local pattern="$2" + local label="$3" + + if [[ $(grep -c "$pattern" "$pkgbuild") -ne 1 ]]; then + print_error "Expected exactly one $label assignment in $pkgbuild" + return 1 + fi +} + +set_pkgbuild_scalar() { + local pkgbuild="$1" + local field="$2" + local value="$3" + + assert_single_assignment "$pkgbuild" "^${field}=" "$field" || return 1 + sed -i "s/^${field}=.*/${field}=${value}/" "$pkgbuild" +} + +# Replace an array assignment, however many lines the original spans. +set_pkgbuild_array() { + local pkgbuild="$1" + local name="$2" + shift 2 + local values=("$@") + + assert_single_assignment "$pkgbuild" "^${name}=(" "$name" || return 1 + + if [[ ${#values[@]} -eq 0 ]]; then + print_error "No values to write for ${name}" + return 1 + fi + + local block="$TEMP_DIR/array-block" + if [[ ${#values[@]} -eq 1 ]]; then + printf "%s=('%s')\n" "$name" "${values[0]}" > "$block" || return 1 + else + { + printf '%s=(\n' "$name" + printf " '%s'\n" "${values[@]}" + printf ')\n' + } > "$block" || return 1 + fi + + local rewritten="$TEMP_DIR/pkgbuild-rewritten" + if ! awk -v prefix="${name}=(" -v block="$block" ' + !replaced && index($0, prefix) == 1 { + while ((getline line < block) > 0) print line + close(block) + replaced = 1 + # A ")" anywhere past the opening closes the array; testing for one at end + # of line instead would treat a trailing comment as a continuation and eat + # every line up to the next ")". + if (index(substr($0, length(prefix) + 1), ")") == 0) skipping = 1 + next + } + skipping { if ($0 ~ /\)/) skipping = 0; next } + { print } + ' "$pkgbuild" > "$rewritten"; then + print_error "Failed to rewrite ${name} in $pkgbuild" + rm -f "$rewritten" + return 1 + fi + + mv "$rewritten" "$pkgbuild" +} + +# pacman's own comparator, because nothing else agrees with it at the corners: +# sort -V calls 1.0a newer than 1.0, vercmp calls it older, and pacman is what +# decides whether a published package is an upgrade. +version_is_newer() { + local candidate="$1" + local current="$2" + + [[ "$candidate" != "$current" ]] || return 1 + [[ "$(vercmp "$candidate" "$current")" -gt 0 ]] +} + +validate_release() { + local release="$1" + + # pkgver is written into the PKGBUILD, which makepkg sources as shell, so it + # is held to pacman's own character set rather than merely being non-empty. + # The anchors are \A and \z, not ^ and $: jq's $ also matches before a + # trailing newline, which would let "1.0\n" through and break the rewrite. + jq -e ' + (.pkgver | type == "string" and test("\\A[A-Za-z0-9._+]+\\z")) + and (.sha256sums | type == "object" and length > 0) + and (.sha256sums | to_entries | all( + .key | test("\\A[a-z0-9_]+\\z") + )) + and (.sha256sums | to_entries | all( + .value | type == "array" and length > 0 and all(test("\\A[0-9a-f]{64}\\z")) + )) + ' <<<"$release" >/dev/null +} + +# Confirm the rewritten PKGBUILD parses and actually holds what we meant to put +# in it. Editing shell with awk and sed can go wrong in ways no amount of +# pattern-matching anticipates -- an array element carrying a ")" in a comment, +# say -- so the result is checked rather than trusted. +verify_pkgbuild() { + local pkgbuild="$1" + local release="$2" + local pkgver="$3" + shift 3 + local arrays=("$@") + + if ! bash -n "$pkgbuild" 2>/dev/null; then + print_error "Rewritten PKGBUILD is not valid shell" + return 1 + fi + + local dump + if ! dump=$(CARCH=x86_64 bash -c ' + source "$1" >/dev/null 2>&1 || exit 1 + printf "pkgver\t%s\n" "$pkgver" + printf "pkgrel\t%s\n" "$pkgrel" + for name in "${@:2}"; do + declare -n array="$name" + printf "%s\t%s\n" "$name" "${array[*]}" + done + ' _ "$pkgbuild" "${arrays[@]}" 2>/dev/null); then + print_error "Rewritten PKGBUILD could not be read back" + return 1 + fi + + local expected + expected=$( + printf 'pkgver\t%s\n' "$pkgver" + printf 'pkgrel\t1\n' + local array arch + for array in "${arrays[@]}"; do + arch="${array#sha256sums}" + arch="${arch#_}" + [[ -n "$arch" ]] || arch="any" + printf '%s\t%s\n' "$array" \ + "$(jq -r --arg arch "$arch" '.sha256sums[$arch] | join(" ")' <<<"$release")" + done + ) + + if [[ "$dump" != "$expected" ]]; then + print_error "Rewritten PKGBUILD does not hold the reported release" + diff <(echo "$expected") <(echo "$dump") | sed 's/^/ /' >&2 || true + return 1 + fi +} + +apply_release() { + local package_dir="$1" + local release="$2" + local pkgver="$3" + local pkgbuild="$package_dir/PKGBUILD" + + local arch array values + local arrays=() + + while IFS= read -r arch; do + if [[ "$arch" == "any" ]]; then + array="sha256sums" + else + array="sha256sums_$arch" + fi + arrays+=("$array") + done < <(jq -r '.sha256sums | keys[]' <<<"$release") + + # validate_release guarantees at least one entry, so an empty list here means + # jq died inside the process substitution rather than that there is nothing + # to do. + if [[ ${#arrays[@]} -eq 0 ]]; then + print_error "Could not read the checksum architectures from the reported release" + return 1 + fi + + # Every edit lands on a scratch copy that replaces the PKGBUILD in one rename + # at the end, so a failure part way through leaves the original untouched + # rather than half updated. + local scratch="$pkgbuild.sync-upstream" + cp "$pkgbuild" "$scratch" || return 1 + + if ! ( + assert_single_assignment "$scratch" '^pkgver=' pkgver || exit 1 + assert_single_assignment "$scratch" '^pkgrel=' pkgrel || exit 1 + + for array in "${arrays[@]}"; do + arch="${array#sha256sums}" + arch="${arch#_}" + [[ -n "$arch" ]] || arch="any" + + mapfile -t values < <(jq -r --arg arch "$arch" '.sha256sums[$arch][]' <<<"$release") + set_pkgbuild_array "$scratch" "$array" "${values[@]}" || exit 1 + done + + set_pkgbuild_scalar "$scratch" pkgver "$pkgver" || exit 1 + set_pkgbuild_scalar "$scratch" pkgrel 1 || exit 1 + + verify_pkgbuild "$scratch" "$release" "$pkgver" "${arrays[@]}" || exit 1 + ); then + rm -f "$scratch" + return 1 + fi + + chmod --reference="$pkgbuild" "$scratch" + mv "$scratch" "$pkgbuild" +} + +sync_package() { + local package="$1" + local package_dir="$PKGBUILDS_DIR/$package" + local hook="$package_dir/.omarchy/upstream.sh" + + if [[ ! -f "$package_dir/PKGBUILD" ]]; then + print_error "Package $package has no PKGBUILD" + ((++FAILED)) + return 0 + fi + + if [[ ! -f "$hook" ]]; then + if [[ "$SPECIFIC_MODE" == true ]]; then + print_error "Package $package is missing .omarchy/upstream.sh" + ((++FAILED)) + else + print_info "Skipping $package: no upstream hook" + ((++SKIPPED)) + fi + return 0 + fi + + print_info "Checking $package for upstream releases..." + + local release + if ! release=$(cd "$package_dir" && PACKAGE_NAME="$package" bash .omarchy/upstream.sh); then + print_error "Upstream hook failed for $package" + ((++FAILED)) + return 0 + fi + + if ! jq -e . >/dev/null 2>&1 <<<"$release"; then + print_error "Upstream hook for $package did not report valid JSON" + ((++FAILED)) + return 0 + fi + + if [[ "$(jq -r 'has("pkgver")' <<<"$release")" == "false" ]]; then + print_info " No upstream update reported" + ((++SKIPPED)) + return 0 + fi + + if ! validate_release "$release"; then + print_error "Upstream hook for $package reported a malformed release" + ((++FAILED)) + return 0 + fi + + local pkgver current_pkgver + pkgver=$(jq -r '.pkgver' <<<"$release") + current_pkgver=$(get_pkgver "$package_dir") + + if [[ -z "$current_pkgver" ]]; then + print_error "Could not read pkgver from $package_dir/PKGBUILD" + ((++FAILED)) + return 0 + fi + + if [[ "$pkgver" == "$current_pkgver" ]]; then + print_info " Already at $current_pkgver" + ((++SKIPPED)) + return 0 + fi + + if ! version_is_newer "$pkgver" "$current_pkgver"; then + print_warning " Upstream reports $pkgver, older than the checked-in $current_pkgver; leaving it alone" + ((++SKIPPED)) + return 0 + fi + + if ! apply_release "$package_dir" "$release" "$pkgver"; then + print_error "Failed to update $package" + ((++FAILED)) + return 0 + fi + + print_success " $current_pkgver -> $pkgver" + ((++UPDATED)) +} + +if [[ ${#SPECIFIC_PACKAGES[@]} -gt 0 ]]; then + SPECIFIC_MODE=true + for package in "${SPECIFIC_PACKAGES[@]}"; do + sync_package "$package" + done +else + while IFS= read -r package; do + sync_package "$package" + done < <(packages_for_upstream_sync) +fi + +echo "" +if [[ $FAILED -gt 0 ]]; then + print_error "Upstream sync completed with failures" +else + print_success "Upstream sync complete!" +fi +echo " Target: $PKGBUILDS_DIR" +echo " Updated: $UPDATED" +echo " Skipped: $SKIPPED" +echo " Failed: $FAILED" + +if [[ $FAILED -gt 0 ]]; then + exit 1 +fi diff --git a/helpers/package-metadata.sh b/helpers/package-metadata.sh index 1160fff..b1f1b70 100644 --- a/helpers/package-metadata.sh +++ b/helpers/package-metadata.sh @@ -135,6 +135,19 @@ packages_for_aur_sync() { done } +package_has_upstream_hook() { + local pkgdir="$1" + [[ -f "$pkgdir/.omarchy/upstream.sh" ]] +} + +packages_for_upstream_sync() { + package_dirs | while IFS= read -r pkgdir; do + if package_has_upstream_hook "$pkgdir"; then + basename "$pkgdir" + fi + done +} + packages_for_mirror() { local mirror="$1" diff --git a/pkgbuilds/openai-codex-desktop/.omarchy/package.json b/pkgbuilds/openai-codex-desktop/.omarchy/package.json index 8d7f14b..db153c3 100644 --- a/pkgbuilds/openai-codex-desktop/.omarchy/package.json +++ b/pkgbuilds/openai-codex-desktop/.omarchy/package.json @@ -1,5 +1,4 @@ { - "source": "aur", - "release_ring": "fast", - "upstream_commit": "05f12e3c51ce07efb996698d4fae94327f45f03b" + "source": "local", + "release_ring": "fast" } diff --git a/pkgbuilds/openai-codex-desktop/.omarchy/patches/max-zstd-compression.patch b/pkgbuilds/openai-codex-desktop/.omarchy/patches/max-zstd-compression.patch deleted file mode 100644 index 58bd5a8..0000000 --- a/pkgbuilds/openai-codex-desktop/.omarchy/patches/max-zstd-compression.patch +++ /dev/null @@ -1,15 +0,0 @@ ---- a/PKGBUILD -+++ b/PKGBUILD -@@ -55,6 +55,12 @@ - conflicts=('chatgpt') - options=('!debug' '!strip') - -+# Omarchy: the build image compresses with zstd at its default level, which -+# leaves this 1.3 GB Electron tree at 447 MB. Maximum zstd takes it to 322 MB -+# for ~4 extra minutes of build time -- worth it for a package this large that -+# every user re-downloads on each of OpenAI's frequent releases. -+COMPRESSZST=(zstd -c -z -q --ultra -22 --threads=0 -) -+ - _deb_x86_64="chatgpt_${pkgver}_amd64.deb" - _deb_aarch64="chatgpt_${pkgver}_arm64.deb" - source=('chatgpt-launcher.sh') diff --git a/pkgbuilds/openai-codex-desktop/.omarchy/upstream.sh b/pkgbuilds/openai-codex-desktop/.omarchy/upstream.sh new file mode 100755 index 0000000..a090a35 --- /dev/null +++ b/pkgbuilds/openai-codex-desktop/.omarchy/upstream.sh @@ -0,0 +1,66 @@ +#!/bin/bash +# OpenAI ships the ChatGPT desktop app from its own Debian repository. The +# per-architecture package index carries both the version and the SHA256 of +# every deb, so an update costs two small HTTP requests instead of a 750 MB +# download, and the pool keeps old versions, so the URLs pinned in the PKGBUILD +# stay resolvable after the next release. +set -euo pipefail + +BASE_URL="https://persistent.oaistatic.com/codex-app-prod/linux/deb" +declare -A DEB_ARCHES=([x86_64]=amd64 [aarch64]=arm64) + +# Print " " for the newest stanza in a Packages index. Newest +# is vercmp's opinion, which is the one bin/sync-upstream and pacman both use; +# sort -V disagrees with it over versions like 1.0a. +newest_release() { + local index="$1" + local version sha256 best_version="" best_sha256="" + + while read -r version sha256; do + if [[ -z "$best_version" ]] || [[ "$(vercmp "$version" "$best_version")" -gt 0 ]]; then + best_version="$version" + best_sha256="$sha256" + fi + done < <(awk ' + { sub(/\r$/, "") } + /^Version:/ { version = $2 } + /^SHA256:/ { sha256 = $2 } + /^$/ { if (version && sha256) print version, sha256; version = sha256 = "" } + END { if (version && sha256) print version, sha256 } + ' <<<"$index") + + [[ -n "$best_version" ]] || return 1 + echo "$best_version $best_sha256" +} + +versions=() +declare -A checksums=() + +for arch in "${!DEB_ARCHES[@]}"; do + index=$(curl -fsSL "$BASE_URL/dists/stable/main/binary-${DEB_ARCHES[$arch]}/Packages") + + read -r version sha256 <<<"$(newest_release "$index")" + if [[ -z "${version:-}" || -z "${sha256:-}" ]]; then + echo "No usable release found for $arch in the upstream package index" >&2 + exit 1 + fi + + versions+=("$version") + checksums[$arch]="$sha256" +done + +# A release lands one architecture at a time, and a single pkgver has to cover +# both. Report no update until they agree; the next run picks it up. +for version in "${versions[@]}"; do + if [[ "$version" != "${versions[0]}" ]]; then + echo "Upstream architectures are mid-release (${versions[*]}); skipping" >&2 + echo '{}' + exit 0 + fi +done + +jq -n \ + --arg pkgver "${versions[0]}" \ + --arg x86_64 "${checksums[x86_64]}" \ + --arg aarch64 "${checksums[aarch64]}" \ + '{pkgver: $pkgver, sha256sums: {x86_64: [$x86_64], aarch64: [$aarch64]}}' diff --git a/pkgbuilds/openai-codex-desktop/LICENSE b/pkgbuilds/openai-codex-desktop/LICENSE deleted file mode 100644 index b87c5e4..0000000 --- a/pkgbuilds/openai-codex-desktop/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -Copyright Arch Linux Contributors - -Permission to use, copy, modify, and/or distribute this software for -any purpose with or without fee is hereby granted. - -THE SOFTWARE IS PROVIDED β€œAS IS” AND THE AUTHOR DISCLAIMS ALL -WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES -OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE -FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY -DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN -AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT -OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/pkgbuilds/openai-codex-desktop/LICENSES/0BSD.txt b/pkgbuilds/openai-codex-desktop/LICENSES/0BSD.txt deleted file mode 120000 index ea5b606..0000000 --- a/pkgbuilds/openai-codex-desktop/LICENSES/0BSD.txt +++ /dev/null @@ -1 +0,0 @@ -../LICENSE \ No newline at end of file diff --git a/pkgbuilds/openai-codex-desktop/PKGBUILD b/pkgbuilds/openai-codex-desktop/PKGBUILD index 52393e7..a92ee95 100644 --- a/pkgbuilds/openai-codex-desktop/PKGBUILD +++ b/pkgbuilds/openai-codex-desktop/PKGBUILD @@ -1,10 +1,12 @@ -# Maintainer: Parsiad Azimzadeh -# Maintainer: mothran -# Official downloads: https://chatgpt.com/codex/ +# Maintainer: David Heinemeier Hansson + +# Omarchy tracks OpenAI's own Debian repository rather than the AUR, which lags +# behind releases that ship several times a week. .omarchy/upstream.sh rewrites +# the version and checksums below from that repository's package index. pkgname=openai-codex-desktop -pkgver=26.803.81509 -pkgrel=8.1 +pkgver=26.810.52044 +pkgrel=1 pkgdesc="Official ChatGPT desktop app with Codex" arch=('x86_64' 'aarch64') url="https://chatgpt.com/codex/" @@ -64,16 +66,13 @@ COMPRESSZST=(zstd -c -z -q --ultra -22 --threads=0 -) _deb_x86_64="chatgpt_${pkgver}_amd64.deb" _deb_aarch64="chatgpt_${pkgver}_arm64.deb" source=('chatgpt-launcher.sh') -source_x86_64=( - "${_deb_x86_64}::https://persistent.oaistatic.com/codex-app-prod/linux/deb/latest/chatgpt_amd64.deb" -) -source_aarch64=( - "${_deb_aarch64}::https://persistent.oaistatic.com/codex-app-prod/linux/deb/latest/chatgpt_arm64.deb" -) +_pool="https://persistent.oaistatic.com/codex-app-prod/linux/deb/pool/main/c/chatgpt" +source_x86_64=("${_deb_x86_64}::${_pool}/${_deb_x86_64}") +source_aarch64=("${_deb_aarch64}::${_pool}/${_deb_aarch64}") noextract=("${_deb_x86_64}" "${_deb_aarch64}") -sha256sums=('4e3ca9302600bed268f8fd3ba2c9ac2f1ceb99da139ed71c50db0289b118d06f') -sha256sums_x86_64=('a9bf91a368f9f7c4eea38082a9fb8fb46b8d005b719a6d7715d2e5a1982c38eb') -sha256sums_aarch64=('f38fcc194eca9ab0327dc10c92340681eae77c5d75164df700384ce2adaccbc1') +sha256sums=('b3a4503b5931f102444bc7015c3cf4e40266cf034e0d682bd2a407dc5b3ee58c') +sha256sums_x86_64=('708a15a1bb76e2bb7f0e376e5145391fa277ad3a64057c1d32537bdc2a1b4e6e') +sha256sums_aarch64=('6ebea681b1e494d218a199f638b4bc886e94e1458dd61079b1e390a6fb98fdd2') package() { cd "${srcdir}" diff --git a/pkgbuilds/openai-codex-desktop/REUSE.toml b/pkgbuilds/openai-codex-desktop/REUSE.toml deleted file mode 100644 index 49e3625..0000000 --- a/pkgbuilds/openai-codex-desktop/REUSE.toml +++ /dev/null @@ -1,25 +0,0 @@ -version = 1 - -[[annotations]] -path = [ - "PKGBUILD", - "README.md", - "keys/**", - ".SRCINFO", - ".gitignore", - ".nvchecker.toml", - "*.install", - "*.sysusers", - "*sysusers.conf", - "*.tmpfiles", - "*tmpfiles.conf", - "*.logrotate", - "*.pam", - "*.service", - "*.socket", - "*.timer", - "*.desktop", - "*.hook", -] -SPDX-FileCopyrightText = "Arch Linux contributors" -SPDX-License-Identifier = "0BSD" diff --git a/pkgbuilds/openai-codex-desktop/chatgpt-launcher.sh b/pkgbuilds/openai-codex-desktop/chatgpt-launcher.sh old mode 100644 new mode 100755 index 0f8bc6b..2c4f4f2 --- a/pkgbuilds/openai-codex-desktop/chatgpt-launcher.sh +++ b/pkgbuilds/openai-codex-desktop/chatgpt-launcher.sh @@ -1,37 +1,32 @@ #!/bin/bash -# SPDX-FileCopyrightText: 2026 Arch Linux Contributors -# SPDX-License-Identifier: 0BSD set -euo pipefail user_flags=() -ozone_flags=() - config_home="${XDG_CONFIG_HOME:-}" -if [[ -z "${config_home}" && -n "${HOME:-}" ]]; then - config_home="${HOME}/.config" +[[ -n "$config_home" || -z "${HOME:-}" ]] || config_home="$HOME/.config" +flags_file="${config_home:+$config_home/codex-flags.conf}" + +if [[ -n "$flags_file" && -f "$flags_file" && -r "$flags_file" ]]; then + while IFS= read -r line || [[ -n "$line" ]]; do + line="${line%%#*}" + [[ -n "${line//[[:space:]]/}" ]] || continue + read -r -a flags <<<"$line" + user_flags+=("${flags[@]}") + done <"$flags_file" fi -if [[ -n "${config_home}" && -f "${config_home}/codex-flags.conf" ]]; then - while IFS= read -r flag_line || [[ -n "${flag_line}" ]]; do - flag_line="${flag_line%%#*}" - read -r -a flag_parts <<<"${flag_line}" - user_flags+=("${flag_parts[@]}") - done <"${config_home}/codex-flags.conf" +# Chromium's own Ozone detection falls back to XWayland often enough to matter, +# and the result is a blurry window on every scaled display. Ask for Wayland +# directly, unless the user has already picked a platform themselves. +platform_flags=() +if [[ -n "${WAYLAND_DISPLAY:-}" || "${XDG_SESSION_TYPE:-}" == wayland ]]; then + platform_flags=(--ozone-platform=wayland) + + for flag in "${user_flags[@]}" "$@"; do + case "$flag" in + --ozone-platform=* | --ozone-platform-hint=*) platform_flags=() ;; + esac + done fi -# Use native Wayland rendering in Wayland sessions. Chromium's automatic Ozone -# selection can fall back to XWayland, which produces a blurry UI on scaled -# displays. An explicit platform argument from the user always takes precedence. -if [[ "${XDG_SESSION_TYPE:-}" == wayland || -n "${WAYLAND_DISPLAY:-}" ]]; then - ozone_flags=(--ozone-platform=wayland) -fi - -# A platform selected in the flags file or on the command line overrides the -# native Wayland default. -for flag in "${user_flags[@]}" "$@"; do - case "${flag}" in - --ozone-platform=*|--ozone-platform-hint=*) ozone_flags=() ;; - esac -done - -exec /usr/lib/chatgpt/ChatGPT "${ozone_flags[@]}" "${user_flags[@]}" "$@" +exec /usr/lib/chatgpt/ChatGPT "${platform_flags[@]}" "${user_flags[@]}" "$@"