diff --git a/.changeset/techdocs-chatt-months-report-too.md b/.changeset/techdocs-chatt-months-report-too.md new file mode 100644 index 0000000000..612a4506a5 --- /dev/null +++ b/.changeset/techdocs-chatt-months-report-too.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-techdocs': patch +--- + +Fixed entity triplet case handling for certain locales. diff --git a/.changeset/techdocs-chatty-months-report.md b/.changeset/techdocs-chatty-months-report.md new file mode 100644 index 0000000000..7d3fa773bf --- /dev/null +++ b/.changeset/techdocs-chatty-months-report.md @@ -0,0 +1,5 @@ +--- +'@backstage/techdocs-common': patch +--- + +Added OpenStack Swift case migration support. diff --git a/packages/techdocs-common/package.json b/packages/techdocs-common/package.json index 25577df1dd..b44e68374d 100644 --- a/packages/techdocs-common/package.json +++ b/packages/techdocs-common/package.json @@ -45,7 +45,7 @@ "@backstage/search-common": "^0.2.1", "@backstage/integration": "^0.6.9", "@google-cloud/storage": "^5.6.0", - "@trendyol-js/openstack-swift-sdk": "^0.0.4", + "@trendyol-js/openstack-swift-sdk": "^0.0.5", "@types/express": "^4.17.6", "aws-sdk": "^2.840.0", "express": "^4.17.1", diff --git a/packages/techdocs-common/src/stages/publish/openStackSwift.ts b/packages/techdocs-common/src/stages/publish/openStackSwift.ts index a463157552..7b623933e3 100644 --- a/packages/techdocs-common/src/stages/publish/openStackSwift.ts +++ b/packages/techdocs-common/src/stages/publish/openStackSwift.ts @@ -24,7 +24,11 @@ import { SwiftClient } from '@trendyol-js/openstack-swift-sdk'; import { NotFound } from '@trendyol-js/openstack-swift-sdk/lib/types'; import { Stream, Readable } from 'stream'; import { Logger } from 'winston'; -import { getFileTreeRecursively, getHeadersForFileExtension } from './helpers'; +import { + getFileTreeRecursively, + getHeadersForFileExtension, + lowerCaseEntityTripletInStoragePath, +} from './helpers'; import { PublisherBase, PublishRequest, @@ -289,4 +293,67 @@ export class OpenStackSwiftPublish implements PublisherBase { return false; } } + + async migrateDocsCase({ + removeOriginal = false, + concurrency = 25, + }): Promise { + // Iterate through every file in the root of the publisher. + const allObjects = await this.getAllObjectsFromContainer(); + const limiter = createLimiter(concurrency); + await Promise.all( + allObjects.map(f => + limiter(async file => { + let newPath; + try { + newPath = lowerCaseEntityTripletInStoragePath(file); + } catch (e) { + assertError(e); + this.logger.warn(e.message); + return; + } + + // If all parts are already lowercase, ignore. + if (file === newPath) { + return; + } + + try { + this.logger.verbose(`Migrating ${file} to ${newPath}`); + await this.storageClient.copy( + this.containerName, + file, + this.containerName, + newPath, + ); + if (removeOriginal) { + await this.storageClient.delete(this.containerName, file); + } + } catch (e) { + assertError(e); + this.logger.warn(`Unable to migrate ${file}: ${e.message}`); + } + }, f), + ), + ); + } + + /** + * Returns a list of all object keys from the configured container. + */ + protected async getAllObjectsFromContainer( + { prefix } = { prefix: '' }, + ): Promise { + let objects: string[] = []; + const OSS_MAX_LIMIT = Math.pow(2, 31) - 1; + + const allObjects = await this.storageClient.list( + this.containerName, + prefix, + OSS_MAX_LIMIT, + ); + objects = allObjects.map((object: any) => object.name); + + return objects; + } } diff --git a/plugins/techdocs/src/home/components/DocsCardGrid.tsx b/plugins/techdocs/src/home/components/DocsCardGrid.tsx index e84454ae54..77e69995ae 100644 --- a/plugins/techdocs/src/home/components/DocsCardGrid.tsx +++ b/plugins/techdocs/src/home/components/DocsCardGrid.tsx @@ -39,7 +39,7 @@ export const DocsCardGrid = ({ 'techdocs.legacyUseCaseSensitiveTripletPaths', ) ? (str: string) => str - : (str: string) => str.toLocaleLowerCase(); + : (str: string) => str.toLocaleLowerCase('en-US'); if (!entities) return null; return ( diff --git a/plugins/techdocs/src/home/components/DocsTable.tsx b/plugins/techdocs/src/home/components/DocsTable.tsx index f210e5f678..0e64c2e2e8 100644 --- a/plugins/techdocs/src/home/components/DocsTable.tsx +++ b/plugins/techdocs/src/home/components/DocsTable.tsx @@ -56,7 +56,7 @@ export const DocsTable = ({ 'techdocs.legacyUseCaseSensitiveTripletPaths', ) ? (str: string) => str - : (str: string) => str.toLocaleLowerCase(); + : (str: string) => str.toLocaleLowerCase('en-US'); if (!entities) return null; diff --git a/yarn.lock b/yarn.lock index 9bff375969..adf51ccb32 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6714,10 +6714,10 @@ resolved "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@trendyol-js/openstack-swift-sdk@^0.0.4": - version "0.0.4" - resolved "https://registry.npmjs.org/@trendyol-js/openstack-swift-sdk/-/openstack-swift-sdk-0.0.4.tgz#570c6ab950319156c175ace005b4fb4d9f895d47" - integrity sha512-9YKOjov+V+yzptei6+B9QPuC5pOMTBTg/NQpb1ZbxvlOaYpWU4HHpSH2BkIFYZ8vYyAfzFNG1T2rjpQ2ZQDUtQ== +"@trendyol-js/openstack-swift-sdk@^0.0.5": + version "0.0.5" + resolved "https://registry.npmjs.org/@trendyol-js/openstack-swift-sdk/-/openstack-swift-sdk-0.0.5.tgz#65be3c42b8dbafc57f2f2a46c327e2ad51e5a70e" + integrity sha512-KS5nz0cvd35UUyMzhZm+btGV4prtA1KNE7CCMOGBdVxoMGl06Qidli3HgHoc2I9jLPmky1SPp5yzQUwrsyWa0g== dependencies: agentkeepalive "^4.1.4" axios "^0.21.1"