mirror of
https://github.com/langgenius/dify.git
synced 2026-05-23 02:18:23 +08:00
feat(api,web,cli): difyctl v1.0 — OAuth device flow, /openapi/v1 auth pipeline, CLI client
This commit is contained in:
132
cli/scripts/install-cli.sh
Executable file
132
cli/scripts/install-cli.sh
Executable file
@ -0,0 +1,132 @@
|
||||
#!/bin/sh
|
||||
# install-cli.sh — one-line difyctl installer for Linux and macOS.
|
||||
#
|
||||
# usage:
|
||||
# curl -fsSL https://raw.githubusercontent.com/langgenius/dify/main/cli/scripts/install-cli.sh | sh
|
||||
#
|
||||
# env: DIFYCTL_VERSION (default latest), DIFYCTL_PREFIX (default $HOME/.local),
|
||||
# DIFYCTL_REPO (default langgenius/dify).
|
||||
# requires: curl, tar (xz), uname, jq, sha256sum or shasum.
|
||||
|
||||
set -eu
|
||||
|
||||
REPO="${DIFYCTL_REPO:-langgenius/dify}"
|
||||
VERSION="${DIFYCTL_VERSION:-latest}"
|
||||
PREFIX="${DIFYCTL_PREFIX:-${HOME}/.local}"
|
||||
|
||||
err() { printf '%s\n' "install-cli: $*" >&2; }
|
||||
die() { err "$*"; exit 1; }
|
||||
need() { command -v "$1" >/dev/null 2>&1 || die "$1 is required"; }
|
||||
|
||||
need curl
|
||||
need tar
|
||||
need uname
|
||||
need jq
|
||||
|
||||
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
|
||||
|
||||
case "$(uname -s)" in
|
||||
Linux*) os=linux ;;
|
||||
Darwin*) os=darwin ;;
|
||||
*) die "unsupported OS: $(uname -s)" ;;
|
||||
esac
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64|amd64) arch=x64 ;;
|
||||
arm64|aarch64) arch=arm64 ;;
|
||||
*) die "unsupported arch: $(uname -m)" ;;
|
||||
esac
|
||||
|
||||
target="${os}-${arch}"
|
||||
|
||||
if [ "$VERSION" = "latest" ]; then
|
||||
api="https://api.github.com/repos/${REPO}/releases/latest"
|
||||
else
|
||||
api="https://api.github.com/repos/${REPO}/releases/tags/${VERSION}"
|
||||
fi
|
||||
|
||||
release=$(curl -fsSL "$api") || die "could not fetch release metadata from ${api}"
|
||||
tag=$(printf '%s' "$release" | jq -r '.tag_name')
|
||||
[ -n "$tag" ] && [ "$tag" != "null" ] || die "release has no tag_name"
|
||||
|
||||
matches=$(printf '%s' "$release" \
|
||||
| jq -r --arg t "$target" '.assets[].name | select(test("^difyctl-v[0-9]+\\.[0-9]+\\.[0-9]+(-[0-9A-Za-z.-]+)?-\($t)\\.tar\\.xz$"))')
|
||||
count=$(printf '%s' "$matches" | grep -c . || true)
|
||||
case "$count" in
|
||||
0) die "no difyctl asset for ${target} on ${tag}" ;;
|
||||
1) asset="$matches" ;;
|
||||
*) die "expected exactly 1 difyctl asset for ${target} on ${tag}, found ${count}: ${matches}" ;;
|
||||
esac
|
||||
|
||||
no_target="${asset%-${target}.tar.xz}"
|
||||
cli_v="${no_target#difyctl-}"
|
||||
checksums="difyctl-${cli_v}-checksums.txt"
|
||||
|
||||
printf '%s' "$release" | jq -e --arg c "$checksums" '.assets[] | select(.name == $c)' >/dev/null \
|
||||
|| die "checksum file ${checksums} missing on ${tag}; refusing to install unverified binary"
|
||||
|
||||
url="https://github.com/${REPO}/releases/download/${tag}/${asset}"
|
||||
sums_url="https://github.com/${REPO}/releases/download/${tag}/${checksums}"
|
||||
|
||||
tmp=$(mktemp -d 2>/dev/null || mktemp -d -t difyctl-install)
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
|
||||
printf 'downloading %s\n from %s\n' "$asset" "$url"
|
||||
curl -fsSL --retry 3 "$url" -o "${tmp}/${asset}"
|
||||
curl -fsSL --retry 3 "$sums_url" -o "${tmp}/${checksums}"
|
||||
|
||||
(
|
||||
cd "$tmp"
|
||||
grep " ${asset}\$" "$checksums" | $HASH -c -
|
||||
) || die "checksum mismatch for ${asset}"
|
||||
|
||||
if command -v cosign >/dev/null 2>&1; then
|
||||
sig_url="${url}.sig"
|
||||
pem_url="${url}.pem"
|
||||
curl -fsSL --retry 3 "$sig_url" -o "${tmp}/${asset}.sig" \
|
||||
|| die "tarball signature missing on ${tag}; refusing to install (cosign present)"
|
||||
curl -fsSL --retry 3 "$pem_url" -o "${tmp}/${asset}.pem" \
|
||||
|| die "tarball cert missing on ${tag}; refusing to install (cosign present)"
|
||||
COSIGN_EXPERIMENTAL=1 cosign verify-blob \
|
||||
--certificate "${tmp}/${asset}.pem" \
|
||||
--signature "${tmp}/${asset}.sig" \
|
||||
--certificate-identity-regexp '^https://github.com/langgenius/dify/' \
|
||||
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
|
||||
"${tmp}/${asset}" \
|
||||
|| die "cosign verification failed for ${asset}"
|
||||
printf 'cosign: verified %s\n' "$asset"
|
||||
else
|
||||
printf 'note: cosign not installed; skipping signature verification (sha256 still enforced)\n' >&2
|
||||
fi
|
||||
|
||||
share_dir="${PREFIX}/share/difyctl"
|
||||
bin_dir="${PREFIX}/bin"
|
||||
mkdir -p "$share_dir" "$bin_dir"
|
||||
|
||||
printf 'extracting to %s\n' "$share_dir"
|
||||
tar -xJf "${tmp}/${asset}" -C "$share_dir" --strip-components=1
|
||||
|
||||
target_bin="${share_dir}/bin/difyctl"
|
||||
[ -x "$target_bin" ] || die "expected binary at ${target_bin} after extract"
|
||||
|
||||
ln -sf "$target_bin" "${bin_dir}/difyctl"
|
||||
|
||||
printf '\ndifyctl %s installed: %s/difyctl\n' "$cli_v" "$bin_dir"
|
||||
|
||||
case ":${PATH}:" in
|
||||
*":${bin_dir}:"*)
|
||||
"${bin_dir}/difyctl" version >/dev/null 2>&1 \
|
||||
&& printf 'verify: run "difyctl version"\n' \
|
||||
|| err "binary present but failed to execute; check ${bin_dir}/difyctl"
|
||||
;;
|
||||
*)
|
||||
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
|
||||
Reference in New Issue
Block a user