diff --git a/docs/ibm-cloud-rules.md b/docs/ibm-cloud-rules.md
index 548f0f20..7c5557d6 100644
--- a/docs/ibm-cloud-rules.md
+++ b/docs/ibm-cloud-rules.md
@@ -2400,7 +2400,7 @@ components:
Description: |
Each path defined within the API definition should include a path segment for the API major version,
of the form v<n>, and all paths should have the same API major version segment.
-The API major version can appear in either the server URL or in each path entry.
+The API major version can appear in either the server URL or in each path entry. In the path entry, the first segment of the API's path must be the major version of the API.
|
diff --git a/packages/ruleset/src/functions/major-version-in-path.js b/packages/ruleset/src/functions/major-version-in-path.js
index ccc67e72..ad9e6cdc 100644
--- a/packages/ruleset/src/functions/major-version-in-path.js
+++ b/packages/ruleset/src/functions/major-version-in-path.js
@@ -127,6 +127,16 @@ function checkMajorVersion(apiDef) {
];
}
+ if (!versionIsFirstInPaths(urls) && versionIsInPath(urls)) {
+ logger.debug(`${ruleId}: first segment of path isn't the major version`);
+ return [
+ {
+ message: "First segment of path isn't the major version of the API",
+ path: ['paths'],
+ },
+ ];
+ }
+
if (versions.length >= 1 && versions[0]) {
// Major version present in server URL and all match -- all good
logger.debug(
@@ -197,3 +207,15 @@ function getDefaultUrl(server) {
return urlString;
}
+
+function versionIsFirstInPaths(paths) {
+ const versionRegex = /^\/v\d+\//;
+
+ return paths.every(path => versionRegex.test(path));
+}
+
+function versionIsInPath(paths) {
+ const versionRegex = /\/v\d+\//;
+
+ return paths.every(path => versionRegex.test(path));
+}
diff --git a/packages/ruleset/test/rules/major-version-in-path.test.js b/packages/ruleset/test/rules/major-version-in-path.test.js
index 5dd6ba8e..89deeab3 100644
--- a/packages/ruleset/test/rules/major-version-in-path.test.js
+++ b/packages/ruleset/test/rules/major-version-in-path.test.js
@@ -135,4 +135,21 @@ describe(`Spectral rule: ${ruleId}`, () => {
expect(validation.path).toStrictEqual([]);
expect(validation.severity).toBe(severityCodes.warning);
});
+
+ it('should error when paths start with different versions', async () => {
+ const testDocument = makeCopy(rootDocument);
+ testDocument.paths['metadata/v1/some_path'] = {};
+
+ const results = await testRule(ruleId, rule, testDocument);
+
+ expect(results).toHaveLength(1);
+
+ const validation = results[0];
+ expect(validation.code).toBe(ruleId);
+ expect(validation.message).toBe(
+ "First segment of path isn't the major version of the API"
+ );
+ expect(validation.path).toStrictEqual(['paths']);
+ expect(validation.severity).toBe(severityCodes.warning);
+ });
});