From d09ba2379676179cbee805b78b8cf14dfbf7b800 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 13 Jul 2023 12:03:25 +0200 Subject: [PATCH 1/5] docs: add TypeScript versioning policy Signed-off-by: Patrik Oldsberg --- docs/overview/versioning-policy.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/overview/versioning-policy.md b/docs/overview/versioning-policy.md index fdb3a974b1..ebfdcec76b 100644 --- a/docs/overview/versioning-policy.md +++ b/docs/overview/versioning-policy.md @@ -172,3 +172,13 @@ When we say _Supporting_ a Node.js release, that means the following: - The CI pipeline in the main Backstage repo tests towards the supported releases, and we encourage any other Backstage related projects to do the same. - New Backstage projects created with `@backstage/create-app` will have their `engines.node` version set accordingly. - Dropping compatibility with unsupported releases is not considered a breaking change. This includes using new syntax or APIs, as well as bumping dependencies that drop support for these versions. + +## TypeScript Releases + +The Backstage project uses [TypeScript](https://www.typescriptlang.org/) for type checking within the project, as well as external APIs and documentation. It is important to have a clear policy for which TypeScript versions we support, since we want to be able to adopt new TypeScript features, but at the same time not breaking existing projects that are using older versions. + +The TypeScript release cadence is roughly every three months. An important aspect of the TypeScript versioning is that it does not follow semver. In particular, there is no differentiation between major and minor versions, both of them are breaking. One way to think about it is to merge the two, for example version 4.7 can be considered major version 47, 5.0 is 50, and so on. Within these releases there can be a number of patch releases, which do follow semver. + +Our policy is to support the last 3 TypeScript versions, for example 4.8, 4.9, and 5.0. Converted to time, this means that we typically support the TypeScript version from the last six to nine months, depending on where in the TypeScript release window we are. This policy applies as a snapshot at the time of any given Backstage release, new TypeScript releases only apply to the following Backstage main-line release, not to the current one. + +For anyone maintaining their own Backstage project, this means that you should strive to bump to the latest TypeScript version at least every 6 months, or you may encounter breakages as you upgrade Backstage packages. If you encounter any issues in doing so, please [file an issue in the main Backstage repository](https://github.com/backstage/backstage/issues/new/choose), as per this policy we should always support the latest version. In order to ensure that we do not start using new TypeScript features too early, the Backstage project itself uses the version at the beginning of the currently supported window, in the above example that would be version 4.8. From 4b4cd47b8848ef59a5e551ad935cd47c2cd6cad9 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 13 Jul 2023 12:19:33 +0200 Subject: [PATCH 2/5] root: downgrade TypeScript to 4.9 according to new policy Signed-off-by: Patrik Oldsberg --- package.json | 2 +- yarn.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 9cd621388c..f3d6ee3575 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "semver": "^7.5.3", "shx": "^0.3.2", "ts-node": "^10.4.0", - "typescript": "~5.0.0" + "typescript": "~4.9.0" }, "prettier": "@spotify/prettier-config", "lint-staged": { diff --git a/yarn.lock b/yarn.lock index 6a45c08cfd..e1f456638d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -37865,7 +37865,7 @@ __metadata: semver: ^7.5.3 shx: ^0.3.2 ts-node: ^10.4.0 - typescript: ~5.0.0 + typescript: ~4.9.0 languageName: unknown linkType: soft @@ -40778,13 +40778,13 @@ __metadata: languageName: node linkType: hard -"typescript@npm:~5.0.0": - version: 5.0.4 - resolution: "typescript@npm:5.0.4" +"typescript@npm:~4.9.0": + version: 4.9.5 + resolution: "typescript@npm:4.9.5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 82b94da3f4604a8946da585f7d6c3025fff8410779e5bde2855ab130d05e4fd08938b9e593b6ebed165bda6ad9292b230984f10952cf82f0a0ca07bbeaa08172 + checksum: ee000bc26848147ad423b581bd250075662a354d84f0e06eb76d3b892328d8d4440b7487b5a83e851b12b255f55d71835b008a66cbf8f255a11e4400159237db languageName: node linkType: hard @@ -40798,13 +40798,13 @@ __metadata: languageName: node linkType: hard -"typescript@patch:typescript@~5.0.0#~builtin": - version: 5.0.4 - resolution: "typescript@patch:typescript@npm%3A5.0.4#~builtin::version=5.0.4&hash=a1c5e5" +"typescript@patch:typescript@~4.9.0#~builtin": + version: 4.9.5 + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=a1c5e5" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 6a1fe9a77bb9c5176ead919cc4a1499ee63e46b4e05bf667079f11bf3a8f7887f135aa72460a4c3b016e6e6bb65a822cb8689a6d86cbfe92d22cc9f501f09213 + checksum: 2eee5c37cad4390385db5db5a8e81470e42e8f1401b0358d7390095d6f681b410f2c4a0c496c6ff9ebd775423c7785cdace7bcdad76c7bee283df3d9718c0f20 languageName: node linkType: hard From d03258bb52cd928e299ab1412d2e5dd199d8b8dd Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 13 Jul 2023 13:21:16 +0200 Subject: [PATCH 3/5] core-components: internal refactor to support revert to TS 4.9 Signed-off-by: Patrik Oldsberg --- .../core-components/src/layout/TabbedCard/TabbedCard.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index 90cc928169..a09ea11b3d 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -95,8 +95,11 @@ export function TabbedCard(props: PropsWithChildren) { }); } else { React.Children.map(children, child => { - if (React.isValidElement(child) && child?.props.value === value) { - selectedTabContent = child?.props?.children; + if ( + React.isValidElement<{ children?: unknown; value?: unknown }>(child) && + child?.props.value === value + ) { + selectedTabContent = child?.props.children; } }); } From 4b4f904760cec55b8ab6309a3ef15ccaf789d048 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Thu, 13 Jul 2023 13:40:52 +0200 Subject: [PATCH 4/5] update API reports for TypeScript 4.9 Signed-off-by: Patrik Oldsberg --- plugins/catalog-backend/alpha-api-report.md | 4 +++- plugins/permission-node/api-report.md | 13 +++++++++---- plugins/playlist-backend/api-report.md | 5 ++++- plugins/scaffolder-backend/alpha-api-report.md | 9 +++++++-- plugins/scaffolder-react/api-report.md | 2 +- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/plugins/catalog-backend/alpha-api-report.md b/plugins/catalog-backend/alpha-api-report.md index 8fd0eb571f..df3e809ade 100644 --- a/plugins/catalog-backend/alpha-api-report.md +++ b/plugins/catalog-backend/alpha-api-report.md @@ -79,7 +79,9 @@ export const catalogPlugin: () => BackendFeature; // @alpha export const createCatalogConditionalDecision: ( permission: ResourcePermission<'catalog-entity'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'catalog-entity', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha diff --git a/plugins/permission-node/api-report.md b/plugins/permission-node/api-report.md index ea99d22fc5..2a9a79377b 100644 --- a/plugins/permission-node/api-report.md +++ b/plugins/permission-node/api-report.md @@ -75,14 +75,17 @@ export type ConditionTransformer = ( // @public export const createConditionAuthorizer: ( - rules: PermissionRule[], + rules: PermissionRule[], ) => (decision: PolicyDecision, resource: TResource | undefined) => boolean; // @public export const createConditionExports: < TResourceType extends string, TResource, - TRules extends Record>, + TRules extends Record< + string, + PermissionRule + >, >(options: { pluginId: string; resourceType: TResourceType; @@ -91,7 +94,9 @@ export const createConditionExports: < conditions: Conditions; createConditionalDecision: ( permission: ResourcePermission, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition + >, ) => ConditionalPolicyDecision; }; @@ -106,7 +111,7 @@ export const createConditionFactory: < // @public export const createConditionTransformer: < TQuery, - TRules extends PermissionRule[], + TRules extends PermissionRule[], >( permissionRules: [...TRules], ) => ConditionTransformer; diff --git a/plugins/playlist-backend/api-report.md b/plugins/playlist-backend/api-report.md index b755347205..6b51f316c4 100644 --- a/plugins/playlist-backend/api-report.md +++ b/plugins/playlist-backend/api-report.md @@ -15,6 +15,7 @@ import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionEvaluator } from '@backstage/plugin-permission-common'; import { PermissionPolicy } from '@backstage/plugin-permission-node'; import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { PlaylistMetadata } from '@backstage/plugin-playlist-common'; import { PluginDatabaseManager } from '@backstage/backend-common'; import { PluginEndpointDiscovery } from '@backstage/backend-common'; @@ -25,7 +26,9 @@ import { ResourcePermission } from '@backstage/plugin-permission-common'; // @public (undocumented) export const createPlaylistConditionalDecision: ( permission: ResourcePermission<'playlist-list'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'playlist-list', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @public (undocumented) diff --git a/plugins/scaffolder-backend/alpha-api-report.md b/plugins/scaffolder-backend/alpha-api-report.md index 1fe1d4a6ed..363fcafd17 100644 --- a/plugins/scaffolder-backend/alpha-api-report.md +++ b/plugins/scaffolder-backend/alpha-api-report.md @@ -10,6 +10,7 @@ import { JsonObject } from '@backstage/types'; import { PermissionCondition } from '@backstage/plugin-permission-common'; import { PermissionCriteria } from '@backstage/plugin-permission-common'; import { PermissionRule } from '@backstage/plugin-permission-node'; +import { PermissionRuleParams } from '@backstage/plugin-permission-common'; import { ResourcePermission } from '@backstage/plugin-permission-common'; import { TaskBroker } from '@backstage/plugin-scaffolder-backend'; import { TemplateAction } from '@backstage/plugin-scaffolder-node'; @@ -24,13 +25,17 @@ export const catalogModuleTemplateKind: () => BackendFeature; // @alpha (undocumented) export const createScaffolderActionConditionalDecision: ( permission: ResourcePermission<'scaffolder-action'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'scaffolder-action', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha export const createScaffolderTemplateConditionalDecision: ( permission: ResourcePermission<'scaffolder-template'>, - conditions: PermissionCriteria>, + conditions: PermissionCriteria< + PermissionCondition<'scaffolder-template', PermissionRuleParams> + >, ) => ConditionalPolicyDecision; // @alpha diff --git a/plugins/scaffolder-react/api-report.md b/plugins/scaffolder-react/api-report.md index 82610a2fc3..c618050810 100644 --- a/plugins/scaffolder-react/api-report.md +++ b/plugins/scaffolder-react/api-report.md @@ -326,7 +326,7 @@ export type TemplateParameterSchema = { // @public export const useCustomFieldExtensions: < - TComponentDataType = FieldExtensionOptions, + TComponentDataType = FieldExtensionOptions, >( outlet: React.ReactNode, ) => TComponentDataType[]; From bfb9f157eecd262d2e50e77ad1e3a8470f76e63b Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 14 Jul 2023 09:39:36 +0200 Subject: [PATCH 5/5] Update docs/overview/versioning-policy.md Signed-off-by: Patrik Oldsberg --- docs/overview/versioning-policy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/overview/versioning-policy.md b/docs/overview/versioning-policy.md index ebfdcec76b..f34c74d55d 100644 --- a/docs/overview/versioning-policy.md +++ b/docs/overview/versioning-policy.md @@ -175,7 +175,7 @@ When we say _Supporting_ a Node.js release, that means the following: ## TypeScript Releases -The Backstage project uses [TypeScript](https://www.typescriptlang.org/) for type checking within the project, as well as external APIs and documentation. It is important to have a clear policy for which TypeScript versions we support, since we want to be able to adopt new TypeScript features, but at the same time not breaking existing projects that are using older versions. +The Backstage project uses [TypeScript](https://www.typescriptlang.org/) for type checking within the project, as well as external APIs and documentation. It is important to have a clear policy for which TypeScript versions we support, since we want to be able to adopt new TypeScript features, but at the same time not break existing projects that are using older versions. The TypeScript release cadence is roughly every three months. An important aspect of the TypeScript versioning is that it does not follow semver. In particular, there is no differentiation between major and minor versions, both of them are breaking. One way to think about it is to merge the two, for example version 4.7 can be considered major version 47, 5.0 is 50, and so on. Within these releases there can be a number of patch releases, which do follow semver.