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
2 changes: 1 addition & 1 deletion src/conda/NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ conda install python=3.7

## OS Support

This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed.
This Feature should work on recent versions of Debian/Ubuntu-based distributions with the `apt` package manager installed. Both `x86_64` and `aarch64` architectures are supported.

`bash` is required to execute the `install.sh` script.
2 changes: 1 addition & 1 deletion src/conda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A cross-platform, language-agnostic binary package manager

```json
"features": {
"ghcr.io/devcontainers/features/conda:1": {}
"ghcr.io/devcontainers/features/conda:2": {}
}
```

Expand Down
6 changes: 3 additions & 3 deletions src/conda/devcontainer-feature.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "conda",
"version": "1.2.6",
"version": "2.0.0",
"name": "Conda",
"description": "A cross-platform, language-agnostic binary package manager",
"documentationURL": "https://github.com/devcontainers/features/tree/main/src/conda",
Expand All @@ -9,8 +9,8 @@
"type": "string",
"proposals": [
"latest",
"4.11.0",
"4.12.0"
"24.11.3",
"24.7.1"
],
"default": "latest",
"description": "Select or enter a conda version."
Expand Down
115 changes: 44 additions & 71 deletions src/conda/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,14 @@ elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
fi

architecture="$(uname -m)"
if [ "${architecture}" != "x86_64" ]; then
echo "(!) Architecture $architecture unsupported"
exit 1
fi
case "${architecture}" in
x86_64) MINICONDA_ARCH="x86_64" ;;
aarch64|arm64) MINICONDA_ARCH="aarch64" ;;
*)
echo "(!) Architecture $architecture unsupported"
exit 1
;;
esac

# Checks if packages are installed and installs them if not
check_packages() {
Expand All @@ -75,6 +79,17 @@ install_user_package() {
sudo_if "${CONDA_DIR}/bin/python3" -m pip install --user --upgrade "$PACKAGE"
}

accept_anaconda_tos_if_needed() {
if ! "${CONDA_DIR}/bin/conda" tos --help > /dev/null 2>&1; then
return 0
fi

for channel in "https://repo.anaconda.com/pkgs/main" "https://repo.anaconda.com/pkgs/r"; do
echo "Accepting Conda Terms of Service for ${channel}..."
"${CONDA_DIR}/bin/conda" tos accept --override-channels --channel "${channel}"
done
}

# Install Conda if it's missing
if ! conda --version &> /dev/null ; then
if ! cat /etc/group | grep -e "^conda:" > /dev/null 2>&1; then
Expand All @@ -85,78 +100,36 @@ if ! conda --version &> /dev/null ; then
# Install dependencies
check_packages curl ca-certificates

echo "Installing Conda..."
echo "Installing Conda via Miniconda installer..."

# Download .deb package directly from repository (bypassing SHA1 signature issue)
TEMP_DEB="$(mktemp -t conda_XXXXXX.deb)"
CONDA_REPO_BASE="https://repo.anaconda.com/pkgs/misc/debrepo/conda"

# Determine package filename based on requested version
ARCH="$(dpkg --print-architecture 2>/dev/null || echo "amd64")"
PACKAGES_URL="https://repo.anaconda.com/pkgs/misc/debrepo/conda/dists/stable/main/binary-${ARCH}/Packages"

if [ "${VERSION}" = "latest" ]; then
# For latest, we need to query the repository to find the current version
echo "Fetching package list to determine latest version..."
CONDA_PKG_INFO=$(curl -fsSL "${PACKAGES_URL}" | grep -A 30 "^Package: conda$" | head -n 31)
CONDA_VERSION=$(echo "${CONDA_PKG_INFO}" | grep "^Version:" | head -n 1 | awk '{print $2}')
CONDA_FILENAME=$(echo "${CONDA_PKG_INFO}" | grep "^Filename:" | head -n 1 | awk '{print $2}')

if [ -z "${CONDA_VERSION}" ] || [ -z "${CONDA_FILENAME}" ]; then
echo "ERROR: Could not determine latest conda version or filename from ${PACKAGES_URL}"
echo "This may indicate an unsupported architecture or repository unavailability."
rm -f "${TEMP_DEB}"
exit 1
fi

CONDA_PKG_NAME="${CONDA_FILENAME}"
else
# For specific versions, query the Packages file to find the exact filename
echo "Fetching package list to find version ${VERSION}..."
# Search for version pattern - user may specify 4.12.0 but package has 4.12.0-0
CONDA_PKG_INFO=$(curl -fsSL "${PACKAGES_URL}" | grep -A 30 "^Package: conda$" | grep -B 5 -A 25 "^Version: ${VERSION}")
CONDA_FILENAME=$(echo "${CONDA_PKG_INFO}" | grep "^Filename:" | head -n 1 | awk '{print $2}')

if [ -z "${CONDA_FILENAME}" ]; then
echo "ERROR: Could not find conda version ${VERSION} in ${PACKAGES_URL}"
echo "Please verify the version specified is valid."
rm -f "${TEMP_DEB}"
exit 1
fi

CONDA_PKG_NAME="${CONDA_FILENAME}"
fi

# Download the .deb package
CONDA_DEB_URL="${CONDA_REPO_BASE}/${CONDA_PKG_NAME}"
echo "Downloading conda package from ${CONDA_DEB_URL}..."

if ! curl -fsSL "${CONDA_DEB_URL}" -o "${TEMP_DEB}"; then
echo "ERROR: Failed to download conda .deb package from ${CONDA_DEB_URL}"
echo "Please verify the version specified is valid."
rm -f "${TEMP_DEB}"
exit 1
fi

# Verify the package was downloaded successfully
if [ ! -f "${TEMP_DEB}" ] || [ ! -s "${TEMP_DEB}" ]; then
echo "ERROR: Conda .deb package file is missing or empty"
rm -f "${TEMP_DEB}"
# Download and run the official Miniconda installer
MINICONDA_INSTALLER="$(mktemp -t miniconda_XXXXXX.sh)"
MINICONDA_URL="https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-${MINICONDA_ARCH}.sh"

echo "Downloading Miniconda installer from ${MINICONDA_URL}..."
if ! curl -fsSL --connect-timeout 10 --max-time 120 "${MINICONDA_URL}" -o "${MINICONDA_INSTALLER}"; then
echo "ERROR: Failed to download Miniconda installer from ${MINICONDA_URL}"
rm -f "${MINICONDA_INSTALLER}"
exit 1
fi

# Install the package using apt (which handles dependencies automatically)
echo "Installing conda package..."
if ! apt-get install -y "${TEMP_DEB}"; then
echo "ERROR: Failed to install conda package"
rm -f "${TEMP_DEB}"
exit 1

# Run installer in batch mode (no prompts) and install to CONDA_DIR
bash "${MINICONDA_INSTALLER}" -b -p "${CONDA_DIR}"
rm -f "${MINICONDA_INSTALLER}"

# Conda defaults channels now require a non-interactive ToS acknowledgement.
accept_anaconda_tos_if_needed

# Install specific conda version if requested (latest Miniconda already bundles a recent conda)
if [ "${VERSION}" != "latest" ]; then
echo "Installing conda version ${VERSION}..."
if ! "${CONDA_DIR}/bin/conda" install -y "conda=${VERSION}"; then
echo "ERROR: Failed to install conda version ${VERSION}. Please verify the version is valid and available."
exit 1
fi
fi

# Clean up downloaded package
rm -f "${TEMP_DEB}"

CONDA_SCRIPT="/opt/conda/etc/profile.d/conda.sh"
CONDA_SCRIPT="${CONDA_DIR}/etc/profile.d/conda.sh"
. $CONDA_SCRIPT

if [ "${ADD_CONDA_FORGE}" = "true" ]; then
Expand Down
4 changes: 2 additions & 2 deletions test/conda/conda_channel_creation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ source dev-container-features-test-lib

## Test Conda
check "conda-update-conda" bash -c "conda update -c defaults -y conda"
check "conda-install-tensorflow" bash -c "conda create --name test-env -c conda-forge --yes tensorflow"
check "conda-install-pytorch" bash -c "conda create --name test-env -c conda-forge --yes pytorch"
check "conda-install-tensorflow" bash -c "conda create --name tensorflow-test-env -c conda-forge --yes tensorflow"
check "conda-install-pytorch" bash -c "conda create --name pytorch-test-env -c conda-forge --yes pytorch"

# Report result
reportResults
4 changes: 3 additions & 1 deletion test/conda/install_conda.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ set -e
# Optional: Import test library
source dev-container-features-test-lib

check "conda" conda --version | grep 4.12.0
check "conda" conda --version
check "conda update" conda update -n base -c defaults -y conda
check "conda updated version" conda --version
check "conda-forge" conda config --show channels | grep conda-forge
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt

Expand Down
3 changes: 3 additions & 0 deletions test/conda/install_conda_package_after_upgrade.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@ source dev-container-features-test-lib
# This validates the fix for the pluggy/conda version mismatch issue where
# conda self-upgrades but the older pluggy lacks the 'wrapper' attribute
check "conda version" conda --version
check "conda update" conda update -n base -c defaults -y conda
check "conda updated version" conda --version
check "install pyopenssl" conda install -y -c defaults pyopenssl
check "install cryptography" conda install -y -c defaults cryptography
check "install scipy with bioconda" conda install -y -c bioconda scipy
check "conda-forge" conda config --show channels | grep conda-forge
check "if conda-notice.txt exists" cat /usr/local/etc/vscode-dev-containers/conda-notice.txt

Expand Down
2 changes: 1 addition & 1 deletion test/conda/scenarios.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"image": "ubuntu:noble",
"features": {
"conda": {
"version": "4.12.0",
"version": "latest",
"addCondaForge": "true"
}
}
Expand Down
Loading