Merge remote-tracking branch 'origin/master' into abort-task

# Conflicts:
#	microsite/pages/en/plugins.js
This commit is contained in:
Bogdan Nechyporenko
2023-03-10 23:46:21 +01:00
106 changed files with 9812 additions and 21352 deletions
@@ -31,16 +31,19 @@ allow most templates built for `fetch:cookiecutter` to work without any changes.
2. Set `cookiecutterCompat` to `true` in the `fetch:template` step input in
`template.yaml`.
```diff
steps:
- id: fetch-base
name: Fetch Base
- action: fetch:cookiecutter
+ action: fetch:template
input:
url: ./skeleton
+ cookiecutterCompat: true
values:
```yaml title="template.yaml"
steps:
- id: fetch-base
name: Fetch Base
# highlight-remove-next-line
action: fetch:cookiecutter
# highlight-add-next-line
action: fetch:template
input:
url: ./skeleton
# highlight-add-next-line
cookiecutterCompat: true
values:
```
### Manual migration
@@ -38,14 +38,20 @@ to upgrade.
An important change is to add the required processor to your `packages/backend/src/plugins/catalog.ts`
```diff
+import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
```ts title="packages/backend/src/plugins/catalog.ts"
/* highlight-add-next-line */
import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend';
...
export default async function createPlugin(
env: PluginEnvironment,
): Promise<Router> {
const builder = await CatalogBuilder.create(env);
/* highlight-add-next-line */
builder.addProcessor(new ScaffolderEntitiesProcessor());
const { processingEngine, router } = await builder.build();
const builder = await CatalogBuilder.create(env);
+ builder.addProcessor(new ScaffolderEntitiesProcessor());
const { processingEngine, router } = await builder.build();
// ..
}
```
## `backstage.io/v1beta2` -> `scaffolder.backstage.io/v1beta3`
@@ -53,10 +59,12 @@ An important change is to add the required processor to your `packages/backend/s
The most important change is that you'll need to switch over the `apiVersion` in
your templates to the new one.
```diff
```yaml
kind: Template
- apiVersion: backstage.io/v1beta2
+ apiVersion: scaffolder.backstage.io/v1beta3
# highlight-remove-next-line
apiVersion: backstage.io/v1beta2
# highlight-add-next-line
apiVersion: scaffolder.backstage.io/v1beta3
```
## `${{ }}` instead of `"{{ }}"`
@@ -68,15 +76,19 @@ was pretty annoying, as it also meant that all things look like strings. Now
that's no longer the case, you can now remove the `""` and take advantage of
writing nice `yaml` files that just work.
```diff
spec:
steps:
input:
allowedHosts: ['github.com']
- description: 'This is {{ parameters.name }}'
+ description: This is ${{ parameters.name }}
- repoUrl: '{{ parameters.repoUrl }}'
+ repoUrl: ${{ parameters.repoUrl }}
```yaml
spec:
steps:
input:
allowedHosts: ['github.com']
# highlight-remove-next-line
description: 'This is {{ parameters.name }}'
# highlight-add-next-line
description: This is ${{ parameters.name }}
# highlight-remove-next-line
repoUrl: '{{ parameters.repoUrl }}'
# highlight-add-next-line
repoUrl: ${{ parameters.repoUrl }}
```
## No more `eq` or `not` helpers
@@ -85,24 +97,26 @@ These helpers are no longer needed with the more expressive `api` that
`nunjucks` provides. You can simply use the built-in `nunjucks` and `jinja2`
style operators.
```diff
spec:
steps:
input:
- if: '{{ eq parameters.value "backstage" }}'
+ if: ${{ parameters.value === "backstage" }}
...
```yaml
spec:
steps:
input:
# highlight-remove-next-line
if: '{{ eq parameters.value "backstage" }}'
# highlight-add-next-line
if: ${{ parameters.value === "backstage" }}
```
And then for the `not`
```diff
spec:
steps:
input:
- if: '{{ not parameters.value "backstage" }}'
+ if: ${{ parameters.value !== "backstage" }}
...
```yaml
spec:
steps:
input:
# highlight-remove-next-line
if: '{{ not parameters.value "backstage" }}'
# highlight-add-next-line
if: ${{ parameters.value !== "backstage" }}
```
Much better right? ✨
@@ -115,32 +129,36 @@ supporting the additional primitive values now rather than everything being a
should all work as expected and keep the type that has been declared in the
input schema.
```diff
spec:
parameters:
test:
type: number
name: Test Number
address:
type: object
required:
- line1
properties:
line1:🙏
type: string
name: Line 1
line2:
type: string
name: Line 2
```yaml
spec:
parameters:
test:
type: number
name: Test Number
address:
type: object
required:
- line1
properties:
line1:
type: string
name: Line 1
line2:
type: string
name: Line 2
steps:
- id: test step
action: run:something
input:
- address: '{{ json parameters.address }}'
+ address: ${{ parameters.address }}
- test: '{{ parameters.test }}'
+ test: ${{ parameters.test }} # this will now make sure that the type of test is a number 🙏
steps:
- id: test step
action: run:something
input:
# highlight-remove-next-line
address: '{{ json parameters.address }}'
# highlight-add-next-line
address: ${{ parameters.address }}
# highlight-remove-next-line
test: '{{ parameters.test }}'
# highlight-add-next-line
test: ${{ parameters.test }} # this will now make sure that the type of test is a number 🙏
```
## `parseRepoUrl` is now a `filter`
@@ -148,13 +166,14 @@ input schema.
All calls to `parseRepoUrl` are now a `jinja2` `filter`, which means you'll need
to update the syntax.
```diff
spec:
steps:
input:
- repoUrl: '{{ parseRepoUrl parameters.repoUrl }}'
+ repoUrl: ${{ parameters.repoUrl | parseRepoUrl }}
...
```yaml
spec:
steps:
input:
# highlight-remove-next-line
repoUrl: '{{ parseRepoUrl parameters.repoUrl }}'
# highlight-add-next-line
repoUrl: ${{ parameters.repoUrl | parseRepoUrl }}
```
Now we have complex value support here too, expect that this `filter` will go
@@ -167,39 +186,46 @@ away in future versions and the `RepoUrlPicker` will return an object so
Previously, it was possible to provide links to the frontend using the named output `entityRef` and `remoteUrl`.
These should be moved to `links` under the `output` object instead.
```diff
output:
- remoteUrl: {{ steps['publish'].output.remoteUrl }}
- entityRef: {{ steps['register'].output.entityRef }}
+ links:
+ - title: Repository
+ url: ${{ steps['publish'].output.remoteUrl }}
+ - title: Open in catalog
+ icon: catalog
+ entityRef: ${{ steps['register'].output.entityRef }}
```yaml
output:
# highlight-remove-start
remoteUrl: {{ steps['publish'].output.remoteUrl }}
entityRef: {{ steps['register'].output.entityRef }}
# highlight-remove-end
# highlight-add-start
links:
- title: Repository
url: ${{ steps['publish'].output.remoteUrl }}
- title: Open in catalog
icon: catalog
entityRef: ${{ steps['register'].output.entityRef }}
# highlight-add-end
```
## Watch out for `dash-case`
The nunjucks compiler can run into issues if the `id` fields in your template steps use dash characters, since these IDs translate directly to JavaScript object properties when accessed as output. One possible migration path is to use `camelCase` for your action IDs.
```diff
```yaml
steps:
- id: my-custom-action
- ...
-
- id: publish-pull-request
- input:
- repoUrl: {{ steps.my-custom-action.output.repoUrl }} # Will not recognize 'my-custom-action' as a JS property since it contains dashes!
# highlight-remove-start
id: my-custom-action
...
id: publish-pull-request
input:
repoUrl: {{ steps.my-custom-action.output.repoUrl }} # Will not recognize 'my-custom-action' as a JS property since it contains dashes!
# highlight-remove-end
steps:
+ id: myCustomAction
+ ...
+
+ id: publishPullRequest
+ input:
+ repoUrl: ${{ steps.myCustomAction.output.repoUrl }}
# highlight-add-start
id: myCustomAction
...
id: publishPullRequest
input:
repoUrl: ${{ steps.myCustomAction.output.repoUrl }}
# highlight-add-end
```
Alternatively, it's possible to keep the `dash-case` syntax and use brackets for property access as you would in JavaScript:
@@ -41,39 +41,42 @@ It's also worth calling out that if you do test this out, and find some issues o
The `ScaffolderPage` router has a completely different export for the `scaffolder/next` work, so you will want to change any import from the old `ScaffolderPage` to the new `NextScaffolderPage`
```diff
- import { ScaffolderPage } from '@backstage/plugin-scaffolder';
+ import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha';
```tsx
/* highlight-remove-next-line */
import { ScaffolderPage } from '@backstage/plugin-scaffolder';
/* highlight-add-next-line */
import { NextScaffolderPage } from '@backstage/plugin-scaffolder/alpha';
```
And this API should be the exact same as the previous Router, so you should be able to make a change like the following further down in this file:
```diff
<Route
path="/create"
element={
- <ScaffolderPage
+ <NextScaffolderPage
groups={[
{
title: 'Recommended',
filter: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
]}
/>
}
>
<ScaffolderFieldExtensions>
<LowerCaseValuePickerFieldExtension />
... other extensions
</ScaffolderFieldExtensions>
<ScaffolderLayouts>
<TwoColumnLayout />
... other layouts
</ScaffolderLayouts>
</Route>
```tsx
<Route
path="/create"
element={
{/* highlight-remove-next-line */}
<ScaffolderPage
{/* highlight-add-next-line */}
<NextScaffolderPage
groups={[
{
title: 'Recommended',
filter: entity =>
entity?.metadata?.tags?.includes('recommended') ?? false,
},
]}
/>
}
>
<ScaffolderFieldExtensions>
<LowerCaseValuePickerFieldExtension />
{/* ... other extensions */}
</ScaffolderFieldExtensions>
<ScaffolderLayouts>
<TwoColumnLayout />
{/* ... other layouts */}
</ScaffolderLayouts>
</Route>
```
### Make the required changes to your `CustomFieldExtensions`
@@ -95,13 +98,17 @@ export const EntityNamePickerFieldExtension = scaffolderPlugin.provide(
References for `createScaffolderFieldExtension` have an `/alpha` version of `createNextScaffolderFieldExtension`, which should be used instead.
```diff
-import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder';
+import { createNextScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react/alpha';
```ts
/* highlight-remove-next-line */
import { createScaffolderFieldExtension } from '@backstage/plugin-scaffolder';
/* highlight-add-next-line */
import { createNextScaffolderFieldExtension } from '@backstage/plugin-scaffolder-react/alpha';
export const EntityNamePickerFieldExtension = scaffolderPlugin.provide(
- createScaffolderFieldExtension({
+ createNextScaffolderFieldExtension({
/* highlight-remove-next-line */
createScaffolderFieldExtension({
/* highlight-add-next-line */
createNextScaffolderFieldExtension({
component: EntityNamePicker,
name: 'EntityNamePicker',
validation: entityNamePickerValidation,
@@ -113,7 +120,7 @@ Once you've done this you will find that you will have two squiggly lines under
Let's take the following code for the `EntityNamePicker` component:
```ts
```tsx
export const EntityNamePicker = (
props: FieldExtensionComponentProps<string, EntityNamePickerProps>,
) => {
@@ -127,19 +134,23 @@ export const EntityNamePicker = (
idSchema,
placeholder,
} = props;
...
}
// ..
};
```
There's another `/alpha` export that you need to replace `FieldExtensionComponentProps` with which is the `NextFieldExtensionComponentProps`.
```diff
- import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react';
+ import { NextFieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react/alpha';
```tsx
/* highlight-remove-next-line */
import { FieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react';
/* highlight-add-next-line */
import { NextFieldExtensionComponentProps } from '@backstage/plugin-scaffolder-react/alpha';
export const EntityNamePicker = (
- props: FieldExtensionComponentProps<string, EntityNamePickerProps>,
+ props: NextFieldExtensionComponentProps<string, EntityNamePickerProps>,
/* highlight-remove-next-line */
props: FieldExtensionComponentProps<string, EntityNamePickerProps>,
/* highlight-add-next-line */
props: NextFieldExtensionComponentProps<string, EntityNamePickerProps>,
) => {
const {
onChange,
@@ -147,13 +158,15 @@ export const EntityNamePicker = (
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
formData,
- uiSchema: { 'ui:autofocus': autoFocus },
+ uiSchema: { 'ui:autofocus': autoFocus } = {},
/* highlight-remove-next-line */
uiSchema: { 'ui:autofocus': autoFocus },
/* highlight-add-next-line */
uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
...
}
// ..
};
```
You'll notice that there's an additional change here, which is that we're now defaulting the `uiSchema` to an empty object. This is because the `uiSchema` is now optional, and if you don't provide it, it will be `undefined` instead of an empty object. There's more around this in the [breaking changes](#breaking-changes) section.
@@ -182,8 +195,10 @@ You will need to change the import for `FieldValidation` to point at the new `re
> Note: you will probably need to install this dependency too, by using `yarn add @rjsf/utils` in the package where you define these validation functions, this could also be in the `packages/app` folder, so you can install it there if needed.
```diff
```ts
/* highlight-remove-next-line */
- import { FieldValidation } from '@rjsf/core';
/* highlight-add-next-line */
+ import { FieldValidation } from '@rjsf/utils;
import { KubernetesValidatorFunctions } from '@backstage/catalog-model';
@@ -201,34 +216,40 @@ Once we fully release the code that is in the `/alpha` exports right now onto th
Later releases of `react-jsonschema-form` have made the `uiSchema` optional, and if you don't provide it, it will be `undefined` instead of an empty object. This means that you will need to make sure that you're defaulting the `uiSchema` to an empty object if you're using it in your code.
```diff
const {
onChange,
required,
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
formData,
- uiSchema: { 'ui:autofocus': autoFocus },
+ uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
```tsx
const {
onChange,
required,
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
formData,
/* highlight-remove-next-line */
uiSchema: { 'ui:autofocus': autoFocus },
/* highlight-add-next-line */
uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
// ..
```
### `formData` can also be `undefined`
If you were using the `formData` and assuming that it was set to an empty object when building `Field Extensions` that return objects, then this will be `undefined` now due to a change in the `react-jsonschema-form` library.
```diff
const {
onChange,
required,
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
- formData,
+ formData = {}, // or maybe some other default value that you would prefer
uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
```tsx
const {
onChange,
required,
schema: { title = 'Name', description = 'Unique name of the component' },
rawErrors,
/* highlight-remove-next-line */
formData,
/* highlight-add-next-line */
formData = {}, // or maybe some other default value that you would prefer
uiSchema: { 'ui:autofocus': autoFocus } = {},
idSchema,
placeholder,
} = props;
// ..
```