Skip to content

Commit

Permalink
feat(github-issues): add support for new frontend system
Browse files Browse the repository at this point in the history
Adding github-issues support for the new frontend system

Signed-off-by: Craig Tracey <craig@arctir.com>
  • Loading branch information
craigtracey committed Oct 30, 2024
1 parent 9643308 commit affab87
Show file tree
Hide file tree
Showing 12 changed files with 512 additions and 3 deletions.
5 changes: 5 additions & 0 deletions workspaces/github-issues/.changeset/heavy-berries-clean.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@backstage-community/plugin-github-issues': patch
---

Adding support for the new frontend system, available at the `/alpha` export.
29 changes: 29 additions & 0 deletions workspaces/github-issues/plugins/github-issues/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,32 @@ However, you can configure the plugin with props:
}}
/>
```

## Integrating with the vew Frontend System

Follow this section if you are using Backstage's [new frontend system](https://backstage.io/docs/frontend-system/).

1. Import `githubIssuesPlugin` in your `App.tsx` and add it to your app's `features` array:

```typescript
import githubIssuesPlugin from '@backstage-community/plugin-github-issues/alpha';
// ...
export const app = createApp({
features: [
// ...
githubIssuesPlugin,
// ...
],
});
```

2. Next, enable your desired extensions in `app-config.yaml`

```yaml
app:
extensions:
- entity-content:github-issues/entity
- entity-card:github-issues/overview
```
3. Whichever extensions you've enabled should now appear in your entity page.
22 changes: 19 additions & 3 deletions workspaces/github-issues/plugins/github-issues/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@
]
},
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
"access": "public"
},
"exports": {
".": "./src/index.ts",
"./alpha": "./src/alpha.ts",
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
"alpha": [
"src/alpha.ts"
],
"package.json": [
"package.json"
]
}
},
"homepage": "https://backstage.io",
"repository": {
Expand All @@ -37,9 +50,11 @@
},
"dependencies": {
"@backstage/catalog-model": "^1.7.0",
"@backstage/core-compat-api": "^0.3.1",
"@backstage/core-components": "^0.15.1",
"@backstage/core-plugin-api": "^1.10.0",
"@backstage/errors": "^1.2.4",
"@backstage/frontend-plugin-api": "^0.9.0",
"@backstage/integration": "^1.15.1",
"@backstage/integration-react": "^1.2.0",
"@backstage/plugin-catalog-react": "^1.14.0",
Expand All @@ -54,6 +69,7 @@
"devDependencies": {
"@backstage/cli": "^0.28.0",
"@backstage/dev-utils": "^1.1.2",
"@backstage/frontend-test-utils": "^0.2.1",
"@backstage/test-utils": "^1.7.0",
"@testing-library/dom": "^10.0.0",
"@testing-library/jest-dom": "^6.0.0",
Expand Down
126 changes: 126 additions & 0 deletions workspaces/github-issues/plugins/github-issues/report-alpha.api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
## API Report File for "@backstage-community/plugin-github-issues"

> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
/// <reference types="react" />

import { AnyApiFactory } from '@backstage/core-plugin-api';
import { AnyRouteRefParams } from '@backstage/frontend-plugin-api';
import { ConfigurableExtensionDataRef } from '@backstage/frontend-plugin-api';
import { Entity } from '@backstage/catalog-model';
import { ExtensionDefinition } from '@backstage/frontend-plugin-api';
import { FrontendPlugin } from '@backstage/frontend-plugin-api';
import { JSX as JSX_2 } from 'react';
import { RouteRef } from '@backstage/frontend-plugin-api';

// @alpha (undocumented)
const _default: FrontendPlugin<
{
entityContent: RouteRef<undefined>;
},
{},
{
'api:github-issues': ExtensionDefinition<{
kind: 'api';
name: undefined;
config: {};
configInput: {};
output: ConfigurableExtensionDataRef<
AnyApiFactory,
'core.api.factory',
{}
>;
inputs: {};
params: {
factory: AnyApiFactory;
};
}>;
'entity-card:github-issues/overview': ExtensionDefinition<{
kind: 'entity-card';
name: 'overview';
config: {
filter: string | undefined;
};
configInput: {
filter?: string | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
| ConfigurableExtensionDataRef<
(entity: Entity) => boolean,
'catalog.entity-filter-function',
{
optional: true;
}
>
| ConfigurableExtensionDataRef<
string,
'catalog.entity-filter-expression',
{
optional: true;
}
>;
inputs: {};
params: {
loader: () => Promise<JSX.Element>;
filter?: string | ((entity: Entity) => boolean) | undefined;
};
}>;
'entity-content:github-issues/entity': ExtensionDefinition<{
kind: 'entity-content';
name: 'entity';
config: {
path: string | undefined;
title: string | undefined;
filter: string | undefined;
};
configInput: {
filter?: string | undefined;
title?: string | undefined;
path?: string | undefined;
};
output:
| ConfigurableExtensionDataRef<JSX_2.Element, 'core.reactElement', {}>
| ConfigurableExtensionDataRef<string, 'core.routing.path', {}>
| ConfigurableExtensionDataRef<
RouteRef<AnyRouteRefParams>,
'core.routing.ref',
{
optional: true;
}
>
| ConfigurableExtensionDataRef<
string,
'catalog.entity-content-title',
{}
>
| ConfigurableExtensionDataRef<
(entity: Entity) => boolean,
'catalog.entity-filter-function',
{
optional: true;
}
>
| ConfigurableExtensionDataRef<
string,
'catalog.entity-filter-expression',
{
optional: true;
}
>;
inputs: {};
params: {
loader: () => Promise<JSX.Element>;
defaultPath: string;
defaultTitle: string;
routeRef?: RouteRef<AnyRouteRefParams> | undefined;
filter?: string | ((entity: Entity) => boolean) | undefined;
};
}>;
}
>;
export default _default;

// (No @packageDocumentation comment for this package)
```
38 changes: 38 additions & 0 deletions workspaces/github-issues/plugins/github-issues/src/alpha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright 2024 The Backstage Authors
*
* 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 { convertLegacyRouteRefs } from '@backstage/core-compat-api';
import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
import {
entityGithubIssuesCard,
entityGithubIssuesContent,
githubIssuesApiExtension,
} from './alpha/index';
import { rootRouteRef } from './routes';

/**
* @alpha
*/
export default createFrontendPlugin({
id: 'github-issues',
routes: convertLegacyRouteRefs({
entityContent: rootRouteRef,
}),
extensions: [
entityGithubIssuesContent,
entityGithubIssuesCard,
githubIssuesApiExtension,
],
});
41 changes: 41 additions & 0 deletions workspaces/github-issues/plugins/github-issues/src/alpha/apis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2024 The Backstage Authors
*
* 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 {
configApiRef,
errorApiRef,
ApiBlueprint,
createApiFactory,
} from '@backstage/frontend-plugin-api';
import { scmAuthApiRef } from '@backstage/integration-react';
import { githubIssuesApiRef, githubIssuesApi } from '../api';

/**
* @alpha
*/
export const githubIssuesApiExtension = ApiBlueprint.make({
params: {
factory: createApiFactory({
api: githubIssuesApiRef,
deps: {
configApi: configApiRef,
scmAuthApi: scmAuthApiRef,
errorApi: errorApiRef,
},
factory: ({ configApi, scmAuthApi, errorApi }) =>
githubIssuesApi(scmAuthApi, configApi, errorApi),
}),
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2024 The Backstage Authors
*
* 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 { screen, waitFor } from '@testing-library/react';
import {
createExtensionTester,
renderInTestApp,
TestApiProvider,
} from '@backstage/frontend-test-utils';
import * as cards from './entityCards';
import {
EntityProvider,
catalogApiRef,
CatalogApi,
} from '@backstage/plugin-catalog-react';
import { GithubIssuesApi, githubIssuesApiRef } from '../api';
import { Entity } from '@backstage/catalog-model';
import React from 'react';

const entityComponent = {
metadata: {
annotations: {
'github.com/project-slug': 'backstage/backstage',
'backstage.io/source-location':
'url:https://github.com/backstage/backstage',
},
name: 'backstage',
},
apiVersion: 'backstage.io/v1alpha1',
kind: 'Component',
} as unknown as Entity;

const mockCatalogApi = {
getEntities: () => ({}),
} as CatalogApi;

const mockGithubIssuesApi = {
fetchIssuesByRepoFromGithub: async () => ({
backstage: {
issues: {
totalCount: 0,
edges: [],
},
},
}),
} as GithubIssuesApi;

describe('Entity card extensions', () => {
it('should render', async () => {
const apis = [
[githubIssuesApiRef, mockGithubIssuesApi],
[catalogApiRef, mockCatalogApi],
] as const;

renderInTestApp(
<TestApiProvider apis={apis}>
<EntityProvider entity={entityComponent}>
{createExtensionTester(cards.entityGithubIssuesCard).reactElement()}
</EntityProvider>
</TestApiProvider>,
);

await waitFor(
() => {
expect(screen.getByTestId('no-issues-msg')).toHaveTextContent(
'Hurray! No Issues 🚀',
);
},
{ timeout: 5000 },
);
});
});
Loading

0 comments on commit affab87

Please sign in to comment.