Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 22 additions & 2 deletions .tekton/integration-tests/lightspeed-console-pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ spec:
description: "commit sha to be used in console tests"
script: |
dnf -y install jq
echo -n "$(jq -r --arg component_name "lightspeed-console" '.components[] | select(.name == $component_name) | .containerImage' <<< "$SNAPSHOT")" > $(step.results.console-image.path)
echo -n "$(jq -r --arg component_name "lightspeed-console" '.components[] | select(.name == $component_name) | .source.git.revision' <<< "$SNAPSHOT")" > $(step.results.commit.path)
echo -n "$(jq -r --arg component_name "lightspeed-console-4-19" '.components[] | select(.name == $component_name) | .containerImage' <<< "$SNAPSHOT")" > $(step.results.console-image.path)
echo -n "$(jq -r --arg component_name "lightspeed-console-4-19" '.components[] | select(.name == $component_name) | .source.git.revision' <<< "$SNAPSHOT")" > $(step.results.commit.path)
- name: lint
description: Run lint checks
runAfter:
Expand Down Expand Up @@ -359,3 +359,23 @@ spec:
value: main
- name: pathInRepo
value: stepactions/fail-if-any-step-failed/0.1/fail-if-any-step-failed.yaml
finally:
- name: export-logs-for-retention
taskRef:
resolver: git
params:
- name: url
value: https://github.com/konflux-ci/tekton-integration-catalog.git
- name: revision
value: main
- name: pathInRepo
value: tasks/export-logs/0.1/export-logs-to-quay.yaml
params:
- name: pipeline-run-name
value: $(context.pipelineRun.name)
- name: namespace
value: $(context.pipelineRun.namespace)
- name: quay-repo
value: "quay.io/openshift-lightspeed/ols-console-artifacts"
- name: artifact-credentials-secret
value: ols-konflux-artifacts-bot
81 changes: 78 additions & 3 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,79 @@
import { defineConfig } from 'cypress';
import { plugin as cypressGrepPlugin } from '@cypress/grep/plugin';
import { execFileSync } from 'child_process';
import * as fs from 'fs';
import * as path from 'path';
import * as console from 'console';

const ARTIFACTS_DIR = './gui_test_screenshots/artifacts';
const OLS_NAMESPACE = 'openshift-lightspeed';
const OC_TIMEOUT = 30000;

const CLUSTER_RESOURCES = [
'pods',
'services',
'deployments',
'replicasets',
'routes',
'rolebindings',
'serviceaccounts',
'olsconfig',
'clusterserviceversion',
'installplan',
'configmap',
];

function runOC(args: string[], kubeconfigPath: string): string | null {
const argv = kubeconfigPath ? [...args, '--kubeconfig', kubeconfigPath] : args;
try {
return execFileSync('oc', argv, {
encoding: 'utf-8',
timeout: OC_TIMEOUT,
});
} catch (e: unknown) {
console.error(`oc ${args.slice(0, 3).join(' ')} failed: ${e}`);
return null;
}
}

function gatherClusterArtifacts(kubeconfigPath: string) {
const clusterDir = path.join(ARTIFACTS_DIR, 'cluster');
const podLogsDir = path.join(clusterDir, 'podlogs');
fs.mkdirSync(podLogsDir, { recursive: true });

for (const resource of CLUSTER_RESOURCES) {
const output = runOC(['get', resource, '-n', OLS_NAMESPACE, '-o', 'yaml'], kubeconfigPath);
if (output) {
fs.writeFileSync(path.join(clusterDir, `${resource}.yaml`), output);
}
}

// Pod logs
const podsJson = runOC(['get', 'pods', '-n', OLS_NAMESPACE, '-o', 'json'], kubeconfigPath);
if (podsJson) {
try {
const pods = JSON.parse(podsJson);
for (const pod of pods.items || []) {
const podName = pod.metadata?.name;
const containers = (pod.spec?.containers || []).map((c: { name: string }) => c.name);
for (const container of containers) {
const logs = runOC(
['logs', `pod/${podName}`, '-c', container, '-n', OLS_NAMESPACE],
kubeconfigPath,
);
if (logs) {
fs.writeFileSync(path.join(podLogsDir, `${podName}-${container}.log`), logs);
}
}
}
} catch (e: unknown) {
console.error(`Failed to parse pod JSON: ${e}`);
}
}

console.log(`Cluster artifacts gathered in ${clusterDir}`);
}

export default defineConfig({
screenshotsFolder: './gui_test_screenshots/cypress/screenshots',
screenshotOnRunFailure: true,
Expand Down Expand Up @@ -72,13 +143,17 @@ export default defineConfig({
console.table(data);
return null;
},
gatherClusterArtifacts() {
gatherClusterArtifacts(config.env.KUBECONFIG_PATH || '');
return null;
},
});
cypressGrepPlugin(config);
on('after:spec', (spec: Cypress.Spec, results: CypressCommandLine.RunResult) => {
on('after:spec', (_spec: Cypress.Spec, results: CypressCommandLine.RunResult) => {
if (results && results.video) {
// Do we have failures for any retry attempts?
const failures = results.tests.some((test) =>
test.attempts.some((attempt) => attempt.state === 'failed'),
const failures = results.tests?.some((test) =>
test.attempts?.some((attempt) => attempt.state === 'failed'),
);
if (!failures && fs.existsSync(results.video)) {
// Delete the video if the spec passed and no tests retried
Expand Down
10 changes: 10 additions & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ import { register } from '@cypress/grep';

register();

Cypress.on('uncaught:exception', (err) => {
// The console defines __load_plugin_entry__ via webpack module federation
// before loading plugin bundles, but race conditions during page load can
// cause the plugin script to execute before the global is set.
// This is a console-internal timing issue, not a test failure.
if (err.message?.includes('__load_plugin_entry__')) {
return false;
}
});

Comment on lines +7 to +16
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove this change from this PR since it's not really related to the other changes.

Also, I'm not sure this is something we should really be intercepting like this since it might be hiding a real problem.

// Collect browser console errors and warnings for output after each test
const browserLogs = [];

Expand Down
3 changes: 3 additions & 0 deletions tests/tests/lightspeed-install.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,9 @@ describe('OLS UI', () => {
});

after(() => {
// Gather cluster artifacts before cleanup so resources still exist
cy.task('gatherClusterArtifacts');

if (Cypress.env('SKIP_OLS_SETUP')) {
cy.task('log', 'Skip OLS uninstall because CYPRESS_SKIP_OLS_SETUP is true');
} else {
Expand Down