Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
acd5edffe7 | ||
|
|
4dcab99cb0 | ||
|
|
50a946df0f | ||
|
|
8a0ac3435c | ||
|
|
438c904567 |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -17,6 +17,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: coder/coder/.github/actions/setup-tf@main
|
||||||
- uses: oven-sh/setup-bun@v2
|
- uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
@@ -29,6 +30,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Needed to get tags
|
fetch-depth: 0 # Needed to get tags
|
||||||
|
- uses: coder/coder/.github/actions/setup-tf@main
|
||||||
- uses: oven-sh/setup-bun@v2
|
- uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
bun-version: latest
|
bun-version: latest
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
executeScriptInContainer,
|
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
executeScriptInContainer,
|
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
|
|||||||
@@ -1,10 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe } from "bun:test";
|
||||||
import {
|
import { runTerraformInit, testRequiredVariables } from "../test";
|
||||||
executeScriptInContainer,
|
|
||||||
runTerraformApply,
|
|
||||||
runTerraformInit,
|
|
||||||
testRequiredVariables,
|
|
||||||
} from "../test";
|
|
||||||
|
|
||||||
describe("coder-login", async () => {
|
describe("coder-login", async () => {
|
||||||
await runTerraformInit(import.meta.dir);
|
await runTerraformInit(import.meta.dir);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
executeScriptInContainer,
|
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
executeScriptInContainer,
|
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { type Server, serve } from "bun";
|
||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
createJSONResponse,
|
createJSONResponse,
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
writeCoder,
|
writeCoder,
|
||||||
} from "../test";
|
} from "../test";
|
||||||
import { Server, serve } from "bun";
|
|
||||||
|
|
||||||
describe("github-upload-public-key", async () => {
|
describe("github-upload-public-key", async () => {
|
||||||
await runTerraformInit(import.meta.dir);
|
await runTerraformInit(import.meta.dir);
|
||||||
@@ -21,10 +21,12 @@ describe("github-upload-public-key", async () => {
|
|||||||
it("creates new key if one does not exist", async () => {
|
it("creates new key if one does not exist", async () => {
|
||||||
const { instance, id, server } = await setupContainer();
|
const { instance, id, server } = await setupContainer();
|
||||||
await writeCoder(id, "echo foo");
|
await writeCoder(id, "echo foo");
|
||||||
let exec = await execContainer(id, [
|
|
||||||
|
const url = server.url.toString().slice(0, -1);
|
||||||
|
const exec = await execContainer(id, [
|
||||||
"env",
|
"env",
|
||||||
"CODER_ACCESS_URL=" + server.url.toString().slice(0, -1),
|
`CODER_ACCESS_URL=${url}`,
|
||||||
"GITHUB_API_URL=" + server.url.toString().slice(0, -1),
|
`GITHUB_API_URL=${url}`,
|
||||||
"CODER_OWNER_SESSION_TOKEN=foo",
|
"CODER_OWNER_SESSION_TOKEN=foo",
|
||||||
"CODER_EXTERNAL_AUTH_ID=github",
|
"CODER_EXTERNAL_AUTH_ID=github",
|
||||||
"bash",
|
"bash",
|
||||||
@@ -42,10 +44,12 @@ describe("github-upload-public-key", async () => {
|
|||||||
const { instance, id, server } = await setupContainer();
|
const { instance, id, server } = await setupContainer();
|
||||||
// use keyword to make server return a existing key
|
// use keyword to make server return a existing key
|
||||||
await writeCoder(id, "echo findkey");
|
await writeCoder(id, "echo findkey");
|
||||||
let exec = await execContainer(id, [
|
|
||||||
|
const url = server.url.toString().slice(0, -1);
|
||||||
|
const exec = await execContainer(id, [
|
||||||
"env",
|
"env",
|
||||||
"CODER_ACCESS_URL=" + server.url.toString().slice(0, -1),
|
`CODER_ACCESS_URL=${url}`,
|
||||||
"GITHUB_API_URL=" + server.url.toString().slice(0, -1),
|
`GITHUB_API_URL=${url}`,
|
||||||
"CODER_OWNER_SESSION_TOKEN=foo",
|
"CODER_OWNER_SESSION_TOKEN=foo",
|
||||||
"CODER_EXTERNAL_AUTH_ID=github",
|
"CODER_EXTERNAL_AUTH_ID=github",
|
||||||
"bash",
|
"bash",
|
||||||
@@ -95,7 +99,7 @@ const setupServer = async (): Promise<Server> => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// case: key already exists
|
// case: key already exists
|
||||||
if (req.headers.get("Authorization") == "Bearer findkey") {
|
if (req.headers.get("Authorization") === "Bearer findkey") {
|
||||||
return createJSONResponse([
|
return createJSONResponse([
|
||||||
{
|
{
|
||||||
key: "foo",
|
key: "foo",
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ This module adds a JetBrains Gateway Button to open any workspace with a single
|
|||||||
```tf
|
```tf
|
||||||
module "jetbrains_gateway" {
|
module "jetbrains_gateway" {
|
||||||
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
||||||
version = "1.0.13"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
agent_name = "example"
|
agent_name = "example"
|
||||||
folder = "/home/coder/example"
|
folder = "/home/coder/example"
|
||||||
@@ -32,7 +32,7 @@ module "jetbrains_gateway" {
|
|||||||
```tf
|
```tf
|
||||||
module "jetbrains_gateway" {
|
module "jetbrains_gateway" {
|
||||||
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
||||||
version = "1.0.13"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
agent_name = "example"
|
agent_name = "example"
|
||||||
folder = "/home/coder/example"
|
folder = "/home/coder/example"
|
||||||
@@ -46,7 +46,7 @@ module "jetbrains_gateway" {
|
|||||||
```tf
|
```tf
|
||||||
module "jetbrains_gateway" {
|
module "jetbrains_gateway" {
|
||||||
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
||||||
version = "1.0.13"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
agent_name = "example"
|
agent_name = "example"
|
||||||
folder = "/home/coder/example"
|
folder = "/home/coder/example"
|
||||||
@@ -61,7 +61,7 @@ module "jetbrains_gateway" {
|
|||||||
```tf
|
```tf
|
||||||
module "jetbrains_gateway" {
|
module "jetbrains_gateway" {
|
||||||
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
source = "registry.coder.com/modules/jetbrains-gateway/coder"
|
||||||
version = "1.0.13"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
agent_name = "example"
|
agent_name = "example"
|
||||||
folder = "/home/coder/example"
|
folder = "/home/coder/example"
|
||||||
|
|||||||
@@ -14,6 +14,26 @@ describe("jetbrains-gateway", async () => {
|
|||||||
folder: "/home/foo",
|
folder: "/home/foo",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should create a link with the default values", async () => {
|
||||||
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
|
// These are all required.
|
||||||
|
agent_id: "foo",
|
||||||
|
agent_name: "foo",
|
||||||
|
folder: "/home/coder",
|
||||||
|
});
|
||||||
|
expect(state.outputs.url.value).toBe(
|
||||||
|
"jetbrains-gateway://connect#type=coder&workspace=default&owner=default&agent=foo&folder=/home/coder&url=https://mydeployment.coder.com&token=$SESSION_TOKEN&ide_product_code=IU&ide_build_number=241.14494.240&ide_download_link=https://download.jetbrains.com/idea/ideaIU-2024.1.tar.gz",
|
||||||
|
);
|
||||||
|
|
||||||
|
const coder_app = state.resources.find(
|
||||||
|
(res) => res.type === "coder_app" && res.name === "gateway",
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(coder_app).not.toBeNull();
|
||||||
|
expect(coder_app?.instances.length).toBe(1);
|
||||||
|
expect(coder_app?.instances[0].attributes.order).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it("default to first ide", async () => {
|
it("default to first ide", async () => {
|
||||||
const state = await runTerraformApply(import.meta.dir, {
|
const state = await runTerraformApply(import.meta.dir, {
|
||||||
agent_id: "foo",
|
agent_id: "foo",
|
||||||
|
|||||||
@@ -243,6 +243,7 @@ data "coder_parameter" "jetbrains_ide" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data "coder_workspace" "me" {}
|
data "coder_workspace" "me" {}
|
||||||
|
data "coder_workspace_owner" "me" {}
|
||||||
|
|
||||||
resource "coder_app" "gateway" {
|
resource "coder_app" "gateway" {
|
||||||
agent_id = var.agent_id
|
agent_id = var.agent_id
|
||||||
@@ -254,6 +255,8 @@ resource "coder_app" "gateway" {
|
|||||||
url = join("", [
|
url = join("", [
|
||||||
"jetbrains-gateway://connect#type=coder&workspace=",
|
"jetbrains-gateway://connect#type=coder&workspace=",
|
||||||
data.coder_workspace.me.name,
|
data.coder_workspace.me.name,
|
||||||
|
"&owner=",
|
||||||
|
data.coder_workspace_owner.me.name,
|
||||||
"&agent=",
|
"&agent=",
|
||||||
var.agent_name,
|
var.agent_name,
|
||||||
"&folder=",
|
"&folder=",
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ EOF`;
|
|||||||
const proxies = ["foo", "bar", "baz"]
|
const proxies = ["foo", "bar", "baz"]
|
||||||
.map((r) => `https://${user}:@${fakeFrogApi}/go/${r}`)
|
.map((r) => `https://${user}:@${fakeFrogApi}/go/${r}`)
|
||||||
.join(",");
|
.join(",");
|
||||||
expect(proxyEnv["value"]).toEqual(proxies);
|
expect(proxyEnv.value).toEqual(proxies);
|
||||||
|
|
||||||
const coderScript = findResourceInstance(state, "coder_script");
|
const coderScript = findResourceInstance(state, "coder_script");
|
||||||
expect(coderScript.script).toContain(
|
expect(coderScript.script).toContain(
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ EOF`;
|
|||||||
const proxies = ["foo", "bar", "baz"]
|
const proxies = ["foo", "bar", "baz"]
|
||||||
.map((r) => `https://${user}:${token}@${fakeFrogApi}/go/${r}`)
|
.map((r) => `https://${user}:${token}@${fakeFrogApi}/go/${r}`)
|
||||||
.join(",");
|
.join(",");
|
||||||
expect(proxyEnv["value"]).toEqual(proxies);
|
expect(proxyEnv.value).toEqual(proxies);
|
||||||
|
|
||||||
const coderScript = findResourceInstance(state, "coder_script");
|
const coderScript = findResourceInstance(state, "coder_script");
|
||||||
expect(coderScript.script).toContain(
|
expect(coderScript.script).toContain(
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
|
execContainer,
|
||||||
executeScriptInContainer,
|
executeScriptInContainer,
|
||||||
|
findResourceInstance,
|
||||||
|
runContainer,
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
findResourceInstance,
|
type TerraformState,
|
||||||
runContainer,
|
|
||||||
TerraformState,
|
|
||||||
execContainer,
|
|
||||||
} from "../test";
|
} from "../test";
|
||||||
|
|
||||||
// executes the coder script after installing pip
|
// executes the coder script after installing pip
|
||||||
const executeScriptInContainerWithPip = async (
|
const executeScriptInContainerWithPip = async (
|
||||||
state: TerraformState,
|
state: TerraformState,
|
||||||
image: string,
|
image: string,
|
||||||
shell: string = "sh",
|
shell = "sh",
|
||||||
): Promise<{
|
): Promise<{
|
||||||
exitCode: number;
|
exitCode: number;
|
||||||
stdout: string[];
|
stdout: string[];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe } from "bun:test";
|
||||||
import { runTerraformInit, testRequiredVariables } from "../test";
|
import { runTerraformInit, testRequiredVariables } from "../test";
|
||||||
|
|
||||||
describe("nodejs", async () => {
|
describe("nodejs", async () => {
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
import { readableStreamToText, spawn } from "bun";
|
|
||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
executeScriptInContainer,
|
executeScriptInContainer,
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
runContainer,
|
|
||||||
execContainer,
|
|
||||||
findResourceInstance,
|
|
||||||
} from "../test";
|
} from "../test";
|
||||||
|
|
||||||
describe("personalize", async () => {
|
describe("personalize", async () => {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ executed`,
|
|||||||
it("formats execution with milliseconds", async () => {
|
it("formats execution with milliseconds", async () => {
|
||||||
await assertSlackMessage({
|
await assertSlackMessage({
|
||||||
command: "echo test",
|
command: "echo test",
|
||||||
format: `$COMMAND took $DURATION`,
|
format: "$COMMAND took $DURATION",
|
||||||
durationMS: 150,
|
durationMS: 150,
|
||||||
output: "echo test took 150ms",
|
output: "echo test took 150ms",
|
||||||
});
|
});
|
||||||
@@ -81,7 +81,7 @@ executed`,
|
|||||||
it("formats execution with seconds", async () => {
|
it("formats execution with seconds", async () => {
|
||||||
await assertSlackMessage({
|
await assertSlackMessage({
|
||||||
command: "echo test",
|
command: "echo test",
|
||||||
format: `$COMMAND took $DURATION`,
|
format: "$COMMAND took $DURATION",
|
||||||
durationMS: 15000,
|
durationMS: 15000,
|
||||||
output: "echo test took 15.0s",
|
output: "echo test took 15.0s",
|
||||||
});
|
});
|
||||||
@@ -90,7 +90,7 @@ executed`,
|
|||||||
it("formats execution with minutes", async () => {
|
it("formats execution with minutes", async () => {
|
||||||
await assertSlackMessage({
|
await assertSlackMessage({
|
||||||
command: "echo test",
|
command: "echo test",
|
||||||
format: `$COMMAND took $DURATION`,
|
format: "$COMMAND took $DURATION",
|
||||||
durationMS: 120000,
|
durationMS: 120000,
|
||||||
output: "echo test took 2m 0.0s",
|
output: "echo test took 2m 0.0s",
|
||||||
});
|
});
|
||||||
@@ -99,7 +99,7 @@ executed`,
|
|||||||
it("formats execution with hours", async () => {
|
it("formats execution with hours", async () => {
|
||||||
await assertSlackMessage({
|
await assertSlackMessage({
|
||||||
command: "echo test",
|
command: "echo test",
|
||||||
format: `$COMMAND took $DURATION`,
|
format: "$COMMAND took $DURATION",
|
||||||
durationMS: 60000 * 60,
|
durationMS: 60000 * 60,
|
||||||
output: "echo test took 1hr 0m 0.0s",
|
output: "echo test took 1hr 0m 0.0s",
|
||||||
});
|
});
|
||||||
|
|||||||
30
test.ts
30
test.ts
@@ -1,6 +1,6 @@
|
|||||||
import { readableStreamToText, spawn } from "bun";
|
import { readableStreamToText, spawn } from "bun";
|
||||||
import { afterEach, expect, it } from "bun:test";
|
import { expect, it } from "bun:test";
|
||||||
import { readFile, unlink } from "fs/promises";
|
import { readFile, unlink } from "node:fs/promises";
|
||||||
|
|
||||||
export const runContainer = async (
|
export const runContainer = async (
|
||||||
image: string,
|
image: string,
|
||||||
@@ -21,7 +21,8 @@ export const runContainer = async (
|
|||||||
"-c",
|
"-c",
|
||||||
init,
|
init,
|
||||||
]);
|
]);
|
||||||
let containerID = await readableStreamToText(proc.stdout);
|
|
||||||
|
const containerID = await readableStreamToText(proc.stdout);
|
||||||
const exitCode = await proc.exited;
|
const exitCode = await proc.exited;
|
||||||
if (exitCode !== 0) {
|
if (exitCode !== 0) {
|
||||||
throw new Error(containerID);
|
throw new Error(containerID);
|
||||||
@@ -36,7 +37,7 @@ export const runContainer = async (
|
|||||||
export const executeScriptInContainer = async (
|
export const executeScriptInContainer = async (
|
||||||
state: TerraformState,
|
state: TerraformState,
|
||||||
image: string,
|
image: string,
|
||||||
shell: string = "sh",
|
shell = "sh",
|
||||||
): Promise<{
|
): Promise<{
|
||||||
exitCode: number;
|
exitCode: number;
|
||||||
stdout: string[];
|
stdout: string[];
|
||||||
@@ -116,6 +117,9 @@ export interface CoderScriptAttributes {
|
|||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type ResourceInstance<T extends string = string> =
|
||||||
|
T extends "coder_script" ? CoderScriptAttributes : Record<string, string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* finds the first instance of the given resource type in the given state. If
|
* finds the first instance of the given resource type in the given state. If
|
||||||
* name is specified, it will only find the instance with the given name.
|
* name is specified, it will only find the instance with the given name.
|
||||||
@@ -124,10 +128,7 @@ export const findResourceInstance = <T extends string>(
|
|||||||
state: TerraformState,
|
state: TerraformState,
|
||||||
type: T,
|
type: T,
|
||||||
name?: string,
|
name?: string,
|
||||||
// if type is "coder_script" return CoderScriptAttributes
|
): ResourceInstance<T> => {
|
||||||
): T extends "coder_script"
|
|
||||||
? CoderScriptAttributes
|
|
||||||
: Record<string, string> => {
|
|
||||||
const resource = state.resources.find(
|
const resource = state.resources.find(
|
||||||
(resource) =>
|
(resource) =>
|
||||||
resource.type === type && (name ? resource.name === name : true),
|
resource.type === type && (name ? resource.name === name : true),
|
||||||
@@ -140,7 +141,8 @@ export const findResourceInstance = <T extends string>(
|
|||||||
`Resource ${type} has ${resource.instances.length} instances`,
|
`Resource ${type} has ${resource.instances.length} instances`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return resource.instances[0].attributes as any;
|
|
||||||
|
return resource.instances[0].attributes as ResourceInstance<T>;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -157,15 +159,15 @@ export const testRequiredVariables = <TVars extends TerraformVariables>(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const varNames = Object.keys(vars);
|
const varNames = Object.keys(vars);
|
||||||
varNames.forEach((varName) => {
|
for (const varName of varNames) {
|
||||||
// Ensures that every variable provided is required!
|
// Ensures that every variable provided is required!
|
||||||
it("missing variable " + varName, async () => {
|
it(`missing variable: ${varName}`, async () => {
|
||||||
const localVars: TerraformVariables = {};
|
const localVars: TerraformVariables = {};
|
||||||
varNames.forEach((otherVarName) => {
|
for (const otherVarName of varNames) {
|
||||||
if (otherVarName !== varName) {
|
if (otherVarName !== varName) {
|
||||||
localVars[otherVarName] = vars[otherVarName];
|
localVars[otherVarName] = vars[otherVarName];
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await runTerraformApply(dir, localVars);
|
await runTerraformApply(dir, localVars);
|
||||||
@@ -181,7 +183,7 @@ export const testRequiredVariables = <TVars extends TerraformVariables>(
|
|||||||
}
|
}
|
||||||
throw new Error(`${varName} is not a required variable!`);
|
throw new Error(`${varName} is not a required variable!`);
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
// If we were just compiling for the tests, we could safely target ESNext at
|
||||||
"module": "nodenext",
|
// all times, but just because we've been starting to add more runtime logic
|
||||||
|
// files to some of the modules, erring on the side of caution by having a
|
||||||
|
// older compilation target
|
||||||
|
"target": "ES6",
|
||||||
|
"module": "ESNext",
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"allowSyntheticDefaultImports": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
"moduleResolution": "nodenext",
|
"moduleResolution": "node",
|
||||||
"types": ["bun-types"]
|
"types": ["bun-types"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ This module lets you authenticate with [Hashicorp Vault](https://www.vaultprojec
|
|||||||
```tf
|
```tf
|
||||||
module "vault" {
|
module "vault" {
|
||||||
source = "registry.coder.com/modules/vault-jwt/coder"
|
source = "registry.coder.com/modules/vault-jwt/coder"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
vault_addr = "https://vault.example.com"
|
vault_addr = "https://vault.example.com"
|
||||||
vault_jwt_role = "coder" # The Vault role to use for authentication
|
vault_jwt_role = "coder" # The Vault role to use for authentication
|
||||||
@@ -41,7 +41,7 @@ curl -H "X-Vault-Token: ${VAULT_TOKEN}" -X GET "${VAULT_ADDR}/v1/coder/secrets/d
|
|||||||
```tf
|
```tf
|
||||||
module "vault" {
|
module "vault" {
|
||||||
source = "registry.coder.com/modules/vault-jwt/coder"
|
source = "registry.coder.com/modules/vault-jwt/coder"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
vault_addr = "https://vault.example.com"
|
vault_addr = "https://vault.example.com"
|
||||||
vault_jwt_auth_path = "oidc"
|
vault_jwt_auth_path = "oidc"
|
||||||
@@ -56,7 +56,7 @@ data "coder_workspace_owner" "me" {}
|
|||||||
|
|
||||||
module "vault" {
|
module "vault" {
|
||||||
source = "registry.coder.com/modules/vault-jwt/coder"
|
source = "registry.coder.com/modules/vault-jwt/coder"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
vault_addr = "https://vault.example.com"
|
vault_addr = "https://vault.example.com"
|
||||||
vault_jwt_role = data.coder_workspace_owner.me.groups[0]
|
vault_jwt_role = data.coder_workspace_owner.me.groups[0]
|
||||||
@@ -68,7 +68,7 @@ module "vault" {
|
|||||||
```tf
|
```tf
|
||||||
module "vault" {
|
module "vault" {
|
||||||
source = "registry.coder.com/modules/vault-jwt/coder"
|
source = "registry.coder.com/modules/vault-jwt/coder"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
vault_addr = "https://vault.example.com"
|
vault_addr = "https://vault.example.com"
|
||||||
vault_jwt_role = "coder" # The Vault role to use for authentication
|
vault_jwt_role = "coder" # The Vault role to use for authentication
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ install() {
|
|||||||
printf "Failed to determine the latest Vault version.\n"
|
printf "Failed to determine the latest Vault version.\n"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
VAULT_CLI_VERSION=$${VAULT_CLI_VERSION}
|
VAULT_CLI_VERSION=$${LATEST_VERSION}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check if the vault CLI is installed and has the correct version
|
# Check if the vault CLI is installed and has the correct version
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ describe("vscode-desktop", async () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
(res) => res.type == "coder_app" && res.name == "vscode",
|
(res) => res.type === "coder_app" && res.name === "vscode",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(coder_app).not.toBeNull();
|
expect(coder_app).not.toBeNull();
|
||||||
@@ -79,7 +79,7 @@ describe("vscode-desktop", async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const coder_app = state.resources.find(
|
const coder_app = state.resources.find(
|
||||||
(res) => res.type == "coder_app" && res.name == "vscode",
|
(res) => res.type === "coder_app" && res.name === "vscode",
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(coder_app).not.toBeNull();
|
expect(coder_app).not.toBeNull();
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ Automatically install [Visual Studio Code Server](https://code.visualstudio.com/
|
|||||||
```tf
|
```tf
|
||||||
module "vscode-web" {
|
module "vscode-web" {
|
||||||
source = "registry.coder.com/modules/vscode-web/coder"
|
source = "registry.coder.com/modules/vscode-web/coder"
|
||||||
version = "1.0.14"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
accept_license = true
|
accept_license = true
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ module "vscode-web" {
|
|||||||
```tf
|
```tf
|
||||||
module "vscode-web" {
|
module "vscode-web" {
|
||||||
source = "registry.coder.com/modules/vscode-web/coder"
|
source = "registry.coder.com/modules/vscode-web/coder"
|
||||||
version = "1.0.14"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
install_prefix = "/home/coder/.vscode-web"
|
install_prefix = "/home/coder/.vscode-web"
|
||||||
folder = "/home/coder"
|
folder = "/home/coder"
|
||||||
@@ -42,7 +42,7 @@ module "vscode-web" {
|
|||||||
```tf
|
```tf
|
||||||
module "vscode-web" {
|
module "vscode-web" {
|
||||||
source = "registry.coder.com/modules/vscode-web/coder"
|
source = "registry.coder.com/modules/vscode-web/coder"
|
||||||
version = "1.0.14"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"]
|
extensions = ["github.copilot", "ms-python.python", "ms-toolsai.jupyter"]
|
||||||
accept_license = true
|
accept_license = true
|
||||||
@@ -56,7 +56,7 @@ Configure VS Code's [settings.json](https://code.visualstudio.com/docs/getstarte
|
|||||||
```tf
|
```tf
|
||||||
module "vscode-web" {
|
module "vscode-web" {
|
||||||
source = "registry.coder.com/modules/vscode-web/coder"
|
source = "registry.coder.com/modules/vscode-web/coder"
|
||||||
version = "1.0.14"
|
version = "1.0.20"
|
||||||
agent_id = coder_agent.example.id
|
agent_id = coder_agent.example.id
|
||||||
extensions = ["dracula-theme.theme-dracula"]
|
extensions = ["dracula-theme.theme-dracula"]
|
||||||
settings = {
|
settings = {
|
||||||
|
|||||||
@@ -72,27 +72,25 @@ for extension in "$${EXTENSIONLIST[@]}"; do
|
|||||||
output=$($VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force)
|
output=$($VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force)
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
echo "Failed to install extension: $extension: $output"
|
echo "Failed to install extension: $extension: $output"
|
||||||
exit 1
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
if [ "${AUTO_INSTALL_EXTENSIONS}" = true ]; then
|
if [ "${AUTO_INSTALL_EXTENSIONS}" = true ]; then
|
||||||
if ! command -v jq > /dev/null; then
|
if ! command -v jq > /dev/null; then
|
||||||
echo "jq is required to install extensions from a workspace file."
|
echo "jq is required to install extensions from a workspace file."
|
||||||
exit 0
|
else
|
||||||
fi
|
WORKSPACE_DIR="$HOME"
|
||||||
|
if [ -n "${FOLDER}" ]; then
|
||||||
|
WORKSPACE_DIR="${FOLDER}"
|
||||||
|
fi
|
||||||
|
|
||||||
WORKSPACE_DIR="$HOME"
|
if [ -f "$WORKSPACE_DIR/.vscode/extensions.json" ]; then
|
||||||
if [ -n "${FOLDER}" ]; then
|
printf "🧩 Installing extensions from %s/.vscode/extensions.json...\n" "$WORKSPACE_DIR"
|
||||||
WORKSPACE_DIR="${FOLDER}"
|
extensions=$(jq -r '.recommendations[]' "$WORKSPACE_DIR"/.vscode/extensions.json)
|
||||||
fi
|
for extension in $extensions; do
|
||||||
|
$VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force
|
||||||
if [ -f "$WORKSPACE_DIR/.vscode/extensions.json" ]; then
|
done
|
||||||
printf "🧩 Installing extensions from %s/.vscode/extensions.json...\n" "$WORKSPACE_DIR"
|
fi
|
||||||
extensions=$(jq -r '.recommendations[]' "$WORKSPACE_DIR"/.vscode/extensions.json)
|
|
||||||
for extension in $extensions; do
|
|
||||||
$VSCODE_WEB "$EXTENSION_ARG" --install-extension "$extension" --force
|
|
||||||
done
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { describe, expect, it } from "bun:test";
|
import { describe, expect, it } from "bun:test";
|
||||||
import {
|
import {
|
||||||
TerraformState,
|
type TerraformState,
|
||||||
runTerraformApply,
|
runTerraformApply,
|
||||||
runTerraformInit,
|
runTerraformInit,
|
||||||
testRequiredVariables,
|
testRequiredVariables,
|
||||||
|
|||||||
Reference in New Issue
Block a user