add tests
This commit is contained in:
@@ -10,6 +10,8 @@ To create a new module, clone this repository and run:
|
||||
|
||||
A suite of test-helpers exists to run `terraform apply` on modules with variables, and test script output against containers.
|
||||
|
||||
The testing suite must be able to run docker containers with the `--network=host` flag, which typically requires running the tests on linux as this flag does not apply to Docker Desktop for MacOS and Windows. MacOS users can work around this by using something like [Orbstack](https://orbstack.dev/) instead of Docker Desktop.
|
||||
|
||||
Reference existing `*.test.ts` files for implementation.
|
||||
|
||||
```shell
|
||||
|
||||
89
github-upload-public-key/main.test.ts
Normal file
89
github-upload-public-key/main.test.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { describe, expect, it } from "bun:test";
|
||||
import { createJSONResponse, execContainer, findResourceInstance, runContainer, runTerraformApply, runTerraformInit, testRequiredVariables, writeCoder } from "../test";
|
||||
import { Server, serve } from "bun";
|
||||
|
||||
describe("github-upload-public-key", async () => {
|
||||
await runTerraformInit(import.meta.dir);
|
||||
|
||||
testRequiredVariables(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
});
|
||||
|
||||
it("creates new key if one does not exist", async () => {
|
||||
const { instance, id } = await setupContainer();
|
||||
await writeCoder(id, "echo foo");
|
||||
let exec = await execContainer(id, ["bash", "-c", instance.script]);
|
||||
expect(exec.stdout).toContain("Coder public SSH key uploaded to GitHub!")
|
||||
expect(exec.exitCode).toBe(0);
|
||||
});
|
||||
|
||||
it("does nothing if one already exists", async () => {
|
||||
const { instance, id } = await setupContainer();
|
||||
await writeCoder(id, "echo findkey");
|
||||
let exec = await execContainer(id, ["bash", "-c", instance.script]);
|
||||
expect(exec.stdout).toContain("Coder public SSH key is already uploaded to GitHub!")
|
||||
expect(exec.exitCode).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
const setupContainer = async (
|
||||
image = "lorello/alpine-bash",
|
||||
vars: Record<string, string> = {},
|
||||
) => {
|
||||
const server = await setupServer();
|
||||
const state = await runTerraformApply(import.meta.dir, {
|
||||
agent_id: "foo",
|
||||
// trim the trailing slash on the URL
|
||||
access_url: server.url.toString().slice(0, -1),
|
||||
owner_session_token: "bar",
|
||||
github_api_url: server.url.toString().slice(0, -1),
|
||||
...vars,
|
||||
});
|
||||
const instance = findResourceInstance(state, "coder_script");
|
||||
const id = await runContainer(image);
|
||||
return { id, instance };
|
||||
};
|
||||
|
||||
const setupServer = async (): Promise<Server> => {
|
||||
let url: URL;
|
||||
const fakeSlackHost = serve({
|
||||
fetch: (req) => {
|
||||
url = new URL(req.url);
|
||||
if (url.pathname === "/api/v2/users/me/gitsshkey") {
|
||||
return createJSONResponse({
|
||||
public_key: "exists",
|
||||
});
|
||||
}
|
||||
|
||||
if (url.pathname === "/user/keys") {
|
||||
if (req.method === "POST") {
|
||||
return createJSONResponse({
|
||||
key: "created",
|
||||
}, 201);
|
||||
}
|
||||
|
||||
// case: key already exists
|
||||
if (req.headers.get("Authorization") == "Bearer findkey") {
|
||||
return createJSONResponse([{
|
||||
key: "foo",
|
||||
}, {
|
||||
key: "exists",
|
||||
}]);
|
||||
}
|
||||
|
||||
// case: key does not exist
|
||||
return createJSONResponse([{
|
||||
key: "foo",
|
||||
}]);
|
||||
}
|
||||
|
||||
|
||||
return createJSONResponse({
|
||||
error: "not_found"
|
||||
}, 404);
|
||||
},
|
||||
port: 0,
|
||||
});
|
||||
|
||||
return fakeSlackHost;
|
||||
}
|
||||
@@ -20,14 +20,34 @@ variable "external_auth_id" {
|
||||
default = "github"
|
||||
}
|
||||
|
||||
variable "github_api_url" {
|
||||
type = string
|
||||
description = "The URL of the GitHub instance."
|
||||
default = "https://api.github.com"
|
||||
}
|
||||
|
||||
// Optional variables mostly for testing purposes, will normally come from data.coder_workspace.me
|
||||
variable "access_url" {
|
||||
type = string
|
||||
description = "The access URL of the workspace."
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "owner_session_token" {
|
||||
type = string
|
||||
description = "The owner session token of the workspace."
|
||||
default = ""
|
||||
}
|
||||
|
||||
data "coder_workspace" "me" {}
|
||||
|
||||
resource "coder_script" "github_upload_public_key" {
|
||||
agent_id = var.agent_id
|
||||
script = templatefile("${path.module}/run.sh", {
|
||||
CODER_OWNER_SESSION_TOKEN : data.coder_workspace.me.owner_session_token,
|
||||
CODER_ACCESS_URL : data.coder_workspace.me.access_url,
|
||||
GITHUB_EXTERNAL_AUTH_ID : var.external_auth_id,
|
||||
CODER_OWNER_SESSION_TOKEN : var.owner_session_token != "" ? var.owner_session_token : data.coder_workspace.me.owner_session_token,
|
||||
CODER_ACCESS_URL : var.access_url != "" ? var.access_url : data.coder_workspace.me.access_url,
|
||||
CODER_EXTERNAL_AUTH_ID : var.external_auth_id,
|
||||
GITHUB_API_URL : var.github_api_url,
|
||||
})
|
||||
display_name = "Github Upload Public Key"
|
||||
icon = "/icon/github.svg"
|
||||
|
||||
@@ -4,7 +4,8 @@ set -e
|
||||
|
||||
CODER_ACCESS_URL="${CODER_ACCESS_URL}"
|
||||
CODER_OWNER_SESSION_TOKEN="${CODER_OWNER_SESSION_TOKEN}"
|
||||
GITHUB_EXTERNAL_AUTH_ID="${GITHUB_EXTERNAL_AUTH_ID}"
|
||||
CODER_EXTERNAL_AUTH_ID="${CODER_EXTERNAL_AUTH_ID}"
|
||||
GITHUB_API_URL="${GITHUB_API_URL}"
|
||||
|
||||
if [ -z "$CODER_ACCESS_URL" ]; then
|
||||
echo "No coder access url specified!"
|
||||
@@ -16,13 +17,18 @@ if [ -z "$CODER_OWNER_SESSION_TOKEN" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$GITHUB_EXTERNAL_AUTH_ID" ]; then
|
||||
if [ -z "$CODER_EXTERNAL_AUTH_ID" ]; then
|
||||
echo "No GitHub external auth id specified!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$GITHUB_API_URL" ]; then
|
||||
echo "No GitHub API URL specified!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Fetching GitHub token..."
|
||||
GITHUB_TOKEN=$(coder external-auth access-token $GITHUB_EXTERNAL_AUTH_ID)
|
||||
GITHUB_TOKEN=$(coder external-auth access-token $CODER_EXTERNAL_AUTH_ID)
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Failed to fetch GitHub token!"
|
||||
exit 1
|
||||
@@ -36,7 +42,7 @@ echo "GitHub token found!"
|
||||
echo "Fetching Coder public SSH key..."
|
||||
PUBLIC_KEY_RESPONSE=$(
|
||||
curl -L -s \
|
||||
-w "%%{http_code}" \
|
||||
-w "\n%%{http_code}" \
|
||||
-H 'accept: application/json' \
|
||||
-H "cookie: coder_session_token=$CODER_OWNER_SESSION_TOKEN" \
|
||||
"$CODER_ACCESS_URL/api/v2/users/me/gitsshkey"
|
||||
@@ -61,11 +67,11 @@ fi
|
||||
echo "Fetching GitHub public SSH keys..."
|
||||
GITHUB_KEYS_RESPONSE=$(
|
||||
curl -L -s \
|
||||
-w "%%{http_code}" \
|
||||
-w "\n%%{http_code}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/user/keys
|
||||
$GITHUB_API_URL/user/keys
|
||||
)
|
||||
GITHUB_KEYS_RESPONSE_STATUS=$(tail -n1 <<< "$GITHUB_KEYS_RESPONSE")
|
||||
GITHUB_KEYS_RESPONSE_BODY=$(sed \$d <<< "$GITHUB_KEYS_RESPONSE")
|
||||
@@ -89,11 +95,11 @@ CODER_PUBLIC_KEY_NAME="$CODER_ACCESS_URL Workspaces"
|
||||
UPLOAD_RESPONSE=$(
|
||||
curl -L -s \
|
||||
-X POST \
|
||||
-w "%%{http_code}" \
|
||||
-w "\n%%{http_code}" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
https://api.github.com/user/keys \
|
||||
$GITHUB_API_URL/user/keys \
|
||||
-d "{\"title\":\"$CODER_PUBLIC_KEY_NAME\",\"key\":\"$PUBLIC_KEY\"}"
|
||||
)
|
||||
UPLOAD_RESPONSE_STATUS=$(tail -n1 <<< "$UPLOAD_RESPONSE")
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
runTerraformApply,
|
||||
runTerraformInit,
|
||||
testRequiredVariables,
|
||||
writeCoder,
|
||||
} from "../test";
|
||||
|
||||
describe("slackme", async () => {
|
||||
@@ -119,15 +120,6 @@ const setupContainer = async (
|
||||
return { id, instance };
|
||||
};
|
||||
|
||||
const writeCoder = async (id: string, script: string) => {
|
||||
const exec = await execContainer(id, [
|
||||
"sh",
|
||||
"-c",
|
||||
`echo '${script}' > /usr/bin/coder && chmod +x /usr/bin/coder`,
|
||||
]);
|
||||
expect(exec.exitCode).toBe(0);
|
||||
};
|
||||
|
||||
const assertSlackMessage = async (opts: {
|
||||
command: string;
|
||||
format?: string;
|
||||
|
||||
9
test.ts
9
test.ts
@@ -223,3 +223,12 @@ export const createJSONResponse = (obj: object, statusCode = 200): Response => {
|
||||
status: statusCode,
|
||||
})
|
||||
}
|
||||
|
||||
export const writeCoder = async (id: string, script: string) => {
|
||||
const exec = await execContainer(id, [
|
||||
"sh",
|
||||
"-c",
|
||||
`echo '${script}' > /usr/bin/coder && chmod +x /usr/bin/coder`,
|
||||
]);
|
||||
expect(exec.exitCode).toBe(0);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user