Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 31 additions & 4 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
# irm https://get.devicecloud.dev/install.ps1 | iex
#
# Env vars:
# DCD_VERSION Pin a specific version (default: latest)
# DCD_VERSION Pin a specific version, e.g. for rollback (default: latest stable)
# DCD_BETA Set to any value to install the latest beta/prerelease (opt-in)
# DCD_INSTALL_DIR Override install location (default: $env:USERPROFILE\.dcd\bin)
# DCD_DOWNLOAD_BASE Override the download host (default: https://get.devicecloud.dev)

Expand All @@ -25,13 +26,39 @@ if ([Environment]::Is64BitOperatingSystem -ne $true) {
$asset = 'dcd-windows-x64.exe'

# --- resolve version ---
# Precedence: explicit DCD_VERSION pin > DCD_BETA opt-in > latest stable.
if ($env:DCD_VERSION) {
$version = $env:DCD_VERSION
} else {
Write-Host 'Resolving latest version...'
$manifest = Invoke-RestMethod -Uri "$DownloadBase/latest.json"
if ($env:DCD_BETA) {
Write-Host 'Resolving latest beta version...'
$manifestUrl = "$DownloadBase/latest.json?channel=beta"
$channel = 'beta'
} else {
Write-Host 'Resolving latest version...'
$manifestUrl = "$DownloadBase/latest.json"
$channel = 'stable'
}
try {
$manifest = Invoke-RestMethod -Uri $manifestUrl
} catch {
throw "Could not reach $manifestUrl"
}
# A null version means the channel has no release yet (HTTP 200), as opposed
# to a transient failure (which throws above). Stable is the default and beta
# is strictly opt-in, so refuse to silently fall back to a prerelease.
$version = $manifest.version
if (-not $version) { throw "Could not resolve latest version from $DownloadBase/latest.json" }
if (-not $version) {
if ($channel -eq 'stable') {
throw @"
No stable dcd release is available yet.
Install the latest beta: `$env:DCD_BETA=1; irm '$DownloadBase/install.ps1' | iex
Or pin a version: `$env:DCD_VERSION='5.0.0-beta.1'; irm '$DownloadBase/install.ps1' | iex
"@
} else {
throw "No beta release is available yet from $manifestUrl"
}
}
}

$url = "$DownloadBase/download/$version/$asset"
Expand Down
45 changes: 40 additions & 5 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
# curl -fsSL https://get.devicecloud.dev/install.sh | sh
#
# Env vars:
# DCD_VERSION Pin a specific version (default: latest)
# DCD_VERSION Pin a specific version, e.g. for rollback (default: latest stable)
# DCD_BETA Set to any value to install the latest beta/prerelease (opt-in)
# DCD_INSTALL_DIR Override install location (default: $HOME/.dcd/bin)
# DCD_DOWNLOAD_BASE Override the download host (default: https://get.devicecloud.dev)
#
Expand All @@ -23,6 +24,17 @@ info() {
printf '%s\n' "$1"
}

# Stable is the default channel and beta is strictly opt-in, so when no stable
# release exists yet (only prereleases published) we refuse to silently install a
# beta and instead point the user at the two explicit opt-ins. $DOWNLOAD_BASE is
# echoed so a custom host shows the right command.
no_stable_release_err() {
printf 'error: No stable dcd release is available yet.\n' >&2
printf ' Install the latest beta: curl -fsSL %s/install.sh | DCD_BETA=1 sh\n' "$DOWNLOAD_BASE" >&2
printf ' Or pin a version: curl -fsSL %s/install.sh | DCD_VERSION=5.0.0-beta.1 sh\n' "$DOWNLOAD_BASE" >&2
exit 1
}

# Find a dcd on PATH other than the one we just installed — usually a leftover
# `npm install -g @devicecloud.dev/dcd` that can shadow this binary. Runs in a
# subshell so the temporary IFS change never leaks back to the caller.
Expand Down Expand Up @@ -121,17 +133,40 @@ main() {
asset="dcd-${os_id}-${arch_id}"

# --- resolve version ---
# Precedence: explicit DCD_VERSION pin > DCD_BETA opt-in > latest stable.
if [ -n "${DCD_VERSION:-}" ]; then
version="$DCD_VERSION"
else
info "Resolving latest version..."
# /latest.json returns { "version": "5.1.0", ... }
if [ -n "${DCD_BETA:-}" ]; then
channel=beta
manifest_url="$DOWNLOAD_BASE/latest.json?channel=beta"
info "Resolving latest beta version..."
else
channel=stable
manifest_url="$DOWNLOAD_BASE/latest.json"
info "Resolving latest version..."
fi

# Fetch the manifest separately from parsing so we can tell a transient
# network/proxy failure (curl -f returns non-zero → empty $manifest) apart
# from a channel that simply has no release yet (HTTP 200 with
# "version": null → $manifest non-empty but $version empty).
manifest=$(curl -fsSL "$manifest_url") || manifest=""
[ -z "$manifest" ] && err "Could not reach $manifest_url"
# /latest.json returns { "version": "5.1.0", ... }; a null version is unquoted
# and so won't match this quoted-string pattern.
version=$(
curl -fsSL "$DOWNLOAD_BASE/latest.json" \
printf '%s' "$manifest" \
| sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
| head -n1
)
[ -z "$version" ] && err "Could not resolve latest version from $DOWNLOAD_BASE/latest.json"
if [ -z "$version" ]; then
if [ "$channel" = stable ]; then
no_stable_release_err
else
err "No beta release is available yet from $manifest_url"
fi
fi
fi

url="$DOWNLOAD_BASE/download/${version}/${asset}"
Expand Down
Loading