Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
pull-requests: write
packages: write
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Publish Features"
uses: devcontainers/action@v1
Expand Down
15 changes: 8 additions & 7 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,16 @@ jobs:
strategy:
matrix:
features:
- color
- hello
- doppler-cli
baseImage:
- debian:latest
- ubuntu:latest
- alpine:latest
- fedora:latest
- mcr.microsoft.com/devcontainers/base:ubuntu
- mcr.microsoft.com/devcontainers/base:debian
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli
Expand All @@ -34,10 +36,9 @@ jobs:
strategy:
matrix:
features:
- color
- hello
- doppler-cli
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli
Expand All @@ -49,7 +50,7 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Install latest devcontainer CLI"
run: npm install -g @devcontainers/cli
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
name: "Validate devcontainer-feature.json files"
on:
workflow_dispatch:
pull_request:
workflow_dispatch:

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: "Validate devcontainer-feature.json files"
uses: devcontainers/action@v1
Expand Down
22 changes: 9 additions & 13 deletions src/doppler-cli/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
{
"name": "Doppler CLI",
"id": "doppler-cli",
"version": "1.0.0",
"description": "A feature that installs the Doppler CLI",
"documentationURL": "https://github.com/dopplerhq/devcontainer-features/tree/main/src/doppler-cli",
"containerEnv": {
"DOPPLER_CONFIG_DIR": "/doppler"
"name": "Doppler CLI",
"description": "Installs the Doppler CLI for secrets management.",
"options": {
"version": {
"type": "string",
"default": "latest",
"description": "Version of the Doppler CLI to install (e.g., '3.67.0' or 'latest')"
}
},
"mounts": [
{
"source": "doppler-cli-user-config",
"target": "/doppler",
"type": "volume"
}
],
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
"ghcr.io/devcontainers/features/common-utils"
]
}
179 changes: 163 additions & 16 deletions src/doppler-cli/install.sh
Original file line number Diff line number Diff line change
@@ -1,24 +1,171 @@
#!/usr/bin/env bash

#!/bin/sh
set -e

ensure_curl() {
if ! type curl >/dev/null 2>&1; then
apt-get update -y && apt-get -y install --no-install-recommends curl
fi
echo "=== Doppler CLI Feature Install ==="
echo "VERSION: ${VERSION:-latest}"
echo "_REMOTE_USER: ${_REMOTE_USER:-not set}"

VERSION="${VERSION:-latest}"

# Detect package manager
detect_package_manager() {
if type apt-get >/dev/null 2>&1; then
echo "apt"
elif type apk >/dev/null 2>&1; then
echo "apk"
elif type dnf >/dev/null 2>&1; then
echo "dnf"
elif type yum >/dev/null 2>&1; then
echo "yum"
else
echo "unknown"
fi
}

ensure_gpg() {
if ! type gpg >/dev/null 2>&1; then
apt-get update -y && apt-get -y install --no-install-recommends gnupg2
fi
# Install a package using the detected package manager
install_package() {
local pkg_manager="$1"
shift
local packages="$@"

case "$pkg_manager" in
apt)
apt-get update -y && apt-get install -y --no-install-recommends $packages
rm -rf /var/lib/apt/lists/*
;;
apk)
apk add --no-cache $packages
;;
dnf)
dnf install -y $packages && dnf clean all
rm -rf /var/cache/dnf
;;
yum)
yum install -y $packages && yum clean all
rm -rf /var/cache/yum
;;
*)
echo "ERROR: Unsupported package manager. Please install manually: $packages"
exit 1
;;
esac
}

ensure_curl
ensure_gpg
PKG_MANAGER=$(detect_package_manager)
echo "Detected package manager: $PKG_MANAGER"

# Install dependencies if missing
echo "Checking for curl..."
if ! type curl >/dev/null 2>&1; then
echo "Installing curl..."
case "$PKG_MANAGER" in
apt) install_package "$PKG_MANAGER" curl ca-certificates ;;
apk) install_package "$PKG_MANAGER" curl ca-certificates ;;
dnf|yum) install_package "$PKG_MANAGER" curl ;;
*) echo "ERROR: Cannot install curl"; exit 1 ;;
esac
fi

echo "Checking for gpgv..."
if ! type gpgv >/dev/null 2>&1; then
echo "Installing gpgv..."
case "$PKG_MANAGER" in
apt) install_package "$PKG_MANAGER" gpgv ;;
apk) install_package "$PKG_MANAGER" gpgv ;;
dnf|yum) install_package "$PKG_MANAGER" gnupg2 ;;
*) echo "ERROR: Cannot install gpgv"; exit 1 ;;
esac
fi

# Ensure gpgv is in PATH (may not be after fresh install)
if ! type gpgv >/dev/null 2>&1; then
echo "gpgv not in PATH, checking common locations..."
for path in /usr/bin/gpgv /bin/gpgv /usr/local/bin/gpgv; do
if [ -x "$path" ]; then
echo "Found gpgv at $path, adding to PATH"
export PATH="$(dirname "$path"):$PATH"
break
fi
done
fi

# Final check
if ! type gpgv >/dev/null 2>&1; then
echo "ERROR: gpgv not found after installing gnupg"
exit 1
fi

# Strip 'v' prefix from version if present (e.g., "v3.69.0" -> "3.69.0")
VERSION="${VERSION#v}"

# Install bash if needed (Alpine doesn't have it, but Doppler's install script requires it)
if [ "$PKG_MANAGER" = "apk" ] && ! type bash >/dev/null 2>&1; then
echo "Installing bash (required by Doppler install script)..."
apk add --no-cache bash
fi

# Install Doppler CLI
echo "Installing Doppler CLI (version: $VERSION)..."
if [ "$VERSION" = "latest" ]; then
# Use official install script for latest (includes signature verification)
echo "Fetching Doppler install script..."
curl -Ls --tlsv1.2 --proto "=https" --retry 3 https://cli.doppler.com/install.sh | bash
else
# Download specific version directly from GitHub releases
echo "Downloading Doppler CLI v$VERSION from GitHub releases..."

# Detect OS
OS=$(uname -s | tr '[:upper:]' '[:lower:]')
case "$OS" in
darwin) OS="macos" ;;
linux) OS="linux" ;;
*) echo "ERROR: Unsupported OS: $OS"; exit 1 ;;
esac

# Detect architecture
ARCH=$(uname -m)
case "$ARCH" in
x86_64|amd64) ARCH="amd64" ;;
aarch64|arm64) ARCH="arm64" ;;
armv7l) ARCH="armv7" ;;
armv6l) ARCH="armv6" ;;
i386|i686) ARCH="i386" ;;
*) echo "ERROR: Unsupported architecture: $ARCH"; exit 1 ;;
esac

TEMP_DIR=$(mktemp -d)
TARBALL="doppler_${VERSION}_${OS}_${ARCH}.tar.gz"
DOWNLOAD_URL="https://github.com/DopplerHQ/cli/releases/download/${VERSION}/${TARBALL}"
SIG_URL="${DOWNLOAD_URL}.sig"

# Download tarball
echo "Downloading from: $DOWNLOAD_URL"
curl -Ls --tlsv1.2 --proto "=https" --retry 3 -o "$TEMP_DIR/$TARBALL" "$DOWNLOAD_URL"

# Download signature
echo "Downloading signature from: $SIG_URL"
curl -Ls --tlsv1.2 --proto "=https" --retry 3 -o "$TEMP_DIR/${TARBALL}.sig" "$SIG_URL"

# Download public key
echo "Downloading Doppler public key..."
curl -Ls --tlsv1.2 --proto "=https" --retry 3 -o "$TEMP_DIR/doppler-public-key.gpg" "https://cli.doppler.com/keys/public"

# Verify signature
echo "Verifying signature..."
if ! gpgv --keyring "$TEMP_DIR/doppler-public-key.gpg" "$TEMP_DIR/${TARBALL}.sig" "$TEMP_DIR/$TARBALL" 2>/dev/null; then
echo "ERROR: Signature verification failed!"
rm -rf "$TEMP_DIR"
exit 1
fi
echo "Signature verification successful."

# Extract and install
tar -xzf "$TEMP_DIR/$TARBALL" -C "$TEMP_DIR"
mv "$TEMP_DIR/doppler" /usr/local/bin/doppler
chmod +x /usr/local/bin/doppler

# download and execute the latest installer.
curl -Ls --tlsv1.2 --proto "=https" --retry 3 https://cli.doppler.com/install.sh | sh
rm -rf "$TEMP_DIR"
fi

# ensure /doppler is writable to store CLI config data
mkdir -p /doppler && chown -R ${_REMOTE_USER}:${_REMOTE_USER} /doppler
echo "=== Installation complete ==="
echo "Doppler CLI installed: $(doppler --version)"
27 changes: 27 additions & 0 deletions test/doppler-cli/_common_latest_version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
# Shared test logic for verifying latest version is installed

set -e

source dev-container-features-test-lib

# Install jq if needed for JSON parsing
if ! type jq >/dev/null 2>&1; then
if type apt-get >/dev/null 2>&1; then
apt-get update -y && apt-get -y install --no-install-recommends jq
elif type apk >/dev/null 2>&1; then
apk add --no-cache jq
elif type dnf >/dev/null 2>&1; then
dnf install -y jq
elif type yum >/dev/null 2>&1; then
yum install -y jq
fi
fi

# Get latest version from GitHub API
latest_version=$(curl -s https://api.github.com/repos/dopplerhq/cli/releases/latest | jq -r '.tag_name')

# Verify installed version matches latest
check "latest version installed" bash -c "doppler -v | grep '${latest_version}'"

reportResults
3 changes: 3 additions & 0 deletions test/doppler-cli/latest_on_alpine.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Test latest version on Alpine
source "$(dirname "$0")/_common_latest_version.sh"
3 changes: 3 additions & 0 deletions test/doppler-cli/latest_on_debian.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Test latest version on Debian
source "$(dirname "$0")/_common_latest_version.sh"
3 changes: 3 additions & 0 deletions test/doppler-cli/latest_on_devcontainer_base.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Test latest version on Microsoft devcontainer base
source "$(dirname "$0")/_common_latest_version.sh"
3 changes: 3 additions & 0 deletions test/doppler-cli/latest_on_fedora.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Test latest version on Fedora
source "$(dirname "$0")/_common_latest_version.sh"
3 changes: 3 additions & 0 deletions test/doppler-cli/latest_on_ubuntu.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
# Test latest version on Ubuntu
source "$(dirname "$0")/_common_latest_version.sh"
10 changes: 10 additions & 0 deletions test/doppler-cli/pinned_version_on_ubuntu.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

set -e

source dev-container-features-test-lib

# Verify the specific pinned version is installed
check "pinned version 3.69.0 installed" bash -c "doppler -v | grep 'v3.69.0'"

reportResults
32 changes: 29 additions & 3 deletions test/doppler-cli/scenarios.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
{
"doppler_cli_installed": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"latest_on_ubuntu": {
"image": "ubuntu:latest",
"features": {
"doppler-cli": {}
}
},
"latest_on_debian": {
"image": "debian:latest",
"features": {
"doppler-cli": {}
}
},
"latest_on_alpine": {
"image": "alpine:latest",
"features": {
"doppler-cli": {}
}
},
"latest_on_fedora": {
"image": "fedora:latest",
"features": {
"doppler-cli": {}
}
},
"doppler_cli_version": {
"latest_on_devcontainer_base": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"features": {
"doppler-cli": {}
}
},
"pinned_version_on_ubuntu": {
"image": "ubuntu:latest",
"features": {
"doppler-cli": {
"version": "3.69.0"
}
}
}
}
Loading