From 13764154ba99c14e9a2aa2eb0b21d1ce477e5d53 Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 18 Sep 2023 20:39:24 -0500 Subject: [PATCH 1/3] First pass at "versioned" ruleArchive --- accessibility-checker/src/README.md | 4 +- common/module/src/config/ACConfigManager.ts | 69 ++++++++++++++++++++- common/module/src/config/IArchive.ts | 2 +- common/module/src/config/IConfig.ts | 3 +- karma-accessibility-checker/src/README.md | 2 + 5 files changed, 75 insertions(+), 5 deletions(-) diff --git a/accessibility-checker/src/README.md b/accessibility-checker/src/README.md index 78d93b083..4ddde3355 100644 --- a/accessibility-checker/src/README.md +++ b/accessibility-checker/src/README.md @@ -96,7 +96,9 @@ options for `accessibility-checker`. Following is the structure of the `.achecke ```yml # optional - Specify the rule archive # Default: latest -# Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids +# Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids. +# If "latest", will use the latest rule release +# If "versioned", will use latest rule release at the time this version of the tool was released ruleArchive: latest # optional - Specify one or many policies to scan. diff --git a/common/module/src/config/ACConfigManager.ts b/common/module/src/config/ACConfigManager.ts index b5d205775..31ce4048a 100644 --- a/common/module/src/config/ACConfigManager.ts +++ b/common/module/src/config/ACConfigManager.ts @@ -22,6 +22,7 @@ import * as crypto from 'crypto'; import { IConfig, IConfigInternal } from "./IConfig"; import { fetch_get } from "../api-ext/Fetch"; import { ReporterManager } from "../report/ReporterManager"; +import { IArchive } from "./IArchive"; /** * This function is responsible converting policies into an Array based on string or Array. @@ -62,6 +63,60 @@ function convertPolicies(policies: string | string[]) : string[] { return policies; } +/** + * negative if versionA is less than versionB, positive if versionA is greater than versionB, and zero if they are equal. NaN is treated as 0. + * @param versionA + * @param versionB + */ +function compareVersions(versionA: string, versionB: string) : number { + const versionRE = /[0-9.]+(-rc\.[0-9]+)?/; + versionA = versionA.trim(); + versionB = versionB.trim(); + if (!versionRE.test(versionA)) throw new Error("Invalid version"); + if (!versionRE.test(versionB)) throw new Error("Invalid version"); + if (versionA === versionB) return 0; + // Get x.y.z-rc.a into [x.y.z, a] + // Get x.y.z into [x.y.z] + let split1A = versionA.split("-rc."); + let split1B = versionB.split("-rc."); + // Get x.y.z into [x,y,z] + let split2A = split1A[0].split("."); + let split2B = split1B[0].split("."); + // For the components of the shortest version - can only compare numbers we have + let minLength = Math.min(split2A.length, split2B.length); + for (let idx=0; idx= 0) { + return archive.id; + } + } + // Something wrong, go with the latest + return "latest"; +} + /** * This function is responsible processing the achecker config which was initialized to make sure it contains, * information which matches what the engine reads. @@ -78,8 +133,9 @@ function convertPolicies(policies: string | string[]) : string[] { * * @memberOf this */ -async function processACConfig(ACConfig) { +async function processACConfig(ACConfig: IConfigInternal) { ACConstants.DEBUG && console.log("START 'processACConfig' function"); + const validArchiveKeywords = ["latest", "preview", "versioned"]; // Convert the reportLevels and failLevels to match with what the engine provides // Don't need to convert the levels from the input as we are going to compare with out the level. @@ -111,6 +167,14 @@ async function processACConfig(ACConfig) { ACConstants.DEBUG && console.log("Found archiveFile: " + ruleArchiveFile); ACConfig.ruleArchiveSet = ruleArchiveParse; let ruleArchive = ACConfig.ruleArchive; + // If the user asked us to sync the rule version with the tool version, we need to figure out what the last rule version was + if (ruleArchive === "versioned") { + if (!ACConfig.toolVersion) { + ruleArchive = "latest"; + } else { + ruleArchive = findLatestArchiveId(ACConfig.ruleArchiveSet, ACConfig.toolVersion); + } + } ACConfig.ruleArchiveLabel = ACConfig.ruleArchive; for (let i = 0; i < ACConfig.ruleArchiveSet.length; i++) { if (ruleArchive === ACConfig.ruleArchiveSet[i].id && !ACConfig.ruleArchiveSet[i].sunset) { @@ -126,7 +190,7 @@ async function processACConfig(ACConfig) { throw new Error(errStr); } for (let i = 0; i < ACConfig.ruleArchiveSet.length; i++) { - if (ACConfig.ruleArchiveVersion === ACConfig.ruleArchiveSet[i].version && ACConfig.ruleArchiveSet[i].id !== "latest" && ACConfig.ruleArchiveSet[i].id !== "preview") { + if (ACConfig.ruleArchiveVersion === ACConfig.ruleArchiveSet[i].version && !validArchiveKeywords.includes(ACConfig.ruleArchiveSet[i].id)) { ACConfig.ruleArchivePath = ACConfig.ruleArchiveSet[i].path; break; } @@ -192,6 +256,7 @@ function initializeDefaults(config: IConfigInternal) { // Build the toolID based on name and version config.toolID = packageObject.name + "-v" + packageObject.version; config.toolName = packageObject.name; + config.toolVersion = packageObject.version; // Using the uuid module generate a uuid number which is used to assoiciate to the scans that // are done for a single run of karma. diff --git a/common/module/src/config/IArchive.ts b/common/module/src/config/IArchive.ts index b587017d0..83846afbf 100644 --- a/common/module/src/config/IArchive.ts +++ b/common/module/src/config/IArchive.ts @@ -15,7 +15,7 @@ *****************************************************************************/ export interface IArchive { - id: "latest" | "preview" | string + id: "latest" | "preview" | "versioned" | string name: string path: string policies: Array<{ diff --git a/common/module/src/config/IConfig.ts b/common/module/src/config/IConfig.ts index 44b99465f..4aac34264 100644 --- a/common/module/src/config/IConfig.ts +++ b/common/module/src/config/IConfig.ts @@ -41,7 +41,7 @@ export interface IConfig { * Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids * Default: "latest" */ - ruleArchive?: "latest" | "preview" | string + ruleArchive?: "latest" | "preview" | "versioned" | string /** * (optional) Specify one or many policies to scan. @@ -171,6 +171,7 @@ export type IConfigInternal = IConfig & { toolID?: string toolName?: string + toolVersion?: string scanID?: string diff --git a/karma-accessibility-checker/src/README.md b/karma-accessibility-checker/src/README.md index 1f36b7d2c..2281415f8 100644 --- a/karma-accessibility-checker/src/README.md +++ b/karma-accessibility-checker/src/README.md @@ -159,6 +159,8 @@ options for `karma-accessibility-checker`. This is the structure of the `.acheck # optional - Specify the rule archive # i.e. For march rule archive use ruleArchive: 2017MayDeploy # Default: latest +# If "latest", will use the latest rule release +# If "versioned", will use latest rule release at the time this version of the tool was released # Refer to README.md FAQ section below to get the rule archive ID. ruleArchive: latest From 521f1222f5400b774e24305eaf567d887e3701db Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Mon, 18 Sep 2023 20:45:50 -0500 Subject: [PATCH 2/3] Update README with version info --- accessibility-checker/src/README.md | 3 ++- karma-accessibility-checker/src/README.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/accessibility-checker/src/README.md b/accessibility-checker/src/README.md index 4ddde3355..8c339c2ff 100644 --- a/accessibility-checker/src/README.md +++ b/accessibility-checker/src/README.md @@ -98,7 +98,8 @@ options for `accessibility-checker`. Following is the structure of the `.achecke # Default: latest # Run `npx achecker archives` for a list of valid ruleArchive ids and policy ids. # If "latest", will use the latest rule release -# If "versioned", will use latest rule release at the time this version of the tool was released +# If "versioned" (supported in 3.1.61+), will use latest rule release at +# the time this version of the tool was released ruleArchive: latest # optional - Specify one or many policies to scan. diff --git a/karma-accessibility-checker/src/README.md b/karma-accessibility-checker/src/README.md index 2281415f8..2261e5445 100644 --- a/karma-accessibility-checker/src/README.md +++ b/karma-accessibility-checker/src/README.md @@ -160,7 +160,8 @@ options for `karma-accessibility-checker`. This is the structure of the `.acheck # i.e. For march rule archive use ruleArchive: 2017MayDeploy # Default: latest # If "latest", will use the latest rule release -# If "versioned", will use latest rule release at the time this version of the tool was released +# If "versioned" (supported in 3.1.61+), will use latest rule release at +# the time this version of the tool was released # Refer to README.md FAQ section below to get the rule archive ID. ruleArchive: latest From bce2fa71456542503965db46165cf24a6fb0424f Mon Sep 17 00:00:00 2001 From: Tom Brunet Date: Tue, 19 Sep 2023 10:32:35 -0500 Subject: [PATCH 3/3] Add tests for the version compare function --- common/module/src/config/ACConfigManager.ts | 2 +- .../module/test/config/ACConfigManager.test.ts | 17 ++++++++++++++++- common/module/test/report/ReportManager.test.ts | 3 ++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/common/module/src/config/ACConfigManager.ts b/common/module/src/config/ACConfigManager.ts index 31ce4048a..e2a17e4ef 100644 --- a/common/module/src/config/ACConfigManager.ts +++ b/common/module/src/config/ACConfigManager.ts @@ -68,7 +68,7 @@ function convertPolicies(policies: string | string[]) : string[] { * @param versionA * @param versionB */ -function compareVersions(versionA: string, versionB: string) : number { +export function compareVersions(versionA: string, versionB: string) : number { const versionRE = /[0-9.]+(-rc\.[0-9]+)?/; versionA = versionA.trim(); versionB = versionB.trim(); diff --git a/common/module/test/config/ACConfigManager.test.ts b/common/module/test/config/ACConfigManager.test.ts index 184ad1176..2add3d3c8 100644 --- a/common/module/test/config/ACConfigManager.test.ts +++ b/common/module/test/config/ACConfigManager.test.ts @@ -1,5 +1,20 @@ -import { ACConfigManager } from "../../src/config/ACConfigManager" +import { ACConfigManager, compareVersions } from "../../src/config/ACConfigManager" test("Configuration loads", async () => { const config = await ACConfigManager.getConfig(); // console.log(config); +}) + +test("Version compare", async () => { + expect(compareVersions("0.0.0", "0.0.0")).toBe(0); + expect(compareVersions("0.0.0", "0.0.1")).toBeLessThan(0); + expect(compareVersions("0.0.0", "0.1.0")).toBeLessThan(0); + expect(compareVersions("0.0.0", "1.0.0")).toBeLessThan(0); + expect(compareVersions("0.0.1", "0.0.0")).toBeGreaterThan(0); + expect(compareVersions("0.1.0", "0.0.0")).toBeGreaterThan(0); + expect(compareVersions("1.0.0", "0.0.0")).toBeGreaterThan(0); + expect(compareVersions("1.0.0", "1.0")).toBeGreaterThan(0); + expect(compareVersions("1.0.0", "1.0.0-rc.0")).toBeGreaterThan(0); + expect(compareVersions("1.0.0-rc.0", "1.0.0")).toBeLessThan(0); + expect(compareVersions("1.0.0-rc.0", "1.0.0-rc.1")).toBeLessThan(0); + expect(compareVersions("1.0.0-rc.1", "1.0.0-rc.0")).toBeGreaterThan(0); }) \ No newline at end of file diff --git a/common/module/test/report/ReportManager.test.ts b/common/module/test/report/ReportManager.test.ts index 38be04875..67742e7ef 100644 --- a/common/module/test/report/ReportManager.test.ts +++ b/common/module/test/report/ReportManager.test.ts @@ -70,7 +70,8 @@ const myConfig : IConfigInternal = { "Chrome", "master", "IBMa-Node-TeSt" - ] + ], + engineMode: "DEFAULT" } const rulesets = [