Skip to content

Commit 26e09aa

Browse files
committed
RHTAP-3056 GitLab CI tests fixes and refactoring.
Signed-off-by: Josef Kopriva <[email protected]>
1 parent 745a31e commit 26e09aa

File tree

6 files changed

+102
-57
lines changed

6 files changed

+102
-57
lines changed

default.env

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,19 @@ export QUAY_USERNAME=''
6767
# Quay Password - needed for GitLab CI, GitHub Actions
6868
# Required: no (by default testing on Jenkins is disabled)
6969
# Example: 112b49e9....
70-
export QUAY_PASSWORD=""
70+
export QUAY_PASSWORD=''
71+
72+
# Cosign public key in base64 format - needed for GitLab CI, GitHub Actions, Jenkins
73+
# Required: no (by default testing on Jenkins is disabled)
74+
# Example: 112b49e9....
75+
export COSIGN_PUBLIC_KEY=''
76+
77+
# Cosign private key in base64 format - needed for GitLab CI, GitHub Actions, Jenkins
78+
# Required: no (by default testing on Jenkins is disabled)
79+
# Example: 112b49e9....
80+
export COSIGN_SECRET_KEY=''
81+
82+
# Cosign secret password in base64 format - needed for GitLab CI, GitHub Actions, Jenkins
83+
# Required: no (by default testing on Jenkins is disabled)
84+
# Example: 112b49e9....
85+
export COSIGN_SECRET_PASSWORD=''

src/apis/ci/jenkins.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,13 @@ export class JenkinsCI extends Utils {
9292
}
9393
return response.status === 200;
9494
} catch (error) {
95-
if (error.response && error.response.status === 404) {
96-
return false;
95+
if (axios.isAxiosError(error)) {
96+
if (error.response && error.response.status === 404) {
97+
return false;
98+
} else {
99+
console.error('Axios error checking job existence:', error);
100+
throw error;
101+
}
97102
} else {
98103
console.error('Error checking job existence:', error);
99104
throw error;
@@ -206,7 +211,4 @@ export class JenkinsCI extends Utils {
206211
console.error('Error deleting job:', error);
207212
}
208213
}
209-
210-
211-
212214
}

src/apis/git-providers/gitlab.ts

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export class GitLabProvider extends Utils {
3232
try {
3333
const projects = await this.gitlab.Projects.show(`${namespace}/${repoName}`);
3434
if (projects) {
35-
console.info(`Repository with name '${repoName}' found in namespace '${namespace}'
35+
console.info(`Repository with name '${repoName}' found in organization '${namespace}'
3636
created at '${projects.created_at}' url: gitlab.com/${namespace}/${repoName}`);
3737
return projects.id
3838
}
@@ -61,7 +61,6 @@ export class GitLabProvider extends Utils {
6161
await this.sleep(5000); // Wait 5 seconds before checking again
6262
} catch (error) {
6363
console.error('Error checking for folder creation:', error);
64-
throw error;
6564
}
6665
}
6766
}
@@ -271,25 +270,21 @@ export class GitLabProvider extends Utils {
271270
}
272271
}
273272

274-
public async getLatestPipeline(projectId: number) {
275-
try {
276-
// const response = await this.gitlab.Pipelines.show(projectId, 'latest');
277-
// console.log('Pipeline triggered successfully:', response);
278-
// return response;
279-
280-
const pipelines = await this.gitlab.Pipelines.all(projectId);
281-
if (pipelines.length === 0) {
282-
console.log(`No pipelines found!`);
283-
return null;
284-
}
285-
const latestPipeline = pipelines.sort((a, b) => b.id - a.id)[0];
286-
console.log(`Latest pipeline ID: ${latestPipeline.id} Status: ${latestPipeline.status}`);
287-
return latestPipeline;
288-
} catch (error) {
289-
console.error('Error triggering pipeline:', error);
290-
throw error;
273+
public async getLatestPipeline(projectId: number) {
274+
try {
275+
const pipelines = await this.gitlab.Pipelines.all(projectId);
276+
if (pipelines.length === 0) {
277+
console.log(`No pipelines found!`);
278+
return null;
291279
}
280+
const latestPipeline = pipelines.sort((a, b) => b.id - a.id)[0];
281+
console.log(`Latest pipeline ID: ${latestPipeline.id} Status: ${latestPipeline.status}`);
282+
return latestPipeline;
283+
} catch (error) {
284+
console.error('Error triggering pipeline:', error);
285+
throw error;
292286
}
287+
}
293288

294289
// Trigger a GitLab pipeline
295290
public async triggerPipeline(projectId: number, branchName: string, triggerToken: string) {
@@ -321,7 +316,6 @@ export class GitLabProvider extends Utils {
321316
await this.sleep(5000); // Wait 5 seconds before checking again
322317
} catch (error) {
323318
console.error('Error checking for pipeline creation:', error);
324-
throw error;
325319
}
326320
}
327321
}
@@ -346,7 +340,6 @@ export class GitLabProvider extends Utils {
346340
await this.sleep(5000); // Wait 5 seconds
347341
} catch (error) {
348342
console.error('Error checking pipeline status:', error);
349-
throw error;
350343
}
351344
}
352345
}
@@ -399,7 +392,7 @@ export class GitLabProvider extends Utils {
399392
const fileContent = Buffer.from(file.content, 'base64').toString('utf-8');
400393

401394
// Replace specific text
402-
const updatedContent = fileContent.replace(textToReplace,replacement);
395+
const updatedContent = fileContent.replace(textToReplace, replacement);
403396

404397
// Encode the updated content to base64
405398
const encodedContent = Buffer.from(updatedContent).toString('base64');

src/apis/kubernetes/kube.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export class Kubernetes extends Utils {
334334
const secret = await k8sApi.readNamespacedSecret(secretName, namespace);
335335

336336
// Check if the key exists in the secret data
337-
if (secret.body.data && secret.body.data[keyName]) {
337+
if (secret.body.data && secret.body?.data[keyName]) {
338338
// Decode the base64 encoded secret value
339339
const secretValue = Buffer.from(secret.body.data[keyName], 'base64').toString('utf-8');
340340
return secretValue;
@@ -428,7 +428,7 @@ export class Kubernetes extends Utils {
428428
* @returns {Promise<string>} - returns route URL.
429429
*/
430430
public async getCosignPublicKey(): Promise<string> {
431-
return this.getSecretPartialName("rhtap-app-development", "cosign-pub", "cosign.pub", true);
431+
return this.getSecretPartialName("rhtap-app-development", "cosign-pub", "cosign.pub", false);
432432
}
433433

434434
/**
@@ -438,7 +438,7 @@ export class Kubernetes extends Utils {
438438
* @returns {Promise<string>} - returns route URL.
439439
*/
440440
public async getCosignPrivateKey(): Promise<string> {
441-
return this.getSecretPartialName("rhtap-tas", "fulcio-cert-trusted-artifact-signer", "private", true);
441+
return this.getSecretPartialName("rhtap-tas", "fulcio-cert-trusted-artifact-signer", "private", false);
442442
}
443443

444444
/**

src/utils/test.utils.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { GitHubProvider } from "../../src/apis/git-providers/github";
33
import { Kubernetes } from "../../src/apis/kubernetes/kube";
44
import { DeveloperHubClient } from "../../src/apis/backstage/developer-hub";
55
import { JenkinsCI } from "../../src/apis/ci/jenkins";
6+
import { syncArgoApplication } from "./argocd";
7+
import { TaskIdReponse } from "../../src/apis/backstage/types";
68

79

810
export async function cleanAfterTestGitHub(gitHubClient: GitHubProvider, kubeClient: Kubernetes, rootNamespace: string, githubOrganization: string, repositoryName: string) {
@@ -96,4 +98,57 @@ export async function getGitLabProvider(kubeClient: Kubernetes) {
9698
}
9799
}
98100

101+
export async function getCosignPassword(kubeClient: Kubernetes) {
102+
if (process.env.COSIGN_SECRET_PASSWORD) {
103+
return process.env.COSIGN_SECRET_PASSWORD;
104+
} else {
105+
return await kubeClient.getCosignPassword();
106+
}
107+
}
108+
109+
export async function getCosignPrivateKey(kubeClient: Kubernetes) {
110+
if (process.env.COSIGN_SECRET_KEY) {
111+
return process.env.COSIGN_SECRET_KEY;
112+
} else {
113+
return await kubeClient.getCosignPrivateKey();
114+
}
115+
}
116+
117+
export async function getCosignPublicKey(kubeClient: Kubernetes) {
118+
if (process.env.COSIGN_PUBLIC_KEY) {
119+
return process.env.COSIGN_PUBLIC_KEY;
120+
} else {
121+
return await kubeClient.getCosignPublicKey();
122+
}
123+
}
124+
125+
export async function waitForComponentCreation(backstageClient: DeveloperHubClient, repositoryName: string, developerHubTask: TaskIdReponse) {
126+
const taskCreated = await backstageClient.getTaskProcessed(developerHubTask.id, 120000)
127+
128+
if (taskCreated.status !== 'completed') {
129+
console.log("Failed to create backstage task. Creating logs...");
130+
131+
try {
132+
const logs = await backstageClient.getEventStreamLog(taskCreated.id)
133+
await backstageClient.writeLogsToArtifactDir('backstage-tasks-logs', `gitlab-${repositoryName}.log`, logs)
134+
} catch (error) {
135+
throw new Error(`Failed to write logs to artifact directory: ${error}`);
136+
}
137+
} else {
138+
console.log("Task created successfully in backstage");
139+
}
140+
}
141+
142+
export async function waitForArgoSyncAndRouteContent(kubeClient: Kubernetes, backstageClient: DeveloperHubClient, developmentNamespace: string, developmentEnvironmentName: string, repositoryName: string, stringOnRoute: string) {
143+
console.log("syncing argocd application in development environment")
144+
await syncArgoApplication(await getRHTAPRootNamespace(), `${repositoryName}-${developmentEnvironmentName}`)
145+
const componentRoute = await kubeClient.getOpenshiftRoute(repositoryName, developmentNamespace)
146+
const isReady = await backstageClient.waitUntilComponentEndpointBecomeReady(`https://${componentRoute}`, 10 * 60 * 1000)
147+
if (!isReady) {
148+
throw new Error("Component seems was not synced by ArgoCD in 10 minutes");
149+
}
150+
expect(await waitForStringInPageContent(`https://${componentRoute}`, stringOnRoute, 120000)).toBe(true)
151+
152+
}
153+
99154

tests/gpts/gitlab/suites-config/gitlab_gitlabci_suite.ts

Lines changed: 6 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { GitLabProvider } from "../../../../src/apis/git-providers/gitlab";
55
import { Kubernetes } from "../../../../src/apis/kubernetes/kube";
66
import { ScaffolderScaffoldOptions } from "@backstage/plugin-scaffolder-react";
77
import { generateRandomChars } from "../../../../src/utils/generator";
8-
import { cleanAfterTestGitLab, getDeveloperHubClient, getGitLabProvider, getRHTAPRootNamespace, waitForStringInPageContent } from "../../../../src/utils/test.utils";
8+
import { cleanAfterTestGitLab, getCosignPassword, getCosignPrivateKey, getCosignPublicKey, getDeveloperHubClient, getGitLabProvider, getRHTAPRootNamespace, waitForArgoSyncAndRouteContent, waitForComponentCreation, waitForStringInPageContent } from "../../../../src/utils/test.utils";
99
import { syncArgoApplication } from "../../../../src/utils/argocd";
1010

1111
/**
@@ -113,20 +113,7 @@ export const gitLabProviderGitLabCITests = (softwareTemplateName: string, string
113113
* If the task is not completed within the timeout, it writes logs to the specified directory.
114114
*/
115115
it(`waits for ${softwareTemplateName} component creation to finish`, async () => {
116-
const taskCreated = await backstageClient.getTaskProcessed(developerHubTask.id, 120000)
117-
118-
if (taskCreated.status !== 'completed') {
119-
console.log("Failed to create backstage task. Creating logs...");
120-
121-
try {
122-
const logs = await backstageClient.getEventStreamLog(taskCreated.id)
123-
await backstageClient.writeLogsToArtifactDir('backstage-tasks-logs', `gitlab-${repositoryName}.log`, logs)
124-
} catch (error) {
125-
throw new Error(`Failed to write logs to artifact directory: ${error}`);
126-
}
127-
} else {
128-
console.log("Task created successfully in backstage");
129-
}
116+
await waitForComponentCreation(backstageClient, repositoryName, developerHubTask);
130117
}, 120000);
131118

132119
/**
@@ -162,9 +149,9 @@ export const gitLabProviderGitLabCITests = (softwareTemplateName: string, string
162149
* Waits for the specified ArgoCD application associated with the DeveloperHub task to be synchronized in the cluster.
163150
*/
164151
it(`Setup creds for ${softwareTemplateName} pipeline`, async () => {
165-
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_PUBLIC_KEY", await kubeClient.getCosignPublicKey());
166-
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_SECRET_KEY", await kubeClient.getCosignPrivateKey());
167-
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_SECRET_PASSWORD", await kubeClient.getCosignPassword());
152+
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_PUBLIC_KEY", await getCosignPublicKey(kubeClient));
153+
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_SECRET_KEY", await getCosignPrivateKey(kubeClient));
154+
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "COSIGN_SECRET_PASSWORD", await getCosignPassword(kubeClient));
168155
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "GITOPS_AUTH_USERNAME", 'fakeUsername');
169156
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "GITOPS_AUTH_PASSWORD", await gitLabProvider.getGitlabToken());
170157
await gitLabProvider.setEnvironmentVariable(gitlabRepositoryID, "QUAY_IO_CREDS_PSW", process.env.QUAY_PASSWORD || '');
@@ -199,14 +186,7 @@ export const gitLabProviderGitLabCITests = (softwareTemplateName: string, string
199186
* Obtain the openshift Route for the component and verify that the previous builded image was synced in the cluster and deployed in development environment
200187
*/
201188
it('container component is successfully synced by gitops in development environment', async () => {
202-
console.log("syncing argocd application in development environment")
203-
await syncArgoApplication(RHTAPRootNamespace, `${repositoryName}-${developmentEnvironmentName}`)
204-
const componentRoute = await kubeClient.getOpenshiftRoute(repositoryName, developmentNamespace)
205-
const isReady = await backstageClient.waitUntilComponentEndpointBecomeReady(`https://${componentRoute}`, 10 * 60 * 1000)
206-
if (!isReady) {
207-
throw new Error("Component seems was not synced by ArgoCD in 10 minutes");
208-
}
209-
expect(await waitForStringInPageContent(`https://${componentRoute}`, stringOnRoute, 120000)).toBe(true)
189+
await waitForArgoSyncAndRouteContent(kubeClient, backstageClient, developmentNamespace, developmentEnvironmentName, repositoryName, stringOnRoute);
210190
}, 900000)
211191

212192
/**

0 commit comments

Comments
 (0)