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

Commit 23647ae

Browse files
authored
Contributing.MD Changes for Adding New DCFs (#1246)
1 parent 3c33364 commit 23647ae

File tree

1 file changed

+157
-1
lines changed

1 file changed

+157
-1
lines changed
Lines changed: 157 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,157 @@
1-
This folder includes some explorations around dynamic container feature injection. Nothing stable yet.
1+
# Container Features
2+
3+
This folder includes some explorations around dynamic container feature injection. Nothing stable yet.
4+
5+
## Contributing to Container Features
6+
7+
### Creating a new feature
8+
9+
**Registering a feature**
10+
11+
Create the install script in the [script-library](script-library/) directory with the naming convention `<lowercase-feature-name>-<target-os>.sh`. EG `python-debian.sh` or `common-alpine.sh`
12+
13+
Add a new object to the [features.json](script-library/container-features/src/features.json) file:
14+
15+
```json
16+
{
17+
"id": "<lowercase-feature-name>", // Must match the <lowercase-feature-name> used to name the install script.
18+
"name": "Display Name of Feature",
19+
"documentationURL": "https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/<lowercase-feature-name>.md",
20+
"options": {
21+
"scriptArgument$1": {
22+
"type": "string", // Either "string" or "boolean"
23+
"proposals": [], // Array of valid string values for this option.
24+
"default": "", // Default value if user does not specify.
25+
"description": "" // User-facing description of this option.
26+
},
27+
"scriptArgument$2": {
28+
"type":"boolean", // Either "string" or "boolean"
29+
"default": false, // Either true or false
30+
"description": "" // User-facing description of this option.
31+
}
32+
},
33+
"buildArg": "_VSC_INSTALL_<CAPITALIZED_ID>", // Must match the ENV VAR defined in the feature-scripts.env file.
34+
"extensions": [], // Array of VS Code extensions to install with this feature.
35+
"include": [] // Array of base containers this script can be used on.
36+
}
37+
```
38+
39+
Add your buildArg to the [feature-scripts.env](script-library/container-features/src/feature-scripts.env) file with all script arguments specified (even if they duplicate a script default).
40+
41+
```
42+
_VSC_INSTALL_<FEATURE>="<feature>-debian.sh ${_BUILD_ARG_<FEATURE>_<OPTION1>:-<option1 default>} ${_BUILD_ARG_<FEATURE>_<OPTION2>:-<option2 default>} hardcodedThirdArgument"
43+
```
44+
45+
- Options declared in `features.json` are mapped using the naming convention `_BUILD_ARG_<FEATURE>_<OPTIONNAME>` and their default should match the declared default for that option.
46+
- EG `_VSC_INSTALL_AZURE_CLI="azcli-debian.sh ${_BUILD_ARG_AZURE_CLI_VERSION:-latest}"`
47+
48+
**Feature testing**
49+
50+
*Local testing*
51+
52+
- Create a devcontainer with a target base image.
53+
- Add your script to the root.
54+
- Bring up the container image.
55+
- Run your script in the container with required arguments.
56+
- Verify expected results.
57+
- Bring down container to clean up.
58+
59+
Repeat as needed to iterate from a clean workspace.
60+
61+
*Unit tests*
62+
- Add your feature to the [run-scripts.sh](script-library/test/regression/run-scripts.sh) file to ensure it is included in CI tests.
63+
64+
- Your addition should take the form `runScript <feature> <non-default-args>`.
65+
66+
EG
67+
```sh
68+
runScript dotnet "3.1 true ${USERNAME} false /opt/dotnet dotnet"
69+
```
70+
71+
- If your script takes the installation user as an argument, be sure to specify it as ${USERNAME} in the tests for programatic testing.
72+
73+
*Regression tests*
74+
- Add your feature to the [test-features.env](script-library/container-features/test-features.env) file to include it in regression tests of the container-feature functionality. By setting the `_VSC_INSTALL_<FEATURE>` ENV VAR to true and adding the expected _BUILD_ARG options for your feature.
75+
76+
EG
77+
```
78+
_VSC_INSTALL_DOTNET=true
79+
_BUILD_ARG_DOTNET_VERSION=latest
80+
_BUILD_ARG_DOTNET_RUNTIMEONLY=false
81+
```
82+
83+
**Feature documentation**
84+
85+
Add your new feature to the list of scripts in the [script-library README.md](https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/README.md#scripts).
86+
87+
Add documentation for your new feature script to the [script-library/docs](https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs) directory.
88+
89+
Documentation should include:
90+
- the status of the script, supported operating systems, and maintainer.
91+
- the syntax expected to run as a feature or script
92+
- a description of the script arguments
93+
- detailed usage instructions
94+
95+
Feel free to use other scripts in that directory as inspiration.
96+
97+
### Best practices for writing feature install scripts
98+
99+
- Decouple sections of the shellscript that handle user setup, helper functions, and feature installation. Doing so will apply a logical and natural flow to the script for future developers and maintainers to follow. One way to denote this distinction is to use in-line comments throughout the script.
100+
```md
101+
# Logical flow recommended:
102+
1. File header and description.
103+
2. Define constants and default values.
104+
3. User setup and user validation.
105+
4. Helper functions.
106+
5. Checks for dependencies being installed or installs dependencies.
107+
6. Runs container feature installs.
108+
7. Gives the user correct permissions if necessary.
109+
```
110+
111+
- One way to make troubleshooting the script easier when writing a bash shell script is to echo error messages to `STDERR`. A possible way we implemented this in bash scripts is to create an `err()` function like so:
112+
```sh
113+
# Setup STDERR.
114+
err() {
115+
echo "(!) $*" >&2
116+
}
117+
err "Something went wrong!"
118+
exit 1
119+
```
120+
121+
- If writing a bash shellscript, we recommend using double quotes and braces when referencing named variables:
122+
```sh
123+
variable="My example var"
124+
echo "${variable}"
125+
```
126+
127+
- One method to to ensure the global space in a script is not too crowded with unnecessary variables is to assign return values from functions to a new variable, and use the keyword `local` for vars inside of functions. For example:
128+
```sh
129+
test_function() {
130+
local test = "hello world!"
131+
echo "${test}"
132+
}
133+
global_test=$(test_function)
134+
```
135+
136+
- If using temporary files within the script, we recommend removing all those files once they are no longer needed. One method for doing this is running a cleanup function with a `trap` method when the script exits:
137+
```sh
138+
# Cleanup temporary directory and associated files when exiting the script.
139+
cleanup() {
140+
EXIT_CODE=$?
141+
set +e
142+
if [[ -n "${TMP_DIR}" ]]; then
143+
echo "Executing cleanup of tmp files"
144+
rm -Rf "${TMP_DIR}"
145+
fi
146+
exit $EXIT_CODE
147+
}
148+
trap cleanup EXIT
149+
```
150+
151+
- Consider using [shellcheck](https://github.com/koalaman/shellcheck) or the [vscode-shellcheck extension](https://github.com/vscode-shellcheck/vscode-shellcheck) to apply linting and static code analysis to the bash script to ensure it is formatted correctly.
152+
153+
- Consider using common helper functions from [shared/utils.sh](script-library/shared/utils.sh) when managing common tasks (like updating PATH variables, or managing gpg keys) by copying them directly into your script.
154+
- NOTE: This is done to minimize the impact that any change can have on existing working scripts.
155+
- Similarly, if you add a helper function to your script that could benefit others in the future, consider adding it to the `shared/utils.sh` file as well.
156+
157+
- [shared/settings.env](script-library/shared/settings.env) contains shared environment variables used in many install scripts, such as `GPG Keys` and `Archive Architectures`. Consider adding your new env. variables to this script when applicable, or reusing existing variables when pertinent.

0 commit comments

Comments
 (0)