mirror of
https://github.com/langgenius/dify.git
synced 2026-07-15 01:17:04 +08:00
Centralize release naming (tag, asset filenames, checksum file, target list, arch/os tokens) so producers derive from one source instead of duplicating literals across build, checksum, and workflow files. - cli/package.json: add difyctl.release block (tagPrefix, binName, checksumsSuffix, targets[id/bunTarget/exe]) as the naming data source. - cli/scripts/release-naming.mjs: new format source + validator; subcommands tag/asset/checksums/tag-prefix/targets/validate. - release-build.sh, release-write-checksums.sh: derive target list and asset names from release-naming.mjs; drop hardcoded maps and literals. - release-validate-manifest.sh: run release-naming.mjs validate, rejecting a malformed difyctl.release before any build derives from it. - cli-release.yml: emit tagPrefix from the manifest step; tag guard, idempotency check, tag_name, and files glob all derive from it. - install-cli.sh, install.ps1: standalone installers stay hardcoded by convention; add a comment pointing at the source.
131 lines
4.8 KiB
Bash
Executable File
131 lines
4.8 KiB
Bash
Executable File
#!/bin/sh
|
|
# install-cli.sh — one-line difyctl installer from public GitHub Releases.
|
|
#
|
|
# usage:
|
|
# curl -fsSL https://raw.githubusercontent.com/langgenius/dify/main/cli/scripts/install-cli.sh | sh
|
|
#
|
|
# env:
|
|
# DIFYCTL_CHANNEL track to install: stable (default) | rc
|
|
# DIFYCTL_VERSION exact version pin (e.g. 0.2.0); overrides DIFYCTL_CHANNEL
|
|
# DIFYCTL_PREFIX install dir (default $HOME/.local); binary -> $PREFIX/bin/difyctl
|
|
# DIFYCTL_REPO release source repo (default langgenius/dify)
|
|
# requires: curl, uname, sort -V, and sha256sum or shasum.
|
|
set -eu
|
|
|
|
REPO="${DIFYCTL_REPO:-langgenius/dify}"
|
|
PREFIX="${DIFYCTL_PREFIX:-${HOME}/.local}"
|
|
CHANNEL="${DIFYCTL_CHANNEL:-stable}"
|
|
VERSION="${DIFYCTL_VERSION:-}"
|
|
# Asset/tag naming is convention-locked to cli/package.json `difyctl.release`
|
|
# (and release-naming.mjs). This installer ships standalone (curl | sh) so it
|
|
# cannot read that source at runtime — keep these in sync by hand if it changes.
|
|
TAG_PREFIX="difyctl-v"
|
|
|
|
err() { printf '%s\n' "install-cli: $*" >&2; }
|
|
die() { err "$*"; exit 1; }
|
|
need() { command -v "$1" >/dev/null 2>&1 || die "$1 is required"; }
|
|
|
|
# select_version CHANNEL (reads git/matching-refs JSON on stdin) -> highest matching version
|
|
select_version() {
|
|
_channel="$1"
|
|
_versions=$(grep -oE '"ref"[[:space:]]*:[[:space:]]*"refs/tags/difyctl-v[^"]*"' \
|
|
| sed -E 's#.*"refs/tags/difyctl-v([^"]*)".*#\1#')
|
|
case "$_channel" in
|
|
rc) _versions=$(printf '%s\n' "$_versions" | grep -E -- '-rc\.[0-9]+$' || true) ;;
|
|
stable) _versions=$(printf '%s\n' "$_versions" | grep -vE -- '-' || true) ;;
|
|
*) die "invalid DIFYCTL_CHANNEL: ${_channel} (expected stable | rc)" ;;
|
|
esac
|
|
printf '%s\n' "$_versions" | sed '/^$/d' | sort -V | tail -1
|
|
}
|
|
|
|
detect_target() {
|
|
case "$(uname -s)" in
|
|
Linux*) _os=linux ;;
|
|
Darwin*) _os=darwin ;;
|
|
*) die "unsupported OS: $(uname -s) (use install.ps1 on Windows)" ;;
|
|
esac
|
|
case "$(uname -m)" in
|
|
x86_64|amd64) _arch=x64 ;;
|
|
arm64|aarch64) _arch=arm64 ;;
|
|
*) die "unsupported arch: $(uname -m)" ;;
|
|
esac
|
|
printf '%s-%s' "$_os" "$_arch"
|
|
}
|
|
|
|
resolve_version() {
|
|
if [ -n "$VERSION" ]; then
|
|
printf '%s' "$VERSION"
|
|
return 0
|
|
fi
|
|
_api="https://api.github.com/repos/${REPO}/git/matching-refs/tags/difyctl-v"
|
|
if ! _refs=$(curl -fsSL -H "Accept: application/vnd.github+json" "$_api"); then
|
|
die "failed to query ${REPO} releases (network error or GitHub API rate limit); set DIFYCTL_VERSION to pin a version"
|
|
fi
|
|
_resolved=$(printf '%s' "$_refs" | select_version "$CHANNEL")
|
|
[ -n "$_resolved" ] || die "no ${CHANNEL} difyctl release found in ${REPO}"
|
|
printf '%s' "$_resolved"
|
|
}
|
|
|
|
main() {
|
|
need curl
|
|
need uname
|
|
need sort
|
|
if command -v sha256sum >/dev/null 2>&1; then
|
|
HASH="sha256sum"
|
|
elif command -v shasum >/dev/null 2>&1; then
|
|
HASH="shasum -a 256"
|
|
else
|
|
die "need sha256sum or shasum"
|
|
fi
|
|
|
|
target=$(detect_target)
|
|
version=$(resolve_version)
|
|
tag="${TAG_PREFIX}${version}"
|
|
asset="difyctl-v${version}-${target}"
|
|
checksums="difyctl-v${version}-checksums.txt"
|
|
base="https://github.com/${REPO}/releases/download/${tag}"
|
|
|
|
tmp=$(mktemp -d 2>/dev/null || mktemp -d -t difyctl-install)
|
|
trap 'rm -rf "$tmp"' EXIT INT TERM
|
|
|
|
printf 'downloading %s (%s)...\n' "$asset" "$tag"
|
|
curl -fsSL "${base}/${asset}" -o "${tmp}/${asset}" \
|
|
|| die "download failed: ${base}/${asset}"
|
|
curl -fsSL "${base}/${checksums}" -o "${tmp}/${checksums}" \
|
|
|| die "checksum manifest download failed: ${base}/${checksums}"
|
|
|
|
# exact, end-anchored, regex-safe match of the asset's checksum line; fail-closed on no match
|
|
_pattern=$(printf '%s' "$asset" | sed 's/[][\\.^$*+?(){}|/]/\\&/g')
|
|
_sumline=$(grep -E -- "[[:space:]]${_pattern}\$" "${tmp}/${checksums}") || true
|
|
[ -n "$_sumline" ] || die "no checksum entry for ${asset}"
|
|
(
|
|
cd "$tmp"
|
|
printf '%s\n' "$_sumline" | $HASH -c -
|
|
) || die "checksum mismatch for ${asset}"
|
|
|
|
bin_dir="${PREFIX}/bin"
|
|
mkdir -p "$bin_dir"
|
|
target_bin="${bin_dir}/difyctl"
|
|
cp "${tmp}/${asset}" "$target_bin"
|
|
chmod +x "$target_bin"
|
|
|
|
printf '\ndifyctl v%s installed: %s\n' "$version" "$target_bin"
|
|
|
|
case ":${PATH}:" in
|
|
*":${bin_dir}:"*)
|
|
"$target_bin" version >/dev/null 2>&1 \
|
|
&& printf 'verify: run "difyctl version"\n' \
|
|
|| err "binary present but failed to execute; check ${target_bin}"
|
|
;;
|
|
*)
|
|
printf '\n%s is not on your PATH. Add this to your shell profile:\n' "$bin_dir"
|
|
printf ' export PATH="%s:$PATH"\n' "$bin_dir"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main unless sourced as a library (tests set DIFYCTL_INSTALL_LIB=1).
|
|
if [ "${DIFYCTL_INSTALL_LIB:-0}" != "1" ]; then
|
|
main "$@"
|
|
fi
|