Skip to content

Commit d482b7d

Browse files
authored
feat: DevContainer component (projen#391)
Fixes projen#362 BREAKING CHANGES: - Deprecated `GitpodDocker` for `DevEnvironmentDockerImage`. - Renamed `gitpod.addCustomDocker()` to `gitpod.addDockerImage` - Changed `gitpod.addTasks` to take `Task` instances as inputs. Tasks can be created via `const task = project.addTask('name', { ...options })`. Other changes: - Creates an abstract interface for configuring container-based developer environments like Gitpod and GitHub Codespaces. - Adds `addTaskWithOptions`, `addPorts`, `addPrebuilds`, and `addVscodeExtensions` methods to `Gitpod`. - Adds the `DevContainer` component which emits `.devcontainer.json` files. - Fix bug where `YAMLFile` can synthesize incorrectly because `JsonFileOptions` get ignored. - Refactored several unit tests
1 parent 344d3f0 commit d482b7d

18 files changed

+1348
-231
lines changed

.devcontainer.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"postCreateCommand": "( npx projen devenv:setup )"
3+
}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ tsconfig.json
4646
!/.projen/tasks.json
4747
!/.projen/deps.json
4848
!/.gitpod.yml
49+
!/.devcontainer.json
4950
!/package.json
5051
!/LICENSE
5152
!/.npmignore

.gitpod.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22

33
tasks:
44
- name: Setup
5+
command: npx projen build
56
init: yarn install
67
prebuild: bash ./projen.bash
7-
command: npx projen build

.projen/tasks.json

+11
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,17 @@
212212
"exec": "rm README.md.bak"
213213
}
214214
]
215+
},
216+
"devenv:setup": {
217+
"name": "devenv:setup",
218+
"steps": [
219+
{
220+
"exec": "yarn install"
221+
},
222+
{
223+
"spawn": "build"
224+
}
225+
]
215226
}
216227
},
217228
"env": {

.projenrc.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const project = new JsiiProject({
3535
codeCov: true,
3636
compileBeforeTest: true, // since we want to run the cli in tests
3737
gitpod: true,
38+
devContainer: true,
3839
// since this is projen, we need to always compile before we run
3940
projenCommand: '/bin/bash ./projen.bash',
4041
});
@@ -100,11 +101,16 @@ project.github.addMergifyRules({
100101
],
101102
});
102103

103-
project.gitpod.addTasks({
104+
project.gitpod.addCustomTask({
104105
name: 'Setup',
105106
init: 'yarn install',
106107
prebuild: 'bash ./projen.bash',
107108
command: 'npx projen build',
108109
});
109110

111+
const setup = project.addTask('devenv:setup');
112+
setup.exec('yarn install');
113+
setup.spawn(project.buildTask);
114+
project.devContainer.addTasks(setup);
115+
110116
project.synth();

API.md

+461-60
Large diffs are not rendered by default.

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"eslint": "/bin/bash ./projen.bash eslint",
2727
"compat": "/bin/bash ./projen.bash compat",
2828
"docgen": "/bin/bash ./projen.bash docgen",
29-
"readme-macros": "/bin/bash ./projen.bash readme-macros"
29+
"readme-macros": "/bin/bash ./projen.bash readme-macros",
30+
"devenv:setup": "/bin/bash ./projen.bash devenv:setup"
3031
},
3132
"author": {
3233
"name": "Elad Ben-Israel",

src/dev-env.ts

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { Task } from './tasks';
2+
3+
/**
4+
* Base options for configuring a container-based development environemnt.
5+
*/
6+
export interface DevEnvironmentOptions {
7+
/**
8+
* A Docker image or Dockerfile for the container.
9+
*/
10+
readonly dockerImage?: DevEnvironmentDockerImage;
11+
12+
/**
13+
* An array of tasks that should be run when the container starts.
14+
*/
15+
readonly tasks?: Task[];
16+
17+
/**
18+
* An array of ports that should be exposed from the container.
19+
*/
20+
readonly ports?: string[];
21+
22+
/**
23+
* An array of extension IDs that specify the extensions that should be
24+
* installed inside the container when it is created.
25+
*/
26+
readonly vscodeExtensions?: string[];
27+
}
28+
29+
/**
30+
* Options for specifying the Docker image of the container.
31+
*/
32+
export class DevEnvironmentDockerImage {
33+
/**
34+
* A publicly available Docker image.
35+
* @example 'ubuntu:latest'
36+
* @param image a Docker image
37+
*/
38+
public static fromImage(image: string): DevEnvironmentDockerImage {
39+
return { image };
40+
}
41+
42+
/**
43+
* The relative path of a Dockerfile that defines the container contents.
44+
* @example '.gitpod.Docker'
45+
* @param dockerFile a relative path
46+
*/
47+
public static fromFile(dockerFile: string): DevEnvironmentDockerImage {
48+
return { dockerFile };
49+
}
50+
51+
/**
52+
* A publicly available Docker image.
53+
*/
54+
public readonly image?: string;
55+
56+
/**
57+
* The relative path of a Dockerfile that defines the container contents.
58+
*/
59+
public readonly dockerFile?: string;
60+
61+
private constructor() { }
62+
}
63+
64+
/**
65+
* Abstract interface for container-based development environments, such as
66+
* Gitpod and GitHub Codespaces.
67+
*/
68+
export interface IDevEnvironment {
69+
/**
70+
* Add a custom Docker image or Dockerfile for the container.
71+
*
72+
* @param image The Docker image
73+
*/
74+
addDockerImage(image: DevEnvironmentDockerImage): void;
75+
76+
/**
77+
* Adds tasks to run when the container starts.
78+
*
79+
* @param tasks The new tasks
80+
*/
81+
addTasks(...tasks: Task[]): void;
82+
83+
/**
84+
* Adds ports that should be exposed (forwarded) from the container.
85+
*
86+
* @param ports The new ports
87+
*/
88+
addPorts(...ports: string[]): void;
89+
90+
/**
91+
* Adds a list of VSCode extensions that should be automatically installed
92+
* in the container.
93+
*
94+
* @param extensions The extension IDs
95+
*/
96+
addVscodeExtensions(...extensions: string[]): void;
97+
}

0 commit comments

Comments
 (0)