Skip to content

Commit 8addc78

Browse files
authored
Initial commit
0 parents  commit 8addc78

File tree

18 files changed

+527
-0
lines changed

18 files changed

+527
-0
lines changed

.devcontainer/devcontainer.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// More info: https://containers.dev/implementors/json_reference/
2+
{
3+
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye",
4+
"features": {
5+
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
6+
},
7+
"customizations": {
8+
"vscode": {
9+
"extensions": [
10+
"mads-hartmann.bash-ide-vscode",
11+
"dbaeumer.vscode-eslint"
12+
]
13+
}
14+
},
15+
"postCreateCommand": "npm install -g @devcontainers/cli"
16+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: 'Smoke test'
2+
inputs:
3+
template:
4+
description: 'Template to test'
5+
required: true
6+
7+
runs:
8+
using: composite
9+
steps:
10+
- name: Checkout main
11+
id: checkout_release
12+
uses: actions/checkout@v3
13+
14+
- name: Build template
15+
id: build_template
16+
shell: bash
17+
run: ${{ github.action_path }}/build.sh ${{ inputs.template }}
18+
19+
- name: Test template
20+
id: test_template
21+
shell: bash
22+
run: ${{ github.action_path }}/test.sh ${{ inputs.template }}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
TEMPLATE_ID="$1"
3+
4+
set -e
5+
6+
shopt -s dotglob
7+
8+
SRC_DIR="/tmp/${TEMPLATE_ID}"
9+
cp -R "src/${TEMPLATE_ID}" "${SRC_DIR}"
10+
11+
pushd "${SRC_DIR}"
12+
13+
# Configure templates only if `devcontainer-template.json` contains the `options` property.
14+
OPTION_PROPERTY=( $(jq -r '.options' devcontainer-template.json) )
15+
16+
if [ "${OPTION_PROPERTY}" != "" ] && [ "${OPTION_PROPERTY}" != "null" ] ; then
17+
OPTIONS=( $(jq -r '.options | keys[]' devcontainer-template.json) )
18+
19+
if [ "${OPTIONS[0]}" != "" ] && [ "${OPTIONS[0]}" != "null" ] ; then
20+
echo "(!) Configuring template options for '${TEMPLATE_ID}'"
21+
for OPTION in "${OPTIONS[@]}"
22+
do
23+
OPTION_KEY="\${templateOption:$OPTION}"
24+
OPTION_VALUE=$(jq -r ".options | .${OPTION} | .default" devcontainer-template.json)
25+
26+
if [ "${OPTION_VALUE}" = "" ] || [ "${OPTION_VALUE}" = "null" ] ; then
27+
echo "Template '${TEMPLATE_ID}' is missing a default value for option '${OPTION}'"
28+
exit 1
29+
fi
30+
31+
echo "(!) Replacing '${OPTION_KEY}' with '${OPTION_VALUE}'"
32+
OPTION_VALUE_ESCAPED=$(sed -e 's/[]\/$*.^[]/\\&/g' <<<"${OPTION_VALUE}")
33+
find ./ -type f -print0 | xargs -0 sed -i "s/${OPTION_KEY}/${OPTION_VALUE_ESCAPED}/g"
34+
done
35+
fi
36+
fi
37+
38+
popd
39+
40+
TEST_DIR="test/${TEMPLATE_ID}"
41+
if [ -d "${TEST_DIR}" ] ; then
42+
echo "(*) Copying test folder"
43+
DEST_DIR="${SRC_DIR}/test-project"
44+
mkdir -p ${DEST_DIR}
45+
cp -Rp ${TEST_DIR}/* ${DEST_DIR}
46+
cp test/test-utils/test-utils.sh ${DEST_DIR}
47+
fi
48+
49+
export DOCKER_BUILDKIT=1
50+
echo "(*) Installing @devcontainer/cli"
51+
npm install -g @devcontainers/cli
52+
53+
echo "Building Dev Container"
54+
ID_LABEL="test-container=${TEMPLATE_ID}"
55+
devcontainer up --id-label ${ID_LABEL} --workspace-folder "${SRC_DIR}"

.github/actions/smoke-test/test.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
TEMPLATE_ID="$1"
3+
set -e
4+
5+
SRC_DIR="/tmp/${TEMPLATE_ID}"
6+
echo "Running Smoke Test"
7+
8+
ID_LABEL="test-container=${TEMPLATE_ID}"
9+
devcontainer exec --workspace-folder "${SRC_DIR}" --id-label ${ID_LABEL} /bin/sh -c 'set -e && if [ -f "test-project/test.sh" ]; then cd test-project && if [ "$(id -u)" = "0" ]; then chmod +x test.sh; else sudo chmod +x test.sh; fi && ./test.sh; else ls -a; fi'
10+
11+
# Clean up
12+
docker rm -f $(docker container ls -f "label=${ID_LABEL}" -q)
13+
rm -rf "${SRC_DIR}"

.github/workflows/release.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
name: "Release Dev Container Templates & Generate Documentation"
2+
on:
3+
workflow_dispatch:
4+
5+
jobs:
6+
deploy:
7+
if: ${{ github.ref == 'refs/heads/main' }}
8+
runs-on: ubuntu-latest
9+
permissions:
10+
packages: write
11+
contents: write
12+
pull-requests: write
13+
steps:
14+
- uses: actions/checkout@v3
15+
16+
- name: "Publish Templates"
17+
uses: devcontainers/action@v1
18+
with:
19+
publish-templates: "true"
20+
base-path-to-templates: "./src"
21+
generate-docs: "true"
22+
23+
env:
24+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
25+
26+
- name: Create PR for Documentation
27+
id: push_image_info
28+
env:
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
run: |
31+
set -e
32+
echo "Start."
33+
34+
# Configure git and Push updates
35+
git config --global user.email github-actions[bot]@users.noreply.github.com
36+
git config --global user.name github-actions[bot]
37+
git config pull.rebase false
38+
39+
branch=automated-documentation-update-$GITHUB_RUN_ID
40+
git checkout -b $branch
41+
message='Automated documentation update'
42+
43+
# Add / update and commit
44+
git add */**/README.md
45+
git commit -m 'Automated documentation update [skip ci]' || export NO_UPDATES=true
46+
47+
# Push
48+
if [ "$NO_UPDATES" != "true" ] ; then
49+
git push origin "$branch"
50+
gh pr create --title "$message" --body "$message"
51+
fi

.github/workflows/test-pr.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: "CI - Test Templates"
2+
on:
3+
pull_request:
4+
5+
jobs:
6+
detect-changes:
7+
runs-on: ubuntu-latest
8+
outputs:
9+
templates: ${{ steps.filter.outputs.changes }}
10+
steps:
11+
- uses: dorny/paths-filter@v2
12+
id: filter
13+
with:
14+
filters: |
15+
color: ./**/color/**
16+
hello: ./**/hello/**
17+
18+
test:
19+
needs: [detect-changes]
20+
runs-on: ubuntu-latest
21+
continue-on-error: true
22+
strategy:
23+
matrix:
24+
templates: ${{ fromJSON(needs.detect-changes.outputs.templates) }}
25+
steps:
26+
- uses: actions/checkout@v3
27+
28+
- name: Smoke test for '${{ matrix.templates }}'
29+
id: smoke_test
30+
uses: ./.github/actions/smoke-test
31+
with:
32+
template: "${{ matrix.templates }}"

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Microsoft Corporation
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Dev Container Templates: Self Authoring Guide
2+
3+
> This repo provides a starting point and example for creating your own custom [Dev Container Templates](https://containers.dev/implementors/templates), hosted for free on GitHub Container Registry. The example in this repository follows the [Dev Container Template distribution specification](https://containers.dev/implementors/templates-distribution/).
4+
>
5+
> To provide feedback on the distribution spec, please leave a comment [on spec issue #71](https://github.com/devcontainers/spec/issues/71).
6+
7+
## Repo and Template Structure
8+
9+
This repository contains a _collection_ of two Templates - `hello` and `color`. These Templates serve as simple template implementations which helps containerize the project. Similar to the [`devcontainers/templates`](https://github.com/devcontainers/templates) repo, this repository has a `src` folder. Each Template has its own sub-folder, containing at least a `devcontainer-template.json` and `.devcontainer/devcontainer.json`.
10+
11+
```
12+
├── src
13+
│ ├── color
14+
│ │ ├── devcontainer-template.json
15+
│ │ └──| .devcontainer
16+
│ │ └── devcontainer.json
17+
│ ├── hello
18+
│ │ ├── devcontainer-template.json
19+
│ │ └──| .devcontainer
20+
│ │ ├── devcontainer.json
21+
│ │ └── Dockerfile
22+
| ├── ...
23+
│ │ ├── devcontainer-template.json
24+
│ │ └──| .devcontainer
25+
│ │ └── devcontainer.json
26+
├── test
27+
│ ├── color
28+
│ │ └── test.sh
29+
│ ├── hello
30+
│ │ └── test.sh
31+
│ └──test-utils
32+
│ └── test-utils.sh
33+
...
34+
```
35+
36+
### Options
37+
38+
All available options for a Template should be declared in the `devcontainer-template.json`. The syntax for the `options` property can be found in the [devcontainer Template json properties reference](https://containers.dev/implementors/templates#devcontainer-templatejson-properties).
39+
40+
For example, the `color` Template provides three possible options (`red`, `gold`, `green`), where the default value is set to "red".
41+
42+
```jsonc
43+
{
44+
// ...
45+
"options": {
46+
"favorite": {
47+
"type": "string",
48+
"description": "Choose your favorite color."
49+
"proposals": [
50+
"red",
51+
"gold",
52+
"green"
53+
],
54+
"default": "red"
55+
}
56+
}
57+
}
58+
```
59+
60+
An [implementing tool](https://containers.dev/supporting#tools) will use the `options` property from [the documented Dev Container Template properties](https://containers.dev/implementors/templates#devcontainer-templatejson-properties) for customizing the Template. See [option resolution example](https://containers.dev/implementors/templates#option-resolution-example) for details.
61+
62+
## Distributing Templates
63+
64+
**Note**: *Allow GitHub Actions to create and approve pull requests* should be enabled in the repository's `Settings > Actions > General > Workflow permissions` for auto generation of `src/<template>/README.md` per Template (which merges any existing `src/<template>/NOTES.md`).
65+
66+
### Versioning
67+
68+
Templates are individually versioned by the `version` attribute in a Template's `devcontainer-template.json`. Templates are versioned according to the semver specification. More details can be found in [the Dev Container Template specification](https://containers.dev/implementors/templates-distribution/#versioning).
69+
70+
### Publishing
71+
72+
> NOTE: The Distribution spec can be [found here](https://containers.dev/implementors/templates-distribution/).
73+
>
74+
> While any registry [implementing the OCI Distribution spec](https://github.com/opencontainers/distribution-spec) can be used, this template will leverage GHCR (GitHub Container Registry) as the backing registry.
75+
76+
Templates are source files packaged together that encode configuration for a complete development environment.
77+
78+
This repo contains a GitHub Action [workflow](.github/workflows/release.yaml) that will publish each template to GHCR. By default, each Template will be prefixed with the `<owner/<repo>` namespace. For example, the two Templates in this repository can be referenced by an [implementing tool](https://containers.dev/supporting#tools) with:
79+
80+
```
81+
ghcr.io/devcontainers/template-starter/color:latest
82+
ghcr.io/devcontainers/template-starter/hello:latest
83+
```
84+
85+
The provided GitHub Action will also publish a third "metadata" package with just the namespace, eg: `ghcr.io/devcontainers/template-starter`. This contains information useful for tools aiding in Template discovery.
86+
87+
'`devcontainers/template-starter`' is known as the template collection namespace.
88+
89+
### Marking Template Public
90+
91+
For your Template to be used, it currently needs to be available publicly. By default, OCI Artifacts in GHCR are marked as `private`.
92+
93+
To make them public, navigate to the Template's "package settings" page in GHCR, and set the visibility to 'public`.
94+
95+
```
96+
https://github.com/users/<owner>/packages/container/<repo>%2F<templateName>/settings
97+
```
98+
99+
### Adding Templates to the Index
100+
101+
Next you will need to add your Templates collection to our [public index](https://containers.dev/templates) so that other community members can find them. Just follow these steps once per collection you create:
102+
103+
* Go to [github.com/devcontainers/devcontainers.github.io](https://github.com/devcontainers/devcontainers.github.io)
104+
* This is the GitHub repo backing the [containers.dev](https://containers.dev/) spec site
105+
* Open a PR to modify the [collection-index.yml](https://github.com/devcontainers/devcontainers.github.io/blob/gh-pages/_data/collection-index.yml) file
106+
107+
This index is from where [supporting tools](https://containers.dev/supporting) like [VS Code Dev Containers](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and [GitHub Codespaces](https://github.com/templates/codespaces) surface Templates for their Dev Container Creation Configuration UI.
108+
109+
### Testing Templates
110+
111+
This repo contains a GitHub Action [workflow](.github/workflows/test-pr.yaml) for testing the Templates. Similar to the [`devcontainers/templates`](https://github.com/devcontainers/templates) repo, this repository has a `test` folder. Each Template has its own sub-folder, containing at least a `test.sh`.
112+
113+
For running the tests locally, you would need to execute the following commands -
114+
115+
```
116+
./.github/actions/smoke-test/build.sh ${TEMPLATE-ID}
117+
./.github/actions/smoke-test/test.sh ${TEMPLATE-ID}
118+
```
119+
120+
### Updating Documentation
121+
122+
This repo contains a GitHub Action [workflow](.github/workflows/release.yaml) that will automatically generate documentation (ie. `README.md`) for each Template. This file will be auto-generated from the `devcontainer-template.json` and `NOTES.md`.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "Favorite color",
3+
"image": "mcr.microsoft.com/devcontainers/base:${templateOption:imageVariant}",
4+
5+
// 👇 Features to add to the Dev Container. More info: https://containers.dev/implementors/features.
6+
// "features": {},
7+
8+
// 👇 Use 'forwardPorts' to make a list of ports inside the container available locally.
9+
// "forwardPorts": [],
10+
11+
"postCreateCommand": "echo '${templateOption:favorite}' > /tmp/color.txt"
12+
13+
// 👇 Configure tool-specific properties.
14+
// "customizations": {},
15+
16+
// 👇 Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
17+
// "remoteUser": "root"
18+
}

src/color/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
# My Favorite Color (color)
3+
4+
A Template to remind you of your favorite color
5+
6+
## Options
7+
8+
| Options Id | Description | Type | Default Value |
9+
|-----|-----|-----|-----|
10+
| imageVariant | Debian version (use bullseye on local arm64/Apple Silicon): | string | bullseye |
11+
| favorite | Choose your favorite color. | string | red |
12+
13+
14+
15+
---
16+
17+
_Note: This file was auto-generated from the [devcontainer-template.json](https://github.com/devcontainers/template-starter/blob/main/src/color/devcontainer-template.json). Add additional notes to a `NOTES.md`._

0 commit comments

Comments
 (0)