Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 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
3 changes: 3 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ elemental-ui/
kubewarden-ui/
styleguide/src/stories/Example/
storybook/src/stories/Example/
cypress/dist/
cypress/bin/
cypress/template/
59 changes: 59 additions & 0 deletions .github/workflows/release-cypress-pkg.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Publish Cypress Suite Package

on:
push:
tags:
- 'cypress-pkg-v*'
workflow_call:
inputs:
tag:
required: false
type: string
outputs:
build-release-cypress-suite-status:
value: ${{ jobs.build.outputs.build-status }}

defaults:
run:
shell: bash
working-directory: ./cypress

jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
if: github.repository == 'rancher/dashboard' && (github.event_name == 'workflow_call' || (github.event_name == 'push' && github.event.ref == 'refs/tags/${{ github.ref_name }}'))
outputs:
build-status: ${{ job.status }}
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
cache: 'yarn'

- uses: actions/setup-node@v6
with:
node-version-file: '.nvmrc'
registry-url: 'https://registry.npmjs.org'
scope: '@rancher'

- name: Install packages
run: yarn install --frozen-lockfile

- name: Build Cypress Package
run: yarn build-pkg

- name: Publish Cypress Package to npm
run: yarn publish-pkg
Copy link
Member

Choose a reason for hiding this comment

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

I think you miss --access public

Note that for legacy reasons scoped packages are by default published with an access set to restricted (aka "private packages"). This requires you to register for a paid npm plan. In case you simply wish to publish a public scoped package to the registry (for free), just add the --access public flag. This behavior can be enabled by default through the npmPublishAccess settings.

https://yarnpkg.com/cli/npm/publish#details

Copy link
Member Author

Choose a reason for hiding this comment

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

No, the flag is there:

PUBLISH_ARGS="--no-git-tag-version --access public --registry $NPM_REGISTRY"

https://github.com/torchiaf/dashboard/blob/9cb1ddb10e4ec608963de5524d589ce978b347df/cypress/scripts/publish.sh#L54

env:
TAG: ${{ inputs.tag || github.ref_name }}
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
Copy link
Member

Choose a reason for hiding this comment

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

I'd recommend configuring trusted providers at this point, otherwise we will need to schedule token refreshes on a regular interval; tokens have a maximum lifespan of three months as of November/December.

In order to do this, we need to configure the package in npm:

https://docs.npmjs.com/trusted-publishers

And then ensure that we fetch tokens using oidc in our release workflow:

#16166

Copy link
Member Author

Choose a reason for hiding this comment

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

I pushed the changes, and @richard-cox assigned the trusted publisher to @rancher/cypress.
I tried to push a new version from a dev branch, but I got an authentication error, probably my workflow is not creating an OIDC token (which is required by npm publish now) as it's not running on master.

So, i would test again the release workflow after we merge the PR.

Copy link
Member

@rak-phillip rak-phillip Dec 19, 2025

Choose a reason for hiding this comment

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

If that doesn't work, we may need to include the line to update npm:

      # Ensure npm 11.5.1 or later is installed
      - name: Update npm
        run: npm install -g npm@latest

It appears to be missing from the workflow and will be required for the short-term.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ sw.*
cypress/videos
cypress/screenshots
cypress/accessibility
browser-logs
setupTestEnv.sh

# Storybook
Expand Down
146 changes: 3 additions & 143 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -1,144 +1,4 @@
/* eslint-disable no-console */
import { defineConfig } from 'cypress';
import { removeDirectory } from 'cypress-delete-downloads-folder';
import { getSpecPattern } from '@/scripts/cypress';
import websocketTasks from './cypress/support/utils/webSocket-utils';
import path from 'path';
// Import and use the base configuration from cypress package
import baseConfig from './cypress/base-config';

// Required for env vars to be available in cypress
require('dotenv').config();

/**
* VARIABLES
*/
const hasCoverage = (process.env.TEST_INSTRUMENT === 'true') || false; // Add coverage if instrumented
let testDirs = ['priority', 'components', 'setup', 'pages', 'navigation', 'global-ui', 'features', 'extensions'];
const skipSetup = process.env.TEST_SKIP?.includes('setup');
const baseUrl = (process.env.TEST_BASE_URL || 'https://localhost:8005').replace(/\/$/, '');
const DEFAULT_USERNAME = 'admin';
const username = process.env.TEST_USERNAME || DEFAULT_USERNAME;
const apiUrl = process.env.API || (baseUrl.endsWith('/dashboard') ? baseUrl.split('/').slice(0, -1).join('/') : baseUrl);

if (process.env.TEST_A11Y) {
testDirs = ['accessibility'];
}

/**
* LOGS:
* Summary of the environment variables that we have detected (or are going ot use)
* We won't show any passwords
*/
console.log('E2E Test Configuration');
console.log('');
console.log(` Username: ${ username }`);

if (!process.env.CATTLE_BOOTSTRAP_PASSWORD && !process.env.TEST_PASSWORD) {
console.log(' ❌ You must provide either CATTLE_BOOTSTRAP_PASSWORD or TEST_PASSWORD');
}
if (process.env.CATTLE_BOOTSTRAP_PASSWORD && process.env.TEST_PASSWORD) {
console.log(' ❗ If both CATTLE_BOOTSTRAP_PASSWORD and TEST_PASSWORD are provided, the first will be used');
}
if (!skipSetup && !process.env.CATTLE_BOOTSTRAP_PASSWORD) {
console.log(' ❌ You must provide CATTLE_BOOTSTRAP_PASSWORD when running setup tests');
}
if (skipSetup && !process.env.TEST_PASSWORD) {
console.log(' ❌ You must provide TEST_PASSWORD when running the tests without the setup tests');
}

console.log(` Setup tests will ${ skipSetup ? 'NOT' : '' } be run`);
console.log(` Dashboard URL: ${ baseUrl }`);
console.log(` Rancher API URL: ${ apiUrl }`);

// Check API - sometimes in dev, you might have API set to a different system to the base url - this won't work
// as the login cookie will be for the base url and any API requests will fail as not authenticated
if (apiUrl && !baseUrl.startsWith(apiUrl)) {
console.log('\n ❗ API variable is different to TEST_BASE_URL - tests may fail due to authentication issues');
}

console.log('');

/**
* CONFIGURATION
*/
export default defineConfig({
projectId: process.env.TEST_PROJECT_ID,
defaultCommandTimeout: process.env.TEST_TIMEOUT ? +process.env.TEST_TIMEOUT : 10000,
trashAssetsBeforeRuns: true,
chromeWebSecurity: false,
retries: {
runMode: 2,
openMode: 0
},
env: {
grepFilterSpecs: true,
grepOmitFiltered: true,
baseUrl,
coverage: hasCoverage,
codeCoverage: {
exclude: [
'cypress/**/*.*',
'**/__tests__/**/*.*',
'**/__mocks__/**/*.*',
'**/shell/scripts/**/*.*',
'docusaurus/**/*.*',
'stories/**/*.*',
'drone/**/*.*',
],
include: [
'shell/**/*.{vue,ts,js}',
'pkg/rancher-components/src/components/**/*.{vue,ts,js}',
]
},
api: apiUrl,
username,
password: process.env.CATTLE_BOOTSTRAP_PASSWORD || process.env.TEST_PASSWORD,
bootstrapPassword: process.env.CATTLE_BOOTSTRAP_PASSWORD,
grepTags: process.env.GREP_TAGS,
VAI_ENABLED: process.env.VAI_ENABLED,
// the below env vars are only available to tests that run in Jenkins
awsAccessKey: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY,
azureSubscriptionId: process.env.AZURE_AKS_SUBSCRIPTION_ID,
azureClientId: process.env.AZURE_CLIENT_ID,
azureClientSecret: process.env.AZURE_CLIENT_SECRET,
customNodeIp: process.env.CUSTOM_NODE_IP,
customNodeKey: process.env.CUSTOM_NODE_KEY,
accessibility: !!process.env.TEST_A11Y, // Are we running accessibility tests?
a11yFolder: path.join('.', 'cypress', 'accessibility'),
gkeServiceAccount: process.env.GKE_SERVICE_ACCOUNT,
},
e2e: {
fixturesFolder: 'cypress/e2e/blueprints',
setupNodeEvents(on, config) {
// For more info: https://docs.cypress.io/guides/tooling/code-coverage
require('@cypress/code-coverage/task')(on, config);
require('@cypress/grep/src/plugin')(config);
// For more info: https://www.npmjs.com/package/cypress-delete-downloads-folder

on('task', { removeDirectory });
websocketTasks(on, config);

require('cypress-terminal-report/src/installLogsPrinter')(on, {
outputRoot: `${ config.projectRoot }/browser-logs/`,
outputTarget: { 'out.html': 'html' },
logToFilesOnAfterRun: true,
printLogsToConsole: 'never',
// printLogsToFile: 'always', // default prints on failures
});

// Load Accessibility plugin if configured
// as per https://github.com/rancher/dashboard/pull/15865 load order matters
// this need to go after "cypress-terminal-report" always
if (process.env.TEST_A11Y) {
require('./cypress/support/plugins/accessibility').default(on, config);
}

return config;
},
experimentalSessionAndOrigin: true,
specPattern: getSpecPattern(testDirs, process.env),
baseUrl
},
videoCompression: 15,
videoUploadOnPasses: false,
});
export default baseConfig;
18 changes: 18 additions & 0 deletions cypress/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Ignore node_modules
node_modules/

# Ignore build artifacts
*.log
*.tmp

# Ignore development files
.DS_Store
Thumbs.db

# Ignore any local config
.env
.env.local

# Ignore coverage reports
coverage/
.nyc_output/
Loading