From 0e797b37f4a5fa74d00bd0065aad73dfe140e55c Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Wed, 29 May 2024 10:04:09 -0500
Subject: [PATCH 01/63] Add ability to specify a different relationship name
for MembersListCard
The default relationship remains `memberOf` but could be overridden to
specify (for instance) `leaderOf` if you wanted to have multiple
MembersListCard components on a `Group` page (one for "Members" and
another for "Leaders")
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
.../MembersList/MembersListCard.test.tsx | 30 +++++++++++++++++++
.../Group/MembersList/MembersListCard.tsx | 4 ++-
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
index 793ffe274b..539b0bd892 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
@@ -99,6 +99,7 @@ describe('MemberTab Test', () => {
] as Entity[],
}),
};
+ const getEntitiesSpy = jest.spyOn(catalogApi, 'getEntities');
it('Display Profile Card', async () => {
await renderInTestApp(
@@ -115,6 +116,12 @@ describe('MemberTab Test', () => {
},
},
);
+ expect(getEntitiesSpy).toHaveBeenCalledWith({
+ filter: {
+ kind: 'User',
+ 'relations.memberOf': ['group:default/team-d'],
+ },
+ });
expect(screen.getByAltText('Tara MacGovern')).toHaveAttribute(
'src',
@@ -149,6 +156,29 @@ describe('MemberTab Test', () => {
expect(screen.getByText('Testers (1)')).toBeInTheDocument();
});
+ it('Can query a different relationship', async () => {
+ await renderInTestApp(
+
+
+
+
+ ,
+ {
+ mountedRoutes: {
+ '/catalog/:namespace/:kind/:name': entityRouteRef,
+ '/catalog': rootRouteRef,
+ },
+ },
+ );
+
+ expect(getEntitiesSpy).toHaveBeenCalledWith({
+ filter: {
+ kind: 'User',
+ 'relations.leaderOf': ['group:default/team-d'],
+ },
+ });
+ });
+
describe('Aggregate members toggle', () => {
it('Does not show the aggregate members toggle if the showAggregateMembersToggle prop is undefined', async () => {
await renderInTestApp(
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
index 418a83f5b2..b21ae20c23 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
@@ -138,12 +138,14 @@ export const MembersListCard = (props: {
memberDisplayTitle?: string;
pageSize?: number;
showAggregateMembersToggle?: boolean;
+ relationship?: string;
relationsType?: EntityRelationAggregation;
}) => {
const {
memberDisplayTitle = 'Members',
pageSize = 50,
showAggregateMembersToggle,
+ relationship = 'memberOf',
relationsType = 'direct',
} = props;
const classes = useListStyles();
@@ -187,7 +189,7 @@ export const MembersListCard = (props: {
const membersList = await catalogApi.getEntities({
filter: {
kind: 'User',
- 'relations.memberof': [
+ [`relations.${relationship}`]: [
stringifyEntityRef({
kind: 'group',
namespace: groupNamespace.toLocaleLowerCase('en-US'),
From c307ef471a3d9868395213d4b69eb3c444b4039e Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Wed, 29 May 2024 10:29:23 -0500
Subject: [PATCH 02/63] add changeset
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
.changeset/little-games-fail.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/little-games-fail.md
diff --git a/.changeset/little-games-fail.md b/.changeset/little-games-fail.md
new file mode 100644
index 0000000000..dc5d2f7795
--- /dev/null
+++ b/.changeset/little-games-fail.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-org': patch
+---
+
+Added relationship option to EntityMembersListCard component
From 2644eeccb955fcf0b6e26f9df1c6b6f3e6d88afc Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Wed, 29 May 2024 13:40:23 -0500
Subject: [PATCH 03/63] Add API report
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
plugins/org/api-report.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/plugins/org/api-report.md b/plugins/org/api-report.md
index 1960ce839b..fe641e5a8b 100644
--- a/plugins/org/api-report.md
+++ b/plugins/org/api-report.md
@@ -23,6 +23,7 @@ export const EntityMembersListCard: (props: {
memberDisplayTitle?: string | undefined;
pageSize?: number | undefined;
showAggregateMembersToggle?: boolean | undefined;
+ relationship?: string | undefined;
relationsType?: EntityRelationAggregation | undefined;
}) => JSX_2.Element;
@@ -55,6 +56,7 @@ export const MembersListCard: (props: {
memberDisplayTitle?: string;
pageSize?: number;
showAggregateMembersToggle?: boolean;
+ relationship?: string;
relationsType?: EntityRelationAggregation;
}) => React_2.JSX.Element;
From 05ad87ed3aff16d87aa65a62972b0bc529457770 Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Wed, 29 May 2024 14:37:35 -0500
Subject: [PATCH 04/63] fix case mismatch in relationship name
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
.../Group/MembersList/MembersListCard.test.tsx | 4 ++--
.../Group/MembersList/MembersListCard.tsx | 5 +++--
plugins/org/src/helpers/helpers.ts | 18 +++++++++++-------
3 files changed, 16 insertions(+), 11 deletions(-)
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
index 539b0bd892..3a129348c7 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
@@ -119,7 +119,7 @@ describe('MemberTab Test', () => {
expect(getEntitiesSpy).toHaveBeenCalledWith({
filter: {
kind: 'User',
- 'relations.memberOf': ['group:default/team-d'],
+ 'relations.memberof': ['group:default/team-d'],
},
});
@@ -174,7 +174,7 @@ describe('MemberTab Test', () => {
expect(getEntitiesSpy).toHaveBeenCalledWith({
filter: {
kind: 'User',
- 'relations.leaderOf': ['group:default/team-d'],
+ 'relations.leaderof': ['group:default/team-d'],
},
});
});
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
index b21ae20c23..d1e74200fd 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
@@ -145,7 +145,7 @@ export const MembersListCard = (props: {
memberDisplayTitle = 'Members',
pageSize = 50,
showAggregateMembersToggle,
- relationship = 'memberOf',
+ relationship = 'memberof',
relationsType = 'direct',
} = props;
const classes = useListStyles();
@@ -179,6 +179,7 @@ export const MembersListCard = (props: {
return await getAllDesendantMembersForGroupEntity(
groupEntity,
catalogApi,
+ relationship,
);
}, [catalogApi, groupEntity, showAggregateMembers]);
const {
@@ -189,7 +190,7 @@ export const MembersListCard = (props: {
const membersList = await catalogApi.getEntities({
filter: {
kind: 'User',
- [`relations.${relationship}`]: [
+ [`relations.${relationship.toLocaleLowerCase('en-US')}`]: [
stringifyEntityRef({
kind: 'group',
namespace: groupNamespace.toLocaleLowerCase('en-US'),
diff --git a/plugins/org/src/helpers/helpers.ts b/plugins/org/src/helpers/helpers.ts
index 7da4ee32d8..465f89afa1 100644
--- a/plugins/org/src/helpers/helpers.ts
+++ b/plugins/org/src/helpers/helpers.ts
@@ -31,6 +31,7 @@ import {
export const getMembersFromGroups = async (
groups: CompoundEntityRef[],
catalogApi: CatalogApi,
+ relationship = 'memberof',
) => {
const membersList =
groups.length === 0
@@ -38,13 +39,14 @@ export const getMembersFromGroups = async (
: await catalogApi.getEntities({
filter: {
kind: 'User',
- 'relations.memberof': groups.map(group =>
- stringifyEntityRef({
- kind: 'group',
- namespace: group.namespace.toLocaleLowerCase('en-US'),
- name: group.name.toLocaleLowerCase('en-US'),
- }),
- ),
+ [`relations.${relationship.toLocaleLowerCase('en-US')}`]:
+ groups.map(group =>
+ stringifyEntityRef({
+ kind: 'group',
+ namespace: group.namespace.toLocaleLowerCase('en-US'),
+ name: group.name.toLocaleLowerCase('en-US'),
+ }),
+ ),
},
});
@@ -99,10 +101,12 @@ export const getDescendantGroupsFromGroup = async (
export const getAllDesendantMembersForGroupEntity = async (
groupEntity: GroupEntity,
catalogApi: CatalogApi,
+ relationship = 'memberof',
) =>
getMembersFromGroups(
await getDescendantGroupsFromGroup(groupEntity, catalogApi),
catalogApi,
+ relationship,
);
export const removeDuplicateEntitiesFrom = (entityArray: Entity[]) => {
From 0391e693babafe46b9d25b86862ac6003b1890f6 Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Thu, 6 Jun 2024 06:37:35 -0500
Subject: [PATCH 05/63] use more sensible property for specifying the
relationship type
In the process, the `relationsType` prop is deprecated and renamed to
`relationAggregation`.
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
.../Group/MembersList/MembersListCard.test.tsx | 6 +++---
.../Cards/Group/MembersList/MembersListCard.tsx | 15 +++++++++------
2 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
index 3a129348c7..69d6090687 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.test.tsx
@@ -160,7 +160,7 @@ describe('MemberTab Test', () => {
await renderInTestApp(
-
+
,
{
@@ -376,7 +376,7 @@ describe('MemberTab Test', () => {
@@ -414,7 +414,7 @@ describe('MemberTab Test', () => {
-
+
diff --git a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
index d1e74200fd..f27b071114 100644
--- a/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
+++ b/plugins/org/src/components/Cards/Group/MembersList/MembersListCard.tsx
@@ -138,16 +138,19 @@ export const MembersListCard = (props: {
memberDisplayTitle?: string;
pageSize?: number;
showAggregateMembersToggle?: boolean;
- relationship?: string;
+ relationType?: string;
+ /** @deprecated Please use `relationAggregation` instead */
relationsType?: EntityRelationAggregation;
+ relationAggregation?: EntityRelationAggregation;
}) => {
const {
memberDisplayTitle = 'Members',
pageSize = 50,
showAggregateMembersToggle,
- relationship = 'memberof',
- relationsType = 'direct',
+ relationType = 'memberof',
} = props;
+ const relationAggregation =
+ props.relationAggregation ?? props.relationsType ?? 'direct';
const classes = useListStyles();
const { entity: groupEntity } = useEntity();
@@ -167,7 +170,7 @@ export const MembersListCard = (props: {
};
const [showAggregateMembers, setShowAggregateMembers] = useState(
- relationsType === 'aggregated',
+ relationAggregation === 'aggregated',
);
const { loading: loadingDescendantMembers, value: descendantMembers } =
@@ -179,7 +182,7 @@ export const MembersListCard = (props: {
return await getAllDesendantMembersForGroupEntity(
groupEntity,
catalogApi,
- relationship,
+ relationType,
);
}, [catalogApi, groupEntity, showAggregateMembers]);
const {
@@ -190,7 +193,7 @@ export const MembersListCard = (props: {
const membersList = await catalogApi.getEntities({
filter: {
kind: 'User',
- [`relations.${relationship.toLocaleLowerCase('en-US')}`]: [
+ [`relations.${relationType.toLocaleLowerCase('en-US')}`]: [
stringifyEntityRef({
kind: 'group',
namespace: groupNamespace.toLocaleLowerCase('en-US'),
From 4a99e6463d2c9cb8786bad750b1915b89c2b0c8a Mon Sep 17 00:00:00 2001
From: Brian Phillips <28457+brianphillips@users.noreply.github.com>
Date: Thu, 6 Jun 2024 07:05:29 -0500
Subject: [PATCH 06/63] deprecate all instances of the relationsType property
in favor of relationAggregation
Signed-off-by: Brian Phillips <28457+brianphillips@users.noreply.github.com>
---
.changeset/little-games-fail.md | 4 ++-
plugins/org/api-report.md | 8 +++--
.../Cards/OwnershipCard/ComponentsGrid.tsx | 12 +++++--
.../OwnershipCard/OwnershipCard.test.tsx | 2 +-
.../Cards/OwnershipCard/OwnershipCard.tsx | 31 +++++++++++--------
.../OwnershipCard/useGetEntities.test.ts | 4 +--
.../Cards/OwnershipCard/useGetEntities.ts | 10 +++---
7 files changed, 45 insertions(+), 26 deletions(-)
diff --git a/.changeset/little-games-fail.md b/.changeset/little-games-fail.md
index dc5d2f7795..199f983be8 100644
--- a/.changeset/little-games-fail.md
+++ b/.changeset/little-games-fail.md
@@ -2,4 +2,6 @@
'@backstage/plugin-org': patch
---
-Added relationship option to EntityMembersListCard component
+Added `relationType` property to EntityMembersListCard component that allows for display users related to a group via some other relationship aside from `memberOf`.
+
+Also, as a side effect, the `relationsType` property has been deprecated in favor of a more accurately named `relationAggregation` property.
diff --git a/plugins/org/api-report.md b/plugins/org/api-report.md
index fe641e5a8b..884832c111 100644
--- a/plugins/org/api-report.md
+++ b/plugins/org/api-report.md
@@ -23,8 +23,9 @@ export const EntityMembersListCard: (props: {
memberDisplayTitle?: string | undefined;
pageSize?: number | undefined;
showAggregateMembersToggle?: boolean | undefined;
- relationship?: string | undefined;
+ relationType?: string | undefined;
relationsType?: EntityRelationAggregation | undefined;
+ relationAggregation?: EntityRelationAggregation | undefined;
}) => JSX_2.Element;
// @public (undocumented)
@@ -33,6 +34,7 @@ export const EntityOwnershipCard: (props: {
entityFilterKind?: string[] | undefined;
hideRelationsToggle?: boolean | undefined;
relationsType?: EntityRelationAggregation | undefined;
+ relationAggregation?: EntityRelationAggregation | undefined;
entityLimit?: number | undefined;
}) => JSX_2.Element;
@@ -56,8 +58,9 @@ export const MembersListCard: (props: {
memberDisplayTitle?: string;
pageSize?: number;
showAggregateMembersToggle?: boolean;
- relationship?: string;
+ relationType?: string;
relationsType?: EntityRelationAggregation;
+ relationAggregation?: EntityRelationAggregation;
}) => React_2.JSX.Element;
// @public
@@ -84,6 +87,7 @@ export const OwnershipCard: (props: {
entityFilterKind?: string[];
hideRelationsToggle?: boolean;
relationsType?: EntityRelationAggregation;
+ relationAggregation?: EntityRelationAggregation;
entityLimit?: number;
}) => React_2.JSX.Element;
diff --git a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx
index ff16a4ab2d..586e612e94 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx
+++ b/plugins/org/src/components/Cards/OwnershipCard/ComponentsGrid.tsx
@@ -107,19 +107,27 @@ export const ComponentsGrid = ({
className,
entity,
relationsType,
+ relationAggregation,
entityFilterKind,
entityLimit = 6,
}: {
className?: string;
entity: Entity;
- relationsType: EntityRelationAggregation;
+ /** @deprecated Please use relationAggregation instead */
+ relationsType?: EntityRelationAggregation;
+ relationAggregation?: EntityRelationAggregation;
entityFilterKind?: string[];
entityLimit?: number;
}) => {
const catalogLink = useRouteRef(catalogIndexRouteRef);
+ if (!relationsType && !relationAggregation) {
+ throw new Error(
+ 'The relationAggregation property must be set as an EntityRelationAggregation type.',
+ );
+ }
const { componentsWithCounters, loading, error } = useGetEntities(
entity,
- relationsType,
+ (relationAggregation ?? relationsType)!, // we can safely use the non-null assertion here because of the run-time check above
entityFilterKind,
entityLimit,
);
diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
index f2b949f768..004fb8b964 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
+++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.test.tsx
@@ -288,7 +288,7 @@ describe('OwnershipCard', () => {
const { getByText } = await renderInTestApp(
-
+
,
{
diff --git a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx
index a5b0b7bb19..fce47845bc 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx
+++ b/plugins/org/src/components/Cards/OwnershipCard/OwnershipCard.tsx
@@ -67,31 +67,34 @@ export const OwnershipCard = (props: {
variant?: InfoCardVariants;
entityFilterKind?: string[];
hideRelationsToggle?: boolean;
+ /** @deprecated Please use relationAggregation instead */
relationsType?: EntityRelationAggregation;
+ relationAggregation?: EntityRelationAggregation;
entityLimit?: number;
}) => {
const {
variant,
entityFilterKind,
hideRelationsToggle,
- relationsType,
entityLimit = 6,
} = props;
+ const relationAggregation = props.relationAggregation ?? props.relationsType;
const relationsToggle =
hideRelationsToggle === undefined ? false : hideRelationsToggle;
const classes = useStyles();
const { entity } = useEntity();
- const defaultRelationsType = entity.kind === 'User' ? 'aggregated' : 'direct';
- const [getRelationsType, setRelationsType] = useState(
- relationsType ?? defaultRelationsType,
+ const defaultRelationAggregation =
+ entity.kind === 'User' ? 'aggregated' : 'direct';
+ const [getRelationAggregation, setRelationAggregation] = useState(
+ relationAggregation ?? defaultRelationAggregation,
);
useEffect(() => {
- if (!relationsType) {
- setRelationsType(defaultRelationsType);
+ if (!relationAggregation) {
+ setRelationAggregation(defaultRelationAggregation);
}
- }, [setRelationsType, defaultRelationsType, relationsType]);
+ }, [setRelationAggregation, defaultRelationAggregation, relationAggregation]);
return (
{
- const updatedRelationsType =
- getRelationsType === 'direct' ? 'aggregated' : 'direct';
- setRelationsType(updatedRelationsType);
+ const updatedRelationAggregation =
+ getRelationAggregation === 'direct'
+ ? 'aggregated'
+ : 'direct';
+ setRelationAggregation(updatedRelationAggregation);
}}
name="pin"
inputProps={{ 'aria-label': 'Ownership Type Switch' }}
@@ -136,7 +141,7 @@ export const OwnershipCard = (props: {
className={classes.grid}
entity={entity}
entityLimit={entityLimit}
- relationsType={getRelationsType}
+ relationAggregation={getRelationAggregation}
entityFilterKind={entityFilterKind}
/>
diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts
index eac5a171ba..c6cec557c1 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts
+++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.test.ts
@@ -64,7 +64,7 @@ describe('useGetEntities', () => {
]),
});
- describe('given aggregated relationsType', () => {
+ describe('given aggregated relationAggregation', () => {
const whenHookIsCalledWith = async (_entity: Entity) => {
const { result } = renderHook(
({ entity }) => useGetEntities(entity, 'aggregated'),
@@ -205,7 +205,7 @@ describe('useGetEntities', () => {
});
});
- describe('given direct relationsType', () => {
+ describe('given direct relationAggregation', () => {
const whenHookIsCalledWith = async (_entity: Entity) => {
const { result } = renderHook(
({ entity }) => useGetEntities(entity, 'direct'),
diff --git a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts
index 5a708bcfee..d806bbfef2 100644
--- a/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts
+++ b/plugins/org/src/components/Cards/OwnershipCard/useGetEntities.ts
@@ -125,11 +125,11 @@ const getChildOwnershipEntityRefs = async (
const getOwners = async (
entity: Entity,
- relations: EntityRelationAggregation,
+ relationAggregation: EntityRelationAggregation,
catalogApi: CatalogApi,
): Promise => {
const isGroup = entity.kind === 'Group';
- const isAggregated = relations === 'aggregated';
+ const isAggregated = relationAggregation === 'aggregated';
const isUserEntity = entity.kind === 'User';
if (isAggregated && isGroup) {
@@ -166,7 +166,7 @@ const getOwnedEntitiesByOwners = (
export function useGetEntities(
entity: Entity,
- relations: EntityRelationAggregation,
+ relationAggregation: EntityRelationAggregation,
entityFilterKind?: string[],
entityLimit = 6,
): {
@@ -189,7 +189,7 @@ export function useGetEntities(
error,
value: componentsWithCounters,
} = useAsync(async () => {
- const owners = await getOwners(entity, relations, catalogApi);
+ const owners = await getOwners(entity, relationAggregation, catalogApi);
const ownedEntitiesList = await getOwnedEntitiesByOwners(
owners,
@@ -230,7 +230,7 @@ export function useGetEntities(
kind: string;
queryParams: string;
}>;
- }, [catalogApi, entity, relations]);
+ }, [catalogApi, entity, relationAggregation]);
return {
componentsWithCounters,
From 6e11898ea2dda150e2bd9c58b2428e8e42f59cc6 Mon Sep 17 00:00:00 2001
From: Tavi Nolan
Date: Thu, 6 Jun 2024 14:56:30 +0100
Subject: [PATCH 07/63] Updating template input documentation
Signed-off-by: Tavi Nolan
---
.../software-templates/input-examples.md | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/docs/features/software-templates/input-examples.md b/docs/features/software-templates/input-examples.md
index a95cee24f4..32d37ae17c 100644
--- a/docs/features/software-templates/input-examples.md
+++ b/docs/features/software-templates/input-examples.md
@@ -238,3 +238,51 @@ spec:
input:
url: ${{ parameters.path if parameters.path else '/root' }}
```
+
+## Use placeholders to reference remote files
+
+#### Note: testing of this functionality is not yet supported using _create/edit_
+
+### template.yaml
+
+```yaml
+spec:
+ parameters:
+ - $yaml: https://github.com/example/path/to/example.yaml
+ - title: Fill in some steps
+ properties:
+ path:
+ title: path
+ type: string
+
+ steps:
+ - $yaml: https://github.com//example/path/to/action.yaml
+
+ - id: fetch
+ name: Fetch template
+ action: fetch:template
+ input:
+ url: ${{ parameters.path if parameters.path else '/root' }}
+```
+
+### example.yaml
+
+```yaml
+title: Provide simple information
+required:
+ - url
+properties:
+ url:
+ title: url
+ type: string
+```
+
+### action.yaml
+
+```yaml
+id: publish
+name: Publish files
+action: publish:github
+input:
+ repoUrl: ${{ parameters.url }}
+```
From 083eaf98b3413b814d1c03702627b0c30f052179 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?=
Date: Tue, 18 Jun 2024 17:28:22 +0200
Subject: [PATCH 08/63] fix iso duration parsing in schedules
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Fredrik Adelöw
---
.changeset/curvy-teachers-smell.md | 8 +++
.../scheduler/lib/PluginTaskSchedulerImpl.ts | 2 +-
.../definitions/SchedulerService.test.ts | 5 +-
.../services/definitions/SchedulerService.ts | 6 +-
...adTaskScheduleDefinitionFromConfig.test.ts | 5 +-
.../readTaskScheduleDefinitionFromConfig.ts | 4 +-
.../catalogModuleAwsS3EntityProvider.test.ts | 5 +-
.../src/providers/config.test.ts | 3 +-
...logModuleAzureDevOpsEntityProvider.test.ts | 5 +-
.../src/providers/config.test.ts | 3 +-
...ModuleBitbucketCloudEntityProvider.test.ts | 5 +-
...BitbucketCloudEntityProviderConfig.test.ts | 3 +-
...oduleBitbucketServerEntityProvider.test.ts | 5 +-
...itbucketServerEntityProviderConfig.test.ts | 3 +-
.../catalogModuleGerritEntityProvider.test.ts | 5 +-
.../src/providers/config.test.ts | 3 +-
.../src/module.test.ts | 5 +-
.../src/module/githubCatalogModule.test.ts | 5 +-
.../GithubEntityProviderConfig.test.ts | 3 +-
...leGitlabOrgDiscoveryEntityProvider.test.ts | 5 +-
...oduleGitlabDiscoveryEntityProvider.test.ts | 5 +-
.../src/providers/config.test.ts | 3 +-
.../catalog-backend-module-ldap/api-report.md | 14 ++--
.../src/ldap/config.test.ts | 69 +++++++++++++++++++
.../src/ldap/config.ts | 12 ++--
.../src/processors/LdapOrgEntityProvider.ts | 19 ++---
.../src/microsoftGraph/config.test.ts | 3 +-
...uleMicrosoftGraphOrgEntityProvider.test.ts | 5 +-
.../PuppetDbEntityProviderConfig.test.ts | 7 +-
29 files changed, 142 insertions(+), 83 deletions(-)
create mode 100644 .changeset/curvy-teachers-smell.md
diff --git a/.changeset/curvy-teachers-smell.md b/.changeset/curvy-teachers-smell.md
new file mode 100644
index 0000000000..3f032f2177
--- /dev/null
+++ b/.changeset/curvy-teachers-smell.md
@@ -0,0 +1,8 @@
+---
+'@backstage/plugin-catalog-backend-module-ldap': patch
+'@backstage/backend-plugin-api': patch
+'@backstage/backend-defaults': patch
+'@backstage/backend-tasks': patch
+---
+
+Fix bug where ISO durations could no longer be used for schedules
diff --git a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
index 62b36e024c..40aa9d521c 100644
--- a/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
+++ b/packages/backend-defaults/src/entrypoints/scheduler/lib/PluginTaskSchedulerImpl.ts
@@ -152,7 +152,7 @@ export class PluginTaskSchedulerImpl implements SchedulerService {
export function parseDuration(
frequency: SchedulerServiceTaskScheduleDefinition['frequency'],
): string {
- if ('cron' in frequency) {
+ if (typeof frequency === 'object' && 'cron' in frequency) {
return frequency.cron;
}
diff --git a/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts b/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts
index 7b20487af4..875e24786f 100644
--- a/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts
+++ b/packages/backend-plugin-api/src/services/definitions/SchedulerService.test.ts
@@ -16,7 +16,6 @@
import { ConfigReader } from '@backstage/config';
import { HumanDuration } from '@backstage/types';
-import { Duration } from 'luxon';
import { readSchedulerServiceTaskScheduleDefinitionFromConfig } from './SchedulerService';
describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => {
@@ -35,7 +34,7 @@ describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => {
const result = readSchedulerServiceTaskScheduleDefinitionFromConfig(config);
expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *');
- expect(result.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(result.timeout).toEqual({ minutes: 3 });
expect((result.initialDelay as HumanDuration).minutes).toEqual(20);
expect(result.scope).toBe('global');
});
@@ -51,7 +50,7 @@ describe('readSchedulerServiceTaskScheduleDefinitionFromConfig', () => {
const result = readSchedulerServiceTaskScheduleDefinitionFromConfig(config);
expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *');
- expect(result.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(result.timeout).toEqual({ minutes: 3 });
expect(result.initialDelay).toBeUndefined();
expect(result.scope).toBeUndefined();
});
diff --git a/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts b/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts
index 91edf27ad6..a7ec79a336 100644
--- a/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/SchedulerService.ts
@@ -348,14 +348,14 @@ export interface SchedulerService {
getScheduledTasks(): Promise;
}
-function readDuration(config: Config, key: string): Duration | HumanDuration {
+function readDuration(config: Config, key: string): HumanDuration {
if (typeof config.get(key) === 'string') {
const value = config.getString(key);
const duration = Duration.fromISO(value);
if (!duration.isValid) {
throw new Error(`Invalid duration: ${value}`);
}
- return duration;
+ return duration.toObject();
}
return readDurationFromConfig(config, { key });
@@ -364,7 +364,7 @@ function readDuration(config: Config, key: string): Duration | HumanDuration {
function readCronOrDuration(
config: Config,
key: string,
-): { cron: string } | Duration | HumanDuration {
+): { cron: string } | HumanDuration {
const value = config.get(key);
if (typeof value === 'object' && (value as { cron?: string }).cron) {
return value as { cron: string };
diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts
index c52d59b016..adeb134611 100644
--- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts
+++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.test.ts
@@ -16,7 +16,6 @@
import { ConfigReader } from '@backstage/config';
import { HumanDuration } from '@backstage/types';
-import { Duration } from 'luxon';
import { readTaskScheduleDefinitionFromConfig } from './readTaskScheduleDefinitionFromConfig';
describe('readTaskScheduleDefinitionFromConfig', () => {
@@ -35,7 +34,7 @@ describe('readTaskScheduleDefinitionFromConfig', () => {
const result = readTaskScheduleDefinitionFromConfig(config);
expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *');
- expect(result.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(result.timeout).toEqual({ minutes: 3 });
expect((result.initialDelay as HumanDuration).minutes).toEqual(20);
expect(result.scope).toBe('global');
});
@@ -51,7 +50,7 @@ describe('readTaskScheduleDefinitionFromConfig', () => {
const result = readTaskScheduleDefinitionFromConfig(config);
expect((result.frequency as { cron: string }).cron).toBe('0 30 * * * *');
- expect(result.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(result.timeout).toEqual({ minutes: 3 });
expect(result.initialDelay).toBeUndefined();
expect(result.scope).toBeUndefined();
});
diff --git a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts
index 5a173f246b..e94d06d5c3 100644
--- a/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts
+++ b/packages/backend-tasks/src/tasks/readTaskScheduleDefinitionFromConfig.ts
@@ -19,14 +19,14 @@ import { HumanDuration } from '@backstage/types';
import { TaskScheduleDefinition } from './types';
import { Duration } from 'luxon';
-function readDuration(config: Config, key: string): Duration | HumanDuration {
+function readDuration(config: Config, key: string): HumanDuration {
if (typeof config.get(key) === 'string') {
const value = config.getString(key);
const duration = Duration.fromISO(value);
if (!duration.isValid) {
throw new Error(`Invalid duration: ${value}`);
}
- return duration;
+ return duration.toObject();
}
return readDurationFromConfig(config, { key });
diff --git a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts
index 4addd1cb45..9165eb4322 100644
--- a/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts
+++ b/plugins/catalog-backend-module-aws/src/module/catalogModuleAwsS3EntityProvider.test.ts
@@ -17,7 +17,6 @@
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { catalogModuleAwsS3EntityProvider } from './catalogModuleAwsS3EntityProvider';
import { AwsS3EntityProvider } from '../providers';
@@ -62,8 +61,8 @@ describe('catalogModuleAwsS3EntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'awsS3-provider:default',
diff --git a/plugins/catalog-backend-module-aws/src/providers/config.test.ts b/plugins/catalog-backend-module-aws/src/providers/config.test.ts
index fb2f3c0790..4c7ec9a964 100644
--- a/plugins/catalog-backend-module-aws/src/providers/config.test.ts
+++ b/plugins/catalog-backend-module-aws/src/providers/config.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readAwsS3Configs } from './config';
describe('readAwsS3Configs', () => {
@@ -92,7 +91,7 @@ describe('readAwsS3Configs', () => {
id: 'provider4',
schedule: {
...provider4.schedule,
- frequency: Duration.fromISO(provider4.schedule.frequency),
+ frequency: { minutes: 30 },
},
});
});
diff --git a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts
index 2c674a8061..e406c61e07 100644
--- a/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-azure/src/module/catalogModuleAzureDevOpsEntityProvider.test.ts
@@ -17,7 +17,6 @@
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { catalogModuleAzureDevOpsEntityProvider } from './catalogModuleAzureDevOpsEntityProvider';
import { AzureDevOpsEntityProvider } from '../providers';
@@ -66,8 +65,8 @@ describe('catalogModuleAzureDevOpsEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'AzureDevOpsEntityProvider:test',
diff --git a/plugins/catalog-backend-module-azure/src/providers/config.test.ts b/plugins/catalog-backend-module-azure/src/providers/config.test.ts
index 02dbaab90e..5d5ae930c1 100644
--- a/plugins/catalog-backend-module-azure/src/providers/config.test.ts
+++ b/plugins/catalog-backend-module-azure/src/providers/config.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readAzureDevOpsConfigs } from './config';
describe('readAzureDevOpsConfigs', () => {
@@ -95,7 +94,7 @@ describe('readAzureDevOpsConfigs', () => {
id: 'provider4',
schedule: {
...provider4.schedule,
- frequency: Duration.fromISO(provider4.schedule.frequency),
+ frequency: { minutes: 30 },
},
});
expect(actual[4]).toEqual({
diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts
index db53b0b41b..bcf13e786d 100644
--- a/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-bitbucket-cloud/src/module/catalogModuleBitbucketCloudEntityProvider.test.ts
@@ -21,7 +21,6 @@ import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { TestEventsService } from '@backstage/plugin-events-backend-test-utils';
import { eventsServiceRef } from '@backstage/plugin-events-node';
-import { Duration } from 'luxon';
import { catalogModuleBitbucketCloudEntityProvider } from './catalogModuleBitbucketCloudEntityProvider';
import { BitbucketCloudEntityProvider } from '../providers/BitbucketCloudEntityProvider';
@@ -78,8 +77,8 @@ describe('catalogModuleBitbucketCloudEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(runner).not.toHaveBeenCalled();
const provider = addedProviders!.pop()!;
diff --git a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.test.ts b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.test.ts
index 5a2cc99437..7f13616586 100644
--- a/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.test.ts
+++ b/plugins/catalog-backend-module-bitbucket-cloud/src/providers/BitbucketCloudEntityProviderConfig.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readProviderConfigs } from './BitbucketCloudEntityProviderConfig';
describe('readProviderConfigs', () => {
@@ -130,7 +129,7 @@ describe('readProviderConfigs', () => {
repoSlug: undefined,
},
schedule: {
- frequency: Duration.fromISO('PT30M'),
+ frequency: { minutes: 30 },
timeout: {
minutes: 3,
},
diff --git a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts
index 56b44b29f5..5335b04e2d 100644
--- a/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-bitbucket-server/src/module/catalogModuleBitbucketServerEntityProvider.test.ts
@@ -18,7 +18,6 @@ import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { catalogModuleBitbucketServerEntityProvider } from './catalogModuleBitbucketServerEntityProvider';
-import { Duration } from 'luxon';
import { BitbucketServerEntityProvider } from '../providers';
describe('catalogModuleBitbucketServerEntityProvider', () => {
@@ -70,8 +69,8 @@ describe('catalogModuleBitbucketServerEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'bitbucketServer-provider:default',
diff --git a/plugins/catalog-backend-module-bitbucket-server/src/providers/BitbucketServerEntityProviderConfig.test.ts b/plugins/catalog-backend-module-bitbucket-server/src/providers/BitbucketServerEntityProviderConfig.test.ts
index 9e8aca5dd9..755fa4b58a 100644
--- a/plugins/catalog-backend-module-bitbucket-server/src/providers/BitbucketServerEntityProviderConfig.test.ts
+++ b/plugins/catalog-backend-module-bitbucket-server/src/providers/BitbucketServerEntityProviderConfig.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readProviderConfigs } from './BitbucketServerEntityProviderConfig';
describe('readProviderConfigs', () => {
@@ -111,7 +110,7 @@ describe('readProviderConfigs', () => {
skipArchivedRepos: undefined,
},
schedule: {
- frequency: Duration.fromISO('PT30M'),
+ frequency: { minutes: 30 },
timeout: {
minutes: 3,
},
diff --git a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts
index 66f0cbab2c..dc40e0525d 100644
--- a/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-gerrit/src/module/catalogModuleGerritEntityProvider.test.ts
@@ -17,7 +17,6 @@
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { catalogModuleGerritEntityProvider } from './catalogModuleGerritEntityProvider';
import { GerritEntityProvider } from '../providers/GerritEntityProvider';
@@ -76,8 +75,8 @@ describe('catalogModuleGerritEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'gerrit-provider:test',
diff --git a/plugins/catalog-backend-module-gerrit/src/providers/config.test.ts b/plugins/catalog-backend-module-gerrit/src/providers/config.test.ts
index ecf68d9f3c..85ab3383f0 100644
--- a/plugins/catalog-backend-module-gerrit/src/providers/config.test.ts
+++ b/plugins/catalog-backend-module-gerrit/src/providers/config.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readGerritConfigs } from './config';
describe('readGerritConfigs', () => {
@@ -63,7 +62,7 @@ describe('readGerritConfigs', () => {
id: 'active-g3',
schedule: {
...provider3.schedule,
- frequency: Duration.fromISO(provider3.schedule.frequency),
+ frequency: { minutes: 30 },
},
});
});
diff --git a/plugins/catalog-backend-module-github-org/src/module.test.ts b/plugins/catalog-backend-module-github-org/src/module.test.ts
index 6e03d8d9cc..76ab4d1fbc 100644
--- a/plugins/catalog-backend-module-github-org/src/module.test.ts
+++ b/plugins/catalog-backend-module-github-org/src/module.test.ts
@@ -18,7 +18,6 @@ import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { EntityProvider } from '@backstage/plugin-catalog-node';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { catalogModuleGithubOrgEntityProvider } from './module';
describe('catalogModuleGithubOrgEntityProvider', () => {
@@ -66,8 +65,8 @@ describe('catalogModuleGithubOrgEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders![0].getProviderName()).toEqual(
'GithubMultiOrgEntityProvider:default',
diff --git a/plugins/catalog-backend-module-github/src/module/githubCatalogModule.test.ts b/plugins/catalog-backend-module-github/src/module/githubCatalogModule.test.ts
index 59f8b41a6d..018d339de8 100644
--- a/plugins/catalog-backend-module-github/src/module/githubCatalogModule.test.ts
+++ b/plugins/catalog-backend-module-github/src/module/githubCatalogModule.test.ts
@@ -21,7 +21,6 @@ import {
catalogAnalysisExtensionPoint,
catalogProcessingExtensionPoint,
} from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { githubCatalogModule } from './githubCatalogModule';
import { GithubLocationAnalyzer } from '../analyzers/GithubLocationAnalyzer';
@@ -75,8 +74,8 @@ describe('githubCatalogModule', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'github-provider:default',
diff --git a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts
index c83bfe5db1..296cbc12df 100644
--- a/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts
+++ b/plugins/catalog-backend-module-github/src/providers/GithubEntityProviderConfig.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readProviderConfigs } from './GithubEntityProviderConfig';
describe('readProviderConfigs', () => {
@@ -270,7 +269,7 @@ describe('readProviderConfigs', () => {
visibility: undefined,
},
schedule: {
- frequency: Duration.fromISO('PT30M'),
+ frequency: { minutes: 30 },
timeout: {
minutes: 3,
},
diff --git a/plugins/catalog-backend-module-gitlab-org/src/catalogModuleGitlabOrgDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab-org/src/catalogModuleGitlabOrgDiscoveryEntityProvider.test.ts
index 1078936950..5fbc321cc2 100644
--- a/plugins/catalog-backend-module-gitlab-org/src/catalogModuleGitlabOrgDiscoveryEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-gitlab-org/src/catalogModuleGitlabOrgDiscoveryEntityProvider.test.ts
@@ -22,7 +22,6 @@ import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { TestEventsService } from '@backstage/plugin-events-backend-test-utils';
import { eventsServiceRef } from '@backstage/plugin-events-node';
-import { Duration } from 'luxon';
import { catalogModuleGitlabOrgDiscoveryEntityProvider } from './catalogModuleGitlabOrgDiscoveryEntityProvider';
describe('catalogModuleGitlabOrgDiscoveryEntityProvider', () => {
@@ -90,8 +89,8 @@ describe('catalogModuleGitlabOrgDiscoveryEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(runner).not.toHaveBeenCalled();
diff --git a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts
index e4cff56bbd..636405220b 100644
--- a/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-gitlab/src/module/catalogModuleGitlabDiscoveryEntityProvider.test.ts
@@ -21,7 +21,6 @@ import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
import { TestEventsService } from '@backstage/plugin-events-backend-test-utils';
import { eventsServiceRef } from '@backstage/plugin-events-node';
-import { Duration } from 'luxon';
import { GitlabDiscoveryEntityProvider } from '../providers';
import { catalogModuleGitlabDiscoveryEntityProvider } from './catalogModuleGitlabDiscoveryEntityProvider';
@@ -89,8 +88,8 @@ describe('catalogModuleGitlabDiscoveryEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('P1M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ months: 1 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(runner).not.toHaveBeenCalled();
diff --git a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts
index 09b42e6475..a5c3ab2b28 100644
--- a/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts
+++ b/plugins/catalog-backend-module-gitlab/src/providers/config.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readGitlabConfigs } from './config';
describe('config', () => {
@@ -179,7 +178,7 @@ describe('config', () => {
allowInherited: false,
skipForkedRepos: false,
schedule: {
- frequency: Duration.fromISO('PT30M'),
+ frequency: { minutes: 30 },
timeout: {
minutes: 3,
},
diff --git a/plugins/catalog-backend-module-ldap/api-report.md b/plugins/catalog-backend-module-ldap/api-report.md
index 84de581387..de245b8cd6 100644
--- a/plugins/catalog-backend-module-ldap/api-report.md
+++ b/plugins/catalog-backend-module-ldap/api-report.md
@@ -16,11 +16,11 @@ import { GroupTransformer as GroupTransformer_2 } from '@backstage/plugin-catalo
import { JsonValue } from '@backstage/types';
import { LocationSpec } from '@backstage/plugin-catalog-common';
import { LoggerService } from '@backstage/backend-plugin-api';
-import { PluginTaskScheduler } from '@backstage/backend-tasks';
+import { SchedulerService } from '@backstage/backend-plugin-api';
+import { SchedulerServiceTaskRunner } from '@backstage/backend-plugin-api';
+import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api';
import { SearchEntry } from 'ldapjs';
import { SearchOptions } from 'ldapjs';
-import { TaskRunner } from '@backstage/backend-tasks';
-import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { UserEntity } from '@backstage/catalog-model';
import { UserTransformer as UserTransformer_2 } from '@backstage/plugin-catalog-backend-module-ldap';
@@ -135,7 +135,7 @@ export interface LdapOrgEntityProviderLegacyOptions {
groupTransformer?: GroupTransformer;
id: string;
logger: LoggerService;
- schedule: 'manual' | TaskRunner;
+ schedule: 'manual' | SchedulerServiceTaskRunner;
target: string;
userTransformer?: UserTransformer;
}
@@ -145,8 +145,8 @@ export type LdapOrgEntityProviderOptions =
| LdapOrgEntityProviderLegacyOptions
| {
logger: LoggerService;
- schedule?: 'manual' | TaskRunner;
- scheduler?: PluginTaskScheduler;
+ schedule?: 'manual' | SchedulerServiceTaskRunner;
+ scheduler?: SchedulerService;
userTransformer?: UserTransformer | Record;
groupTransformer?: GroupTransformer | Record;
};
@@ -199,7 +199,7 @@ export type LdapProviderConfig = {
bind?: BindConfig;
users: UserConfig;
groups: GroupConfig;
- schedule?: TaskScheduleDefinition;
+ schedule?: SchedulerServiceTaskScheduleDefinition;
};
// @public
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
index ddea9de03f..4edfaeebea 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/config.test.ts
@@ -79,6 +79,75 @@ describe('readLdapConfig', () => {
expect(actual).toEqual(expected);
});
+ it('reads schedules well', () => {
+ const config = {
+ catalog: {
+ providers: {
+ ldapOrg: {
+ default: {
+ schedule: {
+ frequency: 'PT3M', // should work for ISO durations
+ timeout: { minutes: 1 },
+ },
+ target: 'target',
+ users: {
+ dn: 'udn',
+ },
+ groups: {
+ dn: 'gdn',
+ },
+ },
+ },
+ },
+ },
+ };
+ const actual = readProviderConfigs(new ConfigReader(config));
+ const expected = [
+ {
+ id: 'default',
+ target: 'target',
+ bind: undefined,
+ schedule: {
+ frequency: { minutes: 3 },
+ timeout: { minutes: 1 },
+ },
+ users: {
+ dn: 'udn',
+ options: {
+ scope: 'one',
+ attributes: ['*', '+'],
+ },
+ set: undefined,
+ map: {
+ rdn: 'uid',
+ name: 'uid',
+ displayName: 'cn',
+ email: 'mail',
+ memberOf: 'memberOf',
+ },
+ },
+ groups: {
+ dn: 'gdn',
+ options: {
+ scope: 'one',
+ attributes: ['*', '+'],
+ },
+ set: undefined,
+ map: {
+ rdn: 'cn',
+ name: 'cn',
+ description: 'description',
+ type: 'groupType',
+ displayName: 'cn',
+ memberOf: 'memberOf',
+ members: 'member',
+ },
+ },
+ },
+ ];
+ expect(actual).toEqual(expected);
+ });
+
it('reads all the values', () => {
const config = {
catalog: {
diff --git a/plugins/catalog-backend-module-ldap/src/ldap/config.ts b/plugins/catalog-backend-module-ldap/src/ldap/config.ts
index 2bd21fd166..7c4795fc46 100644
--- a/plugins/catalog-backend-module-ldap/src/ldap/config.ts
+++ b/plugins/catalog-backend-module-ldap/src/ldap/config.ts
@@ -15,9 +15,9 @@
*/
import {
- readTaskScheduleDefinitionFromConfig,
- TaskScheduleDefinition,
-} from '@backstage/backend-tasks';
+ SchedulerServiceTaskScheduleDefinition,
+ readSchedulerServiceTaskScheduleDefinitionFromConfig,
+} from '@backstage/backend-plugin-api';
import { Config } from '@backstage/config';
import { JsonValue } from '@backstage/types';
import { SearchOptions } from 'ldapjs';
@@ -46,7 +46,7 @@ export type LdapProviderConfig = {
// The settings that govern the reading and interpretation of groups
groups: GroupConfig;
// Schedule configuration for refresh tasks.
- schedule?: TaskScheduleDefinition;
+ schedule?: SchedulerServiceTaskScheduleDefinition;
};
/**
@@ -380,7 +380,9 @@ export function readProviderConfigs(config: Config): LdapProviderConfig[] {
const c = providersConfig.getConfig(id);
const schedule = c.has('schedule')
- ? readTaskScheduleDefinitionFromConfig(c.getConfig('schedule'))
+ ? readSchedulerServiceTaskScheduleDefinitionFromConfig(
+ c.getConfig('schedule'),
+ )
: undefined;
const newConfig = {
diff --git a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
index fb8f27d685..0e5fae55bb 100644
--- a/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
+++ b/plugins/catalog-backend-module-ldap/src/processors/LdapOrgEntityProvider.ts
@@ -14,7 +14,6 @@
* limitations under the License.
*/
-import { PluginTaskScheduler, TaskRunner } from '@backstage/backend-tasks';
import {
ANNOTATION_LOCATION,
ANNOTATION_ORIGIN_LOCATION,
@@ -35,7 +34,11 @@ import {
readLdapOrg,
UserTransformer,
} from '../ldap';
-import { LoggerService } from '@backstage/backend-plugin-api';
+import {
+ LoggerService,
+ SchedulerService,
+ SchedulerServiceTaskRunner,
+} from '@backstage/backend-plugin-api';
import { readLdapLegacyConfig, readProviderConfigs } from '../ldap';
/**
@@ -60,16 +63,16 @@ export type LdapOrgEntityProviderOptions =
* manually at some interval.
*
* But more commonly you will pass in the result of
- * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}
+ * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}
* to enable automatic scheduling of tasks.
*/
- schedule?: 'manual' | TaskRunner;
+ schedule?: 'manual' | SchedulerServiceTaskRunner;
/**
* Scheduler used to schedule refreshes based on
* the schedule config.
*/
- scheduler?: PluginTaskScheduler;
+ scheduler?: SchedulerService;
/**
* The function that transforms a user entry in msgraph to an entity.
@@ -122,10 +125,10 @@ export interface LdapOrgEntityProviderLegacyOptions {
* manually at some interval.
*
* But more commonly you will pass in the result of
- * {@link @backstage/backend-tasks#PluginTaskScheduler.createScheduledTaskRunner}
+ * {@link @backstage/backend-plugin-api#SchedulerService.createScheduledTaskRunner}
* to enable automatic scheduling of tasks.
*/
- schedule: 'manual' | TaskRunner;
+ schedule: 'manual' | SchedulerServiceTaskRunner;
/**
* The function that transforms a user entry in LDAP to an entity.
@@ -311,7 +314,7 @@ export class LdapOrgEntityProvider implements EntityProvider {
markCommitComplete();
}
- private schedule(taskRunner: TaskRunner) {
+ private schedule(taskRunner: SchedulerServiceTaskRunner) {
this.scheduleFn = async () => {
const id = `${this.getProviderName()}:refresh`;
await taskRunner.run({
diff --git a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts
index b02894dfd9..c0e9f61f29 100644
--- a/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts
+++ b/plugins/catalog-backend-module-msgraph/src/microsoftGraph/config.test.ts
@@ -15,7 +15,6 @@
*/
import { ConfigReader } from '@backstage/config';
-import { Duration } from 'luxon';
import { readMicrosoftGraphConfig, readProviderConfigs } from './config';
describe('readMicrosoftGraphConfig', () => {
@@ -204,7 +203,7 @@ describe('readProviderConfigs', () => {
groupSelect: ['id', 'displayName', 'description'],
groupFilter: 'securityEnabled eq false',
schedule: {
- frequency: Duration.fromISO('PT30M'),
+ frequency: { minutes: 30 },
timeout: {
minutes: 3,
},
diff --git a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts
index 5742fbbc6c..2a3e66a9b3 100644
--- a/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts
+++ b/plugins/catalog-backend-module-msgraph/src/module/catalogModuleMicrosoftGraphOrgEntityProvider.test.ts
@@ -17,7 +17,6 @@
import { TaskScheduleDefinition } from '@backstage/backend-tasks';
import { mockServices, startTestBackend } from '@backstage/backend-test-utils';
import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha';
-import { Duration } from 'luxon';
import { catalogModuleMicrosoftGraphOrgEntityProvider } from './catalogModuleMicrosoftGraphOrgEntityProvider';
import { MicrosoftGraphOrgEntityProvider } from '../processors';
@@ -67,8 +66,8 @@ describe('catalogModuleMicrosoftGraphOrgEntityProvider', () => {
],
});
- expect(usedSchedule?.frequency).toEqual(Duration.fromISO('PT30M'));
- expect(usedSchedule?.timeout).toEqual(Duration.fromISO('PT3M'));
+ expect(usedSchedule?.frequency).toEqual({ minutes: 30 });
+ expect(usedSchedule?.timeout).toEqual({ minutes: 3 });
expect(addedProviders?.length).toEqual(1);
expect(addedProviders?.pop()?.getProviderName()).toEqual(
'MicrosoftGraphOrgEntityProvider:customProviderId',
diff --git a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProviderConfig.test.ts b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProviderConfig.test.ts
index 8da0fb4150..86335cb97d 100644
--- a/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProviderConfig.test.ts
+++ b/plugins/catalog-backend-module-puppetdb/src/providers/PuppetDbEntityProviderConfig.test.ts
@@ -16,7 +16,6 @@
import { ConfigReader } from '@backstage/config';
import { readProviderConfigs } from './PuppetDbEntityProviderConfig';
-import { Duration } from 'luxon';
describe('readProviderConfigs', () => {
afterEach(() => jest.resetAllMocks());
@@ -120,10 +119,8 @@ describe('readProviderConfigs', () => {
expect(providerConfigs).toHaveLength(1);
expect(providerConfigs[0].schedule).toEqual({
- frequency: Duration.fromISO('PT30M'),
- timeout: {
- minutes: 10,
- },
+ frequency: { minutes: 30 },
+ timeout: { minutes: 10 },
});
});
});
From dcacad5d81c4bae38aab028006ad1fd1f315d2e2 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Thu, 6 Jun 2024 20:15:46 -0400
Subject: [PATCH 09/63] docs: update catalog error eventing/logging
Signed-off-by: Christopher Diaz
---
.../software-catalog/life-of-an-entity.md | 124 +++++++++++++++++-
1 file changed, 120 insertions(+), 4 deletions(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 13fe496fc1..9c45bec814 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -197,13 +197,15 @@ cannot be parsed successfully, etc.
There are two main ways that these errors are surfaced.
-First, the catalog backend will produce detailed logs that should contain
-sufficient information for a reader to find the causes for errors. Since these
-logs are typically not easily found by end users, this can mainly be a useful
+First, the catalog backend will emit [events](https://github.com/backstage/backstage/tree/master/plugins/events-node) you can subscribe to that should contain
+sufficient information for a reader to find the causes for errors.
+Since these events are typically not easily found by end users, this can mainly be a useful
tool for Backstage operators who want to debug problems either with statically
registered entities that are under their control, or to help end users find
problems.
+> Prior to Backstage version v1.26.0 and `@backstage/plugin-catalog-backend` v1.21.9 catalog errors were logged by default. See the docs below on how to enable these logs and an example on how you can further customize how you ingest these errors.
+
Second, for most classes of errors, the entity itself will contain a status
field that describes the problem. The contents of this field is shown at the top
of your entity page in Backstage, if you have placed the corresponding error
@@ -212,6 +214,118 @@ callout component (`EntityProcessingErrorsPanel`) there.
We are still working to improve the surfacing and observability around
processing loop errors.
+### Subscribing to Catalog Errors
+
+Errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
+
+#### New Backend System
+
+Make sure you have the events plugin installed.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-events-backend/alpha'));
+```
+
+Create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
+
+```ts title="packages/backend/src/index.ts"
+import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
+import {
+ coreServices,
+ createBackendModule,
+} from '@backstage/backend-plugin-api';
+import { eventsServiceRef, EventParams } from '@backstage/plugin-events-node';
+
+interface EventsPayload {
+ entity: string;
+ location?: string;
+ errors: Error[];
+}
+
+interface EventsParamsWithPayload extends EventParams {
+ eventPayload: EventsPayload;
+}
+
+const eventsModuleCatalogErrors = createBackendModule({
+ pluginId: 'events',
+ moduleId: 'catalog-errors',
+ register(env) {
+ env.registerInit({
+ deps: {
+ events: eventsServiceRef,
+ logger: coreServices.logger,
+ },
+ async init({ events, logger }) {
+ events.subscribe({
+ id: 'catalog',
+ topics: [CATALOG_ERRORS_TOPIC],
+ async onEvent(params: EventParams): Promise {
+ const event = params as EventsParamsWithPayload;
+ const { entity, location, errors } = event.eventPayload;
+ for (const error of errors) {
+ logger.warn(error.message, {
+ entity,
+ location,
+ });
+ }
+ },
+ });
+ },
+ });
+ },
+});
+```
+
+Now install your module.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(eventsModuleCatalogErrors);
+```
+
+You should now see logs as the catalog emits events.
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
+
+#### Legacy Backend
+
+Make sure you have the events plugin installed. See the legacy backend instructions [here](https://github.com/backstage/backstage/tree/master/plugins/events-node#legacy-backend-system).
+
+Subscribe to the events using the `eventBroker` set in the environment.
+
+```ts
+import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
+
+env.eventBroker.subscribe({
+ supportsEventTopics(): string[] {
+ return [CATALOG_ERRORS_TOPIC];
+ },
+
+ async onEvent(
+ params: EventParams<{
+ entity: string;
+ location?: string;
+ errors: Array;
+ }>,
+ ): Promise {
+ const { entity, location, errors } = params.eventPayload;
+ for (const error of errors) {
+ env.logger.warn(error.message, {
+ entity,
+ location,
+ });
+ }
+ },
+});
+```
+
+You should now see logs as the catalog emits events.
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
+
## Orphaning
As mentioned earlier, entities internally form a graph. The edges go from
@@ -268,8 +382,10 @@ However, if you want to delete orphaned entities automatically anyway, you can
enable the automated clean up with the following app-config option.
```
+
catalog:
- orphanStrategy: delete
+orphanStrategy: delete
+
```
## Implicit Deletion
From 9809a3aadd232b5c74dc42871917ca48cd7e8cc4 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Thu, 6 Jun 2024 20:28:19 -0400
Subject: [PATCH 10/63] fix formatting
Signed-off-by: Christopher Diaz
---
docs/features/software-catalog/life-of-an-entity.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 9c45bec814..3db33bf42b 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -384,7 +384,7 @@ enable the automated clean up with the following app-config option.
```
catalog:
-orphanStrategy: delete
+ orphanStrategy: delete
```
From 12694f9a55b2550ed65d9d897067e843ecac80da Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Thu, 6 Jun 2024 20:28:39 -0400
Subject: [PATCH 11/63] fix formatting
Signed-off-by: Christopher Diaz
---
docs/features/software-catalog/life-of-an-entity.md | 2 --
1 file changed, 2 deletions(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 3db33bf42b..6dfb656c4b 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -382,10 +382,8 @@ However, if you want to delete orphaned entities automatically anyway, you can
enable the automated clean up with the following app-config option.
```
-
catalog:
orphanStrategy: delete
-
```
## Implicit Deletion
From e2de06cf344ab9739a4e047b7df5f5a15f85e8b0 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Thu, 6 Jun 2024 20:29:45 -0400
Subject: [PATCH 12/63] specify the log is an example
Signed-off-by: Christopher Diaz
---
docs/features/software-catalog/life-of-an-entity.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 6dfb656c4b..017b5322be 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -282,7 +282,7 @@ Now install your module.
backend.add(eventsModuleCatalogErrors);
```
-You should now see logs as the catalog emits events.
+You should now see logs as the catalog emits events. Example:
```
[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
@@ -320,7 +320,7 @@ env.eventBroker.subscribe({
});
```
-You should now see logs as the catalog emits events.
+You should now see logs as the catalog emits events. Example:
```
[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
From 6dbe3921ca0fc383f32893f017840c24593c5942 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 11:17:10 -0400
Subject: [PATCH 13/63] update docs
Signed-off-by: Christopher Diaz
---
.../software-catalog/configuration.md | 79 ++++++++++++
.../software-catalog/life-of-an-entity.md | 116 +-----------------
2 files changed, 81 insertions(+), 114 deletions(-)
diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md
index 61366a91f7..54a2b99faf 100644
--- a/docs/features/software-catalog/configuration.md
+++ b/docs/features/software-catalog/configuration.md
@@ -177,3 +177,82 @@ here.
Setting this value too low risks exhausting rate limits on external systems that
are queried by processors, such as version control systems housing catalog-info
files.
+
+## Subscribing to Catalog Errors
+
+Catalog errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
+
+The first step is to add the events backend plugin to your Backstage application. Navigate to your Backstage application directory and add the plugin package.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-events-node
+```
+
+Now you can install the events backend plugin in your backend.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-events-backend/alpha'));
+```
+
+Next, create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
+
+```ts title="packages/backend/src/index.ts"
+import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
+import {
+ coreServices,
+ createBackendModule,
+} from '@backstage/backend-plugin-api';
+import { eventsServiceRef, EventParams } from '@backstage/plugin-events-node';
+
+interface EventsPayload {
+ entity: string;
+ location?: string;
+ errors: Error[];
+}
+
+interface EventsParamsWithPayload extends EventParams {
+ eventPayload: EventsPayload;
+}
+
+const eventsModuleCatalogErrors = createBackendModule({
+ pluginId: 'events',
+ moduleId: 'catalog-errors',
+ register(env) {
+ env.registerInit({
+ deps: {
+ events: eventsServiceRef,
+ logger: coreServices.logger,
+ },
+ async init({ events, logger }) {
+ events.subscribe({
+ id: 'catalog',
+ topics: [CATALOG_ERRORS_TOPIC],
+ async onEvent(params: EventParams): Promise {
+ const event = params as EventsParamsWithPayload;
+ const { entity, location, errors } = event.eventPayload;
+ for (const error of errors) {
+ logger.warn(error.message, {
+ entity,
+ location,
+ });
+ }
+ },
+ });
+ },
+ });
+ },
+});
+```
+
+Now install your module.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(eventsModuleCatalogErrors);
+```
+
+You should now see logs as the catalog emits events. Example:
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 017b5322be..029778510a 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -197,8 +197,8 @@ cannot be parsed successfully, etc.
There are two main ways that these errors are surfaced.
-First, the catalog backend will emit [events](https://github.com/backstage/backstage/tree/master/plugins/events-node) you can subscribe to that should contain
-sufficient information for a reader to find the causes for errors.
+First, the catalog backend will emit events using the [events backend plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node). You can subscribe to the events. The events should contain
+sufficient information for a reader to find the causes for errors. See the configuration documentation [here](./configuration.md#subscribing-to-catalog-errors) for how to subscribe and log these error events.
Since these events are typically not easily found by end users, this can mainly be a useful
tool for Backstage operators who want to debug problems either with statically
registered entities that are under their control, or to help end users find
@@ -214,118 +214,6 @@ callout component (`EntityProcessingErrorsPanel`) there.
We are still working to improve the surfacing and observability around
processing loop errors.
-### Subscribing to Catalog Errors
-
-Errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
-
-#### New Backend System
-
-Make sure you have the events plugin installed.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(import('@backstage/plugin-events-backend/alpha'));
-```
-
-Create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
-
-```ts title="packages/backend/src/index.ts"
-import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
-import {
- coreServices,
- createBackendModule,
-} from '@backstage/backend-plugin-api';
-import { eventsServiceRef, EventParams } from '@backstage/plugin-events-node';
-
-interface EventsPayload {
- entity: string;
- location?: string;
- errors: Error[];
-}
-
-interface EventsParamsWithPayload extends EventParams {
- eventPayload: EventsPayload;
-}
-
-const eventsModuleCatalogErrors = createBackendModule({
- pluginId: 'events',
- moduleId: 'catalog-errors',
- register(env) {
- env.registerInit({
- deps: {
- events: eventsServiceRef,
- logger: coreServices.logger,
- },
- async init({ events, logger }) {
- events.subscribe({
- id: 'catalog',
- topics: [CATALOG_ERRORS_TOPIC],
- async onEvent(params: EventParams): Promise {
- const event = params as EventsParamsWithPayload;
- const { entity, location, errors } = event.eventPayload;
- for (const error of errors) {
- logger.warn(error.message, {
- entity,
- location,
- });
- }
- },
- });
- },
- });
- },
-});
-```
-
-Now install your module.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(eventsModuleCatalogErrors);
-```
-
-You should now see logs as the catalog emits events. Example:
-
-```
-[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
-```
-
-#### Legacy Backend
-
-Make sure you have the events plugin installed. See the legacy backend instructions [here](https://github.com/backstage/backstage/tree/master/plugins/events-node#legacy-backend-system).
-
-Subscribe to the events using the `eventBroker` set in the environment.
-
-```ts
-import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
-
-env.eventBroker.subscribe({
- supportsEventTopics(): string[] {
- return [CATALOG_ERRORS_TOPIC];
- },
-
- async onEvent(
- params: EventParams<{
- entity: string;
- location?: string;
- errors: Array;
- }>,
- ): Promise {
- const { entity, location, errors } = params.eventPayload;
- for (const error of errors) {
- env.logger.warn(error.message, {
- entity,
- location,
- });
- }
- },
-});
-```
-
-You should now see logs as the catalog emits events. Example:
-
-```
-[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
-```
-
## Orphaning
As mentioned earlier, entities internally form a graph. The edges go from
From 21bef93e3535d310abea47bd1173e6ba0a0d4539 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 11:52:48 -0400
Subject: [PATCH 14/63] add logging module to make this easier for users but
retain custom docs
Signed-off-by: Christopher Diaz
---
.../software-catalog/configuration.md | 29 ++++++---
.../catalog-backend-module-logs/.eslintrc.js | 1 +
plugins/catalog-backend-module-logs/README.md | 30 +++++++++
.../catalog-info.yaml | 10 +++
.../catalog-backend-module-logs/package.json | 39 ++++++++++++
.../catalog-backend-module-logs/src/index.ts | 23 +++++++
.../catalog-backend-module-logs/src/module.ts | 61 +++++++++++++++++++
yarn.lock | 13 ++++
8 files changed, 199 insertions(+), 7 deletions(-)
create mode 100644 plugins/catalog-backend-module-logs/.eslintrc.js
create mode 100644 plugins/catalog-backend-module-logs/README.md
create mode 100644 plugins/catalog-backend-module-logs/catalog-info.yaml
create mode 100644 plugins/catalog-backend-module-logs/package.json
create mode 100644 plugins/catalog-backend-module-logs/src/index.ts
create mode 100644 plugins/catalog-backend-module-logs/src/module.ts
diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md
index 54a2b99faf..4bab2313b8 100644
--- a/docs/features/software-catalog/configuration.md
+++ b/docs/features/software-catalog/configuration.md
@@ -195,7 +195,27 @@ Now you can install the events backend plugin in your backend.
backend.add(import('@backstage/plugin-events-backend/alpha'));
```
-Next, create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
+### Logging Errors
+
+If you want to log catalog errors you can install the `@backstage/plugin-catalog-backend-module-logs` module.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
+```
+
+This will log errors with a level of `warn`.
+
+You should now see logs as the catalog emits events. Example:
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
+
+### Custom Error Handling
+
+If you wish to handle catalog errors with logic the following should help you get started.
+
+Create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
```ts title="packages/backend/src/index.ts"
import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
@@ -231,6 +251,7 @@ const eventsModuleCatalogErrors = createBackendModule({
async onEvent(params: EventParams): Promise {
const event = params as EventsParamsWithPayload;
const { entity, location, errors } = event.eventPayload;
+ // Add custom logic here for responding to errors
for (const error of errors) {
logger.warn(error.message, {
entity,
@@ -250,9 +271,3 @@ Now install your module.
```ts title="packages/backend/src/index.ts"
backend.add(eventsModuleCatalogErrors);
```
-
-You should now see logs as the catalog emits events. Example:
-
-```
-[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
-```
diff --git a/plugins/catalog-backend-module-logs/.eslintrc.js b/plugins/catalog-backend-module-logs/.eslintrc.js
new file mode 100644
index 0000000000..e2a53a6ad2
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/.eslintrc.js
@@ -0,0 +1 @@
+module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
diff --git a/plugins/catalog-backend-module-logs/README.md b/plugins/catalog-backend-module-logs/README.md
new file mode 100644
index 0000000000..6c84114306
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/README.md
@@ -0,0 +1,30 @@
+# backstage-plugin-catalog-backend-module-logs
+
+A module that subscribes to catalog related events and logs them.
+
+Catalog errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
+
+The first step is to add the events backend plugin to your Backstage application. Navigate to your Backstage application directory and add the plugin package.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-events-node
+```
+
+Now you can install the events backend plugin in your backend.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-events-backend/alpha'));
+```
+
+Now install the catalog logs module.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
+```
+
+You should now see logs as the catalog emits events. Example:
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
diff --git a/plugins/catalog-backend-module-logs/catalog-info.yaml b/plugins/catalog-backend-module-logs/catalog-info.yaml
new file mode 100644
index 0000000000..f2223174c3
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/catalog-info.yaml
@@ -0,0 +1,10 @@
+apiVersion: backstage.io/v1alpha1
+kind: Component
+metadata:
+ name: backstage-plugin-catalog-backend-module-logs
+ title: '@backstage/plugin-catalog-backend-module-logs'
+ description: A module that subscribes to catalog releated events and logs them.
+spec:
+ lifecycle: experimental
+ type: backstage-backend-plugin-module
+ owner: maintainers
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
new file mode 100644
index 0000000000..f35a8b7816
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -0,0 +1,39 @@
+{
+ "name": "@backstage/plugin-catalog-backend-module-logs",
+ "description": "A module that subscribes to catalog releated events and logs them.",
+ "version": "0.0.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "private": true,
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.cjs.js",
+ "types": "dist/index.d.ts"
+ },
+ "backstage": {
+ "role": "backend-plugin-module"
+ },
+ "scripts": {
+ "start": "backstage-cli package start",
+ "build": "backstage-cli package build",
+ "lint": "backstage-cli package lint",
+ "test": "backstage-cli package test",
+ "clean": "backstage-cli package clean",
+ "prepack": "backstage-cli package prepack",
+ "postpack": "backstage-cli package postpack"
+ },
+ "dependencies": {
+ "@backstage/backend-common": "workspace:^",
+ "@backstage/backend-plugin-api": "workspace:^",
+ "@backstage/plugin-catalog-backend": "workspace:^",
+ "@backstage/plugin-events-node": "workspace:^"
+ },
+ "devDependencies": {
+ "@backstage/backend-test-utils": "workspace:^",
+ "@backstage/cli": "workspace:^"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/catalog-backend-module-logs/src/index.ts b/plugins/catalog-backend-module-logs/src/index.ts
new file mode 100644
index 0000000000..3d5f606d27
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/src/index.ts
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+
+/**
+ * The logs backend module for the catalog plugin.
+ *
+ * @packageDocumentation
+ */
+
+export { catalogModuleLogs as default } from './module';
diff --git a/plugins/catalog-backend-module-logs/src/module.ts b/plugins/catalog-backend-module-logs/src/module.ts
new file mode 100644
index 0000000000..0f41d2e1a6
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/src/module.ts
@@ -0,0 +1,61 @@
+/*
+ * 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 {
+ coreServices,
+ createBackendModule,
+} from '@backstage/backend-plugin-api';
+import { CATALOG_ERRORS_TOPIC } from '@backstage/plugin-catalog-backend';
+import { eventsServiceRef, EventParams } from '@backstage/plugin-events-node';
+
+interface EventsPayload {
+ entity: string;
+ location?: string;
+ errors: Error[];
+}
+
+interface EventsParamsWithPayload extends EventParams {
+ eventPayload: EventsPayload;
+}
+
+export const catalogModuleLogs = createBackendModule({
+ pluginId: 'catalog',
+ moduleId: 'logs',
+ register(env) {
+ env.registerInit({
+ deps: {
+ events: eventsServiceRef,
+ logger: coreServices.logger,
+ },
+ async init({ events, logger }) {
+ events.subscribe({
+ id: 'catalog',
+ topics: [CATALOG_ERRORS_TOPIC],
+ async onEvent(params: EventParams): Promise {
+ const event = params as EventsParamsWithPayload;
+ const { entity, location, errors } = event.eventPayload;
+ for (const error of errors) {
+ logger.warn(error.message, {
+ entity,
+ location,
+ });
+ }
+ },
+ });
+ },
+ });
+ },
+});
diff --git a/yarn.lock b/yarn.lock
index a0a385ca66..542d9242da 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5440,6 +5440,19 @@ __metadata:
languageName: unknown
linkType: soft
+"@backstage/plugin-catalog-backend-module-logs@workspace:plugins/catalog-backend-module-logs":
+ version: 0.0.0-use.local
+ resolution: "@backstage/plugin-catalog-backend-module-logs@workspace:plugins/catalog-backend-module-logs"
+ dependencies:
+ "@backstage/backend-common": "workspace:^"
+ "@backstage/backend-plugin-api": "workspace:^"
+ "@backstage/backend-test-utils": "workspace:^"
+ "@backstage/cli": "workspace:^"
+ "@backstage/plugin-catalog-backend": "workspace:^"
+ "@backstage/plugin-events-node": "workspace:^"
+ languageName: unknown
+ linkType: soft
+
"@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph":
version: 0.0.0-use.local
resolution: "@backstage/plugin-catalog-backend-module-msgraph@workspace:plugins/catalog-backend-module-msgraph"
From 97caf558236a4d2d9ac8029a186607cb9deddd4c Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 11:56:36 -0400
Subject: [PATCH 15/63] add logging module to make this easier for users but
retain custom docs
Signed-off-by: Christopher Diaz
---
.changeset/ten-pots-walk.md | 39 +++++++++++++++++++
.../software-catalog/configuration.md | 9 +++++
plugins/catalog-backend-module-logs/README.md | 9 +++++
3 files changed, 57 insertions(+)
create mode 100644 .changeset/ten-pots-walk.md
diff --git a/.changeset/ten-pots-walk.md b/.changeset/ten-pots-walk.md
new file mode 100644
index 0000000000..6265e8dd7f
--- /dev/null
+++ b/.changeset/ten-pots-walk.md
@@ -0,0 +1,39 @@
+---
+'@backstage/plugin-catalog-backend-module-logs': patch
+---
+
+Creates a new module to make logging catalog errors simple. This module subscribes to catalog events and logs them.
+
+Catalog errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
+
+The first step is to add the events backend plugin to your Backstage application. Navigate to your Backstage application directory and add the plugin package.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-events-node
+```
+
+Now you can install the events backend plugin in your backend.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-events-backend/alpha'));
+```
+
+Install the catalog logs module.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
+```
+
+Now install the catalog logs module.
+
+```ts title="packages/backend/src/index.ts"
+backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
+```
+
+You should now see logs as the catalog emits events. Example:
+
+```
+[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
+```
diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md
index 4bab2313b8..9805eb06dd 100644
--- a/docs/features/software-catalog/configuration.md
+++ b/docs/features/software-catalog/configuration.md
@@ -199,6 +199,15 @@ backend.add(import('@backstage/plugin-events-backend/alpha'));
If you want to log catalog errors you can install the `@backstage/plugin-catalog-backend-module-logs` module.
+Install the catalog logs module.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
+```
+
+Add the module to your backend.
+
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
```
diff --git a/plugins/catalog-backend-module-logs/README.md b/plugins/catalog-backend-module-logs/README.md
index 6c84114306..7e20a0161b 100644
--- a/plugins/catalog-backend-module-logs/README.md
+++ b/plugins/catalog-backend-module-logs/README.md
@@ -13,6 +13,15 @@ yarn --cwd packages/backend add @backstage/plugin-events-node
Now you can install the events backend plugin in your backend.
+Install the catalog logs module.
+
+```ts
+# From your Backstage root directory
+yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
+```
+
+Add the module to your backend.
+
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-events-backend/alpha'));
```
From c4c81bcc73446a29c6cda5456ffded2698c8a816 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 11:57:41 -0400
Subject: [PATCH 16/63] add logging module to make this easier for users but
retain custom docs
Signed-off-by: Christopher Diaz
---
.changeset/ten-pots-walk.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.changeset/ten-pots-walk.md b/.changeset/ten-pots-walk.md
index 6265e8dd7f..e8f68afbe0 100644
--- a/.changeset/ten-pots-walk.md
+++ b/.changeset/ten-pots-walk.md
@@ -26,7 +26,7 @@ Install the catalog logs module.
yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
```
-Now install the catalog logs module.
+Add the module to your backend.
```ts title="packages/backend/src/index.ts"
backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
From 9c8518e29a1c1d40bf096f7a5e44ace9c4e70449 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 12:00:10 -0400
Subject: [PATCH 17/63] module should not be private
Signed-off-by: Christopher Diaz
---
.../catalog-backend-module-logs/package.json | 31 +++++++++----------
1 file changed, 15 insertions(+), 16 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
index f35a8b7816..3d07b115ae 100644
--- a/plugins/catalog-backend-module-logs/package.json
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -1,27 +1,29 @@
{
"name": "@backstage/plugin-catalog-backend-module-logs",
- "description": "A module that subscribes to catalog releated events and logs them.",
"version": "0.0.0",
- "main": "src/index.ts",
- "types": "src/index.ts",
- "license": "Apache-2.0",
- "private": true,
+ "description": "A module that subscribes to catalog releated events and logs them.",
+ "backstage": {
+ "role": "backend-plugin-module"
+ },
"publishConfig": {
"access": "public",
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
- "backstage": {
- "role": "backend-plugin-module"
- },
+ "license": "Apache-2.0",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "files": [
+ "dist"
+ ],
"scripts": {
- "start": "backstage-cli package start",
"build": "backstage-cli package build",
- "lint": "backstage-cli package lint",
- "test": "backstage-cli package test",
"clean": "backstage-cli package clean",
+ "lint": "backstage-cli package lint",
"prepack": "backstage-cli package prepack",
- "postpack": "backstage-cli package postpack"
+ "postpack": "backstage-cli package postpack",
+ "start": "backstage-cli package start",
+ "test": "backstage-cli package test"
},
"dependencies": {
"@backstage/backend-common": "workspace:^",
@@ -32,8 +34,5 @@
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^"
- },
- "files": [
- "dist"
- ]
+ }
}
From acb3c93b4ce5be9bbc4ed5d2ac4a9ab912bb908f Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 12:10:05 -0400
Subject: [PATCH 18/63] add api report
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/api-report.md | 13 +++++++++++++
1 file changed, 13 insertions(+)
create mode 100644 plugins/catalog-backend-module-logs/api-report.md
diff --git a/plugins/catalog-backend-module-logs/api-report.md b/plugins/catalog-backend-module-logs/api-report.md
new file mode 100644
index 0000000000..abad6c3095
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/api-report.md
@@ -0,0 +1,13 @@
+## API Report File for "@backstage/plugin-catalog-backend-module-logs"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+import { BackendFeature } from '@backstage/backend-plugin-api';
+
+// Warning: (ae-missing-release-tag) "catalogModuleLogs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+const catalogModuleLogs: () => BackendFeature;
+export default catalogModuleLogs;
+```
From d9772b13cb1f37dca41b4219dc466ebe59916c72 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 12:17:27 -0400
Subject: [PATCH 19/63] add api report
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/src/index.ts | 1 +
plugins/catalog-backend-module-logs/src/module.ts | 5 +++++
2 files changed, 6 insertions(+)
diff --git a/plugins/catalog-backend-module-logs/src/index.ts b/plugins/catalog-backend-module-logs/src/index.ts
index 3d5f606d27..6808046373 100644
--- a/plugins/catalog-backend-module-logs/src/index.ts
+++ b/plugins/catalog-backend-module-logs/src/index.ts
@@ -18,6 +18,7 @@
* The logs backend module for the catalog plugin.
*
* @packageDocumentation
+ * @public
*/
export { catalogModuleLogs as default } from './module';
diff --git a/plugins/catalog-backend-module-logs/src/module.ts b/plugins/catalog-backend-module-logs/src/module.ts
index 0f41d2e1a6..13a96a64f8 100644
--- a/plugins/catalog-backend-module-logs/src/module.ts
+++ b/plugins/catalog-backend-module-logs/src/module.ts
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+/**
+ * Logs catalog errors from events.
+ *
+ * @public
+ */
import {
coreServices,
createBackendModule,
From 4118216077183039f33434011b0fc9cd0b7cdf8a Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 12:22:25 -0400
Subject: [PATCH 20/63] add api report
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/package.json | 5 +++++
plugins/catalog-backend-module-logs/src/index.ts | 3 +--
plugins/catalog-backend-module-logs/src/module.ts | 2 --
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
index 3d07b115ae..d2e76131fb 100644
--- a/plugins/catalog-backend-module-logs/package.json
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -10,6 +10,11 @@
"main": "dist/index.cjs.js",
"types": "dist/index.d.ts"
},
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/backstage/backstage",
+ "directory": "plugins/catalog-backend-module-logs"
+ },
"license": "Apache-2.0",
"main": "src/index.ts",
"types": "src/index.ts",
diff --git a/plugins/catalog-backend-module-logs/src/index.ts b/plugins/catalog-backend-module-logs/src/index.ts
index 6808046373..717b7bde9e 100644
--- a/plugins/catalog-backend-module-logs/src/index.ts
+++ b/plugins/catalog-backend-module-logs/src/index.ts
@@ -16,9 +16,8 @@
/**
* The logs backend module for the catalog plugin.
- *
- * @packageDocumentation
* @public
+ * @packageDocumentation
*/
export { catalogModuleLogs as default } from './module';
diff --git a/plugins/catalog-backend-module-logs/src/module.ts b/plugins/catalog-backend-module-logs/src/module.ts
index 13a96a64f8..84f92cfe92 100644
--- a/plugins/catalog-backend-module-logs/src/module.ts
+++ b/plugins/catalog-backend-module-logs/src/module.ts
@@ -16,8 +16,6 @@
/**
* Logs catalog errors from events.
- *
- * @public
*/
import {
coreServices,
From abeb6b982ea01473e15207af6c7ae1a80392b75e Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 12:27:24 -0400
Subject: [PATCH 21/63] add api report without warnings
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/api-report.md | 2 --
plugins/catalog-backend-module-logs/src/index.ts | 5 ++---
plugins/catalog-backend-module-logs/src/module.ts | 4 +---
3 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/api-report.md b/plugins/catalog-backend-module-logs/api-report.md
index abad6c3095..7dd45e6119 100644
--- a/plugins/catalog-backend-module-logs/api-report.md
+++ b/plugins/catalog-backend-module-logs/api-report.md
@@ -5,8 +5,6 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
-// Warning: (ae-missing-release-tag) "catalogModuleLogs" is part of the package's API, but it is missing a release tag (@alpha, @beta, @public, or @internal)
-//
// @public (undocumented)
const catalogModuleLogs: () => BackendFeature;
export default catalogModuleLogs;
diff --git a/plugins/catalog-backend-module-logs/src/index.ts b/plugins/catalog-backend-module-logs/src/index.ts
index 717b7bde9e..77a7d424eb 100644
--- a/plugins/catalog-backend-module-logs/src/index.ts
+++ b/plugins/catalog-backend-module-logs/src/index.ts
@@ -15,9 +15,8 @@
*/
/**
- * The logs backend module for the catalog plugin.
- * @public
+ * A catalog module that logs catalog errors using the logger service.
+ *
* @packageDocumentation
*/
-
export { catalogModuleLogs as default } from './module';
diff --git a/plugins/catalog-backend-module-logs/src/module.ts b/plugins/catalog-backend-module-logs/src/module.ts
index 84f92cfe92..54fc428cdf 100644
--- a/plugins/catalog-backend-module-logs/src/module.ts
+++ b/plugins/catalog-backend-module-logs/src/module.ts
@@ -14,9 +14,6 @@
* limitations under the License.
*/
-/**
- * Logs catalog errors from events.
- */
import {
coreServices,
createBackendModule,
@@ -34,6 +31,7 @@ interface EventsParamsWithPayload extends EventParams {
eventPayload: EventsPayload;
}
+/** @public */
export const catalogModuleLogs = createBackendModule({
pluginId: 'catalog',
moduleId: 'logs',
From 486ce82f7fa799725408728ee6dc04da541a81f8 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 14:07:22 -0400
Subject: [PATCH 22/63] add basic test
Signed-off-by: Christopher Diaz
---
.../catalog-backend-module-logs/package.json | 3 +-
.../src/module.test.ts | 45 +++++++++++++++++++
yarn.lock | 1 +
3 files changed, 48 insertions(+), 1 deletion(-)
create mode 100644 plugins/catalog-backend-module-logs/src/module.test.ts
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
index d2e76131fb..879ed3176a 100644
--- a/plugins/catalog-backend-module-logs/package.json
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -38,6 +38,7 @@
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
- "@backstage/cli": "workspace:^"
+ "@backstage/cli": "workspace:^",
+ "@backstage/plugin-events-backend-test-utils": "workspace:^"
}
}
diff --git a/plugins/catalog-backend-module-logs/src/module.test.ts b/plugins/catalog-backend-module-logs/src/module.test.ts
new file mode 100644
index 0000000000..733474512e
--- /dev/null
+++ b/plugins/catalog-backend-module-logs/src/module.test.ts
@@ -0,0 +1,45 @@
+/*
+ * 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 { mockServices, startTestBackend } from '@backstage/backend-test-utils';
+import { catalogModuleLogs } from './module';
+import { createServiceFactory } from '@backstage/backend-plugin-api';
+import { TestEventsService } from '@backstage/plugin-events-backend-test-utils';
+import { eventsServiceRef } from '@backstage/plugin-events-node';
+
+describe('eventsModuleLogs', () => {
+ it('should be correctly wired and set up', async () => {
+ const events = new TestEventsService();
+ const eventsServiceFactory = createServiceFactory({
+ service: eventsServiceRef,
+ deps: {},
+ async factory({}) {
+ return events;
+ },
+ });
+
+ await startTestBackend({
+ features: [
+ mockServices.logger.factory(),
+ eventsServiceFactory(),
+ catalogModuleLogs(),
+ ],
+ });
+
+ expect(events.subscribed).toHaveLength(1);
+ expect(events.subscribed[0].id).toEqual('catalog');
+ });
+});
diff --git a/yarn.lock b/yarn.lock
index 542d9242da..6c298b9c89 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5449,6 +5449,7 @@ __metadata:
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
"@backstage/plugin-catalog-backend": "workspace:^"
+ "@backstage/plugin-events-backend-test-utils": "workspace:^"
"@backstage/plugin-events-node": "workspace:^"
languageName: unknown
linkType: soft
From 5f4090221f598ddfb101db3a629dcf577157edf0 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Fri, 7 Jun 2024 14:08:31 -0400
Subject: [PATCH 23/63] add basic test
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/src/module.test.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/catalog-backend-module-logs/src/module.test.ts b/plugins/catalog-backend-module-logs/src/module.test.ts
index 733474512e..79f1b8c295 100644
--- a/plugins/catalog-backend-module-logs/src/module.test.ts
+++ b/plugins/catalog-backend-module-logs/src/module.test.ts
@@ -20,7 +20,7 @@ import { createServiceFactory } from '@backstage/backend-plugin-api';
import { TestEventsService } from '@backstage/plugin-events-backend-test-utils';
import { eventsServiceRef } from '@backstage/plugin-events-node';
-describe('eventsModuleLogs', () => {
+describe('catalogModuleLogs', () => {
it('should be correctly wired and set up', async () => {
const events = new TestEventsService();
const eventsServiceFactory = createServiceFactory({
From 916449c0452b6e80df5b8a40ed4f3236f84f8d2b Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 10:08:20 -0400
Subject: [PATCH 24/63] Update
docs/features/software-catalog/life-of-an-entity.md
Co-authored-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com>
Signed-off-by: Christopher Diaz
---
docs/features/software-catalog/life-of-an-entity.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index 029778510a..d333b90565 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -198,7 +198,7 @@ cannot be parsed successfully, etc.
There are two main ways that these errors are surfaced.
First, the catalog backend will emit events using the [events backend plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node). You can subscribe to the events. The events should contain
-sufficient information for a reader to find the causes for errors. See the configuration documentation [here](./configuration.md#subscribing-to-catalog-errors) for how to subscribe and log these error events.
+sufficient information for a reader to find the causes for errors. See the [configuration documentation](./configuration.md#subscribing-to-catalog-errors) for how to subscribe and log these error events.
Since these events are typically not easily found by end users, this can mainly be a useful
tool for Backstage operators who want to debug problems either with statically
registered entities that are under their control, or to help end users find
From f304e99204b0c8a211f4a616daf4baec2c469974 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?=
Date: Wed, 19 Jun 2024 16:34:44 +0200
Subject: [PATCH 25/63] Update plugins/catalog-backend-module-logs/package.json
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Fredrik Adelöw
---
plugins/catalog-backend-module-logs/package.json | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
index 879ed3176a..e8ed120872 100644
--- a/plugins/catalog-backend-module-logs/package.json
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -3,7 +3,9 @@
"version": "0.0.0",
"description": "A module that subscribes to catalog releated events and logs them.",
"backstage": {
- "role": "backend-plugin-module"
+ "role": "backend-plugin-module",
+ "pluginId": "catalog",
+ "pluginPackage": "@backstage/plugin-catalog-backend"
},
"publishConfig": {
"access": "public",
From 2a2de3984e6e261a0d0965595bbed5fd69a4bd60 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?=
Date: Wed, 19 Jun 2024 16:34:49 +0200
Subject: [PATCH 26/63] Update plugins/catalog-backend-module-logs/package.json
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Fredrik Adelöw
---
plugins/catalog-backend-module-logs/package.json | 1 -
1 file changed, 1 deletion(-)
diff --git a/plugins/catalog-backend-module-logs/package.json b/plugins/catalog-backend-module-logs/package.json
index e8ed120872..858f7ec198 100644
--- a/plugins/catalog-backend-module-logs/package.json
+++ b/plugins/catalog-backend-module-logs/package.json
@@ -33,7 +33,6 @@
"test": "backstage-cli package test"
},
"dependencies": {
- "@backstage/backend-common": "workspace:^",
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/plugin-catalog-backend": "workspace:^",
"@backstage/plugin-events-node": "workspace:^"
From 066cc7143ef4c51f8baff98b914ab2c2cdb5ff95 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 11:09:50 -0400
Subject: [PATCH 27/63] remove verbage to docs that exist elsewhere
Signed-off-by: Christopher Diaz
---
docs/features/software-catalog/life-of-an-entity.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/features/software-catalog/life-of-an-entity.md b/docs/features/software-catalog/life-of-an-entity.md
index d333b90565..1489688720 100644
--- a/docs/features/software-catalog/life-of-an-entity.md
+++ b/docs/features/software-catalog/life-of-an-entity.md
@@ -204,7 +204,7 @@ tool for Backstage operators who want to debug problems either with statically
registered entities that are under their control, or to help end users find
problems.
-> Prior to Backstage version v1.26.0 and `@backstage/plugin-catalog-backend` v1.21.9 catalog errors were logged by default. See the docs below on how to enable these logs and an example on how you can further customize how you ingest these errors.
+> Prior to Backstage version v1.26.0 and `@backstage/plugin-catalog-backend` v1.21.9 catalog errors were logged by default.
Second, for most classes of errors, the entity itself will contain a status
field that describes the problem. The contents of this field is shown at the top
From 16589947aa9bdc95fba049d17f3cecc50b869e78 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 11:12:30 -0400
Subject: [PATCH 28/63] remove duplicate module docs and point to backstage
docs
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/README.md | 37 ++-----------------
1 file changed, 3 insertions(+), 34 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/README.md b/plugins/catalog-backend-module-logs/README.md
index 7e20a0161b..1771dbe02c 100644
--- a/plugins/catalog-backend-module-logs/README.md
+++ b/plugins/catalog-backend-module-logs/README.md
@@ -2,38 +2,7 @@
A module that subscribes to catalog related events and logs them.
-Catalog errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
+## Getting started
-The first step is to add the events backend plugin to your Backstage application. Navigate to your Backstage application directory and add the plugin package.
-
-```ts
-# From your Backstage root directory
-yarn --cwd packages/backend add @backstage/plugin-events-node
-```
-
-Now you can install the events backend plugin in your backend.
-
-Install the catalog logs module.
-
-```ts
-# From your Backstage root directory
-yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
-```
-
-Add the module to your backend.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(import('@backstage/plugin-events-backend/alpha'));
-```
-
-Now install the catalog logs module.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
-```
-
-You should now see logs as the catalog emits events. Example:
-
-```
-[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
-```
+See [Backstage documentation](https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors) for details on how to install
+and configure the plugin.
From d3f280b51fa7f0c0283cfbd02a7efad73f729aa9 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 11:21:41 -0400
Subject: [PATCH 29/63] remove un-needed line in docs and update changeset to
use a link
Signed-off-by: Christopher Diaz
---
.changeset/ten-pots-walk.md | 35 ++-----------------
.../software-catalog/configuration.md | 2 +-
2 files changed, 3 insertions(+), 34 deletions(-)
diff --git a/.changeset/ten-pots-walk.md b/.changeset/ten-pots-walk.md
index e8f68afbe0..cf540fd0e2 100644
--- a/.changeset/ten-pots-walk.md
+++ b/.changeset/ten-pots-walk.md
@@ -4,36 +4,5 @@
Creates a new module to make logging catalog errors simple. This module subscribes to catalog events and logs them.
-Catalog errors are published to the [events plugin](https://github.com/backstage/backstage/tree/master/plugins/events-node): `@backstage/plugin-events-node`. You can subscribe to events and respond to errors, for example you may wish to log them.
-
-The first step is to add the events backend plugin to your Backstage application. Navigate to your Backstage application directory and add the plugin package.
-
-```ts
-# From your Backstage root directory
-yarn --cwd packages/backend add @backstage/plugin-events-node
-```
-
-Now you can install the events backend plugin in your backend.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(import('@backstage/plugin-events-backend/alpha'));
-```
-
-Install the catalog logs module.
-
-```ts
-# From your Backstage root directory
-yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-logs
-```
-
-Add the module to your backend.
-
-```ts title="packages/backend/src/index.ts"
-backend.add(import('@backstage/plugin-catalog-backend-module-logs'));
-```
-
-You should now see logs as the catalog emits events. Example:
-
-```
-[1] 2024-06-07T00:00:28.787Z events warn Policy check failed for user:default/guest; caused by Error: Malformed envelope, /metadata/tags must be array entity=user:default/guest location=file:/Users/foobar/code/backstage-demo-instance/examples/org.yaml
-```
+See [Backstage documentation](https://backstage.io/docs/features/software-catalog/configuration#subscribing-to-catalog-errors) for details on how to install
+and configure the plugin.
diff --git a/docs/features/software-catalog/configuration.md b/docs/features/software-catalog/configuration.md
index 9805eb06dd..3bbbfd6716 100644
--- a/docs/features/software-catalog/configuration.md
+++ b/docs/features/software-catalog/configuration.md
@@ -222,7 +222,7 @@ You should now see logs as the catalog emits events. Example:
### Custom Error Handling
-If you wish to handle catalog errors with logic the following should help you get started.
+If you wish to handle catalog errors with specific logic different from logging the errors the following should help you get started. For example, you may wish to send a notification or create a ticket for someone to investigate.
Create a backend module that subscribes to the catalog error events. The topic is `experimental.catalog.errors`.
From e61267416795b27e6530a40686c1459ac88b272f Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 11:24:03 -0400
Subject: [PATCH 30/63] update lockfile
Signed-off-by: Christopher Diaz
---
yarn.lock | 1 -
1 file changed, 1 deletion(-)
diff --git a/yarn.lock b/yarn.lock
index 6c298b9c89..7d440ea43f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5444,7 +5444,6 @@ __metadata:
version: 0.0.0-use.local
resolution: "@backstage/plugin-catalog-backend-module-logs@workspace:plugins/catalog-backend-module-logs"
dependencies:
- "@backstage/backend-common": "workspace:^"
"@backstage/backend-plugin-api": "workspace:^"
"@backstage/backend-test-utils": "workspace:^"
"@backstage/cli": "workspace:^"
From 26bd7a7a92971f9157f5a04fc537aed232414925 Mon Sep 17 00:00:00 2001
From: Christopher Diaz
Date: Wed, 19 Jun 2024 12:16:26 -0400
Subject: [PATCH 31/63] try to update api docs
Signed-off-by: Christopher Diaz
---
plugins/catalog-backend-module-logs/api-report.md | 2 +-
plugins/catalog-backend-module-logs/src/module.ts | 7 ++++++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/api-report.md b/plugins/catalog-backend-module-logs/api-report.md
index 7dd45e6119..bb08280566 100644
--- a/plugins/catalog-backend-module-logs/api-report.md
+++ b/plugins/catalog-backend-module-logs/api-report.md
@@ -5,7 +5,7 @@
```ts
import { BackendFeature } from '@backstage/backend-plugin-api';
-// @public (undocumented)
+// @public
const catalogModuleLogs: () => BackendFeature;
export default catalogModuleLogs;
```
diff --git a/plugins/catalog-backend-module-logs/src/module.ts b/plugins/catalog-backend-module-logs/src/module.ts
index 54fc428cdf..bdc916e958 100644
--- a/plugins/catalog-backend-module-logs/src/module.ts
+++ b/plugins/catalog-backend-module-logs/src/module.ts
@@ -31,7 +31,12 @@ interface EventsParamsWithPayload extends EventParams {
eventPayload: EventsPayload;
}
-/** @public */
+/**
+ * A catalog module that logs catalog errors using the logger service.
+ *
+ * @packageDocumentation
+ * @public
+ */
export const catalogModuleLogs = createBackendModule({
pluginId: 'catalog',
moduleId: 'logs',
From c057720a67cd0b34a322de0d492091d42a81a94a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?=
Date: Wed, 19 Jun 2024 19:36:51 +0200
Subject: [PATCH 32/63] api report
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Fredrik Adelöw
---
plugins/catalog-backend-module-logs/api-report.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/plugins/catalog-backend-module-logs/api-report.md b/plugins/catalog-backend-module-logs/api-report.md
index bb08280566..0be2197c9a 100644
--- a/plugins/catalog-backend-module-logs/api-report.md
+++ b/plugins/catalog-backend-module-logs/api-report.md
@@ -3,9 +3,9 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
-import { BackendFeature } from '@backstage/backend-plugin-api';
+import { BackendFeatureCompat } from '@backstage/backend-plugin-api';
// @public
-const catalogModuleLogs: () => BackendFeature;
+const catalogModuleLogs: BackendFeatureCompat;
export default catalogModuleLogs;
```
From 8dc15aae58a74fcca6a978b41b13b1bace21b8e8 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 11:19:40 +0200
Subject: [PATCH 33/63] backend-app-api: httpRouter add healthCheckConfig
Signed-off-by: Vincenzo Scamporlino
---
.../httpRouter/httpRouterServiceFactory.test.ts | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
index 58c074f985..2fd6923125 100644
--- a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
+++ b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
@@ -162,6 +162,18 @@ describe('httpRouterFactory', () => {
});
});
+ it('should always allow the healthcheck endpoint', async () => {
+ const { server } = await startTestBackend({
+ features: [pluginSubject, ...defaultServices],
+ });
+
+ await expect(
+ request(server).get('/api/test/healthcheck'),
+ ).resolves.toMatchObject({
+ status: 200,
+ });
+ });
+
it('should not block unauthenticated requests if default policy is disabled', async () => {
const { server } = await startTestBackend({
features: [
From 8bbbc314f1d0693f616015301a0b06ba418e7ca5 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 11:20:10 +0200
Subject: [PATCH 34/63] backend-app-api: healthcheck middleware
Signed-off-by: Vincenzo Scamporlino
---
.../httpRouter/createHealthcheck.test.ts | 33 ++++++++++++++++++
.../httpRouter/createHealthcheck.ts | 34 +++++++++++++++++++
2 files changed, 67 insertions(+)
create mode 100644 packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts
create mode 100644 packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts
diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts b/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts
new file mode 100644
index 0000000000..c23200a823
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts
@@ -0,0 +1,33 @@
+/*
+ * 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 express from 'express';
+import request from 'supertest';
+import { createHealthcheck } from './createHealthcheck';
+
+describe('createHealthcheck', () => {
+ it('should return a router with a healthcheck endpoint', async () => {
+ const hc = createHealthcheck();
+ const app = express().use(hc.router);
+
+ let response = await request(app).get('/healthcheck').expect(200);
+ expect(response.body).toEqual({ status: 'ok' });
+
+ hc.addHandler(async () => ({ allgood: true }));
+ response = await request(app).get('/healthcheck').expect(200);
+ expect(response.body).toEqual({ allgood: true });
+ });
+});
diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts b/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts
new file mode 100644
index 0000000000..f177822a17
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 { Request, Response } from 'express';
+import Router from 'express-promise-router';
+
+export function createHealthcheck() {
+ const router = Router();
+ let handler = () => Promise.resolve({ status: 'ok' });
+
+ router.get('/healthcheck', async (_request: Request, response: Response) => {
+ const status = await handler();
+ response.json(status);
+ });
+
+ return {
+ router,
+ addHandler: (newHandler: () => Promise) => {
+ handler = newHandler;
+ },
+ };
+}
From 14e982e8d3fa699196c94d392484f581cd426d5d Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 11:34:55 +0200
Subject: [PATCH 35/63] backend-plugin-api: export healthCheckConfig fn
Signed-off-by: Vincenzo Scamporlino
---
.../src/services/definitions/HttpRouterService.ts | 7 +++++++
.../backend-plugin-api/src/services/definitions/index.ts | 1 +
.../backend-test-utils/src/next/services/mockServices.ts | 1 +
3 files changed, 9 insertions(+)
diff --git a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
index 92f7e950f9..2cb5c74649 100644
--- a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
@@ -26,6 +26,11 @@ export interface HttpRouterServiceAuthPolicy {
allow: 'unauthenticated' | 'user-cookie';
}
+/** @public */
+export interface HttpRouterHealthCheckConfig {
+ handler: () => Promise;
+}
+
/**
* Allows plugins to register HTTP routes.
*
@@ -40,6 +45,8 @@ export interface HttpRouterService {
*/
use(handler: Handler): void;
+ healthCheckConfig(healthCheckOptions: HttpRouterHealthCheckConfig): void;
+
/**
* Adds an auth policy to the router. This is used to allow unauthenticated or
* cookie based access to parts of a plugin's API.
diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts
index 6f30c5f980..57cfd404c1 100644
--- a/packages/backend-plugin-api/src/services/definitions/index.ts
+++ b/packages/backend-plugin-api/src/services/definitions/index.ts
@@ -35,6 +35,7 @@ export type { DiscoveryService } from './DiscoveryService';
export type {
HttpRouterService,
HttpRouterServiceAuthPolicy,
+ HttpRouterHealthCheckConfig,
} from './HttpRouterService';
export type { HttpAuthService } from './HttpAuthService';
export type {
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index 24571b634c..379e9473ca 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -348,6 +348,7 @@ export namespace mockServices {
export const factory = httpRouterServiceFactory;
export const mock = simpleMock(coreServices.httpRouter, () => ({
use: jest.fn(),
+ healthCheckConfig: jest.fn(),
addAuthPolicy: jest.fn(),
}));
}
From 53ced701dd6f68b956c3c311da9d674befb0b64a Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 11:41:37 +0200
Subject: [PATCH 36/63] healthcheck changeset
Signed-off-by: Vincenzo Scamporlino
---
.changeset/bright-panthers-leave.md | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 .changeset/bright-panthers-leave.md
diff --git a/.changeset/bright-panthers-leave.md b/.changeset/bright-panthers-leave.md
new file mode 100644
index 0000000000..133760cadd
--- /dev/null
+++ b/.changeset/bright-panthers-leave.md
@@ -0,0 +1,7 @@
+---
+'@backstage/backend-plugin-api': patch
+'@backstage/backend-test-utils': patch
+'@backstage/backend-app-api': patch
+---
+
+Added a default `/healthcheck` endpoint to the HTTP Router.
From 8d4735767dbada61ac99000ec4e126f5d090c292 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 15:17:26 +0200
Subject: [PATCH 37/63] backend-app-api: move healthchecks to healthService
Signed-off-by: Vincenzo Scamporlino
---
.../health/createHealthRouter.test.ts | 81 +++++++++++++++++++
.../health/createHealthRouter.ts | 46 +++++++++++
.../health/healthServiceFactory.ts | 34 ++++++++
.../services/implementations/health/index.ts | 17 ++++
.../createHealthcheck.test.ts | 0
.../createHealthcheck.ts | 0
.../src/services/definitions/HealthService.ts | 20 +++++
.../services/definitions/HttpRouterService.ts | 5 --
.../src/services/definitions/coreServices.ts | 7 ++
.../src/services/definitions/index.ts | 2 +-
.../src/next/services/mockServices.ts | 1 -
11 files changed, 206 insertions(+), 7 deletions(-)
create mode 100644 packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts
create mode 100644 packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
create mode 100644 packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
create mode 100644 packages/backend-app-api/src/services/implementations/health/index.ts
rename packages/backend-app-api/src/services/implementations/{httpRouter => rootHttpRouter}/createHealthcheck.test.ts (100%)
rename packages/backend-app-api/src/services/implementations/{httpRouter => rootHttpRouter}/createHealthcheck.ts (100%)
create mode 100644 packages/backend-plugin-api/src/services/definitions/HealthService.ts
diff --git a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts b/packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts
new file mode 100644
index 0000000000..f8c51ee08d
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts
@@ -0,0 +1,81 @@
+/*
+ * 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 { mockServices } from '@backstage/backend-test-utils';
+import request from 'supertest';
+import { createHealthRouter } from './createHealthRouter';
+import express from 'express';
+
+describe('createHealthRouter', () => {
+ describe('readiness', () => {
+ it(`should return a 500 response if the server hasn't started yet`, async () => {
+ const hc = createHealthRouter({
+ lifecycle: mockServices.rootLifecycle.mock(),
+ });
+ const app = express().use(hc);
+
+ const response = await request(app).get('/v1/readiness');
+ expect(response.status).toBe(500);
+ });
+
+ it('should return 200 if the server has started', async () => {
+ const lifecycle = mockServices.rootLifecycle.mock();
+ let mockServerStartedFn = () => {};
+ lifecycle.addStartupHook.mockImplementation(
+ fn => (mockServerStartedFn = fn),
+ );
+
+ const hc = createHealthRouter({ lifecycle });
+ const app = express().use(hc);
+
+ mockServerStartedFn();
+ const response = await request(app).get('/v1/readiness').expect(200);
+ expect(response.body).toEqual({ status: 'ok' });
+ });
+
+ it(`should return a 500 response if the server has stopped`, async () => {
+ const lifecycle = mockServices.rootLifecycle.mock();
+ let mockServerStartedFn = () => {};
+ let mockServerStoppedFn = () => {};
+ lifecycle.addStartupHook.mockImplementation(
+ fn => (mockServerStartedFn = fn),
+ );
+ lifecycle.addShutdownHook.mockImplementation(
+ fn => (mockServerStoppedFn = fn),
+ );
+
+ const hc = createHealthRouter({ lifecycle });
+ const app = express().use(hc);
+
+ mockServerStartedFn();
+ mockServerStoppedFn();
+ const response = await request(app).get('/v1/readiness');
+ expect(response.status).toBe(500);
+ });
+ });
+
+ describe('liveness', () => {
+ it('should return 200 if the server has started', async () => {
+ const lifecycle = mockServices.rootLifecycle.mock();
+
+ const hc = createHealthRouter({ lifecycle });
+ const app = express().use(hc);
+
+ const response = await request(app).get('/v1/liveness').expect(200);
+ expect(response.body).toEqual({ status: 'ok' });
+ });
+ });
+});
diff --git a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts b/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
new file mode 100644
index 0000000000..f2ff2ecd73
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
@@ -0,0 +1,46 @@
+/*
+ * 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 Router from 'express-promise-router';
+import { Request, Response } from 'express';
+import { RootLifecycleService } from '@backstage/backend-plugin-api';
+
+export function createHealthRouter(options: {
+ lifecycle: RootLifecycleService;
+}) {
+ const router = Router();
+
+ let isRunning = false;
+ options.lifecycle.addStartupHook(() => {
+ isRunning = true;
+ });
+ options.lifecycle.addShutdownHook(() => {
+ isRunning = false;
+ });
+
+ router.get('/v1/readiness', async (_request: Request, response: Response) => {
+ if (!isRunning) {
+ throw new Error('Backend has not started yet');
+ }
+ response.json({ status: 'ok' });
+ });
+
+ router.get('/v1/liveness', async (_request: Request, response: Response) => {
+ response.json({ status: 'ok' });
+ });
+
+ return router;
+}
diff --git a/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts b/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
new file mode 100644
index 0000000000..831f4fa6e8
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
@@ -0,0 +1,34 @@
+/*
+ * 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 {
+ coreServices,
+ createServiceFactory,
+} from '@backstage/backend-plugin-api';
+import { createHealthRouter } from './createHealthRouter';
+
+export const healthServiceFactory = createServiceFactory({
+ service: coreServices.health,
+ deps: {
+ rootHttpRouter: coreServices.rootHttpRouter,
+ lifecycle: coreServices.rootLifecycle,
+ },
+ async factory({ lifecycle, rootHttpRouter }) {
+ rootHttpRouter.use('.backstage/health', createHealthRouter({ lifecycle }));
+
+ return {};
+ },
+});
diff --git a/packages/backend-app-api/src/services/implementations/health/index.ts b/packages/backend-app-api/src/services/implementations/health/index.ts
new file mode 100644
index 0000000000..4aeb4b7979
--- /dev/null
+++ b/packages/backend-app-api/src/services/implementations/health/index.ts
@@ -0,0 +1,17 @@
+/*
+ * 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.
+ */
+
+export { healthServiceFactory } from './healthServiceFactory';
diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts
similarity index 100%
rename from packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.test.ts
rename to packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts
diff --git a/packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts
similarity index 100%
rename from packages/backend-app-api/src/services/implementations/httpRouter/createHealthcheck.ts
rename to packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts
diff --git a/packages/backend-plugin-api/src/services/definitions/HealthService.ts b/packages/backend-plugin-api/src/services/definitions/HealthService.ts
new file mode 100644
index 0000000000..d04a8a6133
--- /dev/null
+++ b/packages/backend-plugin-api/src/services/definitions/HealthService.ts
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * @public
+ */
+export interface HealthService {}
diff --git a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
index 2cb5c74649..30c4fb31c8 100644
--- a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
@@ -26,11 +26,6 @@ export interface HttpRouterServiceAuthPolicy {
allow: 'unauthenticated' | 'user-cookie';
}
-/** @public */
-export interface HttpRouterHealthCheckConfig {
- handler: () => Promise;
-}
-
/**
* Allows plugins to register HTTP routes.
*
diff --git a/packages/backend-plugin-api/src/services/definitions/coreServices.ts b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
index b0518fb9d4..36ec0151c5 100644
--- a/packages/backend-plugin-api/src/services/definitions/coreServices.ts
+++ b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
@@ -102,6 +102,13 @@ export namespace coreServices {
import('./DiscoveryService').DiscoveryService
>({ id: 'core.discovery' });
+ /**
+ * The service reference for the plugin scoped {@link RootHealthService}.
+ */
+ export const health = createServiceRef<
+ import('./RootHealthService').RootHealthService
+ >({ id: 'core.health', scope: 'root' });
+
/**
* Authentication of HTTP requests.
*
diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts
index 57cfd404c1..af0d991f58 100644
--- a/packages/backend-plugin-api/src/services/definitions/index.ts
+++ b/packages/backend-plugin-api/src/services/definitions/index.ts
@@ -32,10 +32,10 @@ export type {
export type { RootConfigService } from './RootConfigService';
export type { DatabaseService } from './DatabaseService';
export type { DiscoveryService } from './DiscoveryService';
+export type { HealthService } from './HealthService';
export type {
HttpRouterService,
HttpRouterServiceAuthPolicy,
- HttpRouterHealthCheckConfig,
} from './HttpRouterService';
export type { HttpAuthService } from './HttpAuthService';
export type {
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index 379e9473ca..24571b634c 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -348,7 +348,6 @@ export namespace mockServices {
export const factory = httpRouterServiceFactory;
export const mock = simpleMock(coreServices.httpRouter, () => ({
use: jest.fn(),
- healthCheckConfig: jest.fn(),
addAuthPolicy: jest.fn(),
}));
}
From b26877ffc50329ce93bd9a7b3d6f016a6f8cd7c6 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 15:18:16 +0200
Subject: [PATCH 38/63] backend-defaults: add healthservice
Signed-off-by: Vincenzo Scamporlino
---
packages/backend-defaults/src/CreateBackend.ts | 2 ++
.../src/services/definitions/HttpRouterService.ts | 2 --
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts
index 9b3fa5d649..453c5fe592 100644
--- a/packages/backend-defaults/src/CreateBackend.ts
+++ b/packages/backend-defaults/src/CreateBackend.ts
@@ -24,6 +24,7 @@ import { authServiceFactory } from '@backstage/backend-defaults/auth';
import { cacheServiceFactory } from '@backstage/backend-defaults/cache';
import { databaseServiceFactory } from '@backstage/backend-defaults/database';
import { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';
+import { rootHealthServiceFactory } from './entrypoints/rootHealth';
import { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';
import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
@@ -58,6 +59,7 @@ export const defaultServiceFactories = [
userInfoServiceFactory(),
urlReaderServiceFactory(),
eventsServiceFactory(),
+ rootHealthServiceFactory(),
];
/**
diff --git a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
index 30c4fb31c8..92f7e950f9 100644
--- a/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts
@@ -40,8 +40,6 @@ export interface HttpRouterService {
*/
use(handler: Handler): void;
- healthCheckConfig(healthCheckOptions: HttpRouterHealthCheckConfig): void;
-
/**
* Adds an auth policy to the router. This is used to allow unauthenticated or
* cookie based access to parts of a plugin's API.
From 1ce0bb70605a3124af959e83993a24f47b58e26e Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 15:20:44 +0200
Subject: [PATCH 39/63] tweak changeset
Signed-off-by: Vincenzo Scamporlino
---
.changeset/bright-panthers-leave.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.changeset/bright-panthers-leave.md b/.changeset/bright-panthers-leave.md
index 133760cadd..acd9764fe6 100644
--- a/.changeset/bright-panthers-leave.md
+++ b/.changeset/bright-panthers-leave.md
@@ -1,7 +1,7 @@
---
'@backstage/backend-plugin-api': patch
-'@backstage/backend-test-utils': patch
+'@backstage/backend-defaults': patch
'@backstage/backend-app-api': patch
---
-Added a default `/healthcheck` endpoint to the HTTP Router.
+Added a new health service which adds new endpoints for health checks.
From 0717aaeda6098f7f3e72f7bb721ec8e38f7062d1 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 19:18:06 +0200
Subject: [PATCH 40/63] backend-app-api: remove test
Signed-off-by: Vincenzo Scamporlino
---
.../httpRouter/httpRouterServiceFactory.test.ts | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
index 2fd6923125..58c074f985 100644
--- a/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
+++ b/packages/backend-defaults/src/entrypoints/httpRouter/httpRouterServiceFactory.test.ts
@@ -162,18 +162,6 @@ describe('httpRouterFactory', () => {
});
});
- it('should always allow the healthcheck endpoint', async () => {
- const { server } = await startTestBackend({
- features: [pluginSubject, ...defaultServices],
- });
-
- await expect(
- request(server).get('/api/test/healthcheck'),
- ).resolves.toMatchObject({
- status: 200,
- });
- });
-
it('should not block unauthenticated requests if default policy is disabled', async () => {
const { server } = await startTestBackend({
features: [
From 49b489088cd9f7e262949c21599001c918349dd6 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Fri, 17 May 2024 20:20:44 +0200
Subject: [PATCH 41/63] backend-app-api: mark healthServiceFactory as public
Signed-off-by: Vincenzo Scamporlino
---
packages/backend-app-api/api-report.md | 4 ++++
.../services/implementations/health/healthServiceFactory.ts | 3 +++
2 files changed, 7 insertions(+)
diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md
index 7518f8e2cc..a18f027273 100644
--- a/packages/backend-app-api/api-report.md
+++ b/packages/backend-app-api/api-report.md
@@ -18,6 +18,7 @@ import { ErrorRequestHandler } from 'express';
import { Express as Express_2 } from 'express';
import { Format } from 'logform';
import { Handler } from 'express';
+import { HealthService } from '@backstage/backend-plugin-api';
import { HelmetOptions } from 'helmet';
import * as http from 'http';
import { HttpAuthService } from '@backstage/backend-plugin-api';
@@ -126,6 +127,9 @@ export const discoveryServiceFactory: () => ServiceFactory<
// @public @deprecated (undocumented)
export type ExtendedHttpServer = ExtendedHttpServer_2;
+// @public (undocumented)
+export const healthServiceFactory: () => ServiceFactory;
+
// @public @deprecated
export class HostDiscovery implements DiscoveryService {
static fromConfig(
diff --git a/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts b/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
index 831f4fa6e8..b79ba34a87 100644
--- a/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
+++ b/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
@@ -20,6 +20,9 @@ import {
} from '@backstage/backend-plugin-api';
import { createHealthRouter } from './createHealthRouter';
+/**
+ * @public
+ */
export const healthServiceFactory = createServiceFactory({
service: coreServices.health,
deps: {
From a38ffb2cb3a72d80027e3293efa74fbd13212a6a Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Mon, 3 Jun 2024 13:33:38 +0200
Subject: [PATCH 42/63] backend-test-utils: mock health service
Signed-off-by: Vincenzo Scamporlino
---
.../backend-test-utils/src/next/services/mockServices.ts | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index 24571b634c..22496bd6e1 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -24,6 +24,7 @@ import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
import { loggerServiceFactory } from '@backstage/backend-defaults/logger';
import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';
+import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';
import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';
@@ -383,6 +384,14 @@ export namespace mockServices {
}));
}
+ export namespace rootHealth {
+ export const factory = rootHealthServiceFactory;
+ export const mock = simpleMock(coreServices.health, () => ({
+ getLiveness: jest.fn(),
+ getReadiness: jest.fn(),
+ }));
+ }
+
export namespace rootLifecycle {
export const factory = rootLifecycleServiceFactory;
export const mock = simpleMock(coreServices.rootLifecycle, () => ({
From 972896d192834f5ff2d0c115bb6513f758a13829 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Mon, 3 Jun 2024 13:33:54 +0200
Subject: [PATCH 43/63] backend-app-api: clean up
Signed-off-by: Vincenzo Scamporlino
---
.../rootHttpRouter/createHealthcheck.test.ts | 33 ------------------
.../rootHttpRouter/createHealthcheck.ts | 34 -------------------
2 files changed, 67 deletions(-)
delete mode 100644 packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts
delete mode 100644 packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts
diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts
deleted file mode 100644
index c23200a823..0000000000
--- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.test.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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 express from 'express';
-import request from 'supertest';
-import { createHealthcheck } from './createHealthcheck';
-
-describe('createHealthcheck', () => {
- it('should return a router with a healthcheck endpoint', async () => {
- const hc = createHealthcheck();
- const app = express().use(hc.router);
-
- let response = await request(app).get('/healthcheck').expect(200);
- expect(response.body).toEqual({ status: 'ok' });
-
- hc.addHandler(async () => ({ allgood: true }));
- response = await request(app).get('/healthcheck').expect(200);
- expect(response.body).toEqual({ allgood: true });
- });
-});
diff --git a/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts b/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts
deleted file mode 100644
index f177822a17..0000000000
--- a/packages/backend-app-api/src/services/implementations/rootHttpRouter/createHealthcheck.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 { Request, Response } from 'express';
-import Router from 'express-promise-router';
-
-export function createHealthcheck() {
- const router = Router();
- let handler = () => Promise.resolve({ status: 'ok' });
-
- router.get('/healthcheck', async (_request: Request, response: Response) => {
- const status = await handler();
- response.json(status);
- });
-
- return {
- router,
- addHandler: (newHandler: () => Promise) => {
- handler = newHandler;
- },
- };
-}
From 652da2e3e342994f72639754cafba858dc1d0a94 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Mon, 3 Jun 2024 13:45:41 +0200
Subject: [PATCH 44/63] docs: add health service
Signed-off-by: Vincenzo Scamporlino
---
docs/backend-system/core-services/01-index.md | 1 +
docs/backend-system/core-services/health.md | 39 +++++++++++++++++++
2 files changed, 40 insertions(+)
create mode 100644 docs/backend-system/core-services/health.md
diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md
index 04d2e57ae8..63324292c1 100644
--- a/docs/backend-system/core-services/01-index.md
+++ b/docs/backend-system/core-services/01-index.md
@@ -20,6 +20,7 @@ import { coreServices } from '@backstage/backend-plugin-api';
- [Cache Service](./cache.md) - Key-value store for caching data.
- [Database Service](./database.md) - Database access and management via [knex](https://knexjs.org/).
- [Discovery Service](./discovery.md) - Service discovery for inter-plugin communication.
+- [Health Service](./health.md) - Health check endpoints for the backend.
- [Http Auth Service](./http-auth.md) - Authentication of HTTP requests.
- [Http Router Service](./http-router.md) - HTTP route registration for plugins.
- [Identity Service](./identity.md) - Deprecated user authentication service, use the [Auth Service](./auth.md) instead.
diff --git a/docs/backend-system/core-services/health.md b/docs/backend-system/core-services/health.md
new file mode 100644
index 0000000000..9a69891624
--- /dev/null
+++ b/docs/backend-system/core-services/health.md
@@ -0,0 +1,39 @@
+---
+id: health
+title: Heath Service
+sidebar_label: Health
+description: Documentation for the Health service
+---
+
+The Health service provides some health check endpoints for the plugins. By default, it attaches `/.backstage/health/v1/readiness` and `/.backstage/health/v1/liveness` endpoints to the backend server, which return a JSON object with the status of the backend services.
+
+## Configuring the service
+
+The following example is how you can override the health service to add custom endpoints.
+
+```ts
+import { coreServices } from '@backstage/backend-plugin-api';
+import { WinstonLogger } from '@backstage/backend-app-api';
+
+const backend = createBackend();
+
+backend.add(
+ createServiceFactory({
+ service: coreServices.health,
+ deps: {
+ rootHttpRouter: coreServices.rootHttpRouter,
+ },
+ async factory({ rootHttpRouter }) {
+ rootHttpRouter.get('.backstage/health/v1/readiness', async (req, res) => {
+ res.json({ status: 'ok' });
+ });
+
+ rootHttpRouter.get('.backstage/health/v1/liveness', async (req, res) => {
+ res.json({ status: 'ok' });
+ });
+
+ return {};
+ },
+ }),
+);
+```
From 78fdc5a39f613a50f6a024b68a9abb1201396d78 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Mon, 3 Jun 2024 14:11:33 +0200
Subject: [PATCH 45/63] health service api report
Signed-off-by: Vincenzo Scamporlino
---
packages/backend-plugin-api/api-report.md | 4 ++++
packages/backend-test-utils/api-report.md | 10 ++++++++++
2 files changed, 14 insertions(+)
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index 258cdefe1b..5e02ad1787 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -194,6 +194,7 @@ export namespace coreServices {
const rootConfig: ServiceRef;
const database: ServiceRef;
const discovery: ServiceRef;
+ const health: ServiceRef;
const httpAuth: ServiceRef;
const httpRouter: ServiceRef;
const lifecycle: ServiceRef;
@@ -333,6 +334,9 @@ export type ExtensionPoint = {
// @public @deprecated (undocumented)
export type ExtensionPointConfig = CreateExtensionPointOptions;
+// @public (undocumented)
+export interface HealthService {}
+
// @public
export interface HttpAuthService {
credentials(
diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md
index 019d398ea6..07b393b653 100644
--- a/packages/backend-test-utils/api-report.md
+++ b/packages/backend-test-utils/api-report.md
@@ -21,6 +21,7 @@ import { DiscoveryService } from '@backstage/backend-plugin-api';
import { EventsService } from '@backstage/plugin-events-node';
import { ExtendedHttpServer } from '@backstage/backend-app-api';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
+import { HealthService } from '@backstage/backend-plugin-api';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { HttpRouterFactoryOptions } from '@backstage/backend-defaults/httpRouter';
import { HttpRouterService } from '@backstage/backend-plugin-api';
@@ -199,6 +200,15 @@ export namespace mockServices {
partialImpl?: Partial | undefined,
) => ServiceMock;
}
+ // (undocumented)
+ export namespace health {
+ const // (undocumented)
+ factory: () => ServiceFactory;
+ const // (undocumented)
+ mock: (
+ partialImpl?: Partial | undefined,
+ ) => ServiceMock;
+ }
export function httpAuth(options?: {
pluginId?: string;
defaultCredentials?: BackstageCredentials;
From fce7887109d2741e896b0c2d25303999db42760c Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Mon, 3 Jun 2024 14:18:11 +0200
Subject: [PATCH 46/63] backend-test-utils: health service mock changeset
Signed-off-by: Vincenzo Scamporlino
---
.changeset/serious-kings-trade.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/serious-kings-trade.md
diff --git a/.changeset/serious-kings-trade.md b/.changeset/serious-kings-trade.md
new file mode 100644
index 0000000000..c07e92b88a
--- /dev/null
+++ b/.changeset/serious-kings-trade.md
@@ -0,0 +1,5 @@
+---
+'@backstage/backend-test-utils': patch
+---
+
+Added mock for health service in `mockServices`.
From 918b397763b17f70bab8494bd7b87ddeb084d1b2 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Wed, 5 Jun 2024 13:27:10 +0200
Subject: [PATCH 47/63] backend-defaults: move over health service
Signed-off-by: Vincenzo Scamporlino
---
.../health/createHealthRouter.ts | 46 --------------
.../health/healthServiceFactory.ts | 37 -----------
.../backend-defaults/api-report-health.md | 13 ++++
packages/backend-defaults/package.json | 4 ++
.../health/healthServiceFactory.test.ts} | 53 ++++++++--------
.../health/healthServiceFactory.ts | 63 +++++++++++++++++++
.../src/entrypoints}/health/index.ts | 0
7 files changed, 107 insertions(+), 109 deletions(-)
delete mode 100644 packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
delete mode 100644 packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
create mode 100644 packages/backend-defaults/api-report-health.md
rename packages/{backend-app-api/src/services/implementations/health/createHealthRouter.test.ts => backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts} (63%)
create mode 100644 packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
rename packages/{backend-app-api/src/services/implementations => backend-defaults/src/entrypoints}/health/index.ts (100%)
diff --git a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts b/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
deleted file mode 100644
index f2ff2ecd73..0000000000
--- a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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 Router from 'express-promise-router';
-import { Request, Response } from 'express';
-import { RootLifecycleService } from '@backstage/backend-plugin-api';
-
-export function createHealthRouter(options: {
- lifecycle: RootLifecycleService;
-}) {
- const router = Router();
-
- let isRunning = false;
- options.lifecycle.addStartupHook(() => {
- isRunning = true;
- });
- options.lifecycle.addShutdownHook(() => {
- isRunning = false;
- });
-
- router.get('/v1/readiness', async (_request: Request, response: Response) => {
- if (!isRunning) {
- throw new Error('Backend has not started yet');
- }
- response.json({ status: 'ok' });
- });
-
- router.get('/v1/liveness', async (_request: Request, response: Response) => {
- response.json({ status: 'ok' });
- });
-
- return router;
-}
diff --git a/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts b/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
deleted file mode 100644
index b79ba34a87..0000000000
--- a/packages/backend-app-api/src/services/implementations/health/healthServiceFactory.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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 {
- coreServices,
- createServiceFactory,
-} from '@backstage/backend-plugin-api';
-import { createHealthRouter } from './createHealthRouter';
-
-/**
- * @public
- */
-export const healthServiceFactory = createServiceFactory({
- service: coreServices.health,
- deps: {
- rootHttpRouter: coreServices.rootHttpRouter,
- lifecycle: coreServices.rootLifecycle,
- },
- async factory({ lifecycle, rootHttpRouter }) {
- rootHttpRouter.use('.backstage/health', createHealthRouter({ lifecycle }));
-
- return {};
- },
-});
diff --git a/packages/backend-defaults/api-report-health.md b/packages/backend-defaults/api-report-health.md
new file mode 100644
index 0000000000..795bdaac78
--- /dev/null
+++ b/packages/backend-defaults/api-report-health.md
@@ -0,0 +1,13 @@
+## API Report File for "@backstage/backend-defaults"
+
+> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
+
+```ts
+import { HealthService } from '@backstage/backend-plugin-api';
+import { ServiceFactory } from '@backstage/backend-plugin-api';
+
+// @public (undocumented)
+export const healthServiceFactory: () => ServiceFactory;
+
+// (No @packageDocumentation comment for this package)
+```
diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json
index 4c34c7f317..c29d973997 100644
--- a/packages/backend-defaults/package.json
+++ b/packages/backend-defaults/package.json
@@ -24,6 +24,7 @@
"./cache": "./src/entrypoints/cache/index.ts",
"./database": "./src/entrypoints/database/index.ts",
"./discovery": "./src/entrypoints/discovery/index.ts",
+ "./health": "./src/entrypoints/health/index.ts",
"./httpAuth": "./src/entrypoints/httpAuth/index.ts",
"./httpRouter": "./src/entrypoints/httpRouter/index.ts",
"./lifecycle": "./src/entrypoints/lifecycle/index.ts",
@@ -54,6 +55,9 @@
"discovery": [
"src/entrypoints/discovery/index.ts"
],
+ "health": [
+ "src/entrypoints/health/index.ts"
+ ],
"httpAuth": [
"src/entrypoints/httpAuth/index.ts"
],
diff --git a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
similarity index 63%
rename from packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts
rename to packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
index f8c51ee08d..40a41d74f5 100644
--- a/packages/backend-app-api/src/services/implementations/health/createHealthRouter.test.ts
+++ b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
@@ -1,3 +1,6 @@
+import { mockServices } from '@backstage/backend-test-utils';
+import { DefaultHealthService } from './healthServiceFactory';
+
/*
* Copyright 2024 The Backstage Authors
*
@@ -13,22 +16,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-import { mockServices } from '@backstage/backend-test-utils';
-import request from 'supertest';
-import { createHealthRouter } from './createHealthRouter';
-import express from 'express';
-
-describe('createHealthRouter', () => {
+describe('DefaultHealthService', () => {
describe('readiness', () => {
it(`should return a 500 response if the server hasn't started yet`, async () => {
- const hc = createHealthRouter({
+ const service = new DefaultHealthService({
lifecycle: mockServices.rootLifecycle.mock(),
});
- const app = express().use(hc);
-
- const response = await request(app).get('/v1/readiness');
- expect(response.status).toBe(500);
+ await expect(service.getReadiness()).resolves.toEqual({ status: 503 });
});
it('should return 200 if the server has started', async () => {
@@ -38,12 +32,16 @@ describe('createHealthRouter', () => {
fn => (mockServerStartedFn = fn),
);
- const hc = createHealthRouter({ lifecycle });
- const app = express().use(hc);
+ const service = new DefaultHealthService({
+ lifecycle: mockServices.rootLifecycle.mock(),
+ });
mockServerStartedFn();
- const response = await request(app).get('/v1/readiness').expect(200);
- expect(response.body).toEqual({ status: 'ok' });
+
+ await expect(service.getReadiness()).resolves.toEqual({
+ status: 200,
+ payload: { status: 'ok' },
+ });
});
it(`should return a 500 response if the server has stopped`, async () => {
@@ -57,25 +55,28 @@ describe('createHealthRouter', () => {
fn => (mockServerStoppedFn = fn),
);
- const hc = createHealthRouter({ lifecycle });
- const app = express().use(hc);
+ const service = new DefaultHealthService({
+ lifecycle: mockServices.rootLifecycle.mock(),
+ });
mockServerStartedFn();
mockServerStoppedFn();
- const response = await request(app).get('/v1/readiness');
- expect(response.status).toBe(500);
+ await expect(service.getReadiness()).resolves.toEqual({
+ status: 503,
+ });
});
});
describe('liveness', () => {
it('should return 200 if the server has started', async () => {
- const lifecycle = mockServices.rootLifecycle.mock();
+ const service = new DefaultHealthService({
+ lifecycle: mockServices.rootLifecycle.mock(),
+ });
- const hc = createHealthRouter({ lifecycle });
- const app = express().use(hc);
-
- const response = await request(app).get('/v1/liveness').expect(200);
- expect(response.body).toEqual({ status: 'ok' });
+ await expect(service.getLiveness()).resolves.toEqual({
+ status: 200,
+ payload: { status: 'ok' },
+ });
});
});
});
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
new file mode 100644
index 0000000000..3f397ce29b
--- /dev/null
+++ b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
@@ -0,0 +1,63 @@
+import {
+ HealthService,
+ RootLifecycleService,
+ coreServices,
+ createServiceFactory,
+} from '@backstage/backend-plugin-api';
+
+/*
+ * 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.
+ */
+
+/** @internal */
+export class DefaultHealthService implements HealthService {
+ #isRunning = false;
+
+ constructor(readonly options: { lifecycle: RootLifecycleService }) {
+ options.lifecycle.addStartupHook(() => {
+ this.#isRunning = true;
+ });
+ options.lifecycle.addShutdownHook(() => {
+ this.#isRunning = false;
+ });
+ }
+
+ async getLiveness(): Promise<{ status: number; payload?: any }> {
+ return { status: 200, payload: { status: 'ok' } };
+ }
+ async getReadiness(): Promise<{ status: number; payload?: any }> {
+ if (!this.#isRunning) {
+ return {
+ status: 503,
+ payload: { message: 'Backend has not started yet', status: 'error' },
+ };
+ }
+
+ return { status: 200, payload: { status: 'ok' } };
+ }
+}
+
+/**
+ * @public
+ */
+export const healthServiceFactory = createServiceFactory({
+ service: coreServices.health,
+ deps: {
+ lifecycle: coreServices.rootLifecycle,
+ },
+ async factory({ lifecycle }) {
+ return new DefaultHealthService({ lifecycle });
+ },
+});
diff --git a/packages/backend-app-api/src/services/implementations/health/index.ts b/packages/backend-defaults/src/entrypoints/health/index.ts
similarity index 100%
rename from packages/backend-app-api/src/services/implementations/health/index.ts
rename to packages/backend-defaults/src/entrypoints/health/index.ts
From 44f97c173bf9eefb3c281928b84aa1f80bc32375 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Wed, 5 Jun 2024 13:27:39 +0200
Subject: [PATCH 48/63] backend-app-api: flip logic of health service
Signed-off-by: Vincenzo Scamporlino
---
.../health/healthServiceFactory.test.ts | 14 ++++++-
.../health/healthServiceFactory.ts | 1 +
.../rootHttpRouter/createHealthRouter.ts | 42 +++++++++++++++++++
.../rootHttpRouterServiceFactory.ts | 9 +++-
packages/backend-plugin-api/api-report.md | 13 +++++-
.../src/services/definitions/HealthService.ts | 5 ++-
.../src/next/services/mockServices.ts | 18 ++++----
7 files changed, 88 insertions(+), 14 deletions(-)
create mode 100644 packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
index 40a41d74f5..7e160cbd82 100644
--- a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
+++ b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
@@ -22,7 +22,13 @@ describe('DefaultHealthService', () => {
const service = new DefaultHealthService({
lifecycle: mockServices.rootLifecycle.mock(),
});
- await expect(service.getReadiness()).resolves.toEqual({ status: 503 });
+ await expect(service.getReadiness()).resolves.toEqual({
+ status: 503,
+ payload: {
+ message: 'Backend has not started yet',
+ status: 'error',
+ },
+ });
});
it('should return 200 if the server has started', async () => {
@@ -33,7 +39,7 @@ describe('DefaultHealthService', () => {
);
const service = new DefaultHealthService({
- lifecycle: mockServices.rootLifecycle.mock(),
+ lifecycle,
});
mockServerStartedFn();
@@ -63,6 +69,10 @@ describe('DefaultHealthService', () => {
mockServerStoppedFn();
await expect(service.getReadiness()).resolves.toEqual({
status: 503,
+ payload: {
+ message: 'Backend has not started yet',
+ status: 'error',
+ },
});
});
});
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
index 3f397ce29b..f68451df74 100644
--- a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
@@ -37,6 +37,7 @@ export class DefaultHealthService implements HealthService {
async getLiveness(): Promise<{ status: number; payload?: any }> {
return { status: 200, payload: { status: 'ok' } };
}
+
async getReadiness(): Promise<{ status: number; payload?: any }> {
if (!this.#isRunning) {
return {
diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
new file mode 100644
index 0000000000..012a268e02
--- /dev/null
+++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
@@ -0,0 +1,42 @@
+import { HealthService } from '@backstage/backend-plugin-api';
+
+/*
+ * 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 Router from 'express-promise-router';
+import { Request, Response } from 'express';
+
+export function createHealthRouter(options: { health: HealthService }) {
+ const router = Router();
+
+ router.get(
+ '.backstage/health/v1/readiness',
+ async (_request: Request, response: Response) => {
+ const { status, payload } = await options.health.getReadiness();
+ response.status(status).json(payload);
+ },
+ );
+
+ router.get(
+ '.backstage/health/v1/liveness',
+ async (_request: Request, response: Response) => {
+ const { status, payload } = await options.health.getLiveness();
+ response.status(status).json(payload);
+ },
+ );
+
+ return router;
+}
diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
index ea3dc42eb7..5f22cf5ced 100644
--- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
@@ -29,6 +29,7 @@ import {
readHttpServerOptions,
} from './http';
import { DefaultRootHttpRouter } from './DefaultRootHttpRouter';
+import { createHealthRouter } from './createHealthRouter';
/**
* @public
@@ -41,6 +42,7 @@ export interface RootHttpRouterConfigureContext {
config: RootConfigService;
logger: LoggerService;
lifecycle: LifecycleService;
+ healthRouter: RequestHandler;
applyDefaults: () => void;
}
@@ -75,8 +77,9 @@ export const rootHttpRouterServiceFactory = createServiceFactory(
config: coreServices.rootConfig,
rootLogger: coreServices.rootLogger,
lifecycle: coreServices.rootLifecycle,
+ health: coreServices.health,
},
- async factory({ config, rootLogger, lifecycle }) {
+ async factory({ config, rootLogger, lifecycle, health }) {
const { indexPath, configure = defaultConfigure } = options ?? {};
const logger = rootLogger.child({ service: 'rootHttpRouter' });
const app = express();
@@ -84,6 +87,8 @@ export const rootHttpRouterServiceFactory = createServiceFactory(
const router = DefaultRootHttpRouter.create({ indexPath });
const middleware = MiddlewareFactory.create({ config, logger });
const routes = router.handler();
+
+ const healthRouter = createHealthRouter({ health });
const server = await createHttpServer(
app,
readHttpServerOptions(config.getOptionalConfig('backend')),
@@ -98,11 +103,13 @@ export const rootHttpRouterServiceFactory = createServiceFactory(
config,
logger,
lifecycle,
+ healthRouter,
applyDefaults() {
app.use(middleware.helmet());
app.use(middleware.cors());
app.use(middleware.compression());
app.use(middleware.logging());
+ app.use(healthRouter);
app.use(routes);
app.use(middleware.notFound());
app.use(middleware.error());
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index 5e02ad1787..ee5aecd63b 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -335,7 +335,18 @@ export type ExtensionPoint = {
export type ExtensionPointConfig = CreateExtensionPointOptions;
// @public (undocumented)
-export interface HealthService {}
+export interface HealthService {
+ // (undocumented)
+ getLiveness(): Promise<{
+ status: number;
+ payload?: any;
+ }>;
+ // (undocumented)
+ getReadiness(): Promise<{
+ status: number;
+ payload?: any;
+ }>;
+}
// @public
export interface HttpAuthService {
diff --git a/packages/backend-plugin-api/src/services/definitions/HealthService.ts b/packages/backend-plugin-api/src/services/definitions/HealthService.ts
index d04a8a6133..b2dc4f415e 100644
--- a/packages/backend-plugin-api/src/services/definitions/HealthService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/HealthService.ts
@@ -17,4 +17,7 @@
/**
* @public
*/
-export interface HealthService {}
+export interface HealthService {
+ getLiveness(): Promise<{ status: number; payload?: any }>;
+ getReadiness(): Promise<{ status: number; payload?: any }>;
+}
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index 22496bd6e1..a59d053b95 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -20,11 +20,11 @@ import {
HostDiscovery,
discoveryServiceFactory,
} from '@backstage/backend-defaults/discovery';
+import { healthServiceFactory } from '@backstage/backend-defaults/health';
import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
import { loggerServiceFactory } from '@backstage/backend-defaults/logger';
import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';
-import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';
import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';
@@ -345,6 +345,14 @@ export namespace mockServices {
}));
}
+ export namespace health {
+ export const factory = healthServiceFactory;
+ export const mock = simpleMock(coreServices.health, () => ({
+ getLiveness: jest.fn(),
+ getReadiness: jest.fn(),
+ }));
+ }
+
export namespace httpRouter {
export const factory = httpRouterServiceFactory;
export const mock = simpleMock(coreServices.httpRouter, () => ({
@@ -384,14 +392,6 @@ export namespace mockServices {
}));
}
- export namespace rootHealth {
- export const factory = rootHealthServiceFactory;
- export const mock = simpleMock(coreServices.health, () => ({
- getLiveness: jest.fn(),
- getReadiness: jest.fn(),
- }));
- }
-
export namespace rootLifecycle {
export const factory = rootLifecycleServiceFactory;
export const mock = simpleMock(coreServices.rootLifecycle, () => ({
From 506fc235567a02a8609c5859f3311cda393aaa04 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 13 Jun 2024 13:11:03 +0200
Subject: [PATCH 49/63] backend-defaults: fix notice
Signed-off-by: Vincenzo Scamporlino
---
.../src/entrypoints/health/healthServiceFactory.ts | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
index f68451df74..652ad8758f 100644
--- a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
@@ -1,10 +1,3 @@
-import {
- HealthService,
- RootLifecycleService,
- coreServices,
- createServiceFactory,
-} from '@backstage/backend-plugin-api';
-
/*
* Copyright 2024 The Backstage Authors
*
@@ -21,6 +14,13 @@ import {
* limitations under the License.
*/
+import {
+ HealthService,
+ RootLifecycleService,
+ coreServices,
+ createServiceFactory,
+} from '@backstage/backend-plugin-api';
+
/** @internal */
export class DefaultHealthService implements HealthService {
#isRunning = false;
From 0c621514042da57665afc28336be9cfa03fe430d Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 13 Jun 2024 13:39:33 +0200
Subject: [PATCH 50/63] Rename HealthService to RootHealthService
Signed-off-by: Vincenzo Scamporlino
---
docs/backend-system/core-services/01-index.md | 2 +-
.../core-services/{health.md => root-health.md} | 0
packages/backend-defaults/package.json | 8 ++++----
packages/backend-defaults/src/CreateBackend.ts | 4 ++--
.../src/entrypoints/{health => rootHealth}/index.ts | 2 +-
.../rootHealthServiceFactory.test.ts} | 12 ++++++------
.../rootHealthServiceFactory.ts} | 8 ++++----
.../entrypoints/rootHttpRouter/createHealthRouter.ts | 4 ++--
.../{HealthService.ts => RootHealthService.ts} | 8 +++++++-
.../src/services/definitions/index.ts | 2 +-
.../src/next/services/mockServices.ts | 6 +++---
11 files changed, 31 insertions(+), 25 deletions(-)
rename docs/backend-system/core-services/{health.md => root-health.md} (100%)
rename packages/backend-defaults/src/entrypoints/{health => rootHealth}/index.ts (89%)
rename packages/backend-defaults/src/entrypoints/{health/healthServiceFactory.test.ts => rootHealth/rootHealthServiceFactory.test.ts} (88%)
rename packages/backend-defaults/src/entrypoints/{health/healthServiceFactory.ts => rootHealth/rootHealthServiceFactory.ts} (88%)
rename packages/backend-plugin-api/src/services/definitions/{HealthService.ts => RootHealthService.ts} (83%)
diff --git a/docs/backend-system/core-services/01-index.md b/docs/backend-system/core-services/01-index.md
index 63324292c1..3be12b2e26 100644
--- a/docs/backend-system/core-services/01-index.md
+++ b/docs/backend-system/core-services/01-index.md
@@ -20,7 +20,6 @@ import { coreServices } from '@backstage/backend-plugin-api';
- [Cache Service](./cache.md) - Key-value store for caching data.
- [Database Service](./database.md) - Database access and management via [knex](https://knexjs.org/).
- [Discovery Service](./discovery.md) - Service discovery for inter-plugin communication.
-- [Health Service](./health.md) - Health check endpoints for the backend.
- [Http Auth Service](./http-auth.md) - Authentication of HTTP requests.
- [Http Router Service](./http-router.md) - HTTP route registration for plugins.
- [Identity Service](./identity.md) - Deprecated user authentication service, use the [Auth Service](./auth.md) instead.
@@ -29,6 +28,7 @@ import { coreServices } from '@backstage/backend-plugin-api';
- [Permissions Service](./permissions.md) - Permission system integration for authorization of user actions.
- [Plugin Metadata Service](./plugin-metadata.md) - Built-in service for accessing metadata about the current plugin.
- [Root Config Service](./root-config.md) - Access to static configuration.
+- [Root Health Service](./root-health.md) - Health check endpoints for the backend.
- [Root Http Router Service](./root-http-router.md) - HTTP route registration for root services.
- [Root Lifecycle Service](./root-lifecycle.md) - Registration of backend startup and shutdown lifecycle hooks.
- [Root Logger Service](./root-logger.md) - Root-level logging.
diff --git a/docs/backend-system/core-services/health.md b/docs/backend-system/core-services/root-health.md
similarity index 100%
rename from docs/backend-system/core-services/health.md
rename to docs/backend-system/core-services/root-health.md
diff --git a/packages/backend-defaults/package.json b/packages/backend-defaults/package.json
index c29d973997..2d84bae308 100644
--- a/packages/backend-defaults/package.json
+++ b/packages/backend-defaults/package.json
@@ -24,13 +24,13 @@
"./cache": "./src/entrypoints/cache/index.ts",
"./database": "./src/entrypoints/database/index.ts",
"./discovery": "./src/entrypoints/discovery/index.ts",
- "./health": "./src/entrypoints/health/index.ts",
"./httpAuth": "./src/entrypoints/httpAuth/index.ts",
"./httpRouter": "./src/entrypoints/httpRouter/index.ts",
"./lifecycle": "./src/entrypoints/lifecycle/index.ts",
"./logger": "./src/entrypoints/logger/index.ts",
"./permissions": "./src/entrypoints/permissions/index.ts",
"./rootConfig": "./src/entrypoints/rootConfig/index.ts",
+ "./rootHealth": "./src/entrypoints/rootHealth/index.ts",
"./rootHttpRouter": "./src/entrypoints/rootHttpRouter/index.ts",
"./rootLifecycle": "./src/entrypoints/rootLifecycle/index.ts",
"./rootLogger": "./src/entrypoints/rootLogger/index.ts",
@@ -55,9 +55,6 @@
"discovery": [
"src/entrypoints/discovery/index.ts"
],
- "health": [
- "src/entrypoints/health/index.ts"
- ],
"httpAuth": [
"src/entrypoints/httpAuth/index.ts"
],
@@ -76,6 +73,9 @@
"rootConfig": [
"src/entrypoints/rootConfig/index.ts"
],
+ "rootHealth": [
+ "src/entrypoints/rootHealth/index.ts"
+ ],
"rootHttpRouter": [
"src/entrypoints/rootHttpRouter/index.ts"
],
diff --git a/packages/backend-defaults/src/CreateBackend.ts b/packages/backend-defaults/src/CreateBackend.ts
index 453c5fe592..e3195748a6 100644
--- a/packages/backend-defaults/src/CreateBackend.ts
+++ b/packages/backend-defaults/src/CreateBackend.ts
@@ -24,13 +24,13 @@ import { authServiceFactory } from '@backstage/backend-defaults/auth';
import { cacheServiceFactory } from '@backstage/backend-defaults/cache';
import { databaseServiceFactory } from '@backstage/backend-defaults/database';
import { discoveryServiceFactory } from '@backstage/backend-defaults/discovery';
-import { rootHealthServiceFactory } from './entrypoints/rootHealth';
import { httpAuthServiceFactory } from '@backstage/backend-defaults/httpAuth';
import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
import { loggerServiceFactory } from '@backstage/backend-defaults/logger';
import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';
import { rootConfigServiceFactory } from '@backstage/backend-defaults/rootConfig';
+import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';
import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
import { rootLoggerServiceFactory } from '@backstage/backend-defaults/rootLogger';
@@ -51,6 +51,7 @@ export const defaultServiceFactories = [
lifecycleServiceFactory(),
loggerServiceFactory(),
permissionsServiceFactory(),
+ rootHealthServiceFactory(),
rootHttpRouterServiceFactory(),
rootLifecycleServiceFactory(),
rootLoggerServiceFactory(),
@@ -59,7 +60,6 @@ export const defaultServiceFactories = [
userInfoServiceFactory(),
urlReaderServiceFactory(),
eventsServiceFactory(),
- rootHealthServiceFactory(),
];
/**
diff --git a/packages/backend-defaults/src/entrypoints/health/index.ts b/packages/backend-defaults/src/entrypoints/rootHealth/index.ts
similarity index 89%
rename from packages/backend-defaults/src/entrypoints/health/index.ts
rename to packages/backend-defaults/src/entrypoints/rootHealth/index.ts
index 4aeb4b7979..35225b39c4 100644
--- a/packages/backend-defaults/src/entrypoints/health/index.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHealth/index.ts
@@ -14,4 +14,4 @@
* limitations under the License.
*/
-export { healthServiceFactory } from './healthServiceFactory';
+export { rootHealthServiceFactory } from './rootHealthServiceFactory';
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
similarity index 88%
rename from packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
rename to packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
index 7e160cbd82..fd786e2b28 100644
--- a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.test.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
@@ -1,5 +1,5 @@
import { mockServices } from '@backstage/backend-test-utils';
-import { DefaultHealthService } from './healthServiceFactory';
+import { DefaultRootHealthService } from './rootHealthServiceFactory';
/*
* Copyright 2024 The Backstage Authors
@@ -16,10 +16,10 @@ import { DefaultHealthService } from './healthServiceFactory';
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-describe('DefaultHealthService', () => {
+describe('DefaultRootHealthService', () => {
describe('readiness', () => {
it(`should return a 500 response if the server hasn't started yet`, async () => {
- const service = new DefaultHealthService({
+ const service = new DefaultRootHealthService({
lifecycle: mockServices.rootLifecycle.mock(),
});
await expect(service.getReadiness()).resolves.toEqual({
@@ -38,7 +38,7 @@ describe('DefaultHealthService', () => {
fn => (mockServerStartedFn = fn),
);
- const service = new DefaultHealthService({
+ const service = new DefaultRootHealthService({
lifecycle,
});
@@ -61,7 +61,7 @@ describe('DefaultHealthService', () => {
fn => (mockServerStoppedFn = fn),
);
- const service = new DefaultHealthService({
+ const service = new DefaultRootHealthService({
lifecycle: mockServices.rootLifecycle.mock(),
});
@@ -79,7 +79,7 @@ describe('DefaultHealthService', () => {
describe('liveness', () => {
it('should return 200 if the server has started', async () => {
- const service = new DefaultHealthService({
+ const service = new DefaultRootHealthService({
lifecycle: mockServices.rootLifecycle.mock(),
});
diff --git a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
similarity index 88%
rename from packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
rename to packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
index 652ad8758f..3a00db8285 100644
--- a/packages/backend-defaults/src/entrypoints/health/healthServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
@@ -15,14 +15,14 @@
*/
import {
- HealthService,
+ RootHealthService,
RootLifecycleService,
coreServices,
createServiceFactory,
} from '@backstage/backend-plugin-api';
/** @internal */
-export class DefaultHealthService implements HealthService {
+export class DefaultRootHealthService implements RootHealthService {
#isRunning = false;
constructor(readonly options: { lifecycle: RootLifecycleService }) {
@@ -53,12 +53,12 @@ export class DefaultHealthService implements HealthService {
/**
* @public
*/
-export const healthServiceFactory = createServiceFactory({
+export const rootHealthServiceFactory = createServiceFactory({
service: coreServices.health,
deps: {
lifecycle: coreServices.rootLifecycle,
},
async factory({ lifecycle }) {
- return new DefaultHealthService({ lifecycle });
+ return new DefaultRootHealthService({ lifecycle });
},
});
diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
index 012a268e02..13691ede28 100644
--- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/createHealthRouter.ts
@@ -1,4 +1,4 @@
-import { HealthService } from '@backstage/backend-plugin-api';
+import { RootHealthService } from '@backstage/backend-plugin-api';
/*
* Copyright 2024 The Backstage Authors
@@ -19,7 +19,7 @@ import { HealthService } from '@backstage/backend-plugin-api';
import Router from 'express-promise-router';
import { Request, Response } from 'express';
-export function createHealthRouter(options: { health: HealthService }) {
+export function createHealthRouter(options: { health: RootHealthService }) {
const router = Router();
router.get(
diff --git a/packages/backend-plugin-api/src/services/definitions/HealthService.ts b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
similarity index 83%
rename from packages/backend-plugin-api/src/services/definitions/HealthService.ts
rename to packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
index b2dc4f415e..ac482b5dbb 100644
--- a/packages/backend-plugin-api/src/services/definitions/HealthService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
@@ -17,7 +17,13 @@
/**
* @public
*/
-export interface HealthService {
+export interface RootHealthService {
+ /**
+ * Get the liveness status of the backend.
+ */
getLiveness(): Promise<{ status: number; payload?: any }>;
+ /**
+ * Get the readiness status of the backend.
+ */
getReadiness(): Promise<{ status: number; payload?: any }>;
}
diff --git a/packages/backend-plugin-api/src/services/definitions/index.ts b/packages/backend-plugin-api/src/services/definitions/index.ts
index af0d991f58..5e30d444fd 100644
--- a/packages/backend-plugin-api/src/services/definitions/index.ts
+++ b/packages/backend-plugin-api/src/services/definitions/index.ts
@@ -32,7 +32,7 @@ export type {
export type { RootConfigService } from './RootConfigService';
export type { DatabaseService } from './DatabaseService';
export type { DiscoveryService } from './DiscoveryService';
-export type { HealthService } from './HealthService';
+export type { RootHealthService } from './RootHealthService';
export type {
HttpRouterService,
HttpRouterServiceAuthPolicy,
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index a59d053b95..5055a9eae8 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -20,11 +20,11 @@ import {
HostDiscovery,
discoveryServiceFactory,
} from '@backstage/backend-defaults/discovery';
-import { healthServiceFactory } from '@backstage/backend-defaults/health';
import { httpRouterServiceFactory } from '@backstage/backend-defaults/httpRouter';
import { lifecycleServiceFactory } from '@backstage/backend-defaults/lifecycle';
import { loggerServiceFactory } from '@backstage/backend-defaults/logger';
import { permissionsServiceFactory } from '@backstage/backend-defaults/permissions';
+import { rootHealthServiceFactory } from '@backstage/backend-defaults/rootHealth';
import { rootHttpRouterServiceFactory } from '@backstage/backend-defaults/rootHttpRouter';
import { rootLifecycleServiceFactory } from '@backstage/backend-defaults/rootLifecycle';
import { schedulerServiceFactory } from '@backstage/backend-defaults/scheduler';
@@ -345,8 +345,8 @@ export namespace mockServices {
}));
}
- export namespace health {
- export const factory = healthServiceFactory;
+ export namespace rootHealth {
+ export const factory = rootHealthServiceFactory;
export const mock = simpleMock(coreServices.health, () => ({
getLiveness: jest.fn(),
getReadiness: jest.fn(),
From 5c4e876e62afbfa56ff3105a2eca0811a7942e8f Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 13 Jun 2024 14:25:02 +0200
Subject: [PATCH 51/63] health api reports
Signed-off-by: Vincenzo Scamporlino
---
...ort-health.md => api-report-rootHealth.md} | 7 +++--
packages/backend-plugin-api/api-report.md | 28 +++++++++----------
2 files changed, 18 insertions(+), 17 deletions(-)
rename packages/backend-defaults/{api-report-health.md => api-report-rootHealth.md} (65%)
diff --git a/packages/backend-defaults/api-report-health.md b/packages/backend-defaults/api-report-rootHealth.md
similarity index 65%
rename from packages/backend-defaults/api-report-health.md
rename to packages/backend-defaults/api-report-rootHealth.md
index 795bdaac78..ffa067605a 100644
--- a/packages/backend-defaults/api-report-health.md
+++ b/packages/backend-defaults/api-report-rootHealth.md
@@ -3,11 +3,14 @@
> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/).
```ts
-import { HealthService } from '@backstage/backend-plugin-api';
+import { RootHealthService } from '@backstage/backend-plugin-api';
import { ServiceFactory } from '@backstage/backend-plugin-api';
// @public (undocumented)
-export const healthServiceFactory: () => ServiceFactory;
+export const rootHealthServiceFactory: () => ServiceFactory<
+ RootHealthService,
+ 'root'
+>;
// (No @packageDocumentation comment for this package)
```
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index ee5aecd63b..f527e366c0 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -194,7 +194,7 @@ export namespace coreServices {
const rootConfig: ServiceRef;
const database: ServiceRef;
const discovery: ServiceRef;
- const health: ServiceRef;
+ const health: ServiceRef;
const httpAuth: ServiceRef;
const httpRouter: ServiceRef;
const lifecycle: ServiceRef;
@@ -334,20 +334,6 @@ export type ExtensionPoint = {
// @public @deprecated (undocumented)
export type ExtensionPointConfig = CreateExtensionPointOptions;
-// @public (undocumented)
-export interface HealthService {
- // (undocumented)
- getLiveness(): Promise<{
- status: number;
- payload?: any;
- }>;
- // (undocumented)
- getReadiness(): Promise<{
- status: number;
- payload?: any;
- }>;
-}
-
// @public
export interface HttpAuthService {
credentials(
@@ -515,6 +501,18 @@ export function resolveSafeChildPath(base: string, path: string): string;
// @public
export interface RootConfigService extends Config {}
+// @public (undocumented)
+export interface RootHealthService {
+ getLiveness(): Promise<{
+ status: number;
+ payload?: any;
+ }>;
+ getReadiness(): Promise<{
+ status: number;
+ payload?: any;
+ }>;
+}
+
// @public
export interface RootHttpRouterService {
use(path: string, handler: Handler): void;
From 73a45650e2872fdad10ea9edc9f37baa1e847957 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 12:11:08 +0200
Subject: [PATCH 52/63] api reports
Signed-off-by: Vincenzo Scamporlino
---
packages/backend-app-api/api-report.md | 4 ----
.../api-report-rootHttpRouter.md | 2 ++
.../rootHealth/rootHealthServiceFactory.ts | 2 +-
.../rootHttpRouterServiceFactory.ts | 2 +-
packages/backend-plugin-api/api-report.md | 2 +-
.../src/services/definitions/coreServices.ts | 4 ++--
packages/backend-test-utils/api-report.md | 20 +++++++++----------
.../src/next/services/mockServices.ts | 2 +-
8 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/packages/backend-app-api/api-report.md b/packages/backend-app-api/api-report.md
index a18f027273..7518f8e2cc 100644
--- a/packages/backend-app-api/api-report.md
+++ b/packages/backend-app-api/api-report.md
@@ -18,7 +18,6 @@ import { ErrorRequestHandler } from 'express';
import { Express as Express_2 } from 'express';
import { Format } from 'logform';
import { Handler } from 'express';
-import { HealthService } from '@backstage/backend-plugin-api';
import { HelmetOptions } from 'helmet';
import * as http from 'http';
import { HttpAuthService } from '@backstage/backend-plugin-api';
@@ -127,9 +126,6 @@ export const discoveryServiceFactory: () => ServiceFactory<
// @public @deprecated (undocumented)
export type ExtendedHttpServer = ExtendedHttpServer_2;
-// @public (undocumented)
-export const healthServiceFactory: () => ServiceFactory;
-
// @public @deprecated
export class HostDiscovery implements DiscoveryService {
static fromConfig(
diff --git a/packages/backend-defaults/api-report-rootHttpRouter.md b/packages/backend-defaults/api-report-rootHttpRouter.md
index b753406202..d9727fd36d 100644
--- a/packages/backend-defaults/api-report-rootHttpRouter.md
+++ b/packages/backend-defaults/api-report-rootHttpRouter.md
@@ -121,6 +121,8 @@ export interface RootHttpRouterConfigureContext {
// (undocumented)
config: RootConfigService;
// (undocumented)
+ healthRouter: RequestHandler;
+ // (undocumented)
lifecycle: LifecycleService;
// (undocumented)
logger: LoggerService;
diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
index 3a00db8285..c8b4ad5394 100644
--- a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.ts
@@ -54,7 +54,7 @@ export class DefaultRootHealthService implements RootHealthService {
* @public
*/
export const rootHealthServiceFactory = createServiceFactory({
- service: coreServices.health,
+ service: coreServices.rootHealth,
deps: {
lifecycle: coreServices.rootLifecycle,
},
diff --git a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
index 5f22cf5ced..22f5c2f310 100644
--- a/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHttpRouter/rootHttpRouterServiceFactory.ts
@@ -77,7 +77,7 @@ export const rootHttpRouterServiceFactory = createServiceFactory(
config: coreServices.rootConfig,
rootLogger: coreServices.rootLogger,
lifecycle: coreServices.rootLifecycle,
- health: coreServices.health,
+ health: coreServices.rootHealth,
},
async factory({ config, rootLogger, lifecycle, health }) {
const { indexPath, configure = defaultConfigure } = options ?? {};
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index f527e366c0..ef5aa22cf4 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -194,7 +194,7 @@ export namespace coreServices {
const rootConfig: ServiceRef;
const database: ServiceRef;
const discovery: ServiceRef;
- const health: ServiceRef;
+ const rootHealth: ServiceRef;
const httpAuth: ServiceRef;
const httpRouter: ServiceRef;
const lifecycle: ServiceRef;
diff --git a/packages/backend-plugin-api/src/services/definitions/coreServices.ts b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
index 36ec0151c5..33d1da2903 100644
--- a/packages/backend-plugin-api/src/services/definitions/coreServices.ts
+++ b/packages/backend-plugin-api/src/services/definitions/coreServices.ts
@@ -105,9 +105,9 @@ export namespace coreServices {
/**
* The service reference for the plugin scoped {@link RootHealthService}.
*/
- export const health = createServiceRef<
+ export const rootHealth = createServiceRef<
import('./RootHealthService').RootHealthService
- >({ id: 'core.health', scope: 'root' });
+ >({ id: 'core.rootHealth', scope: 'root' });
/**
* Authentication of HTTP requests.
diff --git a/packages/backend-test-utils/api-report.md b/packages/backend-test-utils/api-report.md
index 07b393b653..a2fb4b7674 100644
--- a/packages/backend-test-utils/api-report.md
+++ b/packages/backend-test-utils/api-report.md
@@ -21,7 +21,6 @@ import { DiscoveryService } from '@backstage/backend-plugin-api';
import { EventsService } from '@backstage/plugin-events-node';
import { ExtendedHttpServer } from '@backstage/backend-app-api';
import { ExtensionPoint } from '@backstage/backend-plugin-api';
-import { HealthService } from '@backstage/backend-plugin-api';
import { HttpAuthService } from '@backstage/backend-plugin-api';
import { HttpRouterFactoryOptions } from '@backstage/backend-defaults/httpRouter';
import { HttpRouterService } from '@backstage/backend-plugin-api';
@@ -33,6 +32,7 @@ import { LifecycleService } from '@backstage/backend-plugin-api';
import { LoggerService } from '@backstage/backend-plugin-api';
import { PermissionsService } from '@backstage/backend-plugin-api';
import { RootConfigService } from '@backstage/backend-plugin-api';
+import { RootHealthService } from '@backstage/backend-plugin-api';
import { RootHttpRouterFactoryOptions } from '@backstage/backend-defaults/rootHttpRouter';
import { RootHttpRouterService } from '@backstage/backend-plugin-api';
import { RootLifecycleService } from '@backstage/backend-plugin-api';
@@ -200,15 +200,6 @@ export namespace mockServices {
partialImpl?: Partial | undefined,
) => ServiceMock;
}
- // (undocumented)
- export namespace health {
- const // (undocumented)
- factory: () => ServiceFactory;
- const // (undocumented)
- mock: (
- partialImpl?: Partial | undefined,
- ) => ServiceMock;
- }
export function httpAuth(options?: {
pluginId?: string;
defaultCredentials?: BackstageCredentials;
@@ -290,6 +281,15 @@ export namespace mockServices {
) => ServiceFactory;
}
// (undocumented)
+ export namespace rootHealth {
+ const // (undocumented)
+ factory: () => ServiceFactory;
+ const // (undocumented)
+ mock: (
+ partialImpl?: Partial | undefined,
+ ) => ServiceMock;
+ }
+ // (undocumented)
export namespace rootHttpRouter {
const // (undocumented)
factory: (
diff --git a/packages/backend-test-utils/src/next/services/mockServices.ts b/packages/backend-test-utils/src/next/services/mockServices.ts
index 5055a9eae8..d56179d958 100644
--- a/packages/backend-test-utils/src/next/services/mockServices.ts
+++ b/packages/backend-test-utils/src/next/services/mockServices.ts
@@ -347,7 +347,7 @@ export namespace mockServices {
export namespace rootHealth {
export const factory = rootHealthServiceFactory;
- export const mock = simpleMock(coreServices.health, () => ({
+ export const mock = simpleMock(coreServices.rootHealth, () => ({
getLiveness: jest.fn(),
getReadiness: jest.fn(),
}));
From e36e507d592c3a6011b6834cd8a0b751bc38c339 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 12:20:18 +0200
Subject: [PATCH 53/63] docs: update root health docs
Signed-off-by: Vincenzo Scamporlino
---
.../core-services/root-health.md | 40 ++++++++++---------
1 file changed, 21 insertions(+), 19 deletions(-)
diff --git a/docs/backend-system/core-services/root-health.md b/docs/backend-system/core-services/root-health.md
index 9a69891624..2a6625fd70 100644
--- a/docs/backend-system/core-services/root-health.md
+++ b/docs/backend-system/core-services/root-health.md
@@ -1,38 +1,40 @@
---
-id: health
-title: Heath Service
+id: root-health
+title: Root Health Service
sidebar_label: Health
description: Documentation for the Health service
---
-The Health service provides some health check endpoints for the plugins. By default, it attaches `/.backstage/health/v1/readiness` and `/.backstage/health/v1/liveness` endpoints to the backend server, which return a JSON object with the status of the backend services.
+The Root Health service provides some health check endpoints for the backend. By default, the `rootHttpRouter` exposes a `/.backstage/health/v1/readiness` and `/.backstage/health/v1/liveness` endpoints, which return a JSON object with the status of the backend services according the implementation of the Root Health Service.
## Configuring the service
-The following example is how you can override the health service to add custom endpoints.
+The following example is how you can override the health service implementation.
```ts
-import { coreServices } from '@backstage/backend-plugin-api';
+import { RootHealthService, coreServices } from '@backstage/backend-plugin-api';
import { WinstonLogger } from '@backstage/backend-app-api';
const backend = createBackend();
+class MyRootHealthService implements RootHealthService {
+ async getLiveness(): Promise<{ status: number; payload?: any }> {
+ // provide your own implementation
+ return { status: 200, payload: { status: 'ok' } };
+ }
+
+ async getReadiness(): Promise<{ status: number; payload?: any }> {
+ // provide your own implementation
+ return { status: 200, payload: { status: 'ok' } };
+ }
+}
+
backend.add(
createServiceFactory({
- service: coreServices.health,
- deps: {
- rootHttpRouter: coreServices.rootHttpRouter,
- },
- async factory({ rootHttpRouter }) {
- rootHttpRouter.get('.backstage/health/v1/readiness', async (req, res) => {
- res.json({ status: 'ok' });
- });
-
- rootHttpRouter.get('.backstage/health/v1/liveness', async (req, res) => {
- res.json({ status: 'ok' });
- });
-
- return {};
+ service: coreServices.rootHealth,
+ deps: {},
+ async factory({}) {
+ return new MyRootHealthService();
},
}),
);
From 4e8455f0bd18bf4e779df3b2484f9ac1dfd2430f Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 12:43:34 +0200
Subject: [PATCH 54/63] Apply suggestions from code review
Signed-off-by: Vincenzo Scamporlino
---
.changeset/bright-panthers-leave.md | 2 +-
.changeset/serious-kings-trade.md | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.changeset/bright-panthers-leave.md b/.changeset/bright-panthers-leave.md
index acd9764fe6..14798b6b39 100644
--- a/.changeset/bright-panthers-leave.md
+++ b/.changeset/bright-panthers-leave.md
@@ -4,4 +4,4 @@
'@backstage/backend-app-api': patch
---
-Added a new health service which adds new endpoints for health checks.
+Added a new Root Health Service which adds new endpoints for health checks.
diff --git a/.changeset/serious-kings-trade.md b/.changeset/serious-kings-trade.md
index c07e92b88a..826392bf98 100644
--- a/.changeset/serious-kings-trade.md
+++ b/.changeset/serious-kings-trade.md
@@ -2,4 +2,4 @@
'@backstage/backend-test-utils': patch
---
-Added mock for health service in `mockServices`.
+Added mock for the Root Health Service in `mockServices`.
From 73b4e727e9a3c31460f1b8ba4533562404a9b2ad Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 15:22:35 +0200
Subject: [PATCH 55/63] Update .changeset/bright-panthers-leave.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Fredrik Adelöw
Signed-off-by: Vincenzo Scamporlino
---
.changeset/bright-panthers-leave.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/.changeset/bright-panthers-leave.md b/.changeset/bright-panthers-leave.md
index 14798b6b39..35d9c0f869 100644
--- a/.changeset/bright-panthers-leave.md
+++ b/.changeset/bright-panthers-leave.md
@@ -1,7 +1,6 @@
---
'@backstage/backend-plugin-api': patch
'@backstage/backend-defaults': patch
-'@backstage/backend-app-api': patch
---
Added a new Root Health Service which adds new endpoints for health checks.
From cd22b4066660158b247ba2c9d728f6a777e44351 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 15:31:34 +0200
Subject: [PATCH 56/63] Apply suggestions from code review
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Co-authored-by: Fredrik Adelöw
Signed-off-by: Vincenzo Scamporlino
---
docs/backend-system/core-services/root-health.md | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/docs/backend-system/core-services/root-health.md b/docs/backend-system/core-services/root-health.md
index 2a6625fd70..cdf18aa1f9 100644
--- a/docs/backend-system/core-services/root-health.md
+++ b/docs/backend-system/core-services/root-health.md
@@ -9,11 +9,10 @@ The Root Health service provides some health check endpoints for the backend. By
## Configuring the service
-The following example is how you can override the health service implementation.
+The following example shows how you can override the root health service implementation.
```ts
import { RootHealthService, coreServices } from '@backstage/backend-plugin-api';
-import { WinstonLogger } from '@backstage/backend-app-api';
const backend = createBackend();
From 7df5c8875c12058e6b3e61827f074c324e3d82c0 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 15:41:19 +0200
Subject: [PATCH 57/63] backend-defaults: test tweaks
Signed-off-by: Vincenzo Scamporlino
---
.../rootHealthServiceFactory.test.ts | 29 +++++++++----------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
index fd786e2b28..0eee5c18c6 100644
--- a/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
+++ b/packages/backend-defaults/src/entrypoints/rootHealth/rootHealthServiceFactory.test.ts
@@ -1,6 +1,3 @@
-import { mockServices } from '@backstage/backend-test-utils';
-import { DefaultRootHealthService } from './rootHealthServiceFactory';
-
/*
* Copyright 2024 The Backstage Authors
*
@@ -16,6 +13,10 @@ import { DefaultRootHealthService } from './rootHealthServiceFactory';
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+import { mockServices } from '@backstage/backend-test-utils';
+import { DefaultRootHealthService } from './rootHealthServiceFactory';
+
describe('DefaultRootHealthService', () => {
describe('readiness', () => {
it(`should return a 500 response if the server hasn't started yet`, async () => {
@@ -32,11 +33,11 @@ describe('DefaultRootHealthService', () => {
});
it('should return 200 if the server has started', async () => {
- const lifecycle = mockServices.rootLifecycle.mock();
let mockServerStartedFn = () => {};
- lifecycle.addStartupHook.mockImplementation(
- fn => (mockServerStartedFn = fn),
- );
+
+ const lifecycle = mockServices.rootLifecycle.mock({
+ addStartupHook: jest.fn(fn => (mockServerStartedFn = fn)),
+ });
const service = new DefaultRootHealthService({
lifecycle,
@@ -51,18 +52,16 @@ describe('DefaultRootHealthService', () => {
});
it(`should return a 500 response if the server has stopped`, async () => {
- const lifecycle = mockServices.rootLifecycle.mock();
let mockServerStartedFn = () => {};
let mockServerStoppedFn = () => {};
- lifecycle.addStartupHook.mockImplementation(
- fn => (mockServerStartedFn = fn),
- );
- lifecycle.addShutdownHook.mockImplementation(
- fn => (mockServerStoppedFn = fn),
- );
+
+ const lifecycle = mockServices.rootLifecycle.mock({
+ addStartupHook: jest.fn(fn => (mockServerStartedFn = fn)),
+ addShutdownHook: jest.fn(fn => (mockServerStoppedFn = fn)),
+ });
const service = new DefaultRootHealthService({
- lifecycle: mockServices.rootLifecycle.mock(),
+ lifecycle,
});
mockServerStartedFn();
From 878f2efc514810e03567d167b61b92f66cd74790 Mon Sep 17 00:00:00 2001
From: Vincenzo Scamporlino
Date: Thu, 20 Jun 2024 15:45:02 +0200
Subject: [PATCH 58/63] backend-plugin-api: fix typings in health service
Signed-off-by: Vincenzo Scamporlino
---
docs/backend-system/core-services/root-health.md | 4 ++--
packages/backend-plugin-api/api-report.md | 4 ++--
.../src/services/definitions/RootHealthService.ts | 6 ++++--
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/docs/backend-system/core-services/root-health.md b/docs/backend-system/core-services/root-health.md
index cdf18aa1f9..fc73ba9546 100644
--- a/docs/backend-system/core-services/root-health.md
+++ b/docs/backend-system/core-services/root-health.md
@@ -17,12 +17,12 @@ import { RootHealthService, coreServices } from '@backstage/backend-plugin-api';
const backend = createBackend();
class MyRootHealthService implements RootHealthService {
- async getLiveness(): Promise<{ status: number; payload?: any }> {
+ async getLiveness() {
// provide your own implementation
return { status: 200, payload: { status: 'ok' } };
}
- async getReadiness(): Promise<{ status: number; payload?: any }> {
+ async getReadiness() {
// provide your own implementation
return { status: 200, payload: { status: 'ok' } };
}
diff --git a/packages/backend-plugin-api/api-report.md b/packages/backend-plugin-api/api-report.md
index ef5aa22cf4..e9762f652e 100644
--- a/packages/backend-plugin-api/api-report.md
+++ b/packages/backend-plugin-api/api-report.md
@@ -505,11 +505,11 @@ export interface RootConfigService extends Config {}
export interface RootHealthService {
getLiveness(): Promise<{
status: number;
- payload?: any;
+ payload?: JsonValue;
}>;
getReadiness(): Promise<{
status: number;
- payload?: any;
+ payload?: JsonValue;
}>;
}
diff --git a/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
index ac482b5dbb..e6c56e8654 100644
--- a/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
+++ b/packages/backend-plugin-api/src/services/definitions/RootHealthService.ts
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+import { JsonValue } from '@backstage/types';
+
/**
* @public
*/
@@ -21,9 +23,9 @@ export interface RootHealthService {
/**
* Get the liveness status of the backend.
*/
- getLiveness(): Promise<{ status: number; payload?: any }>;
+ getLiveness(): Promise<{ status: number; payload?: JsonValue }>;
/**
* Get the readiness status of the backend.
*/
- getReadiness(): Promise<{ status: number; payload?: any }>;
+ getReadiness(): Promise<{ status: number; payload?: JsonValue }>;
}
From e2e320cac00ab7e511bb58c8a299a5b2f9b35bff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Valentin=20V=C4=82LCIU?=
Date: Thu, 20 Jun 2024 19:16:42 +0300
Subject: [PATCH 59/63] backstage-cli (templates): update dependencies of the
backend plugins
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* remove unneeded dependencies `winston` and `yn` from the template
of backend plugins;
* use `msw` v2 on the backend plugins; migrating later from v1 to v2
is not straight forward; it is better to start with v2;
Signed-off-by: Valentin VĂLCIU
---
.changeset/friendly-stingrays-occur.md | 7 +++++++
.../cli/templates/default-backend-plugin/package.json.hbs | 6 ++----
2 files changed, 9 insertions(+), 4 deletions(-)
create mode 100644 .changeset/friendly-stingrays-occur.md
diff --git a/.changeset/friendly-stingrays-occur.md b/.changeset/friendly-stingrays-occur.md
new file mode 100644
index 0000000000..3383203b40
--- /dev/null
+++ b/.changeset/friendly-stingrays-occur.md
@@ -0,0 +1,7 @@
+---
+'@backstage/cli': patch
+---
+
+- remove unused dependencies `winston` and `yn` from the template of backend plugins;
+- update `msw` to version `2.3.1` in the template of backend plugins;
+ starting with v1 and switching later to v2 is tedious and not straight forward; it's easier to start with v2;
diff --git a/packages/cli/templates/default-backend-plugin/package.json.hbs b/packages/cli/templates/default-backend-plugin/package.json.hbs
index 6b7aa915aa..c20a1854a2 100644
--- a/packages/cli/templates/default-backend-plugin/package.json.hbs
+++ b/packages/cli/templates/default-backend-plugin/package.json.hbs
@@ -35,9 +35,7 @@
"@types/express": "{{versionQuery '@types/express' '4.17.6'}}",
"express": "{{versionQuery 'express' '4.17.1'}}",
"express-promise-router": "{{versionQuery 'express-promise-router' '4.1.0'}}",
- "winston": "{{versionQuery 'winston' '3.2.1'}}",
- "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}",
- "yn": "{{versionQuery 'yn' '4.0.0'}}"
+ "node-fetch": "{{versionQuery 'node-fetch' '2.6.7'}}"
},
"devDependencies": {
"@backstage/cli": "{{versionQuery '@backstage/cli'}}",
@@ -45,7 +43,7 @@
"@backstage/plugin-auth-backend-module-guest-provider": "{{versionQuery '@backstage/plugin-auth-backend-module-guest-provider'}}",
"@types/supertest": "{{versionQuery '@types/supertest' '2.0.12'}}",
"supertest": "{{versionQuery 'supertest' '6.2.4'}}",
- "msw": "{{versionQuery 'msw' '1.0.0'}}"
+ "msw": "{{versionQuery 'msw' '2.3.1'}}"
},
"files": [
"dist"
From 01999b3c78944af74640c2f1c9737399b3c8a2f3 Mon Sep 17 00:00:00 2001
From: blam
Date: Mon, 24 Jun 2024 10:49:49 +0200
Subject: [PATCH 60/63] chore: enter pre Signed-off-by: blam
---
.changeset/pre.json | 190 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 190 insertions(+)
create mode 100644 .changeset/pre.json
diff --git a/.changeset/pre.json b/.changeset/pre.json
new file mode 100644
index 0000000000..dcb909ba99
--- /dev/null
+++ b/.changeset/pre.json
@@ -0,0 +1,190 @@
+{
+ "mode": "pre",
+ "tag": "next",
+ "initialVersions": {
+ "example-app": "0.2.98",
+ "@backstage/app-defaults": "1.5.6",
+ "example-app-next": "0.0.12",
+ "app-next-example-plugin": "0.0.12",
+ "example-backend": "0.0.27",
+ "@backstage/backend-app-api": "0.7.6",
+ "@backstage/backend-common": "0.23.0",
+ "@backstage/backend-defaults": "0.3.0",
+ "@backstage/backend-dev-utils": "0.1.4",
+ "@backstage/backend-dynamic-feature-service": "0.2.11",
+ "example-backend-legacy": "0.2.99",
+ "@backstage/backend-openapi-utils": "0.1.12",
+ "@backstage/backend-plugin-api": "0.6.19",
+ "@backstage/backend-tasks": "0.5.24",
+ "@backstage/backend-test-utils": "0.4.0",
+ "@backstage/catalog-client": "1.6.5",
+ "@backstage/catalog-model": "1.5.0",
+ "@backstage/cli": "0.26.7",
+ "@backstage/cli-common": "0.1.14",
+ "@backstage/cli-node": "0.2.6",
+ "@backstage/codemods": "0.1.49",
+ "@backstage/config": "1.2.0",
+ "@backstage/config-loader": "1.8.1",
+ "@backstage/core-app-api": "1.12.6",
+ "@backstage/core-compat-api": "0.2.6",
+ "@backstage/core-components": "0.14.8",
+ "@backstage/core-plugin-api": "1.9.3",
+ "@backstage/create-app": "0.5.16",
+ "@backstage/dev-utils": "1.0.33",
+ "e2e-test": "0.2.17",
+ "@backstage/e2e-test-utils": "0.1.1",
+ "@backstage/errors": "1.2.4",
+ "@backstage/eslint-plugin": "0.1.8",
+ "@backstage/frontend-app-api": "0.7.1",
+ "@backstage/frontend-plugin-api": "0.6.6",
+ "@backstage/frontend-test-utils": "0.1.8",
+ "@backstage/integration": "1.12.0",
+ "@backstage/integration-aws-node": "0.1.12",
+ "@backstage/integration-react": "1.1.28",
+ "@backstage/release-manifests": "0.0.11",
+ "@backstage/repo-tools": "0.9.1",
+ "@techdocs/cli": "1.8.12",
+ "techdocs-cli-embedded-app": "0.2.97",
+ "@backstage/test-utils": "1.5.6",
+ "@backstage/theme": "0.5.6",
+ "@backstage/types": "1.1.1",
+ "@backstage/version-bridge": "1.0.8",
+ "yarn-plugin-backstage": "0.0.1",
+ "@backstage/plugin-api-docs": "0.11.6",
+ "@backstage/plugin-api-docs-module-protoc-gen-doc": "0.1.7",
+ "@backstage/plugin-app-backend": "0.3.68",
+ "@backstage/plugin-app-node": "0.1.19",
+ "@backstage/plugin-app-visualizer": "0.1.7",
+ "@backstage/plugin-auth-backend": "0.22.6",
+ "@backstage/plugin-auth-backend-module-atlassian-provider": "0.2.0",
+ "@backstage/plugin-auth-backend-module-aws-alb-provider": "0.1.11",
+ "@backstage/plugin-auth-backend-module-azure-easyauth-provider": "0.1.2",
+ "@backstage/plugin-auth-backend-module-bitbucket-provider": "0.1.2",
+ "@backstage/plugin-auth-backend-module-cloudflare-access-provider": "0.1.2",
+ "@backstage/plugin-auth-backend-module-gcp-iap-provider": "0.2.14",
+ "@backstage/plugin-auth-backend-module-github-provider": "0.1.16",
+ "@backstage/plugin-auth-backend-module-gitlab-provider": "0.1.16",
+ "@backstage/plugin-auth-backend-module-google-provider": "0.1.16",
+ "@backstage/plugin-auth-backend-module-guest-provider": "0.1.5",
+ "@backstage/plugin-auth-backend-module-microsoft-provider": "0.1.14",
+ "@backstage/plugin-auth-backend-module-oauth2-provider": "0.2.0",
+ "@backstage/plugin-auth-backend-module-oauth2-proxy-provider": "0.1.12",
+ "@backstage/plugin-auth-backend-module-oidc-provider": "0.2.0",
+ "@backstage/plugin-auth-backend-module-okta-provider": "0.0.12",
+ "@backstage/plugin-auth-backend-module-onelogin-provider": "0.1.0",
+ "@backstage/plugin-auth-backend-module-pinniped-provider": "0.1.13",
+ "@backstage/plugin-auth-backend-module-vmware-cloud-provider": "0.2.0",
+ "@backstage/plugin-auth-node": "0.4.14",
+ "@backstage/plugin-auth-react": "0.1.3",
+ "@backstage/plugin-bitbucket-cloud-common": "0.2.20",
+ "@backstage/plugin-catalog": "1.21.0",
+ "@backstage/plugin-catalog-backend": "1.23.0",
+ "@backstage/plugin-catalog-backend-module-aws": "0.3.14",
+ "@backstage/plugin-catalog-backend-module-azure": "0.1.39",
+ "@backstage/plugin-catalog-backend-module-backstage-openapi": "0.2.2",
+ "@backstage/plugin-catalog-backend-module-bitbucket-cloud": "0.2.6",
+ "@backstage/plugin-catalog-backend-module-bitbucket-server": "0.1.33",
+ "@backstage/plugin-catalog-backend-module-gcp": "0.1.20",
+ "@backstage/plugin-catalog-backend-module-gerrit": "0.1.36",
+ "@backstage/plugin-catalog-backend-module-github": "0.6.2",
+ "@backstage/plugin-catalog-backend-module-github-org": "0.1.14",
+ "@backstage/plugin-catalog-backend-module-gitlab": "0.3.18",
+ "@backstage/plugin-catalog-backend-module-gitlab-org": "0.0.2",
+ "@backstage/plugin-catalog-backend-module-incremental-ingestion": "0.4.24",
+ "@backstage/plugin-catalog-backend-module-ldap": "0.6.0",
+ "@backstage/plugin-catalog-backend-module-msgraph": "0.5.27",
+ "@backstage/plugin-catalog-backend-module-openapi": "0.1.37",
+ "@backstage/plugin-catalog-backend-module-puppetdb": "0.1.25",
+ "@backstage/plugin-catalog-backend-module-scaffolder-entity-model": "0.1.17",
+ "@backstage/plugin-catalog-backend-module-unprocessed": "0.4.6",
+ "@backstage/plugin-catalog-common": "1.0.24",
+ "@backstage/plugin-catalog-graph": "0.4.6",
+ "@backstage/plugin-catalog-import": "0.12.0",
+ "@backstage/plugin-catalog-node": "1.12.1",
+ "@backstage/plugin-catalog-react": "1.12.1",
+ "@backstage/plugin-catalog-unprocessed-entities": "0.2.5",
+ "@backstage/plugin-catalog-unprocessed-entities-common": "0.0.2",
+ "@backstage/plugin-config-schema": "0.1.56",
+ "@backstage/plugin-devtools": "0.1.15",
+ "@backstage/plugin-devtools-backend": "0.3.5",
+ "@backstage/plugin-devtools-common": "0.1.10",
+ "@backstage/plugin-events-backend": "0.3.6",
+ "@backstage/plugin-events-backend-module-aws-sqs": "0.3.5",
+ "@backstage/plugin-events-backend-module-azure": "0.2.5",
+ "@backstage/plugin-events-backend-module-bitbucket-cloud": "0.2.5",
+ "@backstage/plugin-events-backend-module-gerrit": "0.2.5",
+ "@backstage/plugin-events-backend-module-github": "0.2.5",
+ "@backstage/plugin-events-backend-module-gitlab": "0.2.5",
+ "@backstage/plugin-events-backend-test-utils": "0.1.29",
+ "@backstage/plugin-events-node": "0.3.5",
+ "@internal/plugin-todo-list": "1.0.28",
+ "@internal/plugin-todo-list-backend": "1.0.28",
+ "@internal/plugin-todo-list-common": "1.0.19",
+ "@backstage/plugin-home": "0.7.5",
+ "@backstage/plugin-home-react": "0.1.14",
+ "@backstage/plugin-kubernetes": "0.11.11",
+ "@backstage/plugin-kubernetes-backend": "0.18.0",
+ "@backstage/plugin-kubernetes-cluster": "0.0.12",
+ "@backstage/plugin-kubernetes-common": "0.8.0",
+ "@backstage/plugin-kubernetes-node": "0.1.13",
+ "@backstage/plugin-kubernetes-react": "0.4.0",
+ "@backstage/plugin-notifications": "0.2.2",
+ "@backstage/plugin-notifications-backend": "0.3.0",
+ "@backstage/plugin-notifications-backend-module-email": "0.1.0",
+ "@backstage/plugin-notifications-common": "0.0.4",
+ "@backstage/plugin-notifications-node": "0.2.0",
+ "@backstage/plugin-org": "0.6.26",
+ "@backstage/plugin-org-react": "0.1.25",
+ "@backstage/plugin-permission-backend": "0.5.43",
+ "@backstage/plugin-permission-backend-module-allow-all-policy": "0.1.16",
+ "@backstage/plugin-permission-common": "0.7.14",
+ "@backstage/plugin-permission-node": "0.7.30",
+ "@backstage/plugin-permission-react": "0.4.23",
+ "@backstage/plugin-proxy-backend": "0.5.0",
+ "@backstage/plugin-scaffolder": "1.21.0",
+ "@backstage/plugin-scaffolder-backend": "1.22.9",
+ "@backstage/plugin-scaffolder-backend-module-azure": "0.1.11",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket": "0.2.9",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-cloud": "0.1.9",
+ "@backstage/plugin-scaffolder-backend-module-bitbucket-server": "0.1.9",
+ "@backstage/plugin-scaffolder-backend-module-confluence-to-markdown": "0.2.20",
+ "@backstage/plugin-scaffolder-backend-module-cookiecutter": "0.2.43",
+ "@backstage/plugin-scaffolder-backend-module-gerrit": "0.1.11",
+ "@backstage/plugin-scaffolder-backend-module-gitea": "0.1.9",
+ "@backstage/plugin-scaffolder-backend-module-github": "0.3.0",
+ "@backstage/plugin-scaffolder-backend-module-gitlab": "0.4.1",
+ "@backstage/plugin-scaffolder-backend-module-notifications": "0.0.2",
+ "@backstage/plugin-scaffolder-backend-module-rails": "0.4.36",
+ "@backstage/plugin-scaffolder-backend-module-sentry": "0.1.27",
+ "@backstage/plugin-scaffolder-backend-module-yeoman": "0.3.2",
+ "@backstage/plugin-scaffolder-common": "1.5.3",
+ "@backstage/plugin-scaffolder-node": "0.4.5",
+ "@backstage/plugin-scaffolder-node-test-utils": "0.1.5",
+ "@backstage/plugin-scaffolder-react": "1.9.0",
+ "@backstage/plugin-search": "1.4.12",
+ "@backstage/plugin-search-backend": "1.5.10",
+ "@backstage/plugin-search-backend-module-catalog": "0.1.25",
+ "@backstage/plugin-search-backend-module-elasticsearch": "1.5.0",
+ "@backstage/plugin-search-backend-module-explore": "0.1.25",
+ "@backstage/plugin-search-backend-module-pg": "0.5.28",
+ "@backstage/plugin-search-backend-module-stack-overflow-collator": "0.1.12",
+ "@backstage/plugin-search-backend-module-techdocs": "0.1.24",
+ "@backstage/plugin-search-backend-node": "1.2.24",
+ "@backstage/plugin-search-common": "1.2.12",
+ "@backstage/plugin-search-react": "1.7.12",
+ "@backstage/plugin-signals": "0.0.7",
+ "@backstage/plugin-signals-backend": "0.1.5",
+ "@backstage/plugin-signals-node": "0.1.5",
+ "@backstage/plugin-signals-react": "0.0.4",
+ "@backstage/plugin-techdocs": "1.10.6",
+ "@backstage/plugin-techdocs-addons-test-utils": "1.0.33",
+ "@backstage/plugin-techdocs-backend": "1.10.6",
+ "@backstage/plugin-techdocs-module-addons-contrib": "1.1.11",
+ "@backstage/plugin-techdocs-node": "1.12.5",
+ "@backstage/plugin-techdocs-react": "1.2.5",
+ "@backstage/plugin-user-settings": "0.8.7",
+ "@backstage/plugin-user-settings-backend": "0.2.18",
+ "@backstage/plugin-user-settings-common": "0.0.1"
+ },
+ "changesets": []
+}
From db2bdce0a0cac75fb87dfc26566453e3c404cd46 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Piotr=20Pi=C4=85tkiewicz?=
Date: Mon, 24 Jun 2024 11:59:31 +0200
Subject: [PATCH 61/63] Update discord channel name in README.md
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Signed-off-by: Piotr Piątkiewicz
---
docs/features/techdocs/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/features/techdocs/README.md b/docs/features/techdocs/README.md
index a696b850a8..beec6d1fad 100644
--- a/docs/features/techdocs/README.md
+++ b/docs/features/techdocs/README.md
@@ -102,7 +102,7 @@ See [TechDocs Architecture](architecture.md) to get an overview of where the bel
## Get involved
-Reach out to us in the **#docs-like-code** channel of our
+Reach out to us in the **#techdocs** channel of our
[Discord chatroom](https://github.com/backstage/backstage#community).
## Done
From b8230e475399611128f969b2bd185842b1bf6fcc Mon Sep 17 00:00:00 2001
From: Alper Altay
Date: Mon, 24 Jun 2024 12:59:04 +0200
Subject: [PATCH 62/63] feat: matching plugin type to output
Signed-off-by: Alper Altay
---
packages/cli/src/lib/new/factories/pluginCommon.test.ts | 2 +-
packages/cli/src/lib/new/factories/pluginCommon.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/cli/src/lib/new/factories/pluginCommon.test.ts b/packages/cli/src/lib/new/factories/pluginCommon.test.ts
index d85e490510..82c1c87169 100644
--- a/packages/cli/src/lib/new/factories/pluginCommon.test.ts
+++ b/packages/cli/src/lib/new/factories/pluginCommon.test.ts
@@ -67,7 +67,7 @@ describe('pluginCommon factory', () => {
expect(modified).toBe(true);
expectLogsToMatch(output, [
- 'Creating backend plugin backstage-plugin-test-common',
+ 'Creating common plugin package backstage-plugin-test-common',
'Checking Prerequisites:',
`availability plugins${sep}test-common`,
'creating temp dir',
diff --git a/packages/cli/src/lib/new/factories/pluginCommon.ts b/packages/cli/src/lib/new/factories/pluginCommon.ts
index 560386c618..5f694124ea 100644
--- a/packages/cli/src/lib/new/factories/pluginCommon.ts
+++ b/packages/cli/src/lib/new/factories/pluginCommon.ts
@@ -46,7 +46,7 @@ export const pluginCommon = createFactory({
});
Task.log();
- Task.log(`Creating backend plugin ${chalk.cyan(name)}`);
+ Task.log(`Creating common plugin package ${chalk.cyan(name)}`);
const targetDir = ctx.isMonoRepo
? paths.resolveTargetRoot('plugins', suffix)
From 0540c5a6c237f737d4a06af1abf74bf535dd1d98 Mon Sep 17 00:00:00 2001
From: Alper Altay
Date: Mon, 24 Jun 2024 13:07:34 +0200
Subject: [PATCH 63/63] feat: changeset
Signed-off-by: Alper Altay
---
.changeset/funny-laws-tease.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/funny-laws-tease.md
diff --git a/.changeset/funny-laws-tease.md b/.changeset/funny-laws-tease.md
new file mode 100644
index 0000000000..8ecbc87b65
--- /dev/null
+++ b/.changeset/funny-laws-tease.md
@@ -0,0 +1,5 @@
+---
+'@backstage/cli': patch
+---
+
+Updated the scaffolding output message for `plugin-common` in `backstage-cli`. Now, when executing `backstage-cli new` to create a new `plugin-common` package, the output message accurately reflects the action by displaying `Creating common plugin package...` instead of the previous, less accurate `Creating backend plugin...`.