diff --git a/.github/workflows/features-test.yaml b/.github/workflows/features-test.yaml index d84dbd8..155ca40 100644 --- a/.github/workflows/features-test.yaml +++ b/.github/workflows/features-test.yaml @@ -18,12 +18,10 @@ jobs: matrix: features: - asdf + - pixi baseImage: - - debian:latest - - ubuntu:latest - - alpine:latest - mcr.microsoft.com/devcontainers/base:ubuntu - - mcr.microsoft.com/devcontainers/base:alpine + - mcr.microsoft.com/devcontainers/base:debian steps: - uses: actions/checkout@v4 @@ -40,6 +38,7 @@ jobs: matrix: features: - asdf + - pixi steps: - uses: actions/checkout@v4 diff --git a/features/src/pixi/NOTES.md b/features/src/pixi/NOTES.md new file mode 100644 index 0000000..5dcb906 --- /dev/null +++ b/features/src/pixi/NOTES.md @@ -0,0 +1,16 @@ +## Limitations + +The `onCreateCommand` relies on having passwordless `sudo` access. Thus, it demands that +both `sudo` is available and the `${remoteUser}` has passwordless access! + +## OS Support +This feature has been tested on Debian-based distributions (Ubuntu & Debian). As of +**14 Sep 2024**, **Alpine is unsupported**. This is because Alpine does not provide a +the virtual package `__glibc`, which means that packages have `glibc` dependencies +cannot be used (_many of the core `conda` packages require `glibc` in some fashion). +Thus, there's little use in starting from an `alpine` image. + +More details on [this GitHub issue][no-alpine-install] (tracked by the folks at +Prefix.dev). + +[no-alpine-install]: https://github.com/prefix-dev/pixi-docker/issues/23 \ No newline at end of file diff --git a/features/src/pixi/devcontainer-feature.json b/features/src/pixi/devcontainer-feature.json new file mode 100644 index 0000000..db508d2 --- /dev/null +++ b/features/src/pixi/devcontainer-feature.json @@ -0,0 +1,36 @@ +{ + "$schema": "https://github.com/devcontainers/spec/raw/main/schemas/devContainerFeature.schema.json", + "id": "pixi", + "version": "0.1.0", + "name": "pixi", + "documentationURL": "https://github.com/jmuchovej/devcontainers/tree/main/features/pixi", + "description": "Add Pixi (by Prefix.dev) to your Dev Container!", + "options": { + "version": { + "type": "string", + "proposals": [ + "latest", + "v0.29.0", + "v0.28.0", + "v0.27.0", + ], + "default": "latest", + "description": "Select (or enter) the version of pixi you want to install." + }, + }, + "installsAfter": [ + "ghcr.io/devcontainers/features/git", + "ghcr.io/devcontainers/features/github-cli", + "ghcr.io/devcontainers/features/common-utils" + ], + // This mount is provided to ease developer experience, particularly on MacOS. + // By default, MacOS is case-insensitive; however, Linux is [by default] case-sensitive. + // Thus, when running Linux-based containers but bind-mounting `/path/to/.pixi`, any + // libraries with case-sensitive filenames (e.g., `ncurses`) will fail to install. + "mounts": [ + { "type": "volume", "target": "${containerWorkspaceFolder}/.pixi", "source": "${devcontainerId}-pixi", } + ], + "onCreateCommand": { + "update .pixi permissions": "sudo chown -R $(id -u) ${containerWorkspaceFolder}/.pixi", + }, +} \ No newline at end of file diff --git a/features/src/pixi/install.sh b/features/src/pixi/install.sh new file mode 100644 index 0000000..f9c5fb1 --- /dev/null +++ b/features/src/pixi/install.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -e + +if [ "$(id -u)" -ne 0 ]; then + err 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.' + exit 1 +fi + +PIXI_HOME=/usr/local +PIXI_VERSION="${VERSION:-"latest"}" +[ "${PIXI_VERSION}" != "latest" ] && PIXI_VERSION="${PIXI_VERSION}" + +curl -fsSL https://pixi.sh/install.sh | \ + PIXI_VERSION="${PIXI_VERSION}" PIXI_HOME="${PIXI_HOME}" bash + +if [ -f "/etc/bash.bashrc" ]; then +echo <<-EOF | tee -a /etc/bash.bashrc +# From: jmuchovej/features/pixi +eval "$(pixi completion --shell bash)" +EOF +fi + +if [ -f "/etc/zsh/zshrc" ]; then +echo <<-EOF | tee -a /etc/zsh/zshrc +# From: jmuchovej/features/pixi +eval "$(pixi completion --shell zsh)" +EOF +fi diff --git a/features/test/pixi/on-debian.sh b/features/test/pixi/on-debian.sh new file mode 100644 index 0000000..4edeff5 --- /dev/null +++ b/features/test/pixi/on-debian.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +export VERSION +$(dirname ${0})/test.sh \ No newline at end of file diff --git a/features/test/pixi/on-ubuntu.sh b/features/test/pixi/on-ubuntu.sh new file mode 100644 index 0000000..4edeff5 --- /dev/null +++ b/features/test/pixi/on-ubuntu.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +export VERSION +$(dirname ${0})/test.sh \ No newline at end of file diff --git a/features/test/pixi/scenarios.json b/features/test/pixi/scenarios.json new file mode 100644 index 0000000..bccd125 --- /dev/null +++ b/features/test/pixi/scenarios.json @@ -0,0 +1,58 @@ +{ + "on-ubuntu": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "ghcr.io/devcontainers/features/common-utils": { + "installZsh": false, + "installOhMyZsh": false, + "upgradePackages": false + }, + "pixi": { + "version": "latest" + } + }, + "remoteUser": "vscode" + }, + "on-debian": { + "image": "mcr.microsoft.com/devcontainers/base:debian", + "features": { + "ghcr.io/devcontainers/features/common-utils": { + "installZsh": false, + "installOhMyZsh": false, + "upgradePackages": false + }, + "pixi": { + "version": "latest" + } + }, + "remoteUser": "vscode" + }, + "with-v0.29.0": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "ghcr.io/devcontainers/features/common-utils": { + "installZsh": false, + "installOhMyZsh": false, + "upgradePackages": false + }, + "pixi": { + "version": "v0.29.0" + } + }, + "remoteUser": "vscode" + }, + "with-v0.28.0": { + "image": "mcr.microsoft.com/devcontainers/base:ubuntu", + "features": { + "ghcr.io/devcontainers/features/common-utils": { + "installZsh": false, + "installOhMyZsh": false, + "upgradePackages": false + }, + "pixi": { + "version": "v0.28.0" + } + }, + "remoteUser": "vscode" + } +} \ No newline at end of file diff --git a/features/test/pixi/test.sh b/features/test/pixi/test.sh new file mode 100644 index 0000000..085584c --- /dev/null +++ b/features/test/pixi/test.sh @@ -0,0 +1,42 @@ +#!/bin/bash +# This is a generic test since the primary difference in tests is across versions. +set -e + +# Optional: Import test library bundled with the devcontainer CLI +source dev-container-features-test-lib + +if [ "${VERSION}" = "latest" ]; then + VERSION="$(curl -s https://api.github.com/repos/prefix-dev/pixi/releases | jq -r ".[0].tag_name")" +fi + +VERSION_CHECK="${VERSION//v}" + +# Feature-specific tests +# The 'check' command comes from the dev-container-features-test-lib. +check \ + "validate pixi \`${VERSION_CHECK}\` is installed" \ + bash -c "pixi --version | grep \"${VERSION_CHECK}\"" + +check \ + "test that we can \`init\` a pixi project" \ + bash -c "pixi init -p linux-aarch64 -p linux-64 -c conda-forge" + +check \ + "can add libraries?" \ + bash -c "pixi add scipy numpy pandas; pixi clean" + +check \ + "install pixi environments" \ + bash -c "pixi install -a" + +check \ + "run pixi tasks" \ + bash -c "pixi run python --version" + +check \ + "did libraries install?" + bash -c "pixi run python -c 'import pandas'" + +# Report result +# If any of the checks above exited with a non-zero exit code, the test will fail. +reportResults \ No newline at end of file diff --git a/features/test/pixi/with-v0.28.0.sh b/features/test/pixi/with-v0.28.0.sh new file mode 100644 index 0000000..4edeff5 --- /dev/null +++ b/features/test/pixi/with-v0.28.0.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +export VERSION +$(dirname ${0})/test.sh \ No newline at end of file diff --git a/features/test/pixi/with-v0.29.0.sh b/features/test/pixi/with-v0.29.0.sh new file mode 100644 index 0000000..4edeff5 --- /dev/null +++ b/features/test/pixi/with-v0.29.0.sh @@ -0,0 +1,5 @@ +#!/bin/bash +set -e + +export VERSION +$(dirname ${0})/test.sh \ No newline at end of file