Merge remote-tracking branch 'origin/master' into abort-task
# Conflicts: # microsite/pages/en/plugins.js
This commit is contained in:
@@ -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;
|
||||
// ..
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user