From 6c60a90feaefc7873b2bd87ace27e1beb198845d Mon Sep 17 00:00:00 2001 From: Wayne Starr Date: Wed, 10 Apr 2024 16:54:38 -0600 Subject: [PATCH] chore: improve jest test patterns (#73) ## Description This improves the patterns for running jest tests for GLR - we decided against cypress and playwright because both run the tests in browser and cannot make use of spawnSync or KFC. ## Related Issue Fixes #72 ## Type of change - [ ] Bug fix (non-breaking change which fixes an issue) - [ ] New feature (non-breaking change which adds functionality) - [X] Other (security config, docs update, etc) ## Checklist before merging - [X] Test, docs, adr added or updated as needed - [X] [Contributor Guide Steps](https://github.com/defenseunicorns/uds-package-gitlab-runner/blob/main/CONTRIBUTING.md#developer-workflow) followed Co-authored-by: Billy Figueroa --- test/common.ts | 24 ++++++++++++++++ test/journey/pipeline-run.test.ts | 47 ++++++++++++++++--------------- test/journey/registration.test.ts | 18 +++++------- 3 files changed, 55 insertions(+), 34 deletions(-) create mode 100644 test/common.ts diff --git a/test/common.ts b/test/common.ts new file mode 100644 index 00000000..e266e952 --- /dev/null +++ b/test/common.ts @@ -0,0 +1,24 @@ +import { spawnSync } from "child_process"; + +export function zarfExec(args: string[], captureOutput = false) { + const argString = args.join(" ") + return spawnSync( + `uds zarf ${argString}`, { + // Run command in a shell + shell: true, + // Print the command output directly to the shell if we don'e want to capture it (useful for debugging) + stdio: captureOutput ? undefined : 'inherit' + }); +} + +export async function retry(funcCb: Function, retries = 3, timeout = 3000) { + let result = false + for (let i = 0; i < retries; i++) { + await new Promise(r => setTimeout(r, timeout)) + result = await funcCb() + if (result) { + break + } + } + return result +} diff --git a/test/journey/pipeline-run.test.ts b/test/journey/pipeline-run.test.ts index f9a3e0fb..9a0390ed 100644 --- a/test/journey/pipeline-run.test.ts +++ b/test/journey/pipeline-run.test.ts @@ -1,6 +1,6 @@ import { expect, test} from '@jest/globals'; import { K8s, kind } from "kubernetes-fluent-client"; -import { spawnSync } from "child_process"; +import { zarfExec, retry } from "../common"; test('test kicking off a pipeline run', async () => { // Get the root password for GitLab @@ -8,27 +8,30 @@ test('test kicking off a pipeline run', async () => { const rootPassword = atob(rootPasswordSecret.data!.password) // Create a test repository in GitLab using Zarf - spawnSync(`uds zarf package create package --confirm`, { - shell: true, // Run command in a shell - stdio: 'inherit' // Print the command output directly to the shell (useful for debugging) - }); - spawnSync( - `uds zarf package mirror-resources zarf-package-gitlab-runner-test-amd64-0.0.1.tar.zst \ - --git-url https://gitlab.uds.dev/ --git-push-username root --git-push-password ${rootPassword} --confirm`, { - shell: true, // Run command in a shell - stdio: 'inherit' // Print the command output directly to the shell (useful for debugging) - }); + zarfExec(["package", "create", "package", "--confirm"]); + zarfExec([ + "package", + "mirror-resources", + "zarf-package-gitlab-runner-test-amd64-0.0.1.tar.zst", + "--git-url", "https://gitlab.uds.dev/", + "--git-push-username", "root", + "--git-push-password", rootPassword, + "--confirm" + ]); // Get the toolbox pod and add a token to the root GitLab user const tokenName = `if-you-see-me-in-production-something-is-horribly-wrong-${new Date()}` const toolboxPods = await K8s(kind.Pod).InNamespace("gitlab").WithLabel("app", "toolbox").Get() const toolboxPod = toolboxPods.items.at(0) - spawnSync( - `uds zarf tools kubectl --namespace gitlab exec -i ${toolboxPod?.metadata?.name} -- \ - gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode'], name: 'Root Test Token', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"`, { - shell: true, // Run command in a shell - stdio: 'inherit' // Print the command output directly to the shell (useful for debugging) - }); + zarfExec(["tools", + "kubectl", + "--namespace", "gitlab", + "exec", + "-i", + toolboxPod?.metadata?.name!, + "--", + `gitlab-rails runner "token = User.find_by_username('root').personal_access_tokens.create(scopes: ['api', 'admin_mode'], name: 'Root Test Token', expires_at: 1.days.from_now); token.set_token('${tokenName}'); token.save!"` + ]); const headers: HeadersInit = [["PRIVATE-TOKEN", tokenName]] @@ -46,9 +49,7 @@ test('test kicking off a pipeline run', async () => { expect(runnerResp.status).toBe(200) // Check that the pipeline actually ran successfully - let foundTheKitteh = false - for (let i = 0; i < 7; i++) { - await new Promise(r => setTimeout(r, 7000)) + let foundTheKitteh = await retry(async () => { const jobIDResp = await (await fetch(`https://gitlab.uds.dev/api/v4/projects/1/jobs`, { headers })).json() // Print the job response (useful for debugging) @@ -62,11 +63,11 @@ test('test kicking off a pipeline run', async () => { console.log(jobLog) if (jobLog.indexOf("Hello Kitteh") > -1) { - foundTheKitteh = true - break + return true } } - } + return false + }, 7, 7000); expect(foundTheKitteh).toBe(true) }, 90000); diff --git a/test/journey/registration.test.ts b/test/journey/registration.test.ts index db404073..8cb985fb 100644 --- a/test/journey/registration.test.ts +++ b/test/journey/registration.test.ts @@ -1,22 +1,18 @@ import { expect, test} from '@jest/globals'; import { K8s, kind } from "kubernetes-fluent-client"; -import { spawnSync } from "child_process"; +import { zarfExec, retry } from "../common"; test('test registration of the runner succeeded', async () => { - let foundRegistrationSuccess = false - for (let i = 0; i < 3; i++) { - await new Promise(r => setTimeout(r, 3000)) + let foundRegistrationSuccess = await retry(async () => { const runnerPods = await K8s(kind.Pod).InNamespace("gitlab-runner").WithLabel("app", "gitlab-runner").Get() if (runnerPods.items.at(0)?.status?.phase === "Running") { - const podName = runnerPods.items.at(0)?.metadata?.name - const runnerLogs = spawnSync( - `uds zarf tools kubectl logs -n gitlab-runner ${podName} -c gitlab-runner`, { - shell: true, // Run command in a shell - }); + const podName = runnerPods.items.at(0)?.metadata?.name! + const runnerLogs = zarfExec(["tools", "kubectl", "logs", "-n", "gitlab-runner", podName, "-c", "gitlab-runner"], true); if (runnerLogs.stdout.indexOf("Registering runner... succeeded") > -1) { - foundRegistrationSuccess = true + return true } } - } + return false + }) expect(foundRegistrationSuccess).toBe(true) });