Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configFile option #269

Merged
merged 1 commit into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .azure-devops/azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ jobs:
exit 1
fi

- job: test_config_file
displayName: Test configFile option
steps:
- task: DevcontainersCi@0
inputs:
subFolder: github-tests/Dockerfile/config-file
configFile: github-tests/Dockerfile/config-file/.devcontainer/subfolder/devcontainer.json
runCmd: echo $HOSTNAME && [[ $HOSTNAME == "my-host" ]]
- script: |
echo "'runCmdOutput' value: $runCmdOutput"
if [["$runCmdOutput" = *my-host*]]; then
echo "'runCmdOutput' output of test_config_file job doesn't contain expected value 'my-host'"
exit 1
fi

- job: test_build_args
displayName: Test build-args
steps:
Expand Down
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"features": {
"ghcr.io/devcontainers/features/github-cli:1": {
"version": "1.0.11",
"resolved": "ghcr.io/devcontainers/features/github-cli@sha256:464564228ccdd6028f01f8a62a3cfbaf76e9ba7953b29ac0e53ba2c262604312",
"integrity": "sha256:464564228ccdd6028f01f8a62a3cfbaf76e9ba7953b29ac0e53ba2c262604312"
}
}
}
40 changes: 40 additions & 0 deletions .github/workflows/ci_common.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ jobs:
- test-gh-docker-from-docker-root
- test-gh-skip-user-update
- test-compose-features
- test-config-file
- test-simple
- test-no-run
- test-platform-with-runcmd
Expand Down Expand Up @@ -452,6 +453,45 @@ jobs:
env:
runCmdOutput: ${{ steps.simpletest.outputs.runCmdOutput }}

test-config-file:
name: Run test with config file
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout
uses: actions/checkout@v3
with:
persist-credentials: false
# if the following value is missing (i.e. not triggered via comment workflow)
# then the default checkout will apply
ref: ${{ inputs.prRef }}

# Published action contains compiled JS, but we need to compile it here
- uses: actions/setup-node@v3
with:
node-version: 20
- name: Compile GH action
run: |
(cd common && npm install && npm run build)
(cd github-action/ && npm install && npm run build && npm run package)

- name: Run test
uses: ./
id: configfiletest
with:
subFolder: github-tests/Dockerfile/config-file
configFile: github-tests/Dockerfile/config-file/.devcontainer/subfolder/devcontainer.json
runCmd: echo $HOSTNAME && [[ $HOSTNAME == "my-host" ]]
- name: Validate runCmdOutput output
run: |
echo "'runCmdOutput' value: $runCmdOutput"
if [["$runCmdOutput" = *my-host*]]; then
echo "'runCmdOutput' output of configfiletest step doesn't contain expected value 'my-host'"
exit 1
fi
env:
runCmdOutput: ${{ steps.configfiletest.outputs.runCmdOutput }}

test-gh-run-args:
name: Run GitHub run-args test
runs-on: ubuntu-latest
Expand Down
4 changes: 4 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ inputs:
required: false
description: Specify a child folder (containing a .devcontainer) instead of using the repository root
default:
configFile:
required: false
description: Specify the path to a devcontainer.json file instead of using `./.devcontainer/devcontainer.json` or `./.devcontainer.json`
default:
checkoutPath:
required: false
description: Specify path to checked out folder if not using default (or for testing with nektos/act)
Expand Down
6 changes: 6 additions & 0 deletions azdo-task/DevcontainersCi/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export async function runMain(): Promise<void> {
const imageTag = task.getInput('imageTag');
const platform = task.getInput('platform');
const subFolder = task.getInput('subFolder') ?? '.';
const relativeConfigFile = task.getInput('configFile');
const runCommand = task.getInput('runCmd');
const envs = task.getInput('env')?.split('\n') ?? [];
const inputEnvsWithDefaults = populateDefaults(envs);
Expand All @@ -62,6 +63,8 @@ export async function runMain(): Promise<void> {

const log = (message: string): void => console.log(message);
const workspaceFolder = path.resolve(checkoutPath, subFolder);
const configFile =
relativeConfigFile && path.resolve(checkoutPath, relativeConfigFile);

const resolvedImageTag = imageTag ?? 'latest';
const imageTagArray = resolvedImageTag.split(',');
Expand Down Expand Up @@ -91,6 +94,7 @@ export async function runMain(): Promise<void> {
}
const buildArgs: DevContainerCliBuildArgs = {
workspaceFolder,
configFile,
imageName: fullImageNameArray,
platform,
additionalCacheFroms: cacheFrom,
Expand Down Expand Up @@ -120,6 +124,7 @@ export async function runMain(): Promise<void> {
console.log('***');
const upArgs: DevContainerCliUpArgs = {
workspaceFolder,
configFile,
additionalCacheFroms: cacheFrom,
skipContainerUserIdUpdate,
env: inputEnvsWithDefaults,
Expand All @@ -141,6 +146,7 @@ export async function runMain(): Promise<void> {
console.log('***');
const execArgs: DevContainerCliExecArgs = {
workspaceFolder,
configFile,
command: ['bash', '-c', runCommand],
env: inputEnvsWithDefaults,
};
Expand Down
6 changes: 6 additions & 0 deletions azdo-task/DevcontainersCi/task.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
"label": "Specify a child folder (containing a .devcontainer) instead of using the repository root",
"required": false
},
{
"name": "configFile",
"type": "string",
"label": "Specify the path to a devcontainer.json file instead of using `./.devcontainer/devcontainer.json` or `./.devcontainer.json`",
"required": false
},
{
"name": "env",
"type": "multiLine",
Expand Down
1 change: 1 addition & 0 deletions azdo-task/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ In the example above, the devcontainer-build-run will perform the following step
| imageName | true | Image name to use when building the dev container image (including registry) |
| imageTag | false | One or more comma-separated image tags (defaults to `latest`) |
| subFolder | false | Use this to specify the repo-relative path to the folder containing the dev container (i.e. the folder that contains the `.devcontainer` folder). Defaults to repo root |
| configFile | false | Use this to specify the repo-relative path to the devcontainer.json file. Defaults to `./.devcontainer/devcontainer.json` and `./.devcontainer.json`. |
| runCmd | true | The command to run after building the dev container image |
| env | false | Specify environment variables to pass to the dev container when run |
| push | false | One of: `never`, `filter`, `always`. When set to `filter`, the image if pushed if the `sourceBranchFilterForPush`, `buildReasonsForPush`, and `pushOnFailedBuild` conditions are met. Defaults to `filter` if `imageName` is set, `never` otherwise. |
Expand Down
16 changes: 14 additions & 2 deletions common/src/dev-container-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ export interface DevContainerCliBuildResult
extends DevContainerCliSuccessResult {}
export interface DevContainerCliBuildArgs {
workspaceFolder: string;
configFile: string | undefined;
imageName?: string[];
platform?: string;
additionalCacheFroms?: string[];
Expand All @@ -168,6 +169,9 @@ async function devContainerBuild(
'--workspace-folder',
args.workspaceFolder,
];
if (args.configFile) {
commandArgs.push('--config', args.configFile);
}
if (args.imageName) {
args.imageName.forEach(iName =>
commandArgs.push('--image-name', iName),
Expand Down Expand Up @@ -203,6 +207,7 @@ export interface DevContainerCliUpResult extends DevContainerCliSuccessResult {
}
export interface DevContainerCliUpArgs {
workspaceFolder: string;
configFile: string | undefined;
additionalCacheFroms?: string[];
skipContainerUserIdUpdate?: boolean;
env?: string[];
Expand All @@ -220,6 +225,9 @@ async function devContainerUp(
args.workspaceFolder,
...remoteEnvArgs,
];
if (args.configFile) {
commandArgs.push('--config', args.configFile);
}
if (args.additionalCacheFroms) {
args.additionalCacheFroms.forEach(cacheFrom =>
commandArgs.push('--cache-from', cacheFrom),
Expand All @@ -245,6 +253,7 @@ async function devContainerUp(

export interface DevContainerCliExecArgs {
workspaceFolder: string;
configFile: string | undefined;
command: string[];
env?: string[];
userDataFolder?: string;
Expand All @@ -255,12 +264,15 @@ async function devContainerExec(
): Promise<number | null> {
// const remoteEnvArgs = args.env ? args.env.flatMap(e=> ["--remote-env", e]): []; // TODO - test flatMap again
const remoteEnvArgs = getRemoteEnvArray(args.env);
const commandArgs = ["exec", "--workspace-folder", args.workspaceFolder, ...remoteEnvArgs, ...args.command];
const commandArgs = ["exec", "--workspace-folder", args.workspaceFolder, ...remoteEnvArgs];
if (args.configFile) {
commandArgs.push('--config', args.configFile);
}
if (args.userDataFolder) {
commandArgs.push("--user-data-folder", args.userDataFolder);
}
return await runSpecCliNonJsonCommand({
args: commandArgs,
args: commandArgs.concat(args.command),
log,
env: {DOCKER_BUILDKIT: '1', COMPOSE_DOCKER_CLI_BUILD: '1'},
});
Expand Down
1 change: 1 addition & 0 deletions docs/azure-devops-task.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ In the example above, the devcontainer-build-run will perform the following step
| imageName | true | Image name to use when building the dev container image (including registry) |
| imageTag | false | One or more comma-separated image tags (defaults to `latest`) |
| subFolder | false | Use this to specify the repo-relative path to the folder containing the dev container (i.e. the folder that contains the `.devcontainer` folder). Defaults to repo root |
| configFile | false | Use this to specify the repo-relative path to the devcontainer.json file. Defaults to `./.devcontainer/devcontainer.json` and `./.devcontainer.json`. |
| runCmd | true | The command to run after building the dev container image |
| env | false | Specify environment variables to pass to the dev container when run |
| push | false | One of: `never`, `filter`, `always`. When set to `filter`, the image if pushed if the `sourceBranchFilterForPush`, `buildReasonsForPush`, and `pushOnFailedBuild` conditions are met. Defaults to `filter` if `imageName` is set, `never` otherwise. |
Expand Down
1 change: 1 addition & 0 deletions docs/github-action.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ The [`devcontainers/ci` action](https://github.com/marketplace/actions/devcontai
| imageName | true | Image name to use when building the dev container image (including registry) |
| imageTag | false | One or more comma-separated image tags (defaults to `latest`) |
| subFolder | false | Use this to specify the repo-relative path to the folder containing the dev container (i.e. the folder that contains the `.devcontainer` folder). Defaults to repo root |
| configFile | false | Use this to specify the repo-relative path to the devcontainer.json file. Defaults to `./.devcontainer/devcontainer.json` and `./.devcontainer.json`. |
| runCmd | true | The command to run after building the dev container image |
| env | false | Specify environment variables to pass to the dev container when run |
| checkoutPath | false | Only used for development/testing |
Expand Down
8 changes: 8 additions & 0 deletions github-action/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export async function runMain(): Promise<void> {
const imageTag = emptyStringAsUndefined(core.getInput('imageTag'));
const platform = emptyStringAsUndefined(core.getInput('platform'));
const subFolder: string = core.getInput('subFolder');
const relativeConfigFile = emptyStringAsUndefined(
core.getInput('configFile'),
);
const runCommand = core.getInput('runCmd');
const inputEnvs: string[] = core.getMultilineInput('env');
const inputEnvsWithDefaults = populateDefaults(inputEnvs);
Expand All @@ -72,6 +75,8 @@ export async function runMain(): Promise<void> {

const log = (message: string): void => core.info(message);
const workspaceFolder = path.resolve(checkoutPath, subFolder);
const configFile =
relativeConfigFile && path.resolve(checkoutPath, relativeConfigFile);

const resolvedImageTag = imageTag ?? 'latest';
const imageTagArray = resolvedImageTag.split(',');
Expand Down Expand Up @@ -108,6 +113,7 @@ export async function runMain(): Promise<void> {
const buildResult = await core.group('🏗️ build container', async () => {
const args: DevContainerCliBuildArgs = {
workspaceFolder,
configFile,
imageName: fullImageNameArray,
platform,
additionalCacheFroms: cacheFrom,
Expand Down Expand Up @@ -142,6 +148,7 @@ export async function runMain(): Promise<void> {
const upResult = await core.group('🏃 start container', async () => {
const args: DevContainerCliUpArgs = {
workspaceFolder,
configFile,
additionalCacheFroms: cacheFrom,
skipContainerUserIdUpdate,
env: inputEnvsWithDefaults,
Expand All @@ -166,6 +173,7 @@ export async function runMain(): Promise<void> {
async () => {
const args: DevContainerCliExecArgs = {
workspaceFolder,
configFile,
command: ['bash', '-c', runCommand],
env: inputEnvsWithDefaults,
userDataFolder,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "config-file",
"image": "mcr.microsoft.com/devcontainers/base:jammy",
"runArgs": [
"--hostname", "my-host"
]}
Loading