mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-07-30 19:46:17 +00:00
Mirrors the Homebrew cask change. The old design stored a classic `public_repo` PAT as WINGET_TOKEN and handed it to the third-party vedantmgoyal9/winget-releaser action: a token with write access to every public repo the owning account can reach, given to code we do not control, in a place any push-access collaborator could read it from (a pushed branch containing a workflow runs with repo secrets). - CI (bump-winget.yml, now "Sync Winget Manifest Reference") uses GITHUB_TOKEN only: downloads the MSI, computes the sha256, reads the ProductCode from the MSI Property table via msitools, and opens an in-repo PR syncing desktopApp/packaging/winget/. Runs on ubuntu (1x billing) rather than Windows since msitools reads the Property table fine. - scripts/bump-winget.sh does the upstream PR. It needs NO new token: it drives `gh`, which a maintainer already has authenticated, and it does not need wingetcreate (Windows-only) because the manifests are plain YAML — so it runs from macOS or Linux. Add the three reference manifests under desktopApp/packaging/winget/, matching the schema 1.12.0 shape used upstream. All three validate against Microsoft's published JSON schemas. Validation caught one real bug worth noting: an all-digit 64-char InstallerSha256 parses as a YAML *integer* and fails the schema's `string` type, so it is written quoted. ProductCode is re-read every release because jpackage regenerates it per build; it is the ARP key `winget upgrade` matches on. Drops the last package-manager PAT from the secret inventory.
160 lines
6.2 KiB
Bash
Executable File
160 lines
6.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Push the VitorPamplona.Amethyst manifests upstream to microsoft/winget-pkgs.
|
|
#
|
|
# Like scripts/bump-homebrew-cask.sh, this is deliberately not automated: it
|
|
# needs push access to a fork of winget-pkgs, and the previous design kept that
|
|
# as a classic `public_repo` PAT in the WINGET_TOKEN Actions secret, handed to a
|
|
# third-party action. That scope grants write to every public repo the account
|
|
# can reach, and any Actions secret is usable by anyone with push access to this
|
|
# repo. See BUILDING.md § Winget.
|
|
#
|
|
# Unlike the Homebrew script this needs NO new token: it drives `gh`, which you
|
|
# are already authenticated with. It also does not need `wingetcreate` (which is
|
|
# Windows-only) — winget manifests are plain YAML, so this works from macOS or
|
|
# Linux.
|
|
#
|
|
# Everything error-prone (version, sha256, ProductCode) is already done in CI by
|
|
# .github/workflows/bump-winget.yml, which opens a PR syncing
|
|
# desktopApp/packaging/winget/. Merge that PR first; this script reads the merged
|
|
# values so the two can never disagree.
|
|
#
|
|
# Usage:
|
|
# scripts/bump-winget.sh # uses the manifests as-is
|
|
# scripts/bump-winget.sh v1.13.2 # asserts the manifests match this tag
|
|
# DRY_RUN=1 scripts/bump-winget.sh # print what would happen, do nothing
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
SRC="$REPO_ROOT/desktopApp/packaging/winget"
|
|
PKG_ID="VitorPamplona.Amethyst"
|
|
UPSTREAM="microsoft/winget-pkgs"
|
|
EXPECTED_TAG="${1:-}"
|
|
DRY_RUN="${DRY_RUN:-}"
|
|
|
|
die() { echo "error: $*" >&2; exit 1; }
|
|
|
|
command -v gh >/dev/null || die "gh not found — https://cli.github.com"
|
|
gh auth status >/dev/null 2>&1 || die "gh is not authenticated; run: gh auth login"
|
|
[[ -d "$SRC" ]] || die "manifests not found at $SRC"
|
|
|
|
VERSION=$(awk '/^PackageVersion: /{print $2; exit}' "$SRC/$PKG_ID.yaml")
|
|
[[ -n "$VERSION" ]] || die "could not parse PackageVersion out of $SRC/$PKG_ID.yaml"
|
|
|
|
if [[ -n "$EXPECTED_TAG" && "v$VERSION" != "$EXPECTED_TAG" ]]; then
|
|
die "manifests are at v$VERSION but you asked for $EXPECTED_TAG.
|
|
Merge the 'chore: sync winget manifests to $EXPECTED_TAG' PR first, then pull."
|
|
fi
|
|
|
|
# InstallerSha256 and ProductCode are single-quoted in the YAML (see the
|
|
# comments there); strip the quotes when reading them back.
|
|
SHA=$(awk '/^ InstallerSha256: /{print $2; exit}' "$SRC/$PKG_ID.installer.yaml" | tr -d "'")
|
|
URL=$(awk '/^ InstallerUrl: /{print $2; exit}' "$SRC/$PKG_ID.installer.yaml")
|
|
PC=$(awk '/^ ProductCode: /{print $2; exit}' "$SRC/$PKG_ID.installer.yaml" | tr -d "'")
|
|
|
|
[[ "$SHA" =~ ^0+$ ]] && die "InstallerSha256 is still the placeholder.
|
|
Run the sync workflow first: gh workflow run bump-winget.yml -f tag=v$VERSION"
|
|
|
|
echo "package : $PKG_ID"
|
|
echo "version : $VERSION"
|
|
echo "sha256 : $SHA"
|
|
echo "product : $PC"
|
|
echo "url : $URL"
|
|
echo
|
|
|
|
# Re-verify against the live asset. CI already did, but the whole point of a
|
|
# manual gate is that a human confirms what is about to be published.
|
|
echo "==> verifying the release MSI"
|
|
TMP=$(mktemp -d)
|
|
trap 'rm -rf "$TMP"' EXIT
|
|
curl -fsSL -o "$TMP/amethyst.msi" "$URL" || die "could not download $URL"
|
|
|
|
if command -v sha256sum >/dev/null; then
|
|
ACTUAL=$(sha256sum "$TMP/amethyst.msi" | awk '{print $1}')
|
|
else
|
|
ACTUAL=$(shasum -a 256 "$TMP/amethyst.msi" | awk '{print $1}')
|
|
fi
|
|
ACTUAL=$(echo "$ACTUAL" | tr '[:lower:]' '[:upper:]')
|
|
[[ "$ACTUAL" == "$SHA" ]] || die "sha256 mismatch!
|
|
manifest says : $SHA
|
|
actual : $ACTUAL"
|
|
echo " sha256 matches"
|
|
echo
|
|
|
|
DEST="manifests/v/VitorPamplona/Amethyst/$VERSION"
|
|
BRANCH="$PKG_ID-$VERSION"
|
|
|
|
if [[ -n "$DRY_RUN" ]]; then
|
|
echo "DRY_RUN set — would now:"
|
|
echo " fork $UPSTREAM (if needed), branch $BRANCH"
|
|
echo " add $DEST/{$PKG_ID.yaml,$PKG_ID.installer.yaml,$PKG_ID.locale.en-US.yaml}"
|
|
echo " open a PR against $UPSTREAM"
|
|
exit 0
|
|
fi
|
|
|
|
# A new package needs a human-reviewed first submission; after that this script
|
|
# handles every version bump.
|
|
if ! gh api "repos/$UPSTREAM/contents/manifests/v/VitorPamplona/Amethyst" >/dev/null 2>&1; then
|
|
echo "note: $PKG_ID is not in $UPSTREAM yet — this will be the NEW-PACKAGE submission."
|
|
echo " Expect a slower, human-reviewed first pass."
|
|
echo
|
|
fi
|
|
|
|
WORK="$TMP/winget-pkgs"
|
|
echo "==> preparing the fork"
|
|
gh repo fork "$UPSTREAM" --clone=false --remote=false >/dev/null 2>&1 || true
|
|
FORK="$(gh api user --jq .login)/winget-pkgs"
|
|
|
|
# Shallow clone of the fork only — winget-pkgs full history is enormous.
|
|
gh repo clone "$FORK" "$WORK" -- --depth=1 >/dev/null 2>&1 \
|
|
|| die "could not clone $FORK"
|
|
|
|
cd "$WORK"
|
|
git remote add upstream "https://github.com/$UPSTREAM.git" 2>/dev/null || true
|
|
git fetch --depth=1 upstream master >/dev/null 2>&1 || git fetch --depth=1 upstream main >/dev/null 2>&1
|
|
DEFAULT_BRANCH=$(gh api "repos/$UPSTREAM" --jq .default_branch)
|
|
git checkout -B "$BRANCH" "upstream/$DEFAULT_BRANCH" >/dev/null 2>&1
|
|
|
|
mkdir -p "$DEST"
|
|
cp "$SRC/$PKG_ID.yaml" "$SRC/$PKG_ID.installer.yaml" "$SRC/$PKG_ID.locale.en-US.yaml" "$DEST/"
|
|
|
|
# The reference copies carry an Amethyst-repo header comment; upstream manifests
|
|
# should not. Strip leading comment lines, keep the yaml-language-server line.
|
|
for f in "$DEST"/*.yaml; do
|
|
python3 - "$f" <<'PY'
|
|
import sys
|
|
p = sys.argv[1]
|
|
lines = open(p).read().splitlines(keepends=True)
|
|
out, started = [], False
|
|
for ln in lines:
|
|
if not started and ln.startswith('#') and 'yaml-language-server' not in ln:
|
|
continue
|
|
started = True
|
|
out.append(ln)
|
|
open(p, 'w').writelines(out)
|
|
PY
|
|
done
|
|
|
|
git add "$DEST"
|
|
git -c user.name="$(gh api user --jq '.name // .login')" \
|
|
-c user.email="$(gh api user --jq .id)+$(gh api user --jq .login)@users.noreply.github.com" \
|
|
commit -q -m "$PKG_ID version $VERSION"
|
|
git push -q -u origin "$BRANCH" --force
|
|
|
|
echo "==> opening the PR"
|
|
gh pr create --repo "$UPSTREAM" \
|
|
--base "$DEFAULT_BRANCH" \
|
|
--head "$(gh api user --jq .login):$BRANCH" \
|
|
--title "$PKG_ID version $VERSION" \
|
|
--body "Automated manifest sync for [Amethyst](https://github.com/vitorpamplona/amethyst) $VERSION.
|
|
|
|
- Installer: \`amethyst-desktop-$VERSION-windows-x64.msi\` from the official GitHub release
|
|
- SHA256 verified against the published asset
|
|
- ProductCode read from the MSI Property table
|
|
|
|
Manifests are generated from \`desktopApp/packaging/winget/\` in the upstream repo."
|
|
|
|
echo
|
|
echo "Done. Watch the PR at https://github.com/$UPSTREAM/pulls"
|