Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: improve jobs stability #29193

Merged
merged 5 commits into from
Mar 5, 2025
Merged
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
3 changes: 2 additions & 1 deletion .github/actions/run-qunit-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ runs:

- name: Setup Chrome
if: ${{ inputs.browser == 'chrome' }}
uses: ./.github/actions/setup-chrome
uses: ./.github/actions/setup-chrome-headless-shell
with:
chrome-version: '133.0.6943.53'

Expand Down Expand Up @@ -126,6 +126,7 @@ runs:
GITHUBACTION: "true"
TARGET: "test"
DISPLAY: ":99"
CHROME_CMD: ${{ env.CHROME_SHELL }}
run: |
chmod +x ./docker-ci.sh
./docker-ci.sh
Expand Down
34 changes: 34 additions & 0 deletions .github/actions/setup-chrome-headless-shell/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Chrome headless shell installer
description: Install chrome-headless-shell

# Chrome headless shell
# https://developer.chrome.com/blog/chrome-headless-shell

inputs:
chrome-version:
description: Chrome headless shell version to install
default: "latest"

runs:
using: composite
steps:
- name: Setup chrome-headless-shell
shell: bash
env:
CHROME_VERSION: ${{ inputs.chrome-version }}
run: |
if [ -n "$CHROME_VERSION" ]; then
sudo apt-get update
sudo apt-get -y install libu2f-udev
sudo apt-get -y install dbus
echo "version to install: $CHROME_VERSION"
CHROME_BIN=`npx @puppeteer/browsers install chrome-headless-shell@$CHROME_VERSION | awk '{print $2}'`
chmod +x $CHROME_BIN
echo "chrome-headless-shell installed in: $CHROME_BIN"
$CHROME_BIN --version
echo "CHROME_SHELL=$CHROME_BIN" >> $GITHUB_ENV
else
echo "chrome-headless-shell not installed!"
fi
48 changes: 23 additions & 25 deletions .github/workflows/qunit_tests-additional-renovation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,24 +96,27 @@ jobs:
useJQuery: 'false'
useCsp: 'true'

qunit-tests-performance:
needs: build
runs-on: devextreme-shr2
name: Performance
timeout-minutes: 25
steps:
- name: Get sources
uses: actions/checkout@v4

- name: Run QUnit tests
uses: ./.github/actions/run-qunit-tests
with:
name: 'Performance'
browser: 'chrome'
isPerformance: 'true'
useJQuery: 'true'
headless: 'false'
useCsp: 'false'
# TODO Chrome133: skipped during chrome update
# We should run performance tests with non headless chrome
# It fails in headless mode
# qunit-tests-performance:
# needs: build
# runs-on: devextreme-shr2
# name: Performance
# timeout-minutes: 25
# steps:
# - name: Get sources
# uses: actions/checkout@v4
#
# - name: Run QUnit tests
# uses: ./.github/actions/run-qunit-tests
# with:
# name: 'Performance'
# browser: 'chrome'
# isPerformance: 'true'
# useJQuery: 'true'
# headless: 'true'
# useCsp: 'false'

qunit-tests-mobile-and-shadow-dom:
needs: build
Expand All @@ -140,7 +143,6 @@ jobs:
]
kind: [ 'shadow-dom', 'ios10', 'android6' ]
include:
- headless: false
- kind: 'shadow-dom'
userAgent: ''
useShadowDom: true
Expand All @@ -149,10 +151,6 @@ jobs:
- kind: 'android6'
userAgent: 'android6'
useJQuery: true
- constel: 'ui'
headless: true
- constel: 'viz'
headless: true

steps:
- name: Get sources
Expand All @@ -167,7 +165,7 @@ jobs:
useJQuery: ${{ matrix.useJquery || 'false' }}
userAgent: ${{ matrix.userAgent }}
useShadowDom: ${{ matrix.useShadowDom }}
headless: ${{ matrix.headless }}
headless: 'true'
useCsp: 'true'

qunit-tests-firefox:
Expand Down Expand Up @@ -262,7 +260,7 @@ jobs:
needs: [
build,
qunit-tests-timezones,
qunit-tests-performance,
# qunit-tests-performance,
qunit-tests-mobile-and-shadow-dom,
qunit-tests-firefox,
qunit-tests-no-csp
Expand Down
48 changes: 27 additions & 21 deletions .github/workflows/testcafe_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,27 +64,33 @@ jobs:
fail-fast: false
matrix:
ARGS: [
{ componentFolder: "accessibility", name: "accessibility (1/7)", indices: "1/7" },
{ componentFolder: "accessibility", name: "accessibility (2/7)", indices: "2/7" },
{ componentFolder: "accessibility", name: "accessibility (3/7)", indices: "3/7" },
{ componentFolder: "accessibility", name: "accessibility (4/7)", indices: "4/7" },
{ componentFolder: "accessibility", name: "accessibility (5/7)", indices: "5/7" },
{ componentFolder: "accessibility", name: "accessibility (6/7)", indices: "6/7" },
{ componentFolder: "accessibility", name: "accessibility (7/7)", indices: "7/7" },
{ componentFolder: "accessibility", name: "accessibility - material (1/7)", theme: "material.blue.light", indices: "1/7" },
{ componentFolder: "accessibility", name: "accessibility - material (2/7)", theme: "material.blue.light", indices: "2/7" },
{ componentFolder: "accessibility", name: "accessibility - material (3/7)", theme: "material.blue.light", indices: "3/7" },
{ componentFolder: "accessibility", name: "accessibility - material (4/7)", theme: "material.blue.light", indices: "4/7" },
{ componentFolder: "accessibility", name: "accessibility - material (5/7)", theme: "material.blue.light", indices: "5/7" },
{ componentFolder: "accessibility", name: "accessibility - material (6/7)", theme: "material.blue.light", indices: "6/7" },
{ componentFolder: "accessibility", name: "accessibility - material (7/7)", theme: "material.blue.light", indices: "7/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (1/7)", theme: "fluent.blue.light", indices: "1/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (2/7)", theme: "fluent.blue.light", indices: "2/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (3/7)", theme: "fluent.blue.light", indices: "3/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (4/7)", theme: "fluent.blue.light", indices: "4/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (5/7)", theme: "fluent.blue.light", indices: "5/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (6/7)", theme: "fluent.blue.light", indices: "6/7" },
{ componentFolder: "accessibility", name: "accessibility - fluent (7/7)", theme: "fluent.blue.light", indices: "7/7" },
{ componentFolder: "accessibility/common", name: "accessibility (1/7)", indices: "1/7" },
{ componentFolder: "accessibility/common", name: "accessibility (2/7)", indices: "2/7" },
{ componentFolder: "accessibility/common", name: "accessibility (3/7)", indices: "3/7" },
{ componentFolder: "accessibility/common", name: "accessibility (4/7)", indices: "4/7" },
{ componentFolder: "accessibility/common", name: "accessibility (5/7)", indices: "5/7" },
{ componentFolder: "accessibility/common", name: "accessibility (6/7)", indices: "6/7" },
{ componentFolder: "accessibility/common", name: "accessibility (7/7)", indices: "7/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (1/7)", theme: "material.blue.light", indices: "1/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (2/7)", theme: "material.blue.light", indices: "2/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (3/7)", theme: "material.blue.light", indices: "3/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (4/7)", theme: "material.blue.light", indices: "4/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (5/7)", theme: "material.blue.light", indices: "5/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (6/7)", theme: "material.blue.light", indices: "6/7" },
{ componentFolder: "accessibility/common", name: "accessibility - material (7/7)", theme: "material.blue.light", indices: "7/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (1/7)", theme: "fluent.blue.light", indices: "1/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (2/7)", theme: "fluent.blue.light", indices: "2/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (3/7)", theme: "fluent.blue.light", indices: "3/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (4/7)", theme: "fluent.blue.light", indices: "4/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (5/7)", theme: "fluent.blue.light", indices: "5/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (6/7)", theme: "fluent.blue.light", indices: "6/7" },
{ componentFolder: "accessibility/common", name: "accessibility - fluent (7/7)", theme: "fluent.blue.light", indices: "7/7" },
{ componentFolder: "accessibility/list", name: "accessibility - list (1/2)", indices: "1/2" },
{ componentFolder: "accessibility/list", name: "accessibility - list (1/2)", indices: "2/2" },
{ componentFolder: "accessibility/list", name: "accessibility - list - material (1/2)", theme: "material.blue.light", indices: "1/2" },
{ componentFolder: "accessibility/list", name: "accessibility - list - material (1/2)", theme: "material.blue.light", indices: "2/2" },
{ componentFolder: "accessibility/list", name: "accessibility - list - fluent (1/2)", theme: "fluent.blue.light", indices: "1/2" },
{ componentFolder: "accessibility/list", name: "accessibility - list - fluent (1/2)", theme: "fluent.blue.light", indices: "2/2" },
{ componentFolder: "common", name: "common" },
{ componentFolder: "common", name: "common - material", theme: 'material.blue.light' },
{ componentFolder: "common", name: "common - fluent", theme: 'fluent.blue.light' },
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 34 additions & 10 deletions e2e/testcafe-devextreme/runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ const { globSync } = require('glob');
const testPageUtils = require('./helpers/clearPage');
require('nconf').argv();

const LAUNCH_RETRY_ATTEMPTS = 5;
const LAUNCH_RETRY_TIMEOUT = 20000;
const TESTCAFE_CONFIG = {
hostname: 'localhost',
port1: 1437,
port2: 1438,
// eslint-disable-next-line spellcheck/spell-checker
experimentalProxyless: true,
};

const changeTheme = async(t, themeName) => createTestCafe.ClientFunction(() => new Promise((resolve) => {
// eslint-disable-next-line no-undef
window.DevExpress.ui.themes.ready(resolve);
Expand All @@ -33,15 +43,29 @@ const addShadowRootTree = async(t) => {
}).with({ boundTestRun: t })();
};

const wait = async(timeout) => new Promise(resolve => setTimeout(resolve, timeout));

const retry = async(action, attempt) => {
return await action()
.catch(async(error) => {
if(attempt <= 1) {
throw error;
}

/* eslint-disable no-console */
console.log('\n > error occurred during testcafe launch!\n');
console.error(error);
console.info(`\n > waiting ${LAUNCH_RETRY_TIMEOUT / 1000} seconds...\n`);
await wait(LAUNCH_RETRY_TIMEOUT);
console.info('\n > retry launching testcafe\n');
/* eslint-enable no-console */
return await retry(action, attempt - 1);
});
};

let testCafe;
createTestCafe({
hostname: 'localhost',
port1: 1437,
port2: 1438,
// eslint-disable-next-line spellcheck/spell-checker
experimentalProxyless: true,
})
.then(tc => {
createTestCafe(TESTCAFE_CONFIG)
.then(async(tc) => {
testCafe = tc;

const args = getArgs();
Expand Down Expand Up @@ -164,7 +188,7 @@ createTestCafe({
runOptions.disableScreenshots = true;
}

return runner.run(runOptions);
return await retry(() => runner.run(runOptions), LAUNCH_RETRY_ATTEMPTS);
})
.then(failedCount => {
testCafe.close();
Expand All @@ -186,7 +210,7 @@ function setShadowDom(args) {
function expandBrowserAlias(browser, componentFolder) {
switch(browser) {
case 'chrome:devextreme-shr2':
return 'chrome:headless --no-sandbox --disable-gpu --window-size=1200,800 --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl="swiftshader" --disable-features=PaintHolding --js-flags=--random-seed=2147483647 --font-render-hinting=none --disable-font-subpixel-positioning';
return 'chrome:headless --no-sandbox --disable-gpu --window-size=1200,800 --disable-partial-raster --disable-skia-runtime-opts --run-all-compositor-stages-before-draw --disable-new-content-rendering-timeout --disable-threaded-animation --disable-threaded-scrolling --disable-checker-imaging --disable-image-animation-resync --use-gl="swiftshader" --disable-features=PaintHolding --font-render-hinting=none --disable-font-subpixel-positioning';
case 'chrome:docker':
return 'chromium:headless --no-sandbox --disable-gpu --window-size=1200,800';
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Properties } from 'devextreme/ui/accordion.d';
import { Selector as $ } from 'testcafe';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const items = ['Item_1', 'Item_2', 'Item_3'];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Properties } from 'devextreme/ui/action_sheet.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import { isMaterial, isMaterialBased } from '../../helpers/themeUtils';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';
import { isMaterial, isMaterialBased } from '../../../helpers/themeUtils';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const items = [
{ text: 'Call' },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Properties } from 'devextreme/ui/autocomplete.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const items = ['Item_1', 'Item_2', 'Item_3'];

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ClientFunction } from 'testcafe';
import { Properties } from 'devextreme/ui/button.d';
import Button from 'devextreme-testcafe-models/button';
import { isMaterialBased } from '../../helpers/themeUtils';
import url from '../../helpers/getPageUrl';
import { defaultSelector, testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import { isMaterialBased } from '../../../helpers/themeUtils';
import url from '../../../helpers/getPageUrl';
import { defaultSelector, testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const optionsWithSimpleItems: Options<Properties> = {
useSubmitBehavior: [true, false],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Properties } from 'devextreme/ui/button_group.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const elementAttr = { 'aria-label': 'aria-label' };

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Properties } from 'devextreme/ui/calendar.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const msInDay = 1000 * 60 * 60 * 24;
const now = new Date().getTime();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Properties } from 'devextreme/ui/check_box.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const options: Options<Properties> = {
value: [true, false, null],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Properties } from 'devextreme/ui/color_box.d';
import url from '../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../helpers/accessibility/test';
import { Options } from '../../helpers/generateOptionMatrix';
import url from '../../../helpers/getPageUrl';
import { testAccessibility, Configuration } from '../../../helpers/accessibility/test';
import { Options } from '../../../helpers/generateOptionMatrix';

fixture.disablePageReloads`Accessibility`
.page(url(__dirname, '../container.html'));
.page(url(__dirname, '../../container.html'));

const options: Options<Properties> = {
value: [undefined, '#f05b41'],
Expand Down
Loading
Loading