From 0c037adf82d29a96381095d1ab924ac16504aac0 Mon Sep 17 00:00:00 2001 From: Austin Moses Date: Tue, 3 Feb 2026 13:55:30 -0700 Subject: [PATCH] Initial Doppler devcontainer feature --- .../devcontainer.json | 0 .github/workflows/release.yaml | 2 +- .github/workflows/test.yaml | 15 +- .github/workflows/validate.yml | 4 +- LICENSE | 212 ++++++++++++++++-- README.md | 72 ++---- src/doppler-cli/devcontainer-feature.json | 23 +- src/doppler-cli/install.sh | 179 +++++++++++++-- test/doppler-cli/_common_latest_version.sh | 27 +++ test/doppler-cli/latest_on_alpine.sh | 3 + test/doppler-cli/latest_on_debian.sh | 3 + .../latest_on_devcontainer_base.sh | 3 + test/doppler-cli/latest_on_fedora.sh | 3 + test/doppler-cli/latest_on_ubuntu.sh | 3 + test/doppler-cli/pinned_version_on_ubuntu.sh | 10 + test/doppler-cli/scenarios.json | 32 ++- test/doppler-cli/test.sh | 13 +- 17 files changed, 488 insertions(+), 116 deletions(-) rename .devcontainer.json => .devcontainer/devcontainer.json (100%) create mode 100644 test/doppler-cli/_common_latest_version.sh create mode 100644 test/doppler-cli/latest_on_alpine.sh create mode 100644 test/doppler-cli/latest_on_debian.sh create mode 100644 test/doppler-cli/latest_on_devcontainer_base.sh create mode 100644 test/doppler-cli/latest_on_fedora.sh create mode 100644 test/doppler-cli/latest_on_ubuntu.sh create mode 100644 test/doppler-cli/pinned_version_on_ubuntu.sh diff --git a/.devcontainer.json b/.devcontainer/devcontainer.json similarity index 100% rename from .devcontainer.json rename to .devcontainer/devcontainer.json diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 935ef81..22509b2 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -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 diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 9e5f9bf..c5b2576 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -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 @@ -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 @@ -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 diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 5dcc21b..e517a86 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -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 diff --git a/LICENSE b/LICENSE index 35bef52..53cd7b0 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,191 @@ -MIT License - -Copyright (c) 2022 Microsoft Corporation - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to the Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by the Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding any notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2023 Doppler, Inc. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index b684baf..1a2ce4a 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,18 @@ -# Features +# Doppler Dev Container Features -This project **Features** is a set of reusable 'features'. Quickly add a tool/cli to a development container. +A collection of [Dev Container Features](https://containers.dev/implementors/features/) for integrating [Doppler](https://doppler.com) into your development containers. -_Features_ are self-contained units of installation code and development container configuration. Features are designed to install atop a wide-range of base container images (this repo focuses on **debian based images**). +> This repo follows the [dev container feature distribution specification](https://containers.dev/implementors/features-distribution/). -> This repo follows the [**proposed** dev container feature distribution specification](https://containers.dev/implementors/features-distribution/). +## Features -**List of features:** - -- [doppler-cli](src/doppler-cli/README.md): Install the Doppler CLI +| Feature | Description | +| ------- | ----------- | +| [doppler-cli](src/doppler-cli/README.md) | Installs the [Doppler CLI](https://docs.doppler.com/docs/cli) for secrets management | ## Usage -To reference a feature from this repository, add the desired features to a devcontainer.json. Each feature has a README.md that shows how to reference the feature and which options are available for that feature. - -The example below installs the _doppler-cli_ declared in the `./src` directory of this repository. - -See the relevant feature's README for supported options. +Add the desired feature to your `devcontainer.json`: ```jsonc { @@ -27,54 +23,32 @@ See the relevant feature's README for supported options. } ``` -After starting a devcontainer with this feature enabled, you'll need to run -`doppler login` once. The config file is stored in a file located at `/doppler` -which is a mount of a docker volume called `doppler-cli-user-config`. When -starting subsequent devcontainers, your config should be retained so logging -in won't be necessary. If you don't want your session to persist, be sure to -explicitly run `doppler logout` before ending your session. +See the [doppler-cli feature README](src/doppler-cli/README.md) for supported options. -# Development +### Options -To test this locally, you'll need to install the [devcontainer CLI](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli): +| Option | Type | Default | Description | +| ------ | ---- | ------- | ----------- | +| `version` | `string` | `latest` | Version of the Doppler CLI to install (e.g., `3.67.0` or `latest`) | -```shell -npm install -g @devcontainers/cli -``` - -## Running Tests +### OS Support -To run the test suite, execute the following command: - -```shell -devcontainer features test --features doppler-cli --base-image mcr.microsoft.com/devcontainers/base:ubuntu . -``` +This feature supports Debian/Ubuntu-based distributions, Red Hat/Fedora-based distributions, and Alpine Linux. -## Executing Locally +## Development -You can fire up a devcontainer using the `devcontainer` CLI. To start, grab a -sample project like Microsoft's [vscode-remote-try-node](https://github.com/microsoft/vscode-remote-try-node). Clone that locally and then copy the feature -directory to the `.devcontainer` directory in that project. To do that, run this command from the root devcontainer-feature project directory: +To test locally, install the [devcontainer CLI](https://code.visualstudio.com/docs/devcontainers/devcontainer-cli): ```shell -cp -r src/doppler-cli/ /path/to/vscode-remote-try-node/.devcontainer/doppler-cli -``` - -Now, edit the `devcontainer.json` file in the `vscode-remote-try-node` project -by uncommenting the `"features": {},` line and changing it to: - -```jsonc -"features": { - "./doppler-cli": {} -}, +npm install -g @devcontainers/cli ``` -Finally, up one directory from the `vscode-remote-try-node` project, run -this command: +### Running Tests ```shell -devcontainer up --workspace-folder vscode-remote-try-node/ +devcontainer features test --features doppler-cli --base-image mcr.microsoft.com/devcontainers/base:ubuntu . ``` -From there, you can connect to the container, switch to the `vscode` user and -run `doppler login`. \ No newline at end of file +## License + +Licensed under the [Apache License 2.0](LICENSE). diff --git a/src/doppler-cli/devcontainer-feature.json b/src/doppler-cli/devcontainer-feature.json index 95909ab..3b2acf8 100644 --- a/src/doppler-cli/devcontainer-feature.json +++ b/src/doppler-cli/devcontainer-feature.json @@ -1,20 +1,17 @@ { - "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" - } - ], + "licenseURL": "https://github.com/DopplerHQ/devcontainer-features/blob/main/LICENSE", "installsAfter": [ - "ghcr.io/devcontainers/features/common-utils" + "ghcr.io/devcontainers/features/common-utils" ] } diff --git a/src/doppler-cli/install.sh b/src/doppler-cli/install.sh index 4a581f6..1603180 100644 --- a/src/doppler-cli/install.sh +++ b/src/doppler-cli/install.sh @@ -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)" diff --git a/test/doppler-cli/_common_latest_version.sh b/test/doppler-cli/_common_latest_version.sh new file mode 100644 index 0000000..6384bce --- /dev/null +++ b/test/doppler-cli/_common_latest_version.sh @@ -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 diff --git a/test/doppler-cli/latest_on_alpine.sh b/test/doppler-cli/latest_on_alpine.sh new file mode 100644 index 0000000..6d37a8a --- /dev/null +++ b/test/doppler-cli/latest_on_alpine.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Test latest version on Alpine +source "$(dirname "$0")/_common_latest_version.sh" diff --git a/test/doppler-cli/latest_on_debian.sh b/test/doppler-cli/latest_on_debian.sh new file mode 100644 index 0000000..0ab5586 --- /dev/null +++ b/test/doppler-cli/latest_on_debian.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Test latest version on Debian +source "$(dirname "$0")/_common_latest_version.sh" diff --git a/test/doppler-cli/latest_on_devcontainer_base.sh b/test/doppler-cli/latest_on_devcontainer_base.sh new file mode 100644 index 0000000..d210cc1 --- /dev/null +++ b/test/doppler-cli/latest_on_devcontainer_base.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Test latest version on Microsoft devcontainer base +source "$(dirname "$0")/_common_latest_version.sh" \ No newline at end of file diff --git a/test/doppler-cli/latest_on_fedora.sh b/test/doppler-cli/latest_on_fedora.sh new file mode 100644 index 0000000..b866b2f --- /dev/null +++ b/test/doppler-cli/latest_on_fedora.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Test latest version on Fedora +source "$(dirname "$0")/_common_latest_version.sh" diff --git a/test/doppler-cli/latest_on_ubuntu.sh b/test/doppler-cli/latest_on_ubuntu.sh new file mode 100644 index 0000000..1c242ac --- /dev/null +++ b/test/doppler-cli/latest_on_ubuntu.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash +# Test latest version on Ubuntu +source "$(dirname "$0")/_common_latest_version.sh" \ No newline at end of file diff --git a/test/doppler-cli/pinned_version_on_ubuntu.sh b/test/doppler-cli/pinned_version_on_ubuntu.sh new file mode 100644 index 0000000..9763fe8 --- /dev/null +++ b/test/doppler-cli/pinned_version_on_ubuntu.sh @@ -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 diff --git a/test/doppler-cli/scenarios.json b/test/doppler-cli/scenarios.json index 9cea1ce..36426bc 100644 --- a/test/doppler-cli/scenarios.json +++ b/test/doppler-cli/scenarios.json @@ -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" + } + } } } \ No newline at end of file diff --git a/test/doppler-cli/test.sh b/test/doppler-cli/test.sh index 402b5e1..340f11f 100644 --- a/test/doppler-cli/test.sh +++ b/test/doppler-cli/test.sh @@ -7,12 +7,17 @@ set -e -# Optional: Import test library bundled with the devcontainer CLI -# Provides the 'check' and 'reportResults' commands. +# Import test library bundled with the devcontainer CLI source dev-container-features-test-lib -check "version" doppler -v +# Check CLI is installed and executable +check "doppler is installed" command -v doppler + +# Check version outputs valid semver format +check "version format" bash -c "doppler -v | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+'" + +# Check CLI responds to help +check "help output" bash -c "doppler -h | grep 'The official Doppler CLI'" # Report results -# If any of the checks above exited with a non-zero exit code, the test will fail. reportResults \ No newline at end of file