add tests

pull/241/head
Garrett Delfosse 1 year ago
parent 46bf422d61
commit 36fa871e7b

@ -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

@ -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;

@ -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);
};

Loading…
Cancel
Save