From 3c0613ed58acd0f2952ca3b72e50f09145e6c26a Mon Sep 17 00:00:00 2001 From: Jason Garber Date: Tue, 24 Feb 2026 20:23:46 +0000 Subject: [PATCH 1/4] Add Dev Container lockfile --- .devcontainer/devcontainer-lock.json | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .devcontainer/devcontainer-lock.json diff --git a/.devcontainer/devcontainer-lock.json b/.devcontainer/devcontainer-lock.json new file mode 100644 index 0000000..3b83ba3 --- /dev/null +++ b/.devcontainer/devcontainer-lock.json @@ -0,0 +1,24 @@ +{ + "features": { + "ghcr.io/CargoSense/devcontainer-features/shellcheck:1": { + "version": "1.1.0", + "resolved": "ghcr.io/cargosense/devcontainer-features/shellcheck@sha256:bd2efc29446b238a25771a5f80416d69e0f264d5c102c00f8b1de3da013c640d", + "integrity": "sha256:bd2efc29446b238a25771a5f80416d69e0f264d5c102c00f8b1de3da013c640d" + }, + "ghcr.io/devcontainers-extra/features/devcontainers-cli:1": { + "version": "1.0.1", + "resolved": "ghcr.io/devcontainers-extra/features/devcontainers-cli@sha256:855f5c6a10d1d1353fc3127216171653527f2dadaa50bee3ef4c55a261e19749", + "integrity": "sha256:855f5c6a10d1d1353fc3127216171653527f2dadaa50bee3ef4c55a261e19749" + }, + "ghcr.io/devcontainers-extra/features/shfmt:1": { + "version": "1.0.2", + "resolved": "ghcr.io/devcontainers-extra/features/shfmt@sha256:9d87bdd69e7b37554488291e79b37a40d1e18beddfa151454570d5bf72423df8", + "integrity": "sha256:9d87bdd69e7b37554488291e79b37a40d1e18beddfa151454570d5bf72423df8" + }, + "ghcr.io/devcontainers/features/docker-in-docker:2": { + "version": "2.16.0", + "resolved": "ghcr.io/devcontainers/features/docker-in-docker@sha256:31ef1bbfde793bcc62c52fa847c02a15fe659d69e48b2d8c1cfbd4db95f97cf7", + "integrity": "sha256:31ef1bbfde793bcc62c52fa847c02a15fe659d69e48b2d8c1cfbd4db95f97cf7" + } + } +} \ No newline at end of file From 440e0bff6c4a16c9351650f940d8aa39dfad9f33 Mon Sep 17 00:00:00 2001 From: Jason Garber Date: Wed, 25 Feb 2026 19:17:46 +0000 Subject: [PATCH 2/4] Add elixir-project Feature --- src/elixir-project/README.md | 17 ++++++ src/elixir-project/devcontainer-feature.json | 57 +++++++++++++++++++ src/elixir-project/install.sh | 10 ++++ src/elixir-project/scripts/onCreateCommand.sh | 35 ++++++++++++ .../scripts/postCreateCommand.sh | 8 +++ 5 files changed, 127 insertions(+) create mode 100644 src/elixir-project/README.md create mode 100644 src/elixir-project/devcontainer-feature.json create mode 100755 src/elixir-project/install.sh create mode 100755 src/elixir-project/scripts/onCreateCommand.sh create mode 100755 src/elixir-project/scripts/postCreateCommand.sh diff --git a/src/elixir-project/README.md b/src/elixir-project/README.md new file mode 100644 index 0000000..1876746 --- /dev/null +++ b/src/elixir-project/README.md @@ -0,0 +1,17 @@ +# elixir-project + +An opinionated, batteries-included Dev Container Feature for Elixir projects. + +## Usage + +```json +"features": { + "ghcr.io/CargoSense/devcontainer-features/elixir-project:1": {} +} +``` + +## OS Support + +This Feature should work on recent versions of Debian/Ubuntu and Linux distributions. + +`bash` is required to execute the `install.sh` script. diff --git a/src/elixir-project/devcontainer-feature.json b/src/elixir-project/devcontainer-feature.json new file mode 100644 index 0000000..ecff31e --- /dev/null +++ b/src/elixir-project/devcontainer-feature.json @@ -0,0 +1,57 @@ +{ + "id": "elixir-project", + "version": "1.0.0", + "name": "elixir-project", + "description": "An opinionated, batteries-included Dev Container Feature for Elixir projects.", + "documentationURL": "https://github.com/CargoSense/devcontainer-features/tree/main/src/elixir-project", + "licenseURL": "https://github.com/CargoSense/devcontainer-features/blob/main/LICENSE", + "containerEnv": { + "LESS": "-FMR", + "PAGER": "less" + }, + "customizations": { + "vscode": { + "extensions": [ + "ExpertLSP.expert" + ], + "settings": { + "[elixir]": { + "editor.formatOnSave": true + }, + "editor.tabSize": 2, + "files": { + "insertFinalNewline": true, + "trimFinalNewlines": true, + "trimTrailingWhitespace": true + } + } + } + }, + "dependsOn": { + "ghcr.io/devcontainers/features/common-utils:2": { + "installZsh": false, + "username": "vscode", + "userUid": 1000, + "userGid": 1000 + } + }, + "mounts": [ + { + "source": "build-cache-${devcontainerId}", + "target": "${containerWorkspaceFolder}/_build", + "type": "volume" + }, + { + "source": "dependency-cache-${devcontainerId}", + "target": "${containerWorkspaceFolder}/deps", + "type": "volume" + }, + { + "source": "expert-cache-${devcontainerId}", + "target": "${containerWorkspaceFolder}/.expert", + "type": "volume" + } + ], + "onCreateCommand": "CONTAINER_WORKSPACE_FOLDER=${containerWorkspaceFolder} /opt/cargosense/elixir-project/onCreateCommand.sh", + "postCreateCommand": "sudo /opt/cargosense/elixir-project/postCreateCommand.sh" +} diff --git a/src/elixir-project/install.sh b/src/elixir-project/install.sh new file mode 100755 index 0000000..649cd7b --- /dev/null +++ b/src/elixir-project/install.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -e + +FEATURE_SCRIPTS_PATH="/opt/cargosense/elixir-project" + +mkdir -p "${FEATURE_SCRIPTS_PATH}" + +cp "${PWD}"/scripts/*.sh "${FEATURE_SCRIPTS_PATH}" +chmod +x "${FEATURE_SCRIPTS_PATH}"/*.sh diff --git a/src/elixir-project/scripts/onCreateCommand.sh b/src/elixir-project/scripts/onCreateCommand.sh new file mode 100755 index 0000000..14e3965 --- /dev/null +++ b/src/elixir-project/scripts/onCreateCommand.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +set -e + +# Set permissions on volume mounts +sudo chown -R "${USER}":"${USER}" "${CONTAINER_WORKSPACE_FOLDER:?}"/{_build,deps,.expert} + +# Create user Bash configuration directory +BASHRC_DIR="${HOME}/.bashrc.d" + +mkdir -p "${BASHRC_DIR}" +chmod 700 "${BASHRC_DIR}" + +# Configure environment variables that rely on `CONTAINER_WORKSPACE_FOLDER` +cat << EOF > "${BASHRC_DIR}/elixir-project.bashrc" +export HISTFILE="${CONTAINER_WORKSPACE_FOLDER}/.bash_history" +export ERL_AFLAGS="-kernel shell_history enabled -kernel shell_history_path '\\"${CONTAINER_WORKSPACE_FOLDER}/.iex_history\\"'" +EOF + +chmod +x "${BASHRC_DIR}/elixir-project.bashrc" + +BASHRC_FILE="${HOME}/.bashrc" +BASHRC_LINE="for file in \"\${HOME}\"/.bashrc.d/*.bashrc; do source \"\${file}\"; done" + +grep -qxF "${BASHRC_LINE}" "${BASHRC_FILE}" || echo "${BASHRC_LINE}" >> "${BASHRC_FILE}" + +# Configure workspace `.gitignore` +GITIGNORE_FILE="${CONTAINER_WORKSPACE_FOLDER}/.gitignore" +GITIGNORE_LINES=(.bash_history /_build /.expert /.iex_history /deps) + +touch "${GITIGNORE_FILE}" + +for line in "${GITIGNORE_LINES[@]}"; do + grep -qxF "${line}" "${GITIGNORE_FILE}" || echo "${line}" >> "${GITIGNORE_FILE}" +done diff --git a/src/elixir-project/scripts/postCreateCommand.sh b/src/elixir-project/scripts/postCreateCommand.sh new file mode 100755 index 0000000..cb7355c --- /dev/null +++ b/src/elixir-project/scripts/postCreateCommand.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -e + +FEATURE_SCRIPTS_PATH="/opt/cargosense/elixir-project" + +rm -rf "${FEATURE_SCRIPTS_PATH}" +rmdir --ignore-fail-on-non-empty "$(dirname "${FEATURE_SCRIPTS_PATH}")" From c3af25556f34ee51af6b8a5f9f4cba6d8ac08b33 Mon Sep 17 00:00:00 2001 From: Jason Garber Date: Wed, 25 Feb 2026 19:18:04 +0000 Subject: [PATCH 3/4] Add elixir-project to test matrix --- .github/workflows/test.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 09f776b..8218521 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,6 +13,7 @@ jobs: matrix: features: - actionlint + - elixir-project - google-cloud-cli - node - postgresql-client From cb2995824fddc7a211f58b2dbb2cac370c91e72b Mon Sep 17 00:00:00 2001 From: Jason Garber Date: Wed, 25 Feb 2026 19:22:15 +0000 Subject: [PATCH 4/4] Add elixir-project test folder --- test/elixir-project/test.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100755 test/elixir-project/test.sh diff --git a/test/elixir-project/test.sh b/test/elixir-project/test.sh new file mode 100755 index 0000000..a458bad --- /dev/null +++ b/test/elixir-project/test.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -e + +# Optional: Import test library bundled with the devcontainer CLI +# shellcheck source=/dev/null +source dev-container-features-test-lib + +# Feature-specific tests +check "environment" bash -c "env | grep ERL_AFLAGS" +check "gitignore" grep -xF .bash_history .gitignore + +# Report result +reportResults