From df6986072f3f3e85afe3c84db7df539f9d253c83 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Tue, 26 May 2026 21:12:58 +0200 Subject: [PATCH 1/3] [INTERNAL] CI: Migrate from Azure Pipelines to GitHub Actions Replace azure-pipelines.yml with a matrix test workflow at .github/workflows/test.yml covering Node.js 20.11.0/22/24 across ubuntu-24.04, windows-2025 and macos-15. Drop the now-unused test-azure, coverage-xunit and unit-xunit scripts as well as the tap-xunit devDependency. JIRA: CPOUI5FOUNDATION-1218 --- .github/workflows/test.yml | 36 ++++++++ azure-pipelines.yml | 81 ----------------- npm-shrinkwrap.json | 179 ------------------------------------- package.json | 4 - 4 files changed, 36 insertions(+), 264 deletions(-) create mode 100644 .github/workflows/test.yml delete mode 100644 azure-pipelines.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 00000000..6f7e3bbe --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,36 @@ +name: Tests + +on: + push: + branches: + - v4 + pull_request: + branches: + - v4 + +# No permissions are required for this workflow +permissions: {} + +jobs: + test: + name: Unit and Integration + strategy: + fail-fast: false # Do not stop other jobs if one fails + matrix: + version: ["20.11.0", 22, 24] + os: [ubuntu-24.04, windows-2025, macos-15] + runs-on: ${{ matrix.os }} + steps: + + - uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.version }} + + - name: Install dependencies + run: npm ci + + - name: Run unit tests + run: npm run unit diff --git a/azure-pipelines.yml b/azure-pipelines.yml deleted file mode 100644 index ed4f9daa..00000000 --- a/azure-pipelines.yml +++ /dev/null @@ -1,81 +0,0 @@ -# Node.js -# Build a general Node.js project with npm. -# Add steps that analyze code, save build artifacts, deploy, and more: -# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript - -trigger: -- v4 - -variables: - CI: true - -strategy: - matrix: - linux_node_lts_20_min_version: - imageName: 'ubuntu-24.04' - node_version: 20.11.0 - linux_node_22_min_version: - imageName: 'ubuntu-24.04' - node_version: 22.1.0 - linux_node_lts_20: - imageName: 'ubuntu-24.04' - node_version: 20.x - mac_node_lts_20: - imageName: 'macos-15' - node_version: 20.x - windows_node_lts_20: - imageName: 'windows-2022' - node_version: 20.x - linux_node_22: - imageName: 'ubuntu-24.04' - node_version: 22.x - mac_node_22: - imageName: 'macos-15' - node_version: 22.x - windows_node_22: - imageName: 'windows-2022' - node_version: 22.x - linux_node_24: - imageName: 'ubuntu-24.04' - node_version: 24.x - mac_node_24: - imageName: 'macos-15' - node_version: 24.x - windows_node_24: - imageName: 'windows-2022' - node_version: 24.x - -pool: - vmImage: $(imageName) - -steps: -- task: NodeTool@0 - inputs: - versionSpec: $(node_version) - displayName: Install Node.js - -- script: npm ci - displayName: Install Dependencies - -- script: npm ls --prod - displayName: Check for missing / extraneous Dependencies - -- script: npm run test-azure - displayName: Run Tests - -- task: PublishTestResults@2 - displayName: Publish Test Results - condition: succeededOrFailed() - inputs: - testResultsFormat: 'JUnit' - testResultsFiles: '$(System.DefaultWorkingDirectory)/test-results.xml' - -- task: PublishCodeCoverageResults@2 - displayName: Publish Test Coverage Results - condition: succeededOrFailed() - inputs: - summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml' - -- script: npm run coverage - displayName: Run Test Natively in Case of Failures - condition: failed() diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index a2f3ee83..744cb558 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -49,7 +49,6 @@ "rimraf": "^6.1.3", "sinon": "^21.1.2", "strip-ansi": "^7.2.0", - "tap-xunit": "^2.4.1", "testdouble": "^3.20.2" }, "engines": { @@ -5842,13 +5841,6 @@ "node": ">= 0.4" } }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true, - "license": "MIT" - }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -6672,13 +6664,6 @@ "node": ">=0.8.x" } }, - "node_modules/events-to-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/events-to-array/-/events-to-array-1.1.2.tgz", - "integrity": "sha512-inRWzRY7nG+aXZxBzEqYKB3HPgwflZRopAjDCHv0whhRx+MTUr1ei0ICZUypdyE0HRm4L2d5VEcIqLD6yl+BFA==", - "dev": true, - "license": "ISC" - }, "node_modules/execa": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/execa/-/execa-9.6.1.tgz", @@ -13332,103 +13317,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/tap-parser": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tap-parser/-/tap-parser-1.2.2.tgz", - "integrity": "sha512-uXKcosa0qoSjeh73dhmX+OpJvpigDxUciOhBcbGUKtmwzEFJjUT1Ql5dpg4M9I1UjXT9b+6n1W05FB8QmKossA==", - "dev": true, - "license": "MIT", - "dependencies": { - "events-to-array": "^1.0.1", - "inherits": "~2.0.1", - "js-yaml": "^3.2.7" - }, - "bin": { - "tap-parser": "bin/cmd.js" - }, - "optionalDependencies": { - "readable-stream": "^2" - } - }, - "node_modules/tap-parser/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/tap-parser/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/tap-parser/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/tap-parser/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/tap-parser/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/tap-xunit": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/tap-xunit/-/tap-xunit-2.4.1.tgz", - "integrity": "sha512-qcZStDtjjYjMKAo7QNiCtOW256g3tuSyCSe5kNJniG1Q2oeOExJq4vm8CwboHZURpkXAHvtqMl4TVL7mcbMVVA==", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "~0.1.1", - "minimist": "~1.2.0", - "tap-parser": "~1.2.2", - "through2": "~2.0.0", - "xmlbuilder": "~4.2.0", - "xtend": "~4.0.0" - }, - "bin": { - "tap-xunit": "bin/tap-xunit", - "txunit": "bin/tap-xunit" - } - }, "node_modules/tar": { "version": "7.5.15", "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.15.tgz", @@ -13618,50 +13506,6 @@ "dev": true, "license": "MIT" }, - "node_modules/through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/through2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/time-zone": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", @@ -14462,35 +14306,12 @@ "node": ">=4.0" } }, - "node_modules/xmlbuilder": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", - "integrity": "sha512-oEePiEefhQhAeUnwRnIBLBWmk/fsWWbQ53EEWsRuzECbQ3m5o/Esmq6H47CYYwSLW+Ynt0rS9hd0pd2ogMAWjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "lodash": "^4.0.0" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/xmlcreate": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", "license": "Apache-2.0" }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index 2ddb6eb8..2abafae3 100644 --- a/package.json +++ b/package.json @@ -31,15 +31,12 @@ }, "scripts": { "test": "npm run lint && npm run jsdoc-generate && npm run coverage && npm run check-licenses", - "test-azure": "npm run coverage-xunit", "lint": "eslint ./", "unit": "rimraf test/tmp && ava", "unit-verbose": "rimraf test/tmp && cross-env UI5_LOG_LVL=verbose ava --verbose --serial", "unit-watch": "npm run unit -- --watch", - "unit-xunit": "rimraf test/tmp && ava --node-arguments=\"--experimental-loader=@istanbuljs/esm-loader-hook\" --tap | tap-xunit --dontUseCommentsAsTestNames=true > test-results.xml", "unit-inspect": "cross-env UI5_LOG_LVL=verbose ava debug --break", "coverage": "rimraf test/tmp && nyc ava --node-arguments=\"--experimental-loader=@istanbuljs/esm-loader-hook\"", - "coverage-xunit": "nyc --reporter=text --reporter=text-summary --reporter=cobertura npm run unit-xunit", "jsdoc": "npm run jsdoc-generate && open-cli jsdocs/index.html", "jsdoc-generate": "jsdoc -c ./jsdoc.json -t $(npm ls docdash --parseable | head -1) ./lib/ || (echo 'Error during JSDoc generation! Check log.' && exit 1)", "jsdoc-watch": "npm run jsdoc && chokidar \"./lib/**/*.js\" -c \"npm run jsdoc-generate\"", @@ -154,7 +151,6 @@ "rimraf": "^6.1.3", "sinon": "^21.1.2", "strip-ansi": "^7.2.0", - "tap-xunit": "^2.4.1", "testdouble": "^3.20.2" } } From a3202e277e7a667a71d15169015333767ffce655 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Tue, 26 May 2026 21:19:22 +0200 Subject: [PATCH 2/3] [INTERNAL] CI: Add check-engine script and replace --engine-strict Use check-engine-light to verify that installed dependencies are compatible with the repo's Node.js engine requirement, replacing the previous npm ci --engine-strict approach. --- .github/workflows/github-ci.yml | 5 ++++- npm-shrinkwrap.json | 21 +++++++++++++++++++++ package.json | 4 +++- 3 files changed, 28 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github-ci.yml b/.github/workflows/github-ci.yml index a7e1475b..5941c56c 100644 --- a/.github/workflows/github-ci.yml +++ b/.github/workflows/github-ci.yml @@ -25,7 +25,10 @@ jobs: node-version: 20.11.0 - name: Install dependencies - run: npm ci --engine-strict # --engine-strict is used to fail-fast if deps require node versions unsupported by the repo + run: npm ci + + - name: Check Node.js engine compatibility + run: npm run check-engine - name: Perform dependencies analysis run: npm run knip diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 744cb558..a954940d 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -31,6 +31,7 @@ "@eslint/js": "^9.8.0", "@istanbuljs/esm-loader-hook": "^0.3.0", "ava": "^6.4.1", + "check-engine-light": "0.4.0", "chokidar-cli": "^3.0.0", "cross-env": "^10.1.0", "docdash": "^2.0.2", @@ -4633,6 +4634,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/check-engine-light": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/check-engine-light/-/check-engine-light-0.4.0.tgz", + "integrity": "sha512-hZzy5cbJg52nDGgyiNDVpjzrIo6V49lpFVJ7hJiGpbWs9in5mtpRMqdM1VPptab2QTkwYdac98PaXSBmQqh1Tg==", + "dev": true, + "license": "ISC", + "dependencies": { + "debug": "^4.4.3", + "semver": "^7.7.3" + }, + "bin": { + "check-engine-light": "lib/cli.js" + }, + "engines": { + "node": "^20.11 || >=21.2" + }, + "funding": { + "url": "https://ko-fi.com/textbook" + } + }, "node_modules/cheerio": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", diff --git a/package.json b/package.json index 2abafae3..45b81da8 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,8 @@ "prepublishOnly": "git push --follow-tags", "release-note": "git-chglog --sort semver -c .chglog/release-config.yml v$npm_package_version | node .chglog/consolidate-changelogs.js", "knip": "knip --config knip.config.js", - "check-licenses": "licensee --errors-only" + "check-licenses": "licensee --errors-only", + "check-engine": "check-engine-light -f npm-shrinkwrap.json ." }, "files": [ "CHANGELOG.md", @@ -133,6 +134,7 @@ "@eslint/js": "^9.8.0", "@istanbuljs/esm-loader-hook": "^0.3.0", "ava": "^6.4.1", + "check-engine-light": "0.4.0", "chokidar-cli": "^3.0.0", "cross-env": "^10.1.0", "docdash": "^2.0.2", From fbcd6526c19fe6cd872263c2d16723c664cd2bb7 Mon Sep 17 00:00:00 2001 From: Merlin Beutlberger Date: Tue, 26 May 2026 21:22:37 +0200 Subject: [PATCH 3/3] [INTERNAL] CI: Add Node.js 25 and 26 to test matrix --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6f7e3bbe..259e5de7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: strategy: fail-fast: false # Do not stop other jobs if one fails matrix: - version: ["20.11.0", 22, 24] + version: ["20.11.0", 22, 24, 25, 26] os: [ubuntu-24.04, windows-2025, macos-15] runs-on: ${{ matrix.os }} steps: