ajhahn.de
← eeco
Shell 89 lines
#!/bin/sh
# Pushes the generated package-manager manifests into their tap repos so
# `brew install ajhahnde/eeco/eeco` and `scoop install eeco` resolve to
# the current release:
#   dist/eeco.rb   -> ajhahnde/homebrew-eeco : Formula/eeco.rb
#   dist/eeco.json -> ajhahnde/scoop-eeco    : bucket/eeco.json
#
# Run after `make packaging` (which writes the manifests offline from
# dist/SHA256SUMS). This script does the one network step the release
# needs that gen-packaging.sh deliberately omits: the upsert into the
# external tap repos, via the GitHub Contents API (`gh api`). No clone.
#
# Auth: the workflow's GITHUB_TOKEN cannot push to other repos, so a PAT
# with `contents:write` on both tap repos is required in TAP_PUSH_TOKEN.
#
# Inputs (env, with defaults):
#   VERSION         release tag (e.g. v2.0.0); default: git describe
#   TAP_PUSH_TOKEN  PAT with push to the tap repos (required unless --dry-run)
#   BREW_TAP_REPO   default ajhahnde/homebrew-eeco
#   SCOOP_TAP_REPO  default ajhahnde/scoop-eeco
#
# Flags:
#   --dry-run  print what would be pushed; perform no network call
set -eu

VERSION="${VERSION:-$(git describe --tags --dirty --always 2>/dev/null || echo dev)}"
BREW_TAP_REPO="${BREW_TAP_REPO:-ajhahnde/homebrew-eeco}"
SCOOP_TAP_REPO="${SCOOP_TAP_REPO:-ajhahnde/scoop-eeco}"

DRY_RUN=0
for arg in "$@"; do
	case "$arg" in
		--dry-run) DRY_RUN=1 ;;
		*) echo "error: unknown argument: $arg" >&2; exit 2 ;;
	esac
done

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
DIST="${ROOT}/dist"

BREW_SRC="${DIST}/eeco.rb"
SCOOP_SRC="${DIST}/eeco.json"

for f in "${BREW_SRC}" "${SCOOP_SRC}"; do
	if [ ! -f "$f" ]; then
		echo "error: ${f} not found; run 'make packaging' first" >&2
		exit 1
	fi
done

if [ "${DRY_RUN}" -eq 0 ] && [ -z "${TAP_PUSH_TOKEN:-}" ]; then
	echo "error: TAP_PUSH_TOKEN is required (or pass --dry-run)" >&2
	exit 1
fi

# Upsert one file into a tap repo at a fixed path. Creates the file or
# updates it in place, carrying the prior blob sha when one exists.
#   $1 repo (owner/name)   $2 dest path in repo   $3 local source file
sync_one() {
	repo="$1"; dest="$2"; src="$3"

	if [ "${DRY_RUN}" -eq 1 ]; then
		printf 'dry-run: would push %s -> %s:%s (%s)\n' \
			"$src" "$repo" "$dest" "${VERSION}"
		return 0
	fi

	# base64, no newlines — the Contents API wants a single string.
	content="$(base64 < "${src}" | tr -d '\n')"

	# Existing blob sha (empty when the file does not yet exist → create).
	sha="$(GH_TOKEN="${TAP_PUSH_TOKEN}" gh api \
		"repos/${repo}/contents/${dest}" --jq '.sha' 2>/dev/null || true)"

	set -- --method PUT "repos/${repo}/contents/${dest}" \
		-f "message=eeco ${VERSION}: sync ${dest##*/}" \
		-f "content=${content}"
	if [ -n "${sha}" ]; then
		set -- "$@" -f "sha=${sha}"
	fi

	GH_TOKEN="${TAP_PUSH_TOKEN}" gh api "$@" >/dev/null
	printf 'synced %s:%s -> %s\n' "$repo" "$dest" "${VERSION}"
}

sync_one "${BREW_TAP_REPO}"  "Formula/eeco.rb"  "${BREW_SRC}"
sync_one "${SCOOP_TAP_REPO}" "bucket/eeco.json" "${SCOOP_SRC}"