feat(catalog): add github user ID in user entity

Signed-off-by: Jessica He <jhe@redhat.com>
This commit is contained in:
Jessica He
2025-12-03 09:27:42 -05:00
parent f7aef07e50
commit b3286d57cb
14 changed files with 201 additions and 29 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'@backstage/plugin-auth-backend-module-github-provider': minor
'@backstage/plugin-catalog-backend-module-github': minor
---
Added the `github.com/user-id` annotation to store GitHub's user ID (immutable) in user entities. Also includes addition of the `userIdMatchingUserEntityAnnotation` sign-in resolver that matches users by the new ID.
@@ -17,13 +17,25 @@ export default authModuleGithubProvider;
// @public (undocumented)
export const githubAuthenticator: OAuthAuthenticator<
PassportOAuthAuthenticatorHelper,
PassportProfile
GithubProfile
>;
// @public (undocumented)
export type GithubProfile = PassportProfile & {
nodeId?: string;
};
// @public
export namespace githubSignInResolvers {
const usernameMatchingUserEntityName: SignInResolverFactory<
OAuthAuthenticatorResult<PassportProfile>,
OAuthAuthenticatorResult<GithubProfile>,
| {
dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined;
}
| undefined
>;
const userIdMatchingUserEntityAnnotation: SignInResolverFactory<
OAuthAuthenticatorResult<GithubProfile>,
| {
dangerouslyAllowSignInWithoutUserInCatalog?: boolean | undefined;
}
@@ -22,10 +22,18 @@ import {
PassportProfile,
} from '@backstage/plugin-auth-node';
/** @public */
export type GithubProfile = PassportProfile & {
nodeId?: string;
};
const ACCESS_TOKEN_PREFIX = 'access-token-v2.';
/** @public */
export const githubAuthenticator = createOAuthAuthenticator({
export const githubAuthenticator = createOAuthAuthenticator<
PassportOAuthAuthenticatorHelper,
GithubProfile
>({
defaultProfileTransform:
PassportOAuthAuthenticatorHelper.defaultProfileTransform,
scopes: {
@@ -90,7 +98,7 @@ export const githubAuthenticator = createOAuthAuthenticator({
if (!session.refreshToken && !session.expiresInSeconds) {
session.refreshToken = ACCESS_TOKEN_PREFIX + session.accessToken;
}
return { fullProfile, session };
return { fullProfile: fullProfile as GithubProfile, session };
},
async refresh(input, helper) {
@@ -115,7 +123,7 @@ export const githubAuthenticator = createOAuthAuthenticator({
});
return {
fullProfile,
fullProfile: fullProfile as GithubProfile,
session: {
accessToken,
tokenType: 'bearer',
@@ -20,6 +20,6 @@
* @packageDocumentation
*/
export { githubAuthenticator } from './authenticator';
export { githubAuthenticator, type GithubProfile } from './authenticator';
export { authModuleGithubProvider as default } from './module';
export { githubSignInResolvers } from './resolvers';
@@ -17,11 +17,12 @@
import {
createSignInResolverFactory,
OAuthAuthenticatorResult,
PassportProfile,
SignInInfo,
} from '@backstage/plugin-auth-node';
import { z } from 'zod';
import { GithubProfile } from './authenticator';
/**
* Available sign-in resolvers for the GitHub auth provider.
*
@@ -39,7 +40,7 @@ export namespace githubSignInResolvers {
.optional(),
create(options = {}) {
return async (
info: SignInInfo<OAuthAuthenticatorResult<PassportProfile>>,
info: SignInInfo<OAuthAuthenticatorResult<GithubProfile>>,
ctx,
) => {
const { fullProfile } = info.result;
@@ -63,4 +64,44 @@ export namespace githubSignInResolvers {
};
},
});
/**
* Looks up the user by matching their GitHub user ID to the github.com/user-id annotation.
*/
export const userIdMatchingUserEntityAnnotation = createSignInResolverFactory(
{
optionsSchema: z
.object({
dangerouslyAllowSignInWithoutUserInCatalog: z.boolean().optional(),
})
.optional(),
create(options = {}) {
return async (
info: SignInInfo<OAuthAuthenticatorResult<GithubProfile>>,
ctx,
) => {
const { fullProfile } = info.result;
const userId = fullProfile.nodeId;
if (!userId) {
throw new Error(`GitHub user profile does not contain a user ID`);
}
return ctx.signInWithCatalogUser(
{
annotations: {
'github.com/user-id': userId,
},
},
{
dangerousEntityRefFallback:
options?.dangerouslyAllowSignInWithoutUserInCatalog
? { entityRef: { name: userId } }
: undefined,
},
);
};
},
},
);
}
@@ -305,6 +305,7 @@ export type GithubTeam = {
// @public
export type GithubUser = {
login: string;
id?: string;
bio?: string;
avatarUrl?: string;
email?: string;
@@ -35,3 +35,13 @@ export const ANNOTATION_GITHUB_USER_LOGIN = 'github.com/user-login';
* @public
*/
export const ANNOTATION_GITHUB_TEAM_SLUG = 'github.com/team-slug';
/**
* The value of this annotation is the unique identifier for a user on
* [GitHub](https://github.com) (either the public one, or a private GitHub
* Enterprise installation) that is related to this entity. This is a stable
* identifier that persists even if the user changes their login name.
*
* @public
*/
export const ANNOTATION_GITHUB_USER_ID = 'github.com/user-id';
@@ -19,6 +19,7 @@ import { graphql } from '@octokit/graphql';
import {
ANNOTATION_GITHUB_TEAM_SLUG,
ANNOTATION_GITHUB_USER_LOGIN,
ANNOTATION_GITHUB_USER_ID,
} from './annotation';
import { GithubTeam, GithubUser } from './github';
@@ -69,6 +70,7 @@ export const defaultUserTransformer = async (
name: item.login,
annotations: {
[ANNOTATION_GITHUB_USER_LOGIN]: item.login,
...(item.id && { [ANNOTATION_GITHUB_USER_ID]: item.id }),
},
},
spec: {
@@ -112,6 +112,7 @@ export type GithubOrg = {
*/
export type GithubUser = {
login: string;
id?: string;
bio?: string;
avatarUrl?: string;
email?: string;
@@ -202,6 +203,7 @@ export async function getOrganizationUsers(
avatarUrl,
bio,
email @include(if: $email),
id,
login,
name,
${suspendedAtField}
@@ -268,6 +270,7 @@ export async function getOrganizationTeams(
avatarUrl,
bio,
email,
id,
login,
name,
organizationVerifiedDomainEmails(login: $org)
@@ -362,6 +365,7 @@ export async function getOrganizationTeamsFromUsers(
avatarUrl,
bio,
email,
id,
login,
name,
organizationVerifiedDomainEmails(login: $org)
@@ -38,3 +38,8 @@ export {
buildOrgHierarchy,
} from './org';
export { parseGithubOrgUrl } from './util';
export {
ANNOTATION_GITHUB_USER_LOGIN,
ANNOTATION_GITHUB_TEAM_SLUG,
ANNOTATION_GITHUB_USER_ID,
} from './annotation';
@@ -94,6 +94,7 @@ describe('GithubMultiOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -101,6 +102,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'x',
id: 'g',
name: 'y',
bio: 'z',
email: 'w',
@@ -128,7 +130,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'x' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'x', id: 'g' },
],
},
},
],
@@ -156,6 +161,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'q',
id: 'h',
name: 'r',
bio: 's',
email: 't',
@@ -183,7 +189,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'q' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'q', id: 'h' },
],
},
},
],
@@ -215,6 +224,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
description: 'c',
name: 'a',
@@ -241,6 +251,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/x',
'github.com/user-login': 'x',
'github.com/user-id': 'g',
},
description: 'z',
name: 'x',
@@ -267,6 +278,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/q',
'github.com/user-login': 'q',
'github.com/user-id': 'h',
},
description: 's',
name: 'q',
@@ -382,6 +394,7 @@ describe('GithubMultiOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -389,6 +402,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'x',
id: 'g',
name: 'y',
bio: 'z',
email: 'w',
@@ -416,7 +430,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'x' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'x', id: 'g' },
],
},
},
],
@@ -444,6 +461,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'q',
id: 'h',
name: 'r',
bio: 's',
email: 't',
@@ -471,7 +489,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'q' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'q', id: 'h' },
],
},
},
],
@@ -517,6 +538,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
description: 'c',
name: 'a',
@@ -543,6 +565,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/x',
'github.com/user-login': 'x',
'github.com/user-id': 'g',
},
description: 'z',
name: 'x',
@@ -569,6 +592,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/q',
'github.com/user-login': 'q',
'github.com/user-id': 'h',
},
description: 's',
name: 'q',
@@ -656,6 +680,7 @@ describe('GithubMultiOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -663,6 +688,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'x',
id: 'g',
name: 'y',
bio: 'z',
email: 'w',
@@ -690,7 +716,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'x' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'x', id: 'g' },
],
},
},
],
@@ -718,6 +747,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'q',
id: 'h',
name: 'r',
bio: 's',
email: 't',
@@ -745,7 +775,10 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }, { login: 'q' }],
nodes: [
{ login: 'a', id: 'f' },
{ login: 'q', id: 'h' },
],
},
},
],
@@ -783,6 +816,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
description: 'c',
name: 'a',
@@ -809,6 +843,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/x',
'github.com/user-login': 'x',
'github.com/user-id': 'g',
},
description: 'z',
name: 'x',
@@ -835,6 +870,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/q',
'github.com/user-login': 'q',
'github.com/user-id': 'h',
},
description: 's',
name: 'q',
@@ -1099,6 +1135,7 @@ describe('GithubMultiOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -1126,7 +1163,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }],
nodes: [{ login: 'a', id: 'f' }],
},
},
],
@@ -1151,7 +1188,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }],
nodes: [{ login: 'a', id: 'f' }],
},
},
],
@@ -1176,7 +1213,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a' }],
nodes: [{ login: 'a', id: 'f' }],
},
},
],
@@ -1213,6 +1250,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
description: 'c',
name: 'a',
@@ -1300,7 +1338,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -1328,6 +1366,7 @@ describe('GithubMultiOrgEntityProvider', () => {
membership: {
user: {
name: 'a',
node_id: 'f',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
login: 'a',
@@ -1351,6 +1390,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
},
@@ -1398,6 +1438,7 @@ describe('GithubMultiOrgEntityProvider', () => {
membership: {
user: {
name: 'a',
node_id: 'f',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
login: 'a',
@@ -1422,6 +1463,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
},
@@ -1473,7 +1515,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -1493,6 +1535,7 @@ describe('GithubMultiOrgEntityProvider', () => {
membership: {
user: {
name: 'a',
node_id: 'f',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
login: 'a',
@@ -1516,6 +1559,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
},
@@ -1729,7 +1773,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
},
@@ -1741,6 +1785,7 @@ describe('GithubMultiOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -1748,6 +1793,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
{
login: 'w',
id: 'i',
name: 'x',
bio: 'y',
email: 'z',
@@ -1774,7 +1820,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -1798,7 +1844,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -1847,6 +1893,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
description: 'c',
@@ -2110,7 +2157,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
},
@@ -2147,7 +2194,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -2171,7 +2218,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -2194,6 +2241,7 @@ describe('GithubMultiOrgEntityProvider', () => {
member: {
name: 'a',
login: 'a',
node_id: 'f',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
},
@@ -2245,6 +2293,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
},
@@ -2327,7 +2376,7 @@ describe('GithubMultiOrgEntityProvider', () => {
},
members: {
pageInfo: { hasNextPage: false },
nodes: [{ login: 'a', name: 'a' }],
nodes: [{ login: 'a', id: 'f', name: 'a' }],
},
},
],
@@ -2350,6 +2399,7 @@ describe('GithubMultiOrgEntityProvider', () => {
member: {
name: 'a',
login: 'a',
node_id: 'f',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
},
@@ -2401,6 +2451,7 @@ describe('GithubMultiOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
},
@@ -531,7 +531,13 @@ export class GithubMultiOrgEntityProvider implements EntityProvider {
const userTransformer =
this.options.userTransformer || defaultUserTransformer;
const { name, avatar_url: avatarUrl, email, login } = event.membership.user;
const {
name,
avatar_url: avatarUrl,
email,
login,
node_id,
} = event.membership.user;
const org = event.organization.login;
const { headers } =
await this.options.githubCredentialsProvider.getCredentials({
@@ -573,6 +579,7 @@ export class GithubMultiOrgEntityProvider implements EntityProvider {
avatarUrl,
login,
email: email ?? undefined,
id: node_id,
},
{
org,
@@ -818,13 +825,14 @@ export class GithubMultiOrgEntityProvider implements EntityProvider {
const userTransformer =
this.options.userTransformer || defaultUserTransformer;
const { name, avatar_url: avatarUrl, email, login } = event.member;
const { name, avatar_url: avatarUrl, email, login, node_id } = event.member;
const user = await userTransformer(
{
name,
avatarUrl,
login,
email: email ?? undefined,
id: node_id,
},
{
org,
@@ -89,6 +89,7 @@ describe('GithubOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -136,6 +137,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
description: 'c',
name: 'a',
@@ -311,6 +313,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
},
spec: {
@@ -331,6 +334,7 @@ describe('GithubOrgEntityProvider', () => {
user: {
name: 'githubuser',
login: 'githubuser',
node_id: 'githubuserId',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
},
@@ -398,6 +402,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
},
spec: {
@@ -418,6 +423,7 @@ describe('GithubOrgEntityProvider', () => {
user: {
name: 'githubuser',
login: 'githubuser',
node_id: 'githubuserId',
avatar_url: 'https://avatars.githubusercontent.com/u/83820368',
email: 'user1@test.com',
},
@@ -778,6 +784,7 @@ describe('GithubOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -785,6 +792,7 @@ describe('GithubOrgEntityProvider', () => {
},
{
login: 'githubuser',
id: 'githubuserId',
name: 'githubuser',
bio: 'githubuser',
email: 'd',
@@ -865,6 +873,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/a',
'github.com/user-login': 'a',
'github.com/user-id': 'f',
},
name: 'a',
description: 'c',
@@ -891,6 +900,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
name: 'githubuser',
description: 'githubuser',
@@ -1029,6 +1039,7 @@ describe('GithubOrgEntityProvider', () => {
nodes: [
{
login: 'a',
id: 'f',
name: 'b',
bio: 'c',
email: 'd',
@@ -1036,6 +1047,7 @@ describe('GithubOrgEntityProvider', () => {
},
{
login: 'githubuser',
id: 'githubuserId',
name: 'githubuser',
bio: 'githubuser',
email: 'd',
@@ -1112,6 +1124,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
name: 'githubuser',
description: 'githubuser',
@@ -1168,6 +1181,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
name: 'githubuser',
description: 'githubuser',
@@ -1277,6 +1291,7 @@ describe('GithubOrgEntityProvider', () => {
nodes: [
{
login: 'githubuser',
id: 'githubuserId',
name: 'githubuser',
bio: 'githubuser',
email: 'd',
@@ -1336,6 +1351,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
name: 'githubuser',
description: 'githubuser',
@@ -1392,6 +1408,7 @@ describe('GithubOrgEntityProvider', () => {
'backstage.io/managed-by-origin-location':
'url:https://github.com/githubuser',
'github.com/user-login': 'githubuser',
'github.com/user-id': 'githubuserId',
},
name: 'githubuser',
description: 'githubuser',
@@ -565,7 +565,13 @@ export class GithubOrgEntityProvider implements EntityProvider {
const userTransformer =
this.options.userTransformer || defaultUserTransformer;
const { name, avatar_url: avatarUrl, email, login } = event.membership.user;
const {
name,
avatar_url: avatarUrl,
email,
login,
node_id,
} = event.membership.user;
const org = event.organization.login;
const { headers } = await this.credentialsProvider.getCredentials({
url: this.options.orgUrl,
@@ -581,6 +587,7 @@ export class GithubOrgEntityProvider implements EntityProvider {
avatarUrl,
login,
email: email || undefined,
id: node_id,
// we don't have this information in the event, so the refresh will handle that for us
organizationVerifiedDomainEmails: [],
},