Fix resolveUrl for splited openapi definition relative path (issues #27280)

Signed-off-by: Federico Sozio <sozio.federico@gmail.com>
This commit is contained in:
Federico Sozio
2025-01-13 13:32:10 +01:00
parent 8b4ba413a9
commit 7fc6f7c64c
5 changed files with 161 additions and 2 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend-module-openapi': patch
---
Fix resolveUrl for splited openapi definition relative path
@@ -49,6 +49,7 @@
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"@backstage/config": "workspace:^",
"openapi-types": "^12.0.0"
}
}
@@ -13,7 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { bundleFileWithRefs } from './bundle';
import { bundleFileWithRefs, BundlerRead, BundlerResolveUrl } from './bundle';
import { ScmIntegrations } from '@backstage/integration';
import { ConfigReader } from '@backstage/config';
const specification = `
openapi: "3.0.0"
@@ -178,3 +180,153 @@ channels:
expect(result).toEqual(expectedSchema.trimStart());
});
});
describe('bundleFileWithRefs - Testing getRelativePath scenarios', () => {
beforeEach(() => {
jest.clearAllMocks();
});
const scmIntegrations = ScmIntegrations.fromConfig(new ConfigReader({}));
const resolveUrl: BundlerResolveUrl = jest.fn(
(url: string, base: string): string => {
return scmIntegrations.resolveUrl({ url, base });
},
);
const read: BundlerRead = jest.fn(async (url: string) => {
return Buffer.from(url);
});
const baseUrl =
'https://dev.azure.com/organization/project/_git/idp-configurations?path=%2Frepo%2Ftest-openapi.yaml&version=GBmaster';
it('should handle the relative path when refUrl has the same base as baseUrl', async () => {
const fileWithRefs = `
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
$ref: "common.yaml"
`;
const relativePath = 'common.yaml';
const expectedUrl =
'https://dev.azure.com/organization/project/_git/idp-configurations?path=%2Frepo%2Fcommon.yaml&version=GBmaster';
await bundleFileWithRefs(fileWithRefs, baseUrl, read, resolveUrl);
expect(resolveUrl).toHaveBeenCalledWith(relativePath, baseUrl);
expect(read).toHaveBeenCalledWith(expectedUrl);
});
it('should handle the relative path, with subdir, when refUrl has the same base as baseUrl', async () => {
const fileWithRefs = `
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
$ref: "commons/common.yaml"
`;
const relativePath = 'commons/common.yaml';
const expectedUrl =
'https://dev.azure.com/organization/project/_git/idp-configurations?path=%2Frepo%2Fcommons%2Fcommon.yaml&version=GBmaster';
await bundleFileWithRefs(fileWithRefs, baseUrl, read, resolveUrl);
expect(resolveUrl).toHaveBeenCalledWith(relativePath, baseUrl);
expect(read).toHaveBeenCalledWith(expectedUrl);
});
it('should handle the entire refUrl when there is no common base', async () => {
const fileWithRef = `
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
$ref: "https://example.com/commons/common.yaml"
`;
const refUrl = 'https://example.com/commons/common.yaml';
await bundleFileWithRefs(fileWithRef, baseUrl, read, resolveUrl);
expect(resolveUrl).toHaveBeenCalledWith(refUrl, baseUrl);
expect(read).toHaveBeenCalledWith(refUrl);
});
it('should handle the relative path when refUrl has a different subdir', async () => {
const fileWithRefs = `
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
$ref: "../commons/common.yaml"
`;
const exampleBaseUrl =
'https://example.com/path/to/definition/test-openapi.yaml.yaml';
const relativePath = '../commons/common.yaml';
const expectedUrl = 'https://example.com/path/to/commons/common.yaml';
await bundleFileWithRefs(fileWithRefs, exampleBaseUrl, read, resolveUrl);
expect(resolveUrl).toHaveBeenCalledWith(relativePath, exampleBaseUrl);
expect(read).toHaveBeenCalledWith(expectedUrl);
});
it('should handle the relative path when refUrl has a different subdir (azure)', async () => {
const fileWithRefs = `
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
$ref: "../commons/common.yaml"
`;
const relativePath = '../commons/common.yaml';
const expectedUrl =
'https://dev.azure.com/organization/project/_git/idp-configurations?path=%2Fcommons%2Fcommon.yaml&version=GBmaster';
await bundleFileWithRefs(fileWithRefs, baseUrl, read, resolveUrl);
expect(resolveUrl).toHaveBeenCalledWith(relativePath, baseUrl);
expect(read).toHaveBeenCalledWith(expectedUrl);
});
});
@@ -69,6 +69,6 @@ export async function bundleFileWithRefs(
},
};
const fileObject = parse(fileWithRefs);
const bundledObject = await $RefParser.bundle(baseUrl, fileObject, options);
const bundledObject = await $RefParser.bundle(fileObject, options);
return stringify(bundledObject);
}
+1
View File
@@ -6150,6 +6150,7 @@ __metadata:
"@backstage/backend-test-utils": "workspace:^"
"@backstage/catalog-model": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/config": "workspace:^"
"@backstage/integration": "workspace:^"
"@backstage/plugin-catalog-common": "workspace:^"
"@backstage/plugin-catalog-node": "workspace:^"