[TikiWiki-commits] [Git][tikiwiki/tiki][master] [ENH] Continuous integration (CI): Add a test about alphabetical sorting of...
Benoit Grégoire (@benoitg) via TikiWiki-cvs <[email protected]>
| Newsgroups | gmane.comp.cms.tiki.cvs |
|---|---|
| Message-ID | <6902806a1cb_2ce1cd054cb@gitlab-sidekiq-low-urgency-cpu-bound-v2-659d96848d-mljcp.mail> |
Benoit Grégoire pushed to branch master at Tiki Wiki CMS Groupware / Tiki
Commits:
19e5ae44 by David Maene at 2025-10-29T20:52:36+00:00
[ENH] Continuous integration (CI): Add a test about alphabetical sorting of...
---
* [REF] Simplified the function so that it only focuses on checking the order of dependencies
* [ENH] make this script to handle package.json files
* [ENH] CI - Add check for alphabetical sorting of dependencies
* [REF] Continuous integration (CI): Add a test about alphabetical sorting of lists in Tiki source code
See merge request tikiwiki/tiki!8720
- - - - -
7 changed files:
- .gitlab-ci.yml
- + doc/devtools/check_alphabetical_list.php
- path_constants.php
- src/js/common-externals/package.json
- src/js/jquery-tiki/package.json
- vendor_bundled/composer.json
- vendor_bundled/composer.lock
Changes:
=====================================
.gitlab-ci.yml
=====================================
@@ -737,3 +737,18 @@ composer-operator-check:
- if: $CI_PIPELINE_SOURCE == "push"
when: always
allow_failure: false
+
+check-alphabetical-list:
+ stage: unit-tests
+ image: ${DEPENDENCY_PROXY_PREFIX}${BASE_QA_IMAGE}
+ needs:
+ - composer
+ script:
+ - chmod +x doc/devtools/check_alphabetical_list.php
+ - php doc/devtools/check_alphabetical_list.php
+ rules:
+ - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+ when: always
+ - if: $CI_PIPELINE_SOURCE == "push"
+ when: always
+ allow_failure: false
=====================================
doc/devtools/check_alphabetical_list.php
=====================================
@@ -0,0 +1,160 @@
+<?php
+
+require_once __DIR__ . '/../../path_constants.php';
+
+/**
+ * Returns colored text for console output.
+ */
+
+function colorText(string $text, string $color): string
+{
+ static $colors = [
+ 'red' => "\033[31m",
+ 'green' => "\033[32m",
+ 'yellow' => "\033[33m",
+ 'blue' => "\033[34m",
+ 'white' => "\033[1;37m",
+ 'reset' => "\033[0m",
+ ];
+
+ return ($colors[$color] ?? '') . $text . $colors['reset'];
+}
+
+/**
+ * Loads and decodes a JSON file.
+ */
+
+function getJsonData(string $path): array
+{
+ $content = file_get_contents($path);
+ if ($content === false) {
+ throw new RuntimeException("Failed to read $path");
+ }
+
+ $data = json_decode($content, true);
+ if (json_last_error() !== JSON_ERROR_NONE) {
+ throw new RuntimeException("Invalid JSON in $path: " . json_last_error_msg());
+ }
+
+ return $data;
+}
+
+/**
+ * Detects sections that appear to describe dependencies
+ * (based on key name patterns like "require" or "dependency").
+ */
+function detectDependencySections(array $data): array
+{
+ $sections = [];
+
+ foreach ($data as $key => $value) {
+ if (! is_array($value)) {
+ continue;
+ }
+
+ // Detect keys that look like dependency sections
+ if (preg_match('/(require|dependenc(y|ies)|deps)$/i', $key)) {
+ // Must be associative (package => version)
+ if (isAssociativeArray($value) && looksLikeDependencyMap($value)) {
+ $sections[] = $key;
+ }
+ }
+ }
+
+ return $sections;
+}
+
+/**
+ * Checks if array is associative.
+ */
+function isAssociativeArray(array $arr): bool
+{
+ return array_keys($arr) !== range(0, count($arr) - 1);
+}
+
+/**
+ * Heuristic: determine if a section looks like dependencies
+ * (keys are strings, values are strings or numbers)
+ */
+function looksLikeDependencyMap(array $section): bool
+{
+ $sample = array_slice($section, 0, 3, true);
+ foreach ($sample as $k => $v) {
+ if (! is_string($k)) {
+ return false;
+ }
+ if (! is_string($v) && ! is_numeric($v)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Checks if dependencies in a given section are alphabetically sorted.
+ */
+function checkDependenciesOrder(array $data, string $section, string $file): bool
+{
+ $deps = $data[$section] ?? null;
+ if (! is_array($deps) || empty($deps)) {
+ return true;
+ }
+
+ $keys = array_keys($deps);
+ $sorted = $keys;
+ sort($sorted, SORT_STRING);
+
+ if ($keys !== $sorted) {
+ echo colorText("⚠️ Dependencies in '$section' of '$file' are not sorted alphabetically.\n", 'yellow');
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Main validation runner.
+ */
+function main(): void
+{
+ $files = [
+ PRIMARY_COMPOSERJSON_FILE_PATH,
+ PRIMARY_PACKAGEJSON_FILE_PATH,
+ PRIMARY_JQUERYTIKI_PACKAGEJSON_FILE_PATH,
+ PRIMARY_EXTERNAL_PACKAGEJSON_FILE_PATH,
+ ];
+
+ $hasError = false;
+
+ foreach ($files as $file) {
+ $data = getJsonData($file);
+ $sections = detectDependencySections($data);
+
+ if (empty($sections)) {
+ echo colorText("ℹ️ No dependency sections found in $file\n", 'blue');
+ continue;
+ }
+
+ $fileHasError = false;
+ foreach ($sections as $section) {
+ if (! checkDependenciesOrder($data, $section, $file)) {
+ $fileHasError = true;
+ $hasError = true;
+ }
+ }
+
+ if (! $fileHasError) {
+ echo colorText("✅ $file dependencies are properly sorted.\n", 'green');
+ }
+ }
+
+ if ($hasError) {
+ echo colorText("\n❌ CI FAILURE: Some dependencies are unsorted.\n", 'red');
+ exit(1);
+ }
+
+ echo colorText("\nAll dependency sections are sorted correctly.\n", 'green');
+ exit(0);
+}
+
+main();
=====================================
path_constants.php
=====================================
@@ -163,6 +163,10 @@ const PRIMARY_AUTOLOAD_FILE_PATH = 'vendor_bundled/vendor/autoload.php';
const PRIMARY_COMPOSERJSON_FILE_PATH = 'vendor_bundled/composer.json';
const COMPOSERLOCK_FILE_PATH = 'vendor_bundled/composer.lock';
+const PRIMARY_PACKAGEJSON_FILE_PATH = 'package.json';
+const PRIMARY_PACKAGERLOCK_FILE_PATH = 'package-lock.json';
+const PRIMARY_JQUERYTIKI_PACKAGEJSON_FILE_PATH = 'src/js/jquery-tiki/package.json';
+const PRIMARY_EXTERNAL_PACKAGEJSON_FILE_PATH = 'src/js/common-externals/package.json';
/* BEGIN - HTTP PATHS */
const HTTP_PUBLIC_PATH = 'public';
=====================================
src/js/common-externals/package.json
=====================================
@@ -31,27 +31,27 @@
"jquery": "^3.7.1",
"jquery-form": "^4.3.0",
"jquery-migrate": "^3.4.1",
- "jquery-ui": "^1.13.2",
- "jquery-validation": "1.20.0",
"jquery-tagcanvas": "2.9.0",
"jquery-treetable": "^3.2.0-1",
+ "jquery-ui": "^1.13.2",
+ "jquery-validation": "1.20.0",
"jquery-zoom": "^1.7.21",
"minicart": "^3.0.6",
"moment": "^2.30.1",
"ol": "^10.3.1",
"ol-layerswitcher": ">=3.3.0",
+ "plotly.js": "^3.0.3",
"recordrtc": "^5.6.2",
+ "reveal.js": "5.1.0",
"sass-svg-uri": "^2.0.0",
"signature_pad": "^5.0.4",
"smartmenus": "^2.0.0-alpha.1",
- "timeago": "^1.6.7",
- "plotly.js": "^3.0.3",
- "reveal.js": "5.1.0",
"sortablejs": "=1.14.0",
"subtotal": "^1.11.0-alpha.0",
"swagger-ui-dist": "^5.18.2",
- "tablesorter": "^2.32.0",
"swiper": "^11.2.6",
+ "tablesorter": "^2.32.0",
+ "timeago": "^1.6.7",
"vis-timeline": "^7.7.4",
"vue": "^3.5.12",
"vue3-sfc-loader": "^0.9.5"
=====================================
src/js/jquery-tiki/package.json
=====================================
@@ -16,9 +16,9 @@
"@svgedit/svgcanvas": "https://github.com/SVG-Edit/svgedit/blob/master/packages/svgcanvas/CHANGES.md"
},
"devDependencies": {
+ "@event-calendar/core": "^4.5.1",
"@svgedit/svgcanvas": "^7.2.1",
"async-es": "^3.2.6",
- "summernote": "^0.9.1",
- "@event-calendar/core": "^4.5.1"
+ "summernote": "^0.9.1"
}
}
\ No newline at end of file
=====================================
vendor_bundled/composer.json
=====================================
@@ -248,9 +248,9 @@
"phpxmlrpc/phpxmlrpc": "~4.11",
"pragmarx/google2fa": "~9.0",
"rambomst/php-bounce-handler": "~1.6",
- "react/child-process": "~0.6.4",
"ramsey/uuid": "~4.9",
"ratchet/pawl": "~0.4.1",
+ "react/child-process": "~0.6.4",
"robicch/jquery-gantt": "~6.3",
"rubix/ml": "~2.5",
"sabre/dav": "~4.7",
@@ -295,12 +295,12 @@
"kornrunner/dbunit": "~9.1",
"mikey179/vfsstream": "~1.6",
"overtrue/phplint": "~9.0",
+ "php-webdriver/webdriver": "~1.15",
"phpcompatibility/php-compatibility": "~10.x-dev",
"phpcsstandards/phpcsutils": "~1.0",
"phpstan/phpstan": "~2.1",
"phpstan/phpstan-deprecation-rules": "~2.0",
"phpunit/phpunit": "~10.5.26",
- "php-webdriver/webdriver": "~1.15",
"rector/rector": "~2.0",
"sebastian/diff": "~5.1",
"squizlabs/php_codesniffer": "~3.1",
=====================================
vendor_bundled/composer.lock
=====================================
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "27e29f0ca322ceace3f65122724a55eb",
+ "content-hash": "38351e87463d7fc688fb1ff3128a12a9",
"packages": [
{
"name": "amphp/amp",
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/19e5ae44d318a08c59c55234dd49df0270ed6f64
--
View it on GitLab: https://gitlab.com/tikiwiki/tiki/-/commit/19e5ae44d318a08c59c55234dd49df0270ed6f64
You're receiving this email because of your account on gitlab.com.
_______________________________________________
TikiWiki-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/tikiwiki-cvs