diff --git a/README.md b/README.md index 34e7614..010adba 100644 --- a/README.md +++ b/README.md @@ -322,9 +322,49 @@ recent releases are considered. The provider fails closed on anything it cannot read — an unusable tag, timestamp, or checksum stops the sync rather than being skipped. -A package may also declare `"min_release_age": "24h"` (`s`/`m`/`h`/`d` suffix or -bare seconds) to quarantine fresh releases until maintainers have had time to -pull a bad or compromised one. The newest release that has cleared the window +Projects that publish version tags but no checksum manifest can declare the +tag repository, the exact tag shape, and every source that should be hashed: + +```json +"upstream": { + "git_tags": "https://github.com/owner/project.git", + "tag_pattern": "v{pkgver}", + "sources": { + "any": ["https://github.com/owner/project/archive/refs/tags/{tag}.tar.gz"] + } +} +``` + +The newest matching tag is selected with pacman's `vercmp`; unrelated tags are +ignored. `tag_pattern` must contain exactly one `{pkgver}`. Source templates may +use `{tag}` and `{pkgver}`. Each expanded URL must be HTTPS and is downloaded +only when the discovered version is newer. A checked-in patch or other local +source can be included as `file:patch-name.patch`; it is hashed from the package +directory. Keys such as `any`, `x86_64`, and `aarch64` select the corresponding +`sha256sums` array. + +npm packages use the same source mapping, with `{npm_tarball}` available for +the tarball named by the selected dist-tag: + +```json +"upstream": { + "npm": "@scope/package", + "dist_tag": "latest", + "sources": { + "any": ["{npm_tarball}", "https://example.com/v{pkgver}/CHANGELOG.md"] + } +} +``` + +`dist_tag` defaults to `latest`. The registry's publication timestamp is +carried into the provider result, so `min_release_age` works for npm packages. +Exactly one of `github`, `git_tags`, or `npm` may appear in a declaration. + +A timestamped provider may also declare `"min_release_age": "24h"` +(`s`/`m`/`h`/`d` suffix or bare seconds) to quarantine fresh releases until +maintainers have had time to pull a bad or compromised one. GitHub Releases and +npm provide publication times; raw git tags do not, so combining `git_tags` +with this policy fails closed. The newest release that has cleared the window ships, so a fast release cadence cannot starve updates. The window is enforced centrally: whatever reports the release must prove its age via `published_at`, or the sync fails. A maintainer deliberately shipping inside the window runs diff --git a/bin/sync-upstream b/bin/sync-upstream index a0da5f3..d05d5f8 100755 --- a/bin/sync-upstream +++ b/bin/sync-upstream @@ -18,11 +18,11 @@ Usage: $0 [PACKAGE...] Update packages that track an upstream vendor release feed instead of the AUR. -A package whose upstream ships tagged GitHub releases with a checksum manifest -opts in declaratively, via "upstream" in .omarchy/package.json (see -helpers/upstream-github.sh for the schema); no code needed. Anything with a -bespoke feed provides pkgbuilds//.omarchy/upstream.sh instead, a hook -that reports the newest upstream release as JSON on stdout: +Packages opt in declaratively through "upstream" in .omarchy/package.json. +Providers cover GitHub Releases with checksum manifests, semver-shaped git +tags whose source URLs can be hashed, and npm dist-tags. See README.md for the +schemas. Anything outside those conventions may provide +pkgbuilds//.omarchy/upstream.sh, a hook that reports JSON on stdout: { "pkgver": "1.2.3", @@ -332,27 +332,27 @@ sync_package() { return 0 fi - local github_repo has_upstream=false - github_repo=$(package_upstream_github_repo "$package_dir") + local provider has_upstream=false + provider=$(package_upstream_provider "$package_dir") if package_has_upstream_provider "$package_dir"; then has_upstream=true fi # A present-but-unusable declaration fails loudly; treating it like "no # upstream source" would silently drop the package from scheduled runs. - if [[ "$has_upstream" == true && -z "$github_repo" ]]; then - print_error "Package $package has an unusable upstream declaration (needs a github owner/repo)" + if [[ "$has_upstream" == true && -z "$provider" ]]; then + print_error "Package $package has an unusable or ambiguous upstream declaration" ((++FAILED)) return 0 fi - if [[ -n "$github_repo" && -f "$hook" ]]; then - print_error "Package $package declares both upstream.github and an upstream.sh hook; keep exactly one" + if [[ -n "$provider" && -f "$hook" ]]; then + print_error "Package $package declares both an upstream provider and an upstream.sh hook; keep exactly one" ((++FAILED)) return 0 fi - if [[ -z "$github_repo" && ! -f "$hook" ]]; then + if [[ -z "$provider" && ! -f "$hook" ]]; then if [[ "$SPECIFIC_MODE" == true ]]; then print_error "Package $package has neither an upstream declaration nor .omarchy/upstream.sh" ((++FAILED)) @@ -372,10 +372,15 @@ sync_package() { print_info "Checking $package for upstream releases..." - local release - if [[ -n "$github_repo" ]]; then - if ! release=$(github_upstream_release "$package_dir" "$min_age"); then - print_error "GitHub release provider failed for $package" + local release release_status=0 + if [[ -n "$provider" ]]; then + case "$provider" in + github) release=$(github_upstream_release "$package_dir" "$min_age") || release_status=$? ;; + git_tags) release=$(git_tags_upstream_release "$package_dir") || release_status=$? ;; + npm) release=$(npm_upstream_release "$package_dir") || release_status=$? ;; + esac + if [[ ${release_status:-0} -ne 0 ]]; then + print_error "$provider upstream provider failed for $package" ((++FAILED)) return 0 fi @@ -614,10 +619,79 @@ EOF echo '{"source": "local", "upstream": {"github": "example/tool"}}' > "$agepkg/.omarchy/package.json" vst=0; validate_package_metadata "$agepkg" >/dev/null || vst=$? check "upstream without checksums/assets is rejected" "1" "$vst" + echo '{"source":"local","upstream":{"github":"example/tool","git_tags":"https://example/tool.git","checksums":"sums","assets":{"any":"tool"}}}' > "$agepkg/.omarchy/package.json" + vst=0; validate_package_metadata "$agepkg" >/dev/null || vst=$? + check "multiple provider types are rejected" "1" "$vst" cp "$pkg/.omarchy/package.json" "$agepkg/.omarchy/package.json" vst=0; validate_package_metadata "$agepkg" >/dev/null || vst=$? check "the real declaration shape is accepted" "0" "$vst" + echo "Git-tag provider:" + local tagpkg="$TEMP_DIR/selftest-tags" tag_sum remote_sum local_sum + mkdir -p "$tagpkg/.omarchy" + printf 'pkgver=1.0.0\npkgrel=4\nsha256sums=("old" "old")\n' > "$tagpkg/PKGBUILD" + printf 'local fixture\n' > "$tagpkg/local.patch" + cat > "$tagpkg/.omarchy/package.json" <<'EOF' +{ + "source": "local", + "upstream": { + "git_tags": "https://example.test/tool.git", + "tag_pattern": "release/{pkgver}", + "sources": { + "any": ["https://downloads.example.test/tool-{pkgver}.tar.gz", "file:local.patch"] + } + } +} +EOF + git_tags_fetch_refs() { + printf '%s\n' \ + 'aaaa refs/tags/release/1.9.0' \ + 'bbbb refs/tags/release/1.10.0' \ + 'cccc refs/tags/not-a-release' + } + upstream_fetch_source() { printf 'remote fixture for %s\n' "$1" > "$2"; } + tag_sum=$(git_tags_upstream_release "$tagpkg") + remote_sum=$(printf 'remote fixture for %s\n' 'https://downloads.example.test/tool-1.10.0.tar.gz' | sha256sum | cut -d' ' -f1) + local_sum=$(sha256sum "$tagpkg/local.patch" | cut -d' ' -f1) + check "pacman ordering selects 1.10.0 over 1.9.0" "1.10.0" "$(jq -r '.pkgver' <<<"$tag_sum")" + check "remote source template is downloaded and hashed" "$remote_sum" "$(jq -r '.sha256sums.any[0]' <<<"$tag_sum")" + check "local source entry is hashed" "$local_sum" "$(jq -r '.sha256sums.any[1]' <<<"$tag_sum")" + vst=0; validate_package_metadata "$tagpkg" >/dev/null || vst=$? + check "git-tags declaration validates" "0" "$vst" + + echo "npm provider:" + local npmpkg="$TEMP_DIR/selftest-npm" npm_sum npm_tar_sum npm_notes_sum + mkdir -p "$npmpkg/.omarchy" + printf 'pkgver=1.0.0\npkgrel=1\nsha256sums=("old" "old")\n' > "$npmpkg/PKGBUILD" + cat > "$npmpkg/.omarchy/package.json" <<'EOF' +{ + "source": "local", + "upstream": { + "npm": "@example/tool", + "dist_tag": "latest", + "sources": { + "any": ["{npm_tarball}", "https://example.test/tool/{pkgver}/notes"] + } + } +} +EOF + npm_fetch_metadata() { + jq -n '{ + "dist-tags": {latest: "2.0.0"}, + versions: {"2.0.0": {dist: {tarball: "https://registry.npmjs.org/@example/tool/-/tool-2.0.0.tgz"}}}, + time: {"2.0.0": "2024-01-02T03:04:05.000Z"} + }' + } + npm_sum=$(npm_upstream_release "$npmpkg") + npm_tar_sum=$(printf 'remote fixture for %s\n' 'https://registry.npmjs.org/@example/tool/-/tool-2.0.0.tgz' | sha256sum | cut -d' ' -f1) + npm_notes_sum=$(printf 'remote fixture for %s\n' 'https://example.test/tool/2.0.0/notes' | sha256sum | cut -d' ' -f1) + check "npm dist-tag selects its version" "2.0.0" "$(jq -r '.pkgver' <<<"$npm_sum")" + check "npm tarball placeholder is hashed" "$npm_tar_sum" "$(jq -r '.sha256sums.any[0]' <<<"$npm_sum")" + check "npm pkgver template is hashed" "$npm_notes_sum" "$(jq -r '.sha256sums.any[1]' <<<"$npm_sum")" + check "npm publication time is preserved" "2024-01-02T03:04:05.000Z" "$(jq -r '.published_at' <<<"$npm_sum")" + vst=0; validate_package_metadata "$npmpkg" >/dev/null || vst=$? + check "npm declaration validates" "0" "$vst" + # End to end over the real mise-bin package: its checked-in metadata and # PKGBUILD, the full sync_package path (selection, validation, backstop, # rewrite, read-back verification), with only the two network fetches diff --git a/helpers/package-metadata.sh b/helpers/package-metadata.sh index c121b46..b14c3da 100644 --- a/helpers/package-metadata.sh +++ b/helpers/package-metadata.sh @@ -16,6 +16,8 @@ # { "source": "local", "channels": ["edge", "rc", "stable"] } # { "source": "local", "min_release_age": "24h" } # { "source": "local", "upstream": { "github": "owner/repo", "checksums": "SHASUMS256.txt", "assets": { "x86_64": "name-{tag}-x64.tar.xz" } } } +# { "source": "local", "upstream": { "git_tags": "https://example/repo.git", "tag_pattern": "v{pkgver}", "sources": { "any": ["https://example/archive/{tag}.tar.gz"] } } } +# { "source": "local", "upstream": { "npm": "@scope/package", "sources": { "any": ["{npm_tarball}"] } } } # # bin/sync-aur also writes upstream_commit for AUR-backed packages, and # bin/sync-rebuilds writes rebuilt_against for packages declaring rebuild_on. @@ -446,17 +448,33 @@ validate_package_metadata() { # `has` rather than `// {}`: jq's // treats false as absent, which would # let "upstream": false slip through as an empty declaration. if ! jq -e ' + def valid_sources: + type == "object" and length > 0 and (to_entries | all( + (.key | test("\\A[a-z0-9_]+\\z")) + and (.value | type == "array" and length > 0 and all(type == "string" and length > 0)) + )); if has("upstream") | not then true elif (.upstream | type) != "object" then false else .upstream | - ((.github // "") | type == "string" and test("\\A[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+\\z")) - and ((.checksums // "") | type == "string" and length > 0) - and ((.assets // {}) | type == "object" and length > 0 and (to_entries | all( - (.key | test("\\A[a-z0-9_]+\\z")) and (.value | type == "string" and length > 0) - ))) + ([has("github"), has("git_tags"), has("npm")] | map(select(.)) | length) == 1 + and if has("github") then + (.github | type == "string" and test("\\A[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+\\z")) + and (.checksums | type == "string" and length > 0) + and (.assets | type == "object" and length > 0 and (to_entries | all( + (.key | test("\\A[a-z0-9_]+\\z")) and (.value | type == "string" and length > 0) + ))) + elif has("git_tags") then + (.git_tags | type == "string" and test("\\Ahttps://[^[:space:]]+\\.git\\z")) + and (.tag_pattern | type == "string" and (split("{pkgver}") | length) == 2) + and (.sources | valid_sources) + else + (.npm | type == "string" and test("\\A(@[a-z0-9_.-]+/)?[a-z0-9_.-]+\\z")) + and ((.dist_tag // "latest") | type == "string" and test("\\A[a-z0-9_.-]+\\z")) + and (.sources | valid_sources) + end end ' "$metadata" >/dev/null; then - echo "invalid upstream for $(basename "$pkgdir"): needs github owner/repo, checksums asset name, and an assets arch->name map" + echo "invalid upstream for $(basename "$pkgdir"): configure exactly one valid github, git_tags, or npm provider" return 1 fi diff --git a/helpers/upstream-github.sh b/helpers/upstream-github.sh index e37e6ab..14b1446 100644 --- a/helpers/upstream-github.sh +++ b/helpers/upstream-github.sh @@ -1,4 +1,4 @@ -# GitHub-releases upstream provider for bin/sync-upstream. +# Declarative upstream providers for bin/sync-upstream. # # A package whose upstream ships tagged GitHub releases with a checksum # manifest asset needs no upstream.sh hook: the whole feed is data, declared @@ -17,13 +17,20 @@ # "v", which is stripped for pkgver. Drafts and prereleases are ignored. The # provider emits the same JSON contract as an upstream.sh hook, so # bin/sync-upstream's validation and min_release_age backstop apply -# unchanged; a feed that fits no convention keeps a bespoke upstream.sh. +# unchanged. Git-tag and npm providers below cover projects without a release +# checksum manifest; a feed that fits no convention keeps a bespoke hook. -package_upstream_github_repo() { - local pkgdir="$1" - # `objects` drops a non-object upstream value (validation rejects those - # separately) instead of erroring the jq pipeline. - package_metadata_value "$pkgdir" '(.upstream? | objects | .github)' "" +# Return the single declarative provider selected by a package. An empty +# result means either no provider or an invalid/ambiguous declaration; the +# caller distinguishes those through package_has_upstream_provider(). +package_upstream_provider() { + local pkgdir="$1" metadata + metadata=$(metadata_file_for_dir "$pkgdir") + jq -r ' + (.upstream? | objects) as $u + | [$u | keys[] | select(. == "github" or . == "git_tags" or . == "npm")] + | if length == 1 then .[0] else "" end + ' "$metadata" } # Fetches sit behind functions so the self-test can replace them with fixture @@ -43,6 +50,151 @@ github_fetch_checksums() { curl -fsSL "https://github.com/$repo/releases/download/$tag/$asset" } +git_tags_fetch_refs() { + local repo="$1" + git ls-remote --tags "$repo" +} + +npm_fetch_metadata() { + local package="$1" encoded + encoded=$(jq -rn --arg package "$package" '$package | @uri') + curl -fsSL "https://registry.npmjs.org/$encoded" +} + +upstream_fetch_source() { + local url="$1" output="$2" + curl --proto '=https' --proto-redir '=https' -fsSL -o "$output" "$url" +} + +# Hash every URL template in upstream.sources and emit hook-contract JSON. +# Templates may use {pkgver}, {tag}, and (for npm) {npm_tarball}. Downloads +# happen only after discovery reports a version newer than the PKGBUILD. +upstream_hash_sources() { + local package_dir="$1" pkgver="$2" tag="${3:-}" npm_tarball="${4:-}" + local metadata sources work result arch template url file sum sums index=0 + metadata=$(metadata_file_for_dir "$package_dir") + sources=$(jq -c '.upstream.sources' "$metadata") + work=$(mktemp -d) + result=$(jq -n --arg pkgver "$pkgver" '{pkgver: $pkgver, sha256sums: {}}') + + while IFS= read -r arch; do + sums='[]' + while IFS= read -r template; do + if [[ "$template" == file:* ]]; then + file=${template#file:} + if [[ ! "$file" =~ ^[A-Za-z0-9._+-]+$ || ! -f "$package_dir/$file" ]]; then + echo "upstream source names an unsafe or missing local file: '$file'" >&2 + rm -rf "$work" + return 1 + fi + sum=$(sha256sum "$package_dir/$file" | cut -d' ' -f1) + sums=$(jq -c --arg sum "$sum" '. + [$sum]' <<<"$sums") + continue + fi + url=${template//\{pkgver\}/$pkgver} + url=${url//\{tag\}/$tag} + url=${url//\{npm_tarball\}/$npm_tarball} + if [[ ! "$url" =~ ^https://[^[:space:]{}]+$ ]]; then + echo "upstream source template produced an unsafe URL: '$url'" >&2 + rm -rf "$work" + return 1 + fi + file="$work/source-$((index += 1))" + if ! upstream_fetch_source "$url" "$file"; then + echo "could not fetch upstream source: $url" >&2 + rm -rf "$work" + return 1 + fi + sum=$(sha256sum "$file" | cut -d' ' -f1) + sums=$(jq -c --arg sum "$sum" '. + [$sum]' <<<"$sums") + done < <(jq -r --arg arch "$arch" '.[$arch][]' <<<"$sources") + result=$(jq -c --arg arch "$arch" --argjson sums "$sums" '.sha256sums[$arch] = $sums' <<<"$result") + done < <(jq -r 'keys[]' <<<"$sources") + + rm -rf "$work" + printf '%s\n' "$result" +} + +git_tags_upstream_release() { + local package_dir="$1" metadata repo pattern prefix suffix refs + metadata=$(metadata_file_for_dir "$package_dir") + repo=$(jq -r '.upstream.git_tags // ""' "$metadata") + pattern=$(jq -r '.upstream.tag_pattern // ""' "$metadata") + prefix=${pattern%%\{pkgver\}*} + suffix=${pattern#*\{pkgver\}} + + if [[ ! "$repo" =~ ^https://[^[:space:]]+\.git$ || "$pattern" != *'{pkgver}'* || "$suffix" == *'{pkgver}'* ]]; then + echo "invalid git_tags provider configuration" >&2 + return 1 + fi + if ! refs=$(git_tags_fetch_refs "$repo"); then + echo "could not fetch tags from $repo" >&2 + return 1 + fi + + local best_pkgver="" best_tag="" tag candidate + declare -A version_tags=() + while read -r tag; do + tag=${tag%\^\{\}} + [[ "$tag" == "$prefix"*"$suffix" ]] || continue + candidate=${tag#"$prefix"} + [[ -z "$suffix" ]] || candidate=${candidate%"$suffix"} + [[ "$candidate" =~ ^[A-Za-z0-9][A-Za-z0-9._+]*$ ]] || continue + if [[ -n "${version_tags[$candidate]:-}" && "${version_tags[$candidate]}" != "$tag" ]]; then + echo "multiple tags map to pkgver $candidate: ${version_tags[$candidate]} and $tag" >&2 + return 1 + fi + version_tags[$candidate]="$tag" + if [[ -z "$best_pkgver" || $(vercmp "$candidate" "$best_pkgver") -gt 0 ]]; then + best_pkgver="$candidate" + best_tag="$tag" + fi + done < <(sed -n 's#^.*refs/tags/##p' <<<"$refs") + + [[ -n "$best_pkgver" ]] || { echo "no usable tags found at $repo" >&2; return 1; } + local current_pkgver + current_pkgver=$(grep -m1 '^pkgver=' "$package_dir/PKGBUILD" | cut -d= -f2- | tr -d "\"'") + if [[ $(vercmp "$best_pkgver" "$current_pkgver") -le 0 ]]; then + echo '{}' + return 0 + fi + upstream_hash_sources "$package_dir" "$best_pkgver" "$best_tag" +} + +npm_upstream_release() { + local package_dir="$1" metadata package dist_tag npm_metadata pkgver tarball published_at release + metadata=$(metadata_file_for_dir "$package_dir") + package=$(jq -r '.upstream.npm // ""' "$metadata") + dist_tag=$(jq -r '.upstream.dist_tag // "latest"' "$metadata") + if [[ ! "$package" =~ ^(@[a-z0-9_.-]+/)?[a-z0-9_.-]+$ || ! "$dist_tag" =~ ^[a-z0-9_.-]+$ ]]; then + echo "invalid npm provider configuration" >&2 + return 1 + fi + if ! npm_metadata=$(npm_fetch_metadata "$package"); then + echo "could not fetch npm metadata for $package" >&2 + return 1 + fi + pkgver=$(jq -r --arg tag "$dist_tag" '."dist-tags"[$tag] // ""' <<<"$npm_metadata") + tarball=$(jq -r --arg version "$pkgver" '.versions[$version].dist.tarball // ""' <<<"$npm_metadata") + published_at=$(jq -r --arg version "$pkgver" '.time[$version] // ""' <<<"$npm_metadata") + if [[ ! "$pkgver" =~ ^[A-Za-z0-9][A-Za-z0-9._+]*$ || ! "$tarball" =~ ^https://registry\.npmjs\.org/ ]]; then + echo "npm returned an unusable $package release" >&2 + return 1 + fi + + local current_pkgver + current_pkgver=$(grep -m1 '^pkgver=' "$package_dir/PKGBUILD" | cut -d= -f2- | tr -d "\"'") + if [[ $(vercmp "$pkgver" "$current_pkgver") -le 0 ]]; then + echo '{}' + return 0 + fi + release=$(upstream_hash_sources "$package_dir" "$pkgver" "$pkgver" "$tarball") || return 1 + if [[ -n "$published_at" ]]; then + release=$(jq -c --arg published_at "$published_at" '.published_at = $published_at' <<<"$release") + fi + printf '%s\n' "$release" +} + # Emits the newest qualifying release as hook-contract JSON. min_release_age # is honored during selection (newest release older than the window wins, # even when a younger one exists) and BYPASS_MIN_RELEASE_AGE=1 lifts it. diff --git a/pkgbuilds/github-copilot-cli/.omarchy/package.json b/pkgbuilds/github-copilot-cli/.omarchy/package.json index db153c3..29481cf 100644 --- a/pkgbuilds/github-copilot-cli/.omarchy/package.json +++ b/pkgbuilds/github-copilot-cli/.omarchy/package.json @@ -1,4 +1,13 @@ { "source": "local", - "release_ring": "fast" + "release_ring": "fast", + "upstream": { + "npm": "@github/copilot", + "sources": { + "any": [ + "{npm_tarball}", + "https://raw.githubusercontent.com/github/copilot-cli/v{pkgver}/changelog.md" + ] + } + } } diff --git a/pkgbuilds/github-copilot-cli/.omarchy/upstream.sh b/pkgbuilds/github-copilot-cli/.omarchy/upstream.sh deleted file mode 100755 index 92db1d2..0000000 --- a/pkgbuilds/github-copilot-cli/.omarchy/upstream.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash -# GitHub Copilot CLI is published to npm. Track npm's stable `latest` tag, -# then hash both inputs the PKGBUILD downloads. AUR is deliberately not part -# of this update path: Omarchy owns the multi-architecture recipe. -set -euo pipefail - -REGISTRY_URL="https://registry.npmjs.org/@github%2Fcopilot" -CHANGELOG_BASE="https://raw.githubusercontent.com/github/copilot-cli" - -metadata=$(curl -fsSL "$REGISTRY_URL") -version=$(jq -r '."dist-tags".latest // ""' <<<"$metadata") -tarball=$(jq -r --arg version "$version" '.versions[$version].dist.tarball // ""' <<<"$metadata") - -if [[ ! $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ || ! $tarball =~ ^https://registry\.npmjs\.org/ ]]; then - echo "npm returned an unusable Copilot release: version='$version' tarball='$tarball'" >&2 - exit 1 -fi - -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$version" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -work=$(mktemp -d) -trap 'rm -rf "$work"' EXIT -curl -fsSL -o "$work/copilot.tgz" "$tarball" -curl -fsSL -o "$work/changelog.md" "$CHANGELOG_BASE/v${version}/changelog.md" - -jq -n \ - --arg pkgver "$version" \ - --arg package_sum "$(sha256sum "$work/copilot.tgz" | cut -d' ' -f1)" \ - --arg changelog_sum "$(sha256sum "$work/changelog.md" | cut -d' ' -f1)" \ - '{pkgver: $pkgver, sha256sums: {any: [$package_sum, $changelog_sum]}}' diff --git a/pkgbuilds/qmk-hid/.omarchy/package.json b/pkgbuilds/qmk-hid/.omarchy/package.json index 2a9719d..aa2fb82 100644 --- a/pkgbuilds/qmk-hid/.omarchy/package.json +++ b/pkgbuilds/qmk-hid/.omarchy/package.json @@ -1,3 +1,10 @@ { - "source": "local" + "source": "local", + "upstream": { + "git_tags": "https://github.com/FrameworkComputer/qmk_hid.git", + "tag_pattern": "v{pkgver}", + "sources": { + "any": ["https://github.com/FrameworkComputer/qmk_hid/archive/refs/tags/{tag}.tar.gz"] + } + } } diff --git a/pkgbuilds/qmk-hid/.omarchy/upstream.sh b/pkgbuilds/qmk-hid/.omarchy/upstream.sh deleted file mode 100755 index 3cb0167..0000000 --- a/pkgbuilds/qmk-hid/.omarchy/upstream.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -# qmk_hid marks every GitHub Release as a prerelease, including the versions -# it considers current. Track its semver tags instead and hash the tagged -# source archive only when a newer version appears. -set -euo pipefail - -REPO="https://github.com/FrameworkComputer/qmk_hid.git" -best="" -while read -r tag; do - tag=${tag%\^\{\}} - [[ $tag =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]] || continue - version=${BASH_REMATCH[1]} - if [[ -z $best || $(vercmp "$version" "$best") -gt 0 ]]; then - best=$version - fi -done < <(git ls-remote --tags "$REPO" | sed 's#^.*refs/tags/##') - -[[ -n $best ]] || { echo "No usable qmk_hid version tag found" >&2; exit 1; } -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$best" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -sum=$(curl -fsSL "https://github.com/FrameworkComputer/qmk_hid/archive/refs/tags/v${best}.tar.gz" | sha256sum | cut -d' ' -f1) -jq -n --arg pkgver "$best" --arg sha256 "$sum" \ - '{pkgver: $pkgver, sha256sums: {any: [$sha256]}}' diff --git a/pkgbuilds/symfony-cli/.omarchy/package.json b/pkgbuilds/symfony-cli/.omarchy/package.json index db153c3..b9e2950 100644 --- a/pkgbuilds/symfony-cli/.omarchy/package.json +++ b/pkgbuilds/symfony-cli/.omarchy/package.json @@ -1,4 +1,11 @@ { "source": "local", - "release_ring": "fast" + "release_ring": "fast", + "upstream": { + "github": "symfony-cli/symfony-cli", + "checksums": "checksums.txt", + "assets": { + "any": "symfony-cli-{pkgver}.tar.gz" + } + } } diff --git a/pkgbuilds/symfony-cli/.omarchy/upstream.sh b/pkgbuilds/symfony-cli/.omarchy/upstream.sh deleted file mode 100755 index c68049a..0000000 --- a/pkgbuilds/symfony-cli/.omarchy/upstream.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -# Symfony publishes a checksum manifest with every stable GitHub release. -# The `latest` URL is its vendor-maintained stable feed, so no GitHub API or -# AUR state is involved in selecting and verifying the source tarball. -set -euo pipefail - -CHECKSUMS_URL="https://github.com/symfony-cli/symfony-cli/releases/latest/download/checksums.txt" -checksums=$(curl -fsSL "$CHECKSUMS_URL") - -best="" -best_sum="" -while read -r sum filename; do - [[ $filename =~ ^symfony-cli-([0-9]+\.[0-9]+\.[0-9]+)\.tar\.gz$ ]] || continue - version=${BASH_REMATCH[1]} - [[ $sum =~ ^[0-9a-f]{64}$ ]] || continue - if [[ -z $best || $(vercmp "$version" "$best") -gt 0 ]]; then - best=$version - best_sum=$sum - fi -done <<<"$checksums" - -[[ -n $best ]] || { echo "Symfony's latest checksum manifest names no source tarball" >&2; exit 1; } -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$best" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -jq -n --arg pkgver "$best" --arg sha256 "$best_sum" \ - '{pkgver: $pkgver, sha256sums: {any: [$sha256]}}' diff --git a/pkgbuilds/tensaku/.omarchy/package.json b/pkgbuilds/tensaku/.omarchy/package.json index 2a9719d..eb35b0b 100644 --- a/pkgbuilds/tensaku/.omarchy/package.json +++ b/pkgbuilds/tensaku/.omarchy/package.json @@ -1,3 +1,10 @@ { - "source": "local" + "source": "local", + "upstream": { + "git_tags": "https://github.com/jondkinney/tensaku.git", + "tag_pattern": "v{pkgver}", + "sources": { + "any": ["https://github.com/jondkinney/tensaku/archive/refs/tags/{tag}.tar.gz"] + } + } } diff --git a/pkgbuilds/tensaku/.omarchy/upstream.sh b/pkgbuilds/tensaku/.omarchy/upstream.sh deleted file mode 100755 index cf5d9be..0000000 --- a/pkgbuilds/tensaku/.omarchy/upstream.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# Tensaku publishes semver tags but no source checksum manifest. Select the -# newest tag using pacman's ordering and hash its source archive. -set -euo pipefail - -REPO="https://github.com/jondkinney/tensaku.git" -version="" -while read -r tag; do - tag=${tag%\^\{\}} - [[ $tag =~ ^v([0-9]+\.[0-9]+\.[0-9]+)$ ]] || continue - candidate=${BASH_REMATCH[1]} - if [[ -z $version || $(vercmp "$candidate" "$version") -gt 0 ]]; then - version=$candidate - fi -done < <(git ls-remote --tags "$REPO" | sed 's#^.*refs/tags/##') - -[[ -n $version ]] || { echo "No usable Tensaku version tag found" >&2; exit 1; } -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$version" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -sum=$(curl -fsSL "https://github.com/jondkinney/tensaku/archive/refs/tags/v${version}.tar.gz" | sha256sum | cut -d' ' -f1) -jq -n --arg pkgver "$version" --arg sha256 "$sum" \ - '{pkgver: $pkgver, sha256sums: {any: [$sha256]}}' diff --git a/pkgbuilds/tzupdate/.omarchy/package.json b/pkgbuilds/tzupdate/.omarchy/package.json index 2a9719d..31bfd10 100644 --- a/pkgbuilds/tzupdate/.omarchy/package.json +++ b/pkgbuilds/tzupdate/.omarchy/package.json @@ -1,3 +1,10 @@ { - "source": "local" + "source": "local", + "upstream": { + "git_tags": "https://github.com/cdown/tzupdate.git", + "tag_pattern": "{pkgver}", + "sources": { + "any": ["https://github.com/cdown/tzupdate/archive/refs/tags/{tag}.tar.gz"] + } + } } diff --git a/pkgbuilds/tzupdate/.omarchy/upstream.sh b/pkgbuilds/tzupdate/.omarchy/upstream.sh deleted file mode 100755 index 3ccaf44..0000000 --- a/pkgbuilds/tzupdate/.omarchy/upstream.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# tzupdate publishes version tags but no GitHub Releases. Track its semver -# tags and hash the tagged source archive when a new version appears. -set -euo pipefail - -REPO="https://github.com/cdown/tzupdate.git" -best="" -while read -r tag; do - tag=${tag%\^\{\}} - [[ $tag =~ ^v?([0-9]+\.[0-9]+\.[0-9]+)$ ]] || continue - version=${BASH_REMATCH[1]} - if [[ -z $best || $(vercmp "$version" "$best") -gt 0 ]]; then - best=$version - fi -done < <(git ls-remote --tags "$REPO" | sed 's#^.*refs/tags/##') - -[[ -n $best ]] || { echo "No usable tzupdate version tag found" >&2; exit 1; } -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$best" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -sum=$(curl -fsSL "https://github.com/cdown/tzupdate/archive/refs/tags/${best}.tar.gz" | sha256sum | cut -d' ' -f1) -jq -n --arg pkgver "$best" --arg sha256 "$sum" \ - '{pkgver: $pkgver, sha256sums: {any: [$sha256]}}' diff --git a/pkgbuilds/v4l2-relayd/.omarchy/package.json b/pkgbuilds/v4l2-relayd/.omarchy/package.json index 2a9719d..daea885 100644 --- a/pkgbuilds/v4l2-relayd/.omarchy/package.json +++ b/pkgbuilds/v4l2-relayd/.omarchy/package.json @@ -1,3 +1,14 @@ { - "source": "local" + "source": "local", + "upstream": { + "git_tags": "https://gitlab.com/vicamo/v4l2-relayd.git", + "tag_pattern": "upstream/{pkgver}", + "sources": { + "any": [ + "https://gitlab.com/vicamo/v4l2-relayd/-/archive/upstream/{pkgver}/v4l2-relayd-upstream-{pkgver}.tar.gz", + "file:0001-reset-output-on-idle.patch", + "file:0002-escape-optional-splashsrc-expansion.patch" + ] + } + } } diff --git a/pkgbuilds/v4l2-relayd/.omarchy/upstream.sh b/pkgbuilds/v4l2-relayd/.omarchy/upstream.sh deleted file mode 100755 index 4899ac2..0000000 --- a/pkgbuilds/v4l2-relayd/.omarchy/upstream.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/bin/bash -# v4l2-relayd uses GitLab tags named upstream/. Keep Omarchy's local -# patches and follow that authoritative tag stream directly. -set -euo pipefail - -REPO="https://gitlab.com/vicamo/v4l2-relayd.git" -best="" -while read -r tag; do - tag=${tag%\^\{\}} - [[ $tag =~ ^upstream/([0-9]+\.[0-9]+\.[0-9]+)$ ]] || continue - version=${BASH_REMATCH[1]} - if [[ -z $best || $(vercmp "$version" "$best") -gt 0 ]]; then - best=$version - fi -done < <(git ls-remote --tags "$REPO" | sed 's#^.*refs/tags/##') - -[[ -n $best ]] || { echo "No usable v4l2-relayd upstream tag found" >&2; exit 1; } -current=$(grep -m1 '^pkgver=' PKGBUILD | cut -d= -f2- | tr -d "\"'") -if [[ $(vercmp "$best" "$current") -le 0 ]]; then - echo '{}' - exit 0 -fi - -sum=$(curl -fsSL "https://gitlab.com/vicamo/v4l2-relayd/-/archive/upstream/${best}/v4l2-relayd-upstream-${best}.tar.gz" | sha256sum | cut -d' ' -f1) -jq -n --arg pkgver "$best" --arg sha256 "$sum" \ - '{pkgver: $pkgver, sha256sums: {any: [$sha256, "SKIP", "SKIP"]}}' diff --git a/pkgbuilds/v4l2-relayd/PKGBUILD b/pkgbuilds/v4l2-relayd/PKGBUILD index f4784e4..fbe9bbb 100644 --- a/pkgbuilds/v4l2-relayd/PKGBUILD +++ b/pkgbuilds/v4l2-relayd/PKGBUILD @@ -19,8 +19,8 @@ source=("https://gitlab.com/vicamo/v4l2-relayd/-/archive/upstream/${pkgver}/v4l2 "0001-reset-output-on-idle.patch" "0002-escape-optional-splashsrc-expansion.patch") sha256sums=('0c063edf18dcc6edcdef46e695128cfc2b2d60964ea8538c7e79a2454310c53d' - 'SKIP' - 'SKIP') + '07722a8708ced48d2db9575f3eae5b1266868d259d260635e06e9a10baddec78' + '3cb89056af276eed7a45dfc96435e8e48558e4e11c96560360d46d631b1c0b6c') prepare() { cd "$srcdir/${pkgname}-upstream-${pkgver}"