Compare commits

..

No commits in common. '674ed2d73988bf09717df47f74ac069195b08132' and '5b892b4d9ea412f6b1e2b019b943099358670acf' have entirely different histories.

@ -1,25 +1,22 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5c0VHWGM2UFRURTdFSjFF
UTBXWFV1YVVVVkFnRmwxdExJaWdoRGY3ZXljCk0rejFPak5wNmNUUkNCSkEzdGNV
ZHlUTkZyZWo3Z1JVbTdpdEJjVlBpcDgKLT4gWDI1NTE5IFZNRWpCOTlxaWJlWWNT
VXhaVFlGMGdvVEJocm1MRUJKekpsQWw0NnJkSHMKNUY3aTNmM1RMOE5IRzkxaWkx
MGtHS2lsU0VaNGdULzBzeVYvQXEvdS9VZwotPiBYMjU1MTkgRVpJSVozd3hscXg5
WjdKWkdNT0t3Zk0welZPL3lPNHhNNFliVElXRk1HOApmM0Ywa0ltazlVU1ZRQVhW
UmFmaW9aWEVOdXI3MUlUQmx6SlR5WHcrQnFnCi0+IFgyNTUxOSBUVVlYVVlIVWZO
M0VZRlgyQVFWTlhUMTVPSkMvbER1cm9iRXgzMWJPT2lrCnZzalAwK3lYR0w2NGc0
TmFaaDduU21PRTZndkRSNHcrdXBHbVpmUjlja3cKLT4gWDI1NTE5IGUyS2ZmYXJO
YWJrcXZ1NXhsODdwUStoaTNlVjZpUlNPSjdoeEFRSk0wQ1kKd1U4cTMvbGxGRWc2
WU53eXJJYWx5REl2NFFwMXozc2ducWFMaG9KWklJawotLS0gMmErOE00dTM0OTVY
Sno3SkE5QzdOUGQyUnIvOEtBano0QlFKb2RyQUc0SQoI0CZ8EhHJAYGhJtSMCIDF
iWahMnQvIR5zVhXoKdEYvf0uZ2cH4xhsSAXDdGJrhRucPBbaqvWNaQFGVdsfjWAY
Duuq6jKzU9+70WaFPUE6nftH11lZKcpUXtCXzhPlBjM1KdbACrrkuB/fuIK+ALWK
ljnwhgn4a2ojVi8NozRQEqNdk7uscHrwWWgXXvFkBGIkIEKfbLeCoGfNC7zL6J1k
phz+1ZAkxPnMxA8SGBO1xa90gdHFuHKqjS088TS0DIZXro4F6skZ6Rk5gcYW48Fj
ZcwRwnKN+n0MjCuKXTuMfgT89s7n3xgKGdhH+BopKkY2slKqglhLym1YhlzZelnq
/rJQFlytXpt/30Zqt2Jo8w1kUC2l3TK0wfVTFNhDi1bnl3fV5SQBaygBGV/cAFti
CA1UgguS9SPSsnehWzoN5ovwkYa7XvzorS7sGsMlUJY0o/RJGRGIR96eSdWvFohQ
PAlRSXg5FrJmICZB4YrYqVBM+D4ooaHj2G2OO6vK81dbzaINuC+6xDstApcYQSJL
gRNjiMDChutjJtn2qP1pCFMzlu35tb8+SAPld/VTs7SboJNYEkLJlN7a+Og1Ynj7
hBzdKRhV2mODrNbd8PQdgmT5kygIIcEPx4/25TqeTJ0zeChd4DYOriK+lxqc9w34
5Kw1mwgVal+D
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiVWhTekhFZk1WNlBZbU16
ZGtCSUtwWVdHcGJGOGZnakpWNnpmT0J6TTFrCmhnSVpRWFNXMGtvM2RYbDJQaUE2
ek5Mdy9KWit5V3NJQkZWZmdIU3lrVHMKLT4gWDI1NTE5IFV1cHAwRzFmTHg5OURF
UFRwbEIxWkVLVDVrQ3NRM3dmOEY3ek9TZ1hBZ2cKMFBUeGFRN08xenUzUGRXaFVp
cUZuZkZhS0ZHMy9nYnRhNzJlWFRHQUovTQotPiBYMjU1MTkgd1F6VUdWNy9oR0pS
bElCWkloVFhUV1kwME8vbTFpZzdaUDVabzdDSzkzTQoxWXpaejRFMXpQMnVMV1VT
MW9kRmJpQjNSZU4wRXdhMWZWZVA1aDkwc1lzCi0+IFgyNTUxOSB2TmFPRmFRdkZm
RXNSd2huODlnS01wbXhsUmxDNTlaMnhkSHhGOCtXdzMwCm1ublRyc2tUUEJZamo3
a3NyV01IYUhOQnZINEg2U0NNdk9YRUM0RDJNZGMKLT4gWDI1NTE5IDZCbExMMUR0
ZVYzcVFObWVNaE10ejZiZmN2MFI1SlRyRlZQcGZVbkhlMVUKOFFHanFOanFXYS90
TXc3YjhaZ2ZJMVl5a2Z4YkpsWDZqMlppdTF6NXVwawotLS0gOWp3OUdCTFJoaENB
ZG02RDN0QnJ5alRBendvaVhRdEhnSFBnOVA3VFlZdwoIMyto8xTMKMdVYHwgnKij
Qbn8c8RAoaLHNOUEB++UAUZ6JfZgBCAOEyTgMiZSsO2KrhurwHtARqC+kmhzlfSp
G7/TzacmgzIzp51hC5fV/xYsxLDW2IHf/d5usd8HiOS5IVNbcMEgI5KuQdZHMnGd
UNuSskISMHhDfToFReqipK8109MUVliB9asu4QTG7ex5A98yzmcS852WnhfzIedc
LZhKTbGJkme0JAiEs/TQPXCjCi24VPy6qhcyXQgL5hCcyJULCnNz36x+T7nd44zN
R7mqXKXfZ/ySZZLPHC1NLdQ7wEFBPiXks9cK65ut/N35NQRIo40R1abEPGhrpPe2
dZ2XP2cAnn31WxtJ+1u9RR2m0AqsV1SXZ4Ptn3io9oh2ksc+D9DDLmfZdKN/J0rL
w/EgrwGhJudwAGADzcyOW/r90kUsbhqidTRLbjIrLypNhDZLO0cMK9jxq38brrUm
RCSsdNJZ2JyCCS9z3m0uekWvM1B+tk5EdaU+96w=
-----END AGE ENCRYPTED FILE-----

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=age
VERSION=${VERSION:-1.3.2}
VERSION=${VERSION:-1.3.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/FiloSottile/age/releases/download/v${VERSION}/age-v${VERSION}-$(get_os)-$(get_arch).tar.gz

@ -8,11 +8,11 @@ set -euo pipefail
APP=bat
BAT_DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
BAT_CURRENT="${BAT_DEST}/current"
BAT_VERSION=${BAT_VERSION:-0.26.1}
BAT_VERSION=${BAT_VERSION:-0.25.0}
EXTRA_DEST="${XDG_DATA_HOME}/apps/releases/bat-extras"
EXTRA_CURRENT="${EXTRA_DEST}/current"
EXTRA_VERSION=${EXTRA_VERSION:-2024.08.24}
EXTRA_FILE=${EXTRA_FILE:-2024.08.24}
EXTRA_VERSION=${EXTRA_VERSION:-2024.07.10}
EXTRA_FILE=${EXTRA_FILE:-2024.07.10}
MAN_DIR=${XDG_DATA_HOME}/man/man1

@ -5,7 +5,7 @@ set -euo pipefail
# shellcheck disable=SC1090
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
VERSION=${VERSION:-v1.73.0}
VERSION=${VERSION:-v1.66.0}
DEST=${XDG_DATA_HOME}/apps/releases/buf
CURRENT=${DEST}/current
URL=https://github.com/bufbuild/buf/releases/download/${VERSION}/buf-$(uname)-$(uname -m).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=cmctl
VERSION=${VERSION:-1.21.2}
VERSION=${VERSION:-1.19.4}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=chezmoi
VERSION=${VERSION:-2.72.2}
VERSION=${VERSION:-2.69.4}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -4,7 +4,7 @@
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=circleci
VERSION=${VERSION:-0.1.47860}
VERSION=${VERSION:-0.1.34685}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/CircleCI-Public/circleci-cli/releases/download/v${VERSION}/circleci-cli_${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=cloud-sql-proxy
VERSION=${VERSION:-2.25.4}
VERSION=${VERSION:-2.6.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=confluent
VERSION=${VERSION:-4.74.0}
VERSION=${VERSION:-4.53.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/confluentinc/cli/releases/download/v${VERSION}/confluent_${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=dasel
VERSION=${VERSION:-3.11.2}
VERSION=${VERSION:-3.3.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=delta
VERSION=${VERSION:-0.19.2}
VERSION=${VERSION:-0.18.2}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -16,7 +16,7 @@ function get_os () (
APP=deno
VERSION=${VERSION:-2.9.6}
VERSION=${VERSION:-2.8.2}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/denoland/deno/releases/download/v${VERSION}/deno-$(get_os).zip

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=doctl
VERSION=${VERSION:-1.168.0}
VERSION=${VERSION:-1.151.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=dust
VERSION=${VERSION:-1.2.5}
VERSION=${VERSION:-1.2.4}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=etcd
VERSION=${VERSION:-v3.7.1}
VERSION=${VERSION:-v3.6.8}
APPS_DIR=/usr/local/apps/${APP}
URL=https://github.com/etcd-io/etcd/releases/download/${VERSION}/etcd-${VERSION}-$(get_os)-$(get_arch).tar

@ -3,7 +3,7 @@
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=fzf
VERSION=${VERSION:-0.74.4}
VERSION=${VERSION:-0.68.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/junegunn/fzf/releases/download/v${VERSION}/fzf-${VERSION}-$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=geckodriver
VERSION=${VERSION:-0.37.1}
VERSION=${VERSION:-0.36.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -8,7 +8,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=gitea
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
CURRENT=${DEST}/current
VERSION=${VERSION:-1.27.3}
VERSION=${VERSION:-1.21.11}
main() (
URL=https://dl.gitea.io/gitea/${VERSION}/gitea-${VERSION}-$(get_os)-$(get_arch).xz

@ -8,7 +8,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=gitea
DEST=/usr/local/apps/${APP}
CURRENT=${DEST}/current
VERSION=${VERSION:-1.27.3}
VERSION=${VERSION:-1.21.11}
BIN_DIR=/usr/local/bin
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=go
VERSION=${VERSION:-1.27.1}
VERSION=${VERSION:-1.27.0}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://dl.google.com/go/go${VERSION}.$(get_os)-$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -e
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=swagger
VERSION=${VERSION:-0.36.6}
VERSION=${VERSION:-0.33.1}
DEST=${XDG_DATA_HOME}/apps/releases/go-swagger
URL=https://github.com/go-swagger/go-swagger/releases/download/v${VERSION}/swagger_$(get_os)_$(get_arch)

@ -5,7 +5,7 @@ set -euo pipefail
# shellcheck disable=SC1090
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
VERSION=${VERSION:-1.27.1}
VERSION=${VERSION:-1.27.0}
DEST=/usr/local/apps/golang
URL=https://dl.google.com/go/go${VERSION}.$(get_os)-$(get_arch).tar.gz
DEST_BIN=$DEST/current/bin

@ -6,7 +6,7 @@ set -e
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=gofumpt
VERSION=${VERSION:-v0.12.0}
VERSION=${VERSION:-v0.9.2}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/mvdan/gofumpt/releases/download/${VERSION}/gofumpt_${VERSION}_$(get_os)_$(get_arch)

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=helm
VERSION=${VERSION:-3.22.0}
VERSION=${VERSION:-3.17.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
if [[ ! -d "${DEST}/${VERSION}" ]]; then

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=hugo
VERSION=${VERSION:-0.166.0}
VERSION=${VERSION:-0.157.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -7,7 +7,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=kubectl
# https://dl.k8s.io/release/stable.txt
VERSION=${VERSION:-1.37.0}
VERSION=${VERSION:-1.30.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
APP_PATH=${DEST}/${VERSION}/kubectl

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=lego
VERSION=${VERSION:-v5.4.1}
VERSION=${VERSION:-v5.0.3}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/go-acme/lego/releases/download/${VERSION}/lego_${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=lego
VERSION=${VERSION:-v5.4.1}
VERSION=${VERSION:-v5.0.3}
APPS_DIR=/usr/local/apps/${APP}
URL=https://github.com/go-acme/lego/releases/download/${VERSION}/lego_${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -e
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=lf
VERSION=${VERSION:-r42}
VERSION=${VERSION:-r41}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/gokcehan/lf/releases/download/${VERSION}/lf-$(get_os)-$(get_arch).tar.gz

@ -7,7 +7,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
main() (
APP=lua-language-server
VERSION=${VERSION:-3.19.1}
VERSION=${VERSION:-3.17.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/LuaLS/lua-language-server/releases/download/${VERSION}/lua-language-server-${VERSION}-$(get_os)-$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=minikube
VERSION=${VERSION:-1.39.0}
VERSION=${VERSION:-1.38.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/kubernetes/minikube/releases/download/v${VERSION}/minikube-$(get_os)-$(get_arch).tar.gz

@ -6,9 +6,9 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=minikube
VERSION=${VERSION:-1.39.0}
VERSION=${VERSION:-1.38.1}
APPS_DIR=/usr/local/apps/${APP}
URL=https://github.com/kubernetes/minikube/releases/download/v${VERSION}/minikube-$(get_os)-$(get_arch).tar.gz
URL=https://github.com/kubernetes/minikube/releases/download/${VERSION}/minikube-$(get_os)-$(get_arch).tar.gz
extract_tarball "${URL}" "${APPS_DIR}/${VERSION}" "--strip-components 1" sudo
sudo chown --recursive root:root "${APPS_DIR}/${VERSION}"

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=mockery
VERSION=${VERSION:-3.8.0}
VERSION=${VERSION:-3.6.4}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/vektra/mockery/releases/download/v${VERSION}/mockery_${VERSION}_$(uname)_$(uname -m).tar.gz

@ -6,7 +6,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
set -euo pipefail
APP=nats-server
VERSION=${VERSION:-2.14.6}
VERSION=${VERSION:-2.12.4}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=node_exporter
VERSION=${VERSION:-1.12.1}
VERSION=${VERSION:-1.10.2}
APPS_DIR=/usr/local/apps/${APP}
URL=https://github.com/prometheus/node_exporter/releases/download/v${VERSION}/node_exporter-${VERSION}.$(get_os)-$(get_arch).tar.gz

@ -6,7 +6,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
main () (
APP=nushell
VERSION=${VERSION:-0.115.1}
VERSION=${VERSION:-0.112.2}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/nushell/nushell/releases/download/${VERSION}/nu-${VERSION}-$(get_arch)-$(get_os).tar.gz
PLUGIN_DIR=${XDG_CONFIG_HOME}/nushell/plugins

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=procs
VERSION=${VERSION:-0.14.12}
VERSION=${VERSION:-0.14.10}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=prometheus
VERSION=${VERSION:-3.14.0}
VERSION=${VERSION:-3.9.1}
APPS_DIR=/usr/local/apps/${APP}
URL=https://github.com/prometheus/prometheus/releases/download/v${VERSION}/prometheus-${VERSION}.$(get_os)-$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=protoc-gen-go
VERSION=${VERSION:-1.36.12}
VERSION=${VERSION:-1.36.11}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/protocolbuffers/protobuf-go/releases/download/v${VERSION}/protoc-gen-go.v${VERSION}.$(get_os).$(get_arch).tar.gz

@ -1,4 +1,4 @@
#!/usr/bin/env bash
VERSION=${VERSION:-v1.6.2}
VERSION=${VERSION:-v1.6.1}
go install "google.golang.org/grpc/cmd/protoc-gen-go-grpc@${VERSION}"

@ -5,7 +5,7 @@ set -euo pipefail
# shellcheck disable=SC1090
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
VERSION=${VERSION:-2.30.0}
VERSION=${VERSION:-2.28.0}
DEST=${XDG_DATA_HOME}/apps/releases/protoc-grpc-gateway
BASE_URL=https://github.com/grpc-ecosystem/grpc-gateway/releases/download/v${VERSION}
GRPC_GATEWAY_URL=${BASE_URL}/protoc-gen-grpc-gateway-v${VERSION}-$(get_os)-$(uname -m)

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=protoc
VERSION=${VERSION:-34.2}
VERSION=${VERSION:-34.1}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -5,11 +5,11 @@ set -euo pipefail
# shellcheck disable=SC1091
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
VERSION=${VERSION:-34.2}
PROTOC_ZIP=protoc-$VERSION-linux-x86_64.zip
VERSION=${VERSION:-34.1}
PROTOC_ZIP=protoc-$PROTOC_VERSION-linux-x86_64.zip
TMP_DIR=$(mktemp --directory)
DEST_FILE=$TMP_DIR/$PROTOC_ZIP
URL=https://github.com/protocolbuffers/protobuf/releases/download/v$VERSION/$PROTOC_ZIP
URL=https://github.com/protocolbuffers/protobuf/releases/download/v$PROTOC_VERSION/$PROTOC_ZIP
curl --output "$DEST_FILE" --location "$URL"
sudo unzip -o "$DEST_FILE" -d /usr/local bin/protoc

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=pulumi
VERSION=${VERSION:-3.262.0}
VERSION=${VERSION:-3.131.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
main () (
APP=rg
VERSION=${VERSION:-15.2.0}
VERSION=${VERSION:-15.1.0}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/BurntSushi/ripgrep/releases/download/${VERSION}/ripgrep-${VERSION}-$(get_arch)-$(get_os).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=sass
VERSION=${VERSION:-1.104.1}
VERSION=${VERSION:-1.97.3}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=shfmt
VERSION=${VERSION:-3.14.1}
VERSION=${VERSION:-3.12.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=sqlc
VERSION=${VERSION:-1.31.1}
VERSION=${VERSION:-1.30.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://downloads.sqlc.dev/sqlc_${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -4,7 +4,7 @@ source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
main () (
APP=starship
VERSION=${VERSION:-1.26.0}
VERSION=${VERSION:-1.24.2}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/starship/starship/releases/download/v${VERSION}/starship-$(get_arch)-$(get_os).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=templ
VERSION=${VERSION:-v0.3.1020}
VERSION=${VERSION:-v0.3.977}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
URL=https://github.com/a-h/templ/releases/download/${VERSION}/templ_$(uname)_$(uname -m).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=tile38
VERSION=${VERSION:-1.38.0}
VERSION=${VERSION:-1.37.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -4,7 +4,7 @@
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=traefik
VERSION=${VERSION:-3.7.13}
VERSION=${VERSION:-3.6.9}
DEST="${XDG_DATA_HOME}/apps/releases/${APP}"
URL=https://github.com/traefik/traefik/releases/download/v${VERSION}/traefik_v${VERSION}_$(get_os)_$(get_arch).tar.gz

@ -6,7 +6,7 @@ set -euo pipefail
source "${XDG_DATA_HOME}/buddy-up/includes/utils.sh"
APP=zig
VERSION=${VERSION:-0.16.0}
VERSION=${VERSION:-0.13.0}
DEST=${XDG_DATA_HOME}/apps/releases/${APP}
main() (

@ -1,441 +0,0 @@
#!/usr/bin/env node
// Bump the pinned VERSION defaults in dot_local/bin/executable_install-* to
// the latest upstream release, by reconstructing each script's own tag naming
// scheme from its existing URL + default value rather than assuming "vX.Y.Z".
//
// Runs under node, bun, or deno:
// node scripts/update-versions.mjs
// bun scripts/update-versions.mjs
// deno run --allow-net --allow-read --allow-write scripts/update-versions.mjs
import { readdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const REPO_ROOT = path.resolve(__dirname, "..");
const BIN_DIR = path.join(REPO_ROOT, "dot_local", "bin");
const GITHUB_TOKEN = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
const VERSION_RE = /^(?<indent>[ \t]*)(?<var>(?:[A-Za-z_][A-Za-z0-9_]*)?VERSION)=\$\{\k<var>:-(?<val>[^}]*)\}/gmd;
// Scripts whose download URL doesn't point at github.com/owner/repo directly,
// but whose upstream project is still tagged releases on GitHub. prefix/suffix
// reflect the *actual git tag* convention (e.g. "v1.2.3"), which may differ
// from how the download mirror names its own files.
const OVERRIDE_REPO = {
"install-helm": ["helm", "helm", "v", ""],
"install-cloud-sql-proxy": ["GoogleCloudPlatform", "cloud-sql-proxy", "v", ""],
"install-sqlc": ["sqlc-dev", "sqlc", "v", ""],
"install-gitea-home": ["go-gitea", "gitea", "v", ""],
"install-gitea-system": ["go-gitea", "gitea", "v", ""],
"install-pulumi": ["pulumi", "pulumi", "v", ""],
};
// Repos that publish so many unrelated releases (e.g. a separate weekly
// "edge" channel) that the pinned channel's latest tag can fall off the
// first page of results.
const EXTRA_PAGES = {
"linkerd/linkerd2": 5,
};
function githubHeaders() {
const headers = { "User-Agent": "update-versions", Accept: "application/vnd.github+json" };
if (GITHUB_TOKEN) headers.Authorization = `Bearer ${GITHUB_TOKEN}`;
return headers;
}
async function httpJson(url, headers) {
const res = await fetch(url, { headers: headers || { "User-Agent": "update-versions" } });
if (!res.ok) {
const err = new Error(`HTTP ${res.status}: ${res.statusText}`);
err.status = res.status;
throw err;
}
return res.json();
}
async function httpText(url) {
const res = await fetch(url, { headers: { "User-Agent": "update-versions" } });
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
return (await res.text()).trim();
}
async function fetchGithubTags(owner, repo) {
const pages = EXTRA_PAGES[`${owner}/${repo}`] || 1;
let tags = [];
try {
for (let page = 1; page <= pages; page++) {
const data = await httpJson(
`https://api.github.com/repos/${owner}/${repo}/releases?per_page=100&page=${page}`,
githubHeaders()
);
if (!data.length) break;
tags.push(...data.filter((r) => !r.draft).map((r) => r.tag_name));
}
} catch (e) {
if (e.status !== 404) throw e;
}
if (!tags.length) {
// Some projects (e.g. rvm) tag releases without using GitHub Releases.
const data = await httpJson(
`https://api.github.com/repos/${owner}/${repo}/tags?per_page=100`,
githubHeaders()
);
tags = data.map((t) => t.name);
}
return tags;
}
function parseNumericTuple(s) {
return (s.match(/\d+/g) || []).map(Number);
}
function compareTuples(a, b) {
const len = Math.max(a.length, b.length);
for (let i = 0; i < len; i++) {
const x = a[i] ?? -1;
const y = b[i] ?? -1;
if (x !== y) return x - y;
}
return 0;
}
function maxByTuple(candidates) {
return candidates.reduce((best, c) => (compareTuples(c[1], best[1]) > 0 ? c : best));
}
// Picks the newest tag matching prefix/suffix, preferring candidates with the
// same "shape" as the currently pinned version (dot-segment count) and the
// same leading (major) component, so a project running two release trains
// side by side (e.g. helm v3 vs v4, or a date-based tag scheme that changed
// format over time) doesn't get silently jumped to the wrong one.
//
// Returns { chosen, globalMax }: globalMax is the best across all shapes/
// majors, so callers can flag "a newer major exists" without auto-applying it.
function bestMatch(tags, prefix, suffix, currentMid) {
const currentShape = (currentMid.match(/\d+/g) || []).length;
const currentMajor = parseNumericTuple(currentMid)[0];
const candidates = [];
for (const tag of tags) {
if (!tag.startsWith(prefix)) continue;
let middle;
if (suffix) {
if (!tag.endsWith(suffix) || tag.length <= prefix.length + suffix.length) continue;
middle = tag.slice(prefix.length, tag.length - suffix.length);
} else {
middle = tag.slice(prefix.length);
}
// Reject pre-releases (rc/beta/alpha/etc): keep only plain N(.N)* tags.
if (!middle || !/^[0-9]+(?:\.[0-9]+)*$/.test(middle)) continue;
candidates.push([middle, parseNumericTuple(middle)]);
}
if (!candidates.length) return { chosen: null, globalMax: null };
const globalMax = maxByTuple(candidates)[0];
const sameShape = candidates.filter((c) => c[1].length === currentShape);
// A single-component scheme (e.g. lf's "r41", "r42") has no real
// major/minor split -- every release changes the "major", so pinning to it
// would make the tool a permanent no-op. Only apply the major-pin tier when
// there's an actual sub-structure to distinguish major from patch.
const sameMajor = currentShape > 1 ? sameShape.filter((c) => c[1][0] === currentMajor) : [];
for (const pool of [sameMajor, sameShape, candidates]) {
if (pool.length) return { chosen: maxByTuple(pool)[0], globalMax };
}
return { chosen: null, globalMax };
}
async function resolveKubectl() {
return (await httpText("https://dl.k8s.io/release/stable.txt")).replace(/^v/, "");
}
async function resolveGo() {
const data = await httpJson("https://go.dev/dl/?mode=json");
for (const rel of data) {
if (rel.stable) return rel.version.slice("go".length);
}
throw new Error("no stable go release found");
}
async function resolveZig() {
const data = await httpJson("https://ziglang.org/download/index.json");
const versions = Object.keys(data).filter((k) => /^[0-9]+(?:\.[0-9]+)*$/.test(k));
return versions.reduce((a, b) => (compareTuples(parseNumericTuple(a), parseNumericTuple(b)) >= 0 ? a : b));
}
async function resolveGoproxy(modulePath) {
const data = await httpJson(`https://proxy.golang.org/${modulePath}/@latest`);
return data.Version;
}
// Scripts that don't resolve to a plain github release lookup at all.
const SPECIAL_RESOLVERS = {
"install-kubectl": resolveKubectl,
"install-go-home": resolveGo,
"install-go-system": resolveGo,
"install-zig": resolveZig,
"install-protoc-gen-go-grpc": () => resolveGoproxy("google.golang.org/grpc/cmd/protoc-gen-go-grpc"),
};
function escapeRegex(s) {
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function findGithubRef(lines, varName) {
const braced = "${" + varName + "}";
const bareRe = new RegExp("\\$" + escapeRegex(varName) + "(?![A-Za-z0-9_])");
for (const line of lines) {
if (!line.includes(braced) && !bareRe.test(line)) continue;
if (line.includes("github.com")) {
const m = line.match(
/github\.com\/([\w.-]+)\/([\w.-]+)\/(?:releases\/download|archive\/refs\/tags)\/([^/\s"']+)/
);
if (m && (m[3].includes(braced) || bareRe.test(m[3]))) return [m[1], m[2], m[3]];
}
if (line.includes("githubusercontent.com")) {
const m = line.match(/raw\.githubusercontent\.com\/([\w.-]+)\/([\w.-]+)\/([^/\s"']+)/);
if (m && (m[3].includes(braced) || bareRe.test(m[3]))) return [m[1], m[2], m[3]];
}
}
return null;
}
// Splits a path segment like "v${VERSION}" or "v$VERSION" or "bws-v${VERSION}"
// around the variable reference, returning [prefix, suffix].
function splitOnVarRef(tagexpr, varName) {
const braced = "${" + varName + "}";
const bareRe = new RegExp("\\$" + escapeRegex(varName) + "(?![A-Za-z0-9_])");
if (tagexpr.includes(braced)) {
const idx = tagexpr.indexOf(braced);
return [tagexpr.slice(0, idx), tagexpr.slice(idx + braced.length)];
}
const bm = bareRe.exec(tagexpr);
return [tagexpr.slice(0, bm.index), tagexpr.slice(bm.index + bm[0].length)];
}
function looksDynamic(val) {
return val.includes("$(") || val.includes("`") || !/\d/.test(val);
}
// First pass: no network. Returns { text, stem, tasks } where each task is
// an object describing one VERSION default and how to resolve it.
function parseFile(fileName, text) {
const lines = text.split("\n");
const stem = fileName.replace(/^executable_/, "");
const tasks = [];
for (const m of text.matchAll(VERSION_RE)) {
const varName = m.groups.var;
const val = m.groups.val;
const span = m.indices.groups.val;
const task = { var: varName, val, span };
if (looksDynamic(val)) {
task.status = "dynamic";
tasks.push(task);
continue;
}
if (SPECIAL_RESOLVERS[stem]) {
task.resolver = ["special", stem];
tasks.push(task);
continue;
}
let owner, repo, urlPrefix, urlSuffix;
const ref = findGithubRef(lines, varName);
if (ref) {
const [o, r, tagexpr] = ref;
owner = o;
repo = r;
[urlPrefix, urlSuffix] = splitOnVarRef(tagexpr, varName);
} else if (OVERRIDE_REPO[stem]) {
[owner, repo, urlPrefix, urlSuffix] = OVERRIDE_REPO[stem];
} else {
task.status = "no-resolver";
tasks.push(task);
continue;
}
const lead = (val.match(/^\D*/) || [""])[0];
const trail = (val.match(/\D*$/) || [""])[0];
const midVal = val.slice(lead.length, val.length - trail.length);
task.resolver = ["github", owner, repo];
task.lead = lead;
task.trail = trail;
task.midVal = midVal;
task.combinedPrefix = urlPrefix + lead;
task.combinedSuffix = trail + urlSuffix;
tasks.push(task);
}
return { stem, tasks };
}
function parseArgs(argv) {
const args = { filter: [], dryRun: false, verbose: false };
for (const a of argv) {
if (a === "-n" || a === "--dry-run") args.dryRun = true;
else if (a === "-v" || a === "--verbose") args.verbose = true;
else if (a === "-h" || a === "--help") {
console.log("usage: update-versions [-n|--dry-run] [-v|--verbose] [filter ...]");
process.exit(0);
} else args.filter.push(a);
}
return args;
}
async function main() {
const args = parseArgs(process.argv.slice(2));
if (!GITHUB_TOKEN) {
console.error(
"note: no GITHUB_TOKEN/GH_TOKEN set; this checks ~60 repos and may hit " +
"GitHub's 60 req/hour unauthenticated rate limit\n"
);
}
let fileNames = (await readdir(BIN_DIR)).filter((f) => f.startsWith("executable_install-"));
fileNames.sort();
if (args.filter.length) {
fileNames = fileNames.filter((f) => args.filter.some((needle) => f.includes(needle)));
}
const parsed = [];
for (const fileName of fileNames) {
const text = await readFile(path.join(BIN_DIR, fileName), "utf8");
const { stem, tasks } = parseFile(fileName, text);
parsed.push({ fileName, text, stem, tasks });
}
const specialStems = new Set();
const repoKeys = new Set();
for (const { tasks } of parsed) {
for (const t of tasks) {
if (!t.resolver) continue;
if (t.resolver[0] === "special") specialStems.add(t.resolver[1]);
else repoKeys.add(`${t.resolver[1]}/${t.resolver[2]}`);
}
}
const specialResults = new Map();
const repoTags = new Map();
await Promise.all(
[...specialStems].map(async (stem) => {
try {
specialResults.set(stem, { ok: true, value: await SPECIAL_RESOLVERS[stem]() });
} catch (e) {
specialResults.set(stem, { ok: false, error: e.message });
}
})
);
await Promise.all(
[...repoKeys].map(async (key) => {
const [owner, repo] = key.split("/");
try {
repoTags.set(key, { ok: true, value: await fetchGithubTags(owner, repo) });
} catch (e) {
repoTags.set(key, { ok: false, error: `${e.status ? "HTTP " + e.status : "error"}: ${e.message}` });
}
})
);
let changedFiles = 0;
let rateLimited = false;
for (const { fileName, text, stem, tasks } of parsed) {
const edits = [];
const linesOut = [];
for (const task of tasks) {
const { var: varName, val } = task;
let status = task.status;
let newVal = null;
if (!status) {
const kind = task.resolver[0];
if (kind === "special") {
const result = specialResults.get(task.resolver[1]);
if (!result.ok) {
status = `error: ${result.error}`;
} else if (result.value === val) {
status = "current";
} else {
newVal = result.value;
status = "update";
}
} else {
const key = `${task.resolver[1]}/${task.resolver[2]}`;
const result = repoTags.get(key);
if (!result.ok) {
status = `error: ${result.error}`;
if (result.error.includes("403") || result.error.toLowerCase().includes("rate limit")) {
rateLimited = true;
}
} else {
const { chosen, globalMax } = bestMatch(result.value, task.combinedPrefix, task.combinedSuffix, task.midVal);
if (chosen === null) {
status = "no-match";
} else {
const candidate = task.lead + chosen + task.trail;
if (candidate === val) {
status = "current";
if (globalMax !== chosen) {
const globalCandidate = task.lead + globalMax + task.trail;
status = `current; newer major available: ${globalCandidate}`;
}
} else {
newVal = candidate;
status = "update";
}
}
}
}
}
if (status === "update") {
edits.push([task.span, newVal]);
linesOut.push(` ${varName}: ${val} -> ${newVal}`);
} else if (status === "current") {
if (args.verbose) linesOut.push(` ${varName}: ${val} (current)`);
} else if (status === "dynamic") {
if (args.verbose) linesOut.push(` ${varName}: ${val} (dynamic, skipped)`);
} else {
linesOut.push(` ${varName}: ${val} (${status})`);
}
}
if (linesOut.length) {
console.log(stem);
console.log(linesOut.join("\n"));
}
if (edits.length) {
changedFiles++;
if (!args.dryRun) {
let newText = text;
edits.sort((a, b) => b[0][0] - a[0][0]);
for (const [[start, end], newVal] of edits) {
newText = newText.slice(0, start) + newVal + newText.slice(end);
}
await writeFile(path.join(BIN_DIR, fileName), newText);
}
}
}
const verb = args.dryRun ? "would update" : "updated";
console.log(`\n${changedFiles} script(s) ${verb}.`);
if (rateLimited) {
console.error("Some lookups were rate-limited by GitHub; set GITHUB_TOKEN and re-run to pick up the rest.");
}
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
main();
}
export { parseFile, findGithubRef, splitOnVarRef, bestMatch, parseNumericTuple };
Loading…
Cancel
Save