Skip to content
This repository was archived by the owner on Nov 30, 2023. It is now read-only.

Commit 9c54abc

Browse files
Adding a pure Elixir devcontainer (#1102)
1 parent a535d74 commit 9c54abc

File tree

8 files changed

+305
-0
lines changed

8 files changed

+305
-0
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Update the VARIANT arg in docker-compose.yml to pick an Elixir version: 1.9, 1.10, 1.10.4
2+
ARG VARIANT=latest
3+
FROM elixir:${VARIANT}
4+
5+
# This Dockerfile adds a non-root user with sudo access. Update the “remoteUser” property in
6+
# devcontainer.json to use it. More info: https://aka.ms/vscode-remote/containers/non-root-user.
7+
ARG USERNAME=vscode
8+
ARG USER_UID=1000
9+
ARG USER_GID=$USER_UID
10+
11+
# Options for common package install script
12+
ARG INSTALL_ZSH="true"
13+
ARG UPGRADE_PACKAGES="true"
14+
ARG COMMON_SCRIPT_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/common-debian.sh"
15+
ARG COMMON_SCRIPT_SHA="dev-mode"
16+
17+
# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies.
18+
RUN apt-get update \
19+
&& export DEBIAN_FRONTEND=noninteractive \
20+
&& apt-get -y install --no-install-recommends curl ca-certificates 2>&1 \
21+
&& curl -sSL ${COMMON_SCRIPT_SOURCE} -o /tmp/common-setup.sh \
22+
&& ([ "${COMMON_SCRIPT_SHA}" = "dev-mode" ] || (echo "${COMMON_SCRIPT_SHA} */tmp/common-setup.sh" | sha256sum -c -)) \
23+
&& /bin/bash /tmp/common-setup.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \
24+
#
25+
# Install dependencies
26+
&& apt-get install -y build-essential \
27+
#
28+
# Clean up
29+
&& apt-get autoremove -y \
30+
&& apt-get clean -y \
31+
&& rm -rf /var/lib/apt/lists/* /tmp/common-setup.sh /tmp/node-setup.sh
32+
33+
RUN su ${USERNAME} -c "mix local.hex --force \
34+
&& mix local.rebar --force"
35+
36+
# [Optional] Uncomment this section to install additional OS packages.
37+
# RUN apt-get update \
38+
# && export DEBIAN_FRONTEND=noninteractive \
39+
# && apt-get -y install --no-install-recommends <your-package-list-here>
40+
41+
# [Optional] Uncomment this line to install additional package.
42+
# RUN mix ...
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "Elixir",
3+
"build": {
4+
"dockerfile": "Dockerfile",
5+
"args": {
6+
// Elixir Version: 1.9, 1.10, 1.10.4, ...
7+
"VARIANT": "latest"
8+
}
9+
}
10+
11+
// Add the IDs of extensions you want installed when the container is created.
12+
"extensions": [
13+
"jakebecker.elixir-ls"
14+
],
15+
16+
// Use 'forwardPorts' to make a list of ports inside the container available locally.
17+
"forwardPorts": [],
18+
19+
// Use 'postCreateCommand' to run commands after the container is created.
20+
// "postCreateCommand": "mix deps.get"
21+
22+
// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
23+
"remoteUser": "vscode"
24+
}

containers/elixir/.npmignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
README.md
2+
test-project
3+
definition-manifest.json
4+
.vscode
5+
.npmignore

containers/elixir/README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Elixir
2+
3+
## Summary
4+
5+
_Develop Elixir based applications. Includes everything you need to get up and running._
6+
7+
| Metadata | Value |
8+
| --------------------------- | --------------------- |
9+
| _Contributors_ | [idyll](https://github.com/idyll), [Talk2MeGooseman](https://github.com/talk2MeGooseman)|
10+
| _Category_ | Community, Languages |
11+
| _Definition type_ | Dockerfile |
12+
| _Works in Codespaces_ | Yes |
13+
| _Container host OS support_ | Linux, macOS, Windows |
14+
| _Languages, platforms_ | Elixir. |
15+
16+
## Using this definition
17+
18+
While this definition should work unmodified, you can select the version of Elixir the container uses by updating the `VARIANT` arg in the included `docker-compose.yml`.
19+
20+
```yml
21+
services:
22+
elixir:
23+
build: .
24+
args:
25+
# Elixir Version: 1.9, 1.10, 1.10.4, ...
26+
VARIANT: 1.10
27+
# ...
28+
```
29+
30+
### Adding the definition to your folder
31+
32+
1. If this is your first time using a development container, please see getting started information on [setting up](https://aka.ms/vscode-remote/containers/getting-started) Remote-Containers or [creating a codespace](https://aka.ms/ghcs-open-codespace) using GitHub Codespaces.
33+
34+
2. Start VS Code and open your project folder or connect to a codespace.
35+
36+
3. Press <kbd>F1</kbd> select and **Add Development Container Configuration Files...** command for **Remote-Containers** or **Codespaces**.
37+
38+
> **Note:** If needed, you can drag-and-drop the `.devcontainer` folder from this sub-folder in a locally cloned copy of this repository into the VS Code file explorer instead of using the command.
39+
40+
4. Select this definition. You may also need to select **Show All Definitions...** for it to appear.
41+
42+
5. Finally, press <kbd>F1</kbd> and run **Remote-Containers: Reopen Folder in Container** or **Codespaces: Rebuild Container** to start using the definition.
43+
44+
## Testing the definition
45+
46+
This definition includes some test code that will help you verify it is working as expected on your system. Follow these steps:
47+
48+
1. If this is your first time using a development container, please follow the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started) to set up your machine.
49+
2. Clone this repository.
50+
3. Start VS Code, press <kbd>F1</kbd>, and select **Remote-Containers: Open Folder in Container...**
51+
4. Select the `containers/elixir` folder.
52+
5. After the folder has opened in the container, press <kbd>F5</kbd> to start the project.
53+
6. You should see "Hello, Remote Extension Host!" followed by "Hello, Local Extension Host!" in the Debug Console after the program executes.
54+
7. From here, you can add breakpoints or edit the contents of the `test-project` folder to do further testing.
55+
56+
## License
57+
58+
Copyright (c) Microsoft Corporation. All rights reserved.
59+
60+
Licensed under the MIT License. See [LICENSE](https://github.com/microsoft/vscode-dev-containers/blob/main/LICENSE).
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
example/

containers/elixir/test-project/package-lock.json

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
#!/bin/bash
2+
SCRIzT_FOLDER="$(cd "$(dirname $0)" && pwd)"
3+
USERNAME=${1:-vscode}
4+
5+
if [ -z $HOME ]; then
6+
HOME="/root"
7+
fi
8+
9+
FAILED=()
10+
11+
echoStderr()
12+
{
13+
echo "$@" 1>&2
14+
}
15+
16+
check() {
17+
LABEL=$1
18+
shift
19+
echo -e "\n🧪 Testing $LABEL"
20+
if "$@"; then
21+
echo "✅ Passed!"
22+
return 0
23+
else
24+
echoStderr "$LABEL check failed."
25+
FAILED+=("$LABEL")
26+
return 1
27+
fi
28+
}
29+
30+
checkMultiple() {
31+
PASSED=0
32+
LABEL="$1"
33+
echo -e "\n🧪 Testing $LABEL."
34+
shift; MINIMUMPASSED=$1
35+
shift; EXPRESSION="$1"
36+
while [ "$EXPRESSION" != "" ]; do
37+
if $EXPRESSION; then ((PASSED++)); fi
38+
shift; EXPRESSION=$1
39+
done
40+
if [ $PASSED -ge $MINIMUMPASSED ]; then
41+
echo "✅ Passed!"
42+
return 0
43+
else
44+
echoStderr "$LABEL check failed."
45+
FAILED+=("$LABEL")
46+
return 1
47+
fi
48+
}
49+
50+
checkOSPackages() {
51+
LABEL=$1
52+
shift
53+
echo -e "\n🧪 Testing $LABEL"
54+
if dpkg-query --show -f='${Package}: ${Version}\n' "$@"; then
55+
echo "✅ Passed!"
56+
return 0
57+
else
58+
echoStderr "$LABEL check failed."
59+
FAILED+=("$LABEL")
60+
return 1
61+
fi
62+
}
63+
64+
checkExtension() {
65+
# Happens asynchronusly, so keep retrying 10 times with an increasing delay
66+
EXTN_ID="$1"
67+
TIMEOUT_SECONDS="${2:-10}"
68+
RETRY_COUNT=0
69+
echo -e -n "\n🧪 Looking for extension $1 for maximum of ${TIMEOUT_SECONDS}s"
70+
until [ "${RETRY_COUNT}" -eq "${TIMEOUT_SECONDS}" ] || \
71+
[ ! -e $HOME/.vscode-server/extensions/${EXTN_ID}* ] || \
72+
[ ! -e $HOME/.vscode-server-insiders/extensions/${EXTN_ID}* ] || \
73+
[ ! -e $HOME/.vscode-test-server/extensions/${EXTN_ID}* ] || \
74+
[ ! -e $HOME/.vscode-remote/extensions/${EXTN_ID}* ]
75+
do
76+
sleep 1s
77+
(( RETRY_COUNT++ ))
78+
echo -n "."
79+
done
80+
81+
if [ ${RETRY_COUNT} -lt ${TIMEOUT_SECONDS} ]; then
82+
echo -e "\n✅ Passed!"
83+
return 0
84+
else
85+
echoStderr -e "\n❌ Extension $EXTN_ID not found."
86+
FAILED+=("$LABEL")
87+
return 1
88+
fi
89+
}
90+
91+
checkCommon()
92+
{
93+
PACKAGE_LIST="apt-utils \
94+
git \
95+
openssh-client \
96+
less \
97+
iproute2 \
98+
procps \
99+
curl \
100+
wget \
101+
unzip \
102+
nano \
103+
jq \
104+
lsb-release \
105+
ca-certificates \
106+
apt-transport-https \
107+
dialog \
108+
gnupg2 \
109+
libc6 \
110+
libgcc1 \
111+
libgssapi-krb5-2 \
112+
liblttng-ust0 \
113+
libstdc++6 \
114+
zlib1g \
115+
locales \
116+
sudo"
117+
118+
# Actual tests
119+
checkOSPackages "common-os-packages" ${PACKAGE_LIST}
120+
checkMultiple "vscode-server" 1 "[ -d $HOME/.vscode-server/bin ]" "[ -d $HOME/.vscode-server-insiders/bin ]" "[ -d $HOME/.vscode-test-server/bin ]" "[ -d $HOME/.vscode-remote/bin ]" "[ -d $HOME/.vscode-remote/bin ]"
121+
check "non-root-user" id ${USERNAME}
122+
check "locale" [ $(locale -a | grep en_US.utf8) ]
123+
check "sudo" sudo echo "sudo works."
124+
check "zsh" zsh --version
125+
check "oh-my-zsh" [ -d "$HOME/.oh-my-zsh" ]
126+
check "login-shell-path" [ -f "/etc/profile.d/00-restore-env.sh" ]
127+
check "code" which code
128+
}
129+
130+
reportResults() {
131+
if [ ${#FAILED[@]} -ne 0 ]; then
132+
echoStderr -e "\n💥 Failed tests: ${FAILED[@]}"
133+
exit 1
134+
else
135+
echo -e "\n💯 All passed!"
136+
exit 0
137+
fi
138+
}
139+
140+
fixTestProjectFolderPrivs() {
141+
if [ "${USERNAME}" != "root" ]; then
142+
TEST_PROJECT_FOLDER="${1:-$SCRIPT_FOLDER}"
143+
FOLDER_USER="$(stat -c '%U' "${TEST_PROJECT_FOLDER}")"
144+
if [ "${FOLDER_USER}" != "${USERNAME}" ]; then
145+
echoStderr "WARNING: Test project folder is owned by ${FOLDER_USER}. Updating to ${USERNAME}."
146+
sudo chown -R ${USERNAME} "${TEST_PROJECT_FOLDER}"
147+
fi
148+
fi
149+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
cd $(dirname "$0")
3+
4+
source test-utils.sh vscode
5+
6+
# Remote - Containers does not auto-sync UID/GID for Docker Compose,
7+
# so make sure test project prvs match the non-root user in the container.
8+
fixTestProjectFolderPrivs
9+
10+
# Run common tests
11+
checkCommon
12+
13+
# Actual tests
14+
checkExtension "jakebecker.elixir-ls"
15+
check "elixir" iex --version
16+
check "build test project" echo yes | mix new example
17+
check "download deps" cd ./example && mix deps.get && mix deps.compile
18+
rm -rf example
19+
20+
# Report result
21+
reportResults

0 commit comments

Comments
 (0)