diff --git a/.changeset/2826.md b/.changeset/2826.md new file mode 100644 index 0000000000..fb2dbb6877 --- /dev/null +++ b/.changeset/2826.md @@ -0,0 +1,20 @@ +--- +'example-app': minor +'@backstage/core': minor +'@backstage/create-app': minor +'@backstage/plugin-catalog': minor +'@backstage/plugin-github-actions': minor +'@backstage/plugin-jenkins': minor +'@backstage/plugin-lighthouse': minor +--- + +The InfoCard variant `'height100'` is deprecated. Use variant `'gridItem'` instead. + +When the InfoCard is displayed as a grid item within a grid, you may want items to have the same height for all items. +Set to the `'gridItem'` variant to display the InfoCard with full height suitable for Grid: +`...` + +Changed the InfoCards in '@backstage/plugin-github-actions', '@backstage/plugin-jenkins', '@backstage/plugin-lighthouse' +to pass an optional variant to the corresponding card of the plugin. + +As a result the overview content of the EntityPage shows cards with full height suitable for Grid. diff --git a/.changeset/carpal-tunnel-driver.md b/.changeset/carpal-tunnel-driver.md new file mode 100644 index 0000000000..2e6a814533 --- /dev/null +++ b/.changeset/carpal-tunnel-driver.md @@ -0,0 +1,13 @@ +--- +'@backstage/plugin-catalog-backend': minor +--- + +- The `CatalogProcessor` API was updated to have `preProcessEntity` and + `postProcessEntity` methods, instead of just one `processEntity`. This makes + it easier to make processors that have several stages in one, and to make + different processors more position independent in the list of processors. +- The `EntityPolicy` is now given directly to the `LocationReaders`, instead of + being enforced inside a policy. We have decided to separate out the act of + validating an entity to be outside of the processing flow, to make it + possible to apply more liberally and to evolve it as a separate concept. +- Because of the above, the `EntityPolicyProcessor` has been removed. diff --git a/.changeset/funny-readers-breathe.md b/.changeset/funny-readers-breathe.md new file mode 100644 index 0000000000..8897b24cf6 --- /dev/null +++ b/.changeset/funny-readers-breathe.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +fix the warning of all the core components test cases diff --git a/microsite/data/plugins/aws-lambda.yaml b/microsite/data/plugins/aws-lambda.yaml new file mode 100644 index 0000000000..7fa276f444 --- /dev/null +++ b/microsite/data/plugins/aws-lambda.yaml @@ -0,0 +1,9 @@ +--- +title: AWS Lambda +author: roadie.io +authorUrl: https://roadie.io +category: Monitoring +description: View AWS Lambda functions for your components in Backstage. +documentation: https://roadie.io/backstage/plugins/aws-lambda +iconUrl: https://roadie.io/static/77f62f79e27ae8565496e4df7eef8be5/45f2b/logo.png +npmPackageName: '@roadiehq/backstage-plugin-aws-lambda' diff --git a/microsite/static/css/custom.css b/microsite/static/css/custom.css index 6308513276..22855a2b4d 100644 --- a/microsite/static/css/custom.css +++ b/microsite/static/css/custom.css @@ -15,9 +15,6 @@ table tr:nth-child(2n) { background-color: #2b2b2b; } -@media only screen and (min-device-width: 360px) and (max-device-width: 736px) { -} - @media only screen and (min-width: 1024px) and (max-width: 1500px) { /* Experience */ .content-experience { @@ -857,7 +854,6 @@ code { position: relative; padding-top: 75%; width: 100%; - /* border: 1px dotted #f00; */ } .Block__Graphic { diff --git a/packages/app/package.json b/packages/app/package.json index 11c47769a8..dc452e0803 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -35,7 +35,7 @@ "@material-ui/icons": "^4.9.1", "@octokit/rest": "^18.0.0", "@roadiehq/backstage-plugin-github-insights": "^0.2.7", - "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.1", + "@roadiehq/backstage-plugin-github-pull-requests": "^0.5.2", "@roadiehq/backstage-plugin-travis-ci": "^0.2.3", "dayjs": "^1.9.1", "history": "^5.0.0", diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index f30e7ff34f..0a3007237e 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -105,10 +105,12 @@ const RecentCICDRunsSwitcher = ({ entity }: { entity: Entity }) => { let content: ReactNode; switch (true) { case isJenkinsAvailable(entity): - content = ; + content = ; break; case isGitHubActionsAvailable(entity): - content = ; + content = ( + + ); break; case isTravisCIAvailable(entity): content = ; @@ -127,9 +129,9 @@ const RecentCICDRunsSwitcher = ({ entity }: { entity: Entity }) => { }; const OverviewContent = ({ entity }: { entity: Entity }) => ( - + - + {isGitHubAvailable(entity) && ( @@ -145,7 +147,7 @@ const OverviewContent = ({ entity }: { entity: Entity }) => ( )} {isLighthouseAvailable(entity) && ( - + )} {isPullRequestsAvailable(entity) && ( diff --git a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts deleted file mode 100644 index 5d4e60a1a3..0000000000 --- a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import yaml from 'yaml'; -import { ReservedFieldsEntityPolicy } from './ReservedFieldsEntityPolicy'; - -describe('ReservedFieldsEntityPolicy', () => { - let data: any; - let policy: ReservedFieldsEntityPolicy; - - beforeEach(() => { - data = yaml.parse(` - apiVersion: backstage.io/v1alpha1 - kind: Component - metadata: - uid: e01199ab-08cc-44c2-8e19-5c29ded82521 - etag: lsndfkjsndfkjnsdfkjnsd== - generation: 13 - name: my-component-yay - namespace: the-namespace - labels: - backstage.io/custom: ValueStuff - annotations: - example.com/bindings: are-secret - tags: - - java - - data - spec: - custom: stuff - `); - policy = new ReservedFieldsEntityPolicy(); - }); - - it('works for the happy path', async () => { - await expect(policy.enforce(data)).resolves.toBe(data); - }); - - it('rejects reserved keys in the spec root', async () => { - data.spec.apiVersion = 'a/b'; - await expect(policy.enforce(data)).rejects.toThrow(/spec.*apiVersion/i); - }); - - it('rejects reserved keys in labels', async () => { - data.metadata.labels.apiVersion = 'a'; - await expect(policy.enforce(data)).rejects.toThrow(/label.*apiVersion/i); - }); - - it('rejects reserved keys in annotations', async () => { - data.metadata.annotations.apiVersion = 'a'; - await expect(policy.enforce(data)).rejects.toThrow( - /annotation.*apiVersion/i, - ); - }); - - it('rejects core fields mistakenly placed in metadata', async () => { - data.metadata.owner = 'emma'; - await expect(policy.enforce(data)).rejects.toThrow(/owner/i); - }); -}); diff --git a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts b/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts deleted file mode 100644 index edb63cf05c..0000000000 --- a/packages/catalog-model/src/entity/policies/ReservedFieldsEntityPolicy.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import { EntityPolicy } from '../../types'; -import { Entity } from '../Entity'; - -const DEFAULT_RESERVED_ENTITY_FIELDS: string[] = [ - 'apiVersion', - 'kind', - 'spec', - 'metadata.uid', - 'metadata.etag', - 'metadata.generation', - 'metadata.name', - 'metadata.namespace', - 'metadata.description', - 'metadata.labels', - 'metadata.annotations', - 'metadata.tags', - // The below items are known to appear in core kinds, and therefore should - // not be appearing in metadata (which would indicate that the user made a - // mistake in where to place them). - 'spec.lifecycle', - 'spec.owner', -]; - -/** - * Ensures that fields are not given certain reserved names. - */ -export class ReservedFieldsEntityPolicy implements EntityPolicy { - private readonly reservedFields: string[]; - - constructor(fields?: string[]) { - this.reservedFields = [ - ...(fields ?? []), - ...DEFAULT_RESERVED_ENTITY_FIELDS, - ]; - } - - async enforce(entity: Entity): Promise { - for (const path of this.reservedFields) { - const [where, name] = path.includes('.') - ? path.split('.') - : [undefined, path]; - - if (where !== 'metadata' && entity.metadata.hasOwnProperty(name)) { - throw new Error( - `The metadata may not contain the field ${name}, because it has reserved meaning`, - ); - } - if (where !== 'spec' && entity.spec?.hasOwnProperty(name)) { - throw new Error( - `The spec may not contain the field ${name}, because it has reserved meaning`, - ); - } - if (where !== 'labels' && entity.metadata.labels?.hasOwnProperty(name)) { - throw new Error( - `A label may not have the field ${name}, because it has reserved meaning`, - ); - } - if ( - where !== 'annotations' && - entity.metadata.annotations?.hasOwnProperty(name) - ) { - throw new Error( - `An annotation may not have the field ${name}, because it has reserved meaning`, - ); - } - } - return entity; - } -} diff --git a/packages/catalog-model/src/entity/policies/index.ts b/packages/catalog-model/src/entity/policies/index.ts index eb7c0e8378..c381d29a23 100644 --- a/packages/catalog-model/src/entity/policies/index.ts +++ b/packages/catalog-model/src/entity/policies/index.ts @@ -17,5 +17,4 @@ export { DefaultNamespaceEntityPolicy } from './DefaultNamespaceEntityPolicy'; export { FieldFormatEntityPolicy } from './FieldFormatEntityPolicy'; export { NoForeignRootFieldsEntityPolicy } from './NoForeignRootFieldsEntityPolicy'; -export { ReservedFieldsEntityPolicy } from './ReservedFieldsEntityPolicy'; export { SchemaValidEntityPolicy } from './SchemaValidEntityPolicy'; diff --git a/packages/cli/src/commands/remove-plugin/removePlugin.ts b/packages/cli/src/commands/remove-plugin/removePlugin.ts index 643bd599d7..81d8322ffa 100644 --- a/packages/cli/src/commands/remove-plugin/removePlugin.ts +++ b/packages/cli/src/commands/remove-plugin/removePlugin.ts @@ -62,7 +62,7 @@ export const removePluginDirectory = async (destination: string) => { export const removeSymLink = async (destination: string) => { await Task.forItem('removing', 'symbolic link', async () => { - const symLinkExists = fse.pathExists(destination); + const symLinkExists = await fse.pathExists(destination); if (symLinkExists) { try { await fse.remove(destination); @@ -189,7 +189,7 @@ export default async () => { return chalk.red('Please enter an ID for the plugin'); } else if (!/^[a-z0-9]+(-[a-z0-9]+)*$/.test(value)) { return chalk.red( - 'Plugin IDs must be kehbab-cased and contain only letters, digits and dashes.', + 'Plugin IDs must be kebab-cased and contain only letters, digits and dashes.', ); } return true; diff --git a/packages/core/src/components/Button/Button.test.jsx b/packages/core/src/components/Button/Button.test.tsx similarity index 94% rename from packages/core/src/components/Button/Button.test.jsx rename to packages/core/src/components/Button/Button.test.tsx index 115835be3f..8bae5f2767 100644 --- a/packages/core/src/components/Button/Button.test.jsx +++ b/packages/core/src/components/Button/Button.test.tsx @@ -34,7 +34,9 @@ describe('