본문 바로가기
WIKI 기술 지식 베이스

GitHub 조직 데이터

원문 보기 위키 갱신

Backstage 카탈로그는 GitHub 또는 GitHub Enterprise의 조직에서 조직 데이터(사용자와 팀)를 직접 가져오도록 설정할 수 있어요. 그 결과는 조직 설정을 그대로 반영한 User 및 Group 종류 엔티티의 계층 구조예요.

출처: 문서

본문

Backstage 카탈로그는 GitHub 또는 GitHub Enterprise의 조직에서 조직 데이터(사용자와 팀)를 직접 가져오도록 설정할 수 있어요. 그 결과는 조직 설정을 그대로 반영한 User 및 Group 종류 엔티티의 계층 구조예요.

note

이것은 카탈로그에 User와 Group 엔티티를 추가하지만 인증은 제공하지 않습니다. 그건 GitHub auth provider를 참고하세요.

권한

GitHub Org 제공자를 설치하기 전에 올바른 권한이 있는지 확인해야 해요.

  • 개인용 액세스 토큰 권한은 GitHub Locations 문서에 나열돼 있어요.

  • GitHub App(들) 권한은 GitHub Apps 문서에 나열돼 있어요.

설치

GitHub Org 제공자는 기본으로 설치되지 않으므로 백엔드에 추가해야 해요. 따라서 @backstage/plugin-catalog-backend-module-github-org에 대한 종속성을 백엔드 패키지에 추가해야 해요.

Backstage 루트 디렉터리에서

yarn --cwd packages/backend add @backstage/plugin-catalog-backend-module-github-org

다음으로 app-config.yaml에 기본 구성을 추가하세요.

app-config.yaml

catalog:  providers:    githubOrg:      id: production      githubUrl: https://github.com      orgs: ['organization-1', 'organization-2', 'organization-3']      schedule:        initialDelay: { seconds: 30 }        frequency: { hours: 1 }        timeout: { minutes: 50 }

마지막으로 다음 줄을 추가해 백엔드를 업데이트하세요.

packages/backend/src/index.ts

backend.add(import('@backstage/plugin-catalog-backend'));backend.add(import('@backstage/plugin-catalog-backend-module-github-org'));

구성 세부 사항

위 설치 단계에서 필요한 구성의 간단한 예시를 포함했어요. 이 섹션에서는 다양한 구성 옵션에 대해 더 자세히 설명해요.

app-config.yaml

catalog:  providers:    githubOrg:      - id: github        githubUrl: https://github.com        orgs: ['organization-1', 'organization-2', 'organization-3']        schedule:          initialDelay: { seconds: 30 }          frequency: { hours: 1 }          timeout: { minutes: 50 }        pageSizes:          teams: 25          teamMembers: 50          organizationMembers: 50      - id: ghe        githubUrl: https://ghe.mycompany.com        orgs: ['internal-1', 'internal-2', 'internal-3']        schedule:          initialDelay: { seconds: 30 }          frequency: { hours: 1 }          timeout: { minutes: 50 }        excludeSuspendedUsers: true

githubOrg 바로 아래에는 구성 목록이 있고, 각 항목은 다음 요소들을 가진 구조예요.

id: 이 제공자의 안정적인 ID. 이 제공자의 엔티티는 이 ID와 연결되므로, 시간이 지나도 변경하지 않도록 주의해야 해요. 바꾸면 고아 엔티티 및/또는 충돌이 생길 수 있어요.

githubUrl: 이 제공자가 소비해야 할 대상

orgs (선택): 소비할 GitHub org의 목록. 단일 org만 나열하면 생성된 그룹 엔티티가 default 네임스페이스를 사용하고, 그 외에는 org 이름을 네임스페이스로 사용해요. 기본적으로 제공자는 주어진 GitHub 인스턴스에서 접근 가능한 모든 org를 소비해요(GitHub App 통합만 지원). 여러 조직을 소비할 때 어떤 조직에 GitHub App 설치가 누락되어 있거나(또는 자격 증명을 해석할 수 없으면) 제공자는 명확한 경고를 로그하고 수집 실행을 중단해서 기존 카탈로그 엔티티가 조용히 삭제되는 것을 막아요.

schedule: 사용할 새로고침 일정. SchedulerServiceTaskScheduleDefinitionConfig의 구조와 일치해요.

pageSizes (선택): RESOURCE_LIMITS_EXCEEDED 오류를 방지하기 위해 GitHub GraphQL API 쿼리의 페이지 크기를 구성해요. 다음 페이지 크기를 구성할 수 있어요.

  • teams: 조직 팀을 쿼리할 때 페이지당 가져올 팀 수(기본값: 25)

  • teamMembers: 팀 멤버를 쿼리할 때 페이지당 가져올 팀 멤버 수(기본값: 50)

  • organizationMembers: 페이지당 가져올 조직 멤버 수(기본값: 50)

페이지 크기를 줄이면 API 호출이 더 많아지고 동기화 시간이 약간 길어지지만, 팀과 멤버가 많은 조직에서 API 리소스 한도에 걸리는 것을 막을 수 있어요.

excludeSuspendedUsers (선택): 조직 사용자를 쿼리할 때 중지된(suspended) 사용자를 제외할지 여부. GitHub Enterprise 인스턴스에만 해당해요. GitHub.com API에 사용하면 오류가 발생해요.

이벤트 지원

GitHub Org용 카탈로그 모듈에는 이벤트 지원이 활성화되어 있어요. 이 모듈은 관련 토픽을 구독하며, 이 이벤트들이 EventsService를 통해 게시될 것으로 기대해요.

토픽:

  • github.installation

  • github.membership

  • github.organization

  • github.team

추가로, events-backend-module-github의 이벤트 라우터를 설치해야 해요. 이 라우터는 일반 토픽 github에서 받은 이벤트를 이벤트 유형에 따라 더 구체적인 토픽(예: github.membership)으로 라우팅해요.

GitHub로부터 Webhook 이벤트를 받으려면, 이벤트를 Backstage로 어떻게 수집하고 EventsService에 게시할지 정해야 해요. 다음 옵션 중에서 선택할 수 있어요(확장 가능).

  • HTTP 엔드포인트를 통해

  • AWS SQS 큐를 통해

  • Google Pub/Sub를 통해

  • Kafka 토픽을 통해

공식 문서를 확인해 웹훅을 구성하고 요청을 보호할 수 있어요. 웹훅은 organization, team, membership 이벤트를 전달하도록 구성해야 해요.

커스텀 트랜스포머

GH API 응답을 backstage 엔티티로 매핑하는 데 도움이 되는 자체 변환 로직을 주입할 수 있어요. 사용자와 팀 요청에 대해 이 작업을 수행해 엔티티를 추가 처리하거나 업데이트할 수 있어요.

이를 활성화하려면 GitHubOrgEntityProvider에 함수를 전달해요. UserTransformer, TeamTransformer 또는 둘 다를 전달할 수 있어요. 함수는 API에서 반환된 각 항목(사용자 또는 팀)에 대해 호출돼요. 해당 항목을 가져오지 않으려면 Entity(User 또는 Group) 또는 undefined를 반환할 수 있어요.

또한 defaultUserTransformer와 defaultOrganizationTeamTransformer가 있어요. 기본 변환의 응답을 약간만 바꾸면 된다면 이들을 사용해 응답을 꾸밀 수 있어요.

트랜스포머를 사용하는 예시는 다음과 같아요.

packages/backend/src/index.ts

import { createBackend } from '@backstage/backend-defaults';import { createBackendModule } from '@backstage/backend-plugin-api';import { githubOrgEntityProviderTransformsExtensionPoint } from '@backstage/plugin-catalog-backend-module-github-org';import { myTeamTransformer, myUserTransformer } from './transformers';const githubOrgModule = createBackendModule({  pluginId: 'catalog',  moduleId: 'github-org-extensions',  register(env) {    env.registerInit({      deps: {        githubOrg: githubOrgEntityProviderTransformsExtensionPoint,      },      async init({ githubOrg }) {        githubOrg.setTeamTransformer(myTeamTransformer);        githubOrg.setUserTransformer(myUserTransformer);      },    });  },});const backend = createBackend();// Other itemsbackend.add(import('@backstage/plugin-catalog-backend'));backend.add(import('@backstage/plugin-catalog-backend-module-github-org'));backend.add(githubOrgModule);backend.start();

myTeamTransformer와 myUserTransformer 트랜스포머 함수는 아래 섹션의 예시에서 가져온 거예요.

트랜스포머 예시

다음은 각 종류의 트랜스포머에 대한 예시예요. 이것들을 위한 transformers.ts 파일을 packages/backend/src 폴더에 만드는 것을 권장해요.

packages/backend/src/transformers.ts

import {  TeamTransformer,  UserTransformer,  defaultUserTransformer,} from '@backstage/plugin-catalog-backend-module-github';// This team transformer completely replaces the built in logic with custom logic.export const myTeamTransformer: TeamTransformer = async team => {  return {    apiVersion: 'backstage.io/v1alpha1',    kind: 'Group',    metadata: {      name: team.slug,      annotations: {},    },    spec: {      type: 'GitHub Org Team',      profile: {},      children: [],    },  };};// This user transformer makes use of the built in logic, but also sets the description fieldexport const myUserTransformer: UserTransformer = async (user, ctx) => {  const backstageUser = await defaultUserTransformer(user, ctx);  if (backstageUser) {    backstageUser.metadata.description = 'Loaded from GitHub Org Data';  }  return backstageUser;};

조직 이메일로 GitHub 사용자 해석하기

사용자를 인증할 때는 카탈로그 안의 엔티티로 해석해야 해요. 종종 사용하는 인증은 키로 이메일을 제공하는 기업 SSO 시스템일 수 있어요. GitHub 사용자를 찾고 해석할 수 있으려면, 비공개 도메인 검증된 이메일을 backstage의 User 엔티티로 가져오는 것도 유용해요.

통합은 GitHub API에서 organizationVerifiedDomainEmails를 반환하려 시도하고, 이를 UserTransformer에 전달된 객체의 일부로 제공해요. GitHub API는 GitHub Org의 검증된 도메인인 도메인을 사용하는 이메일만 반환해요. 또한 사용자가 자신의 계정에 그런 이메일을 구성했는지에도 의존해요. API는 GitHub App 인증을 사용하고, 이메일 접근을 허용하는 올바른 앱 권한이 있을 때만 이 값을 반환해요.

기본 userTransformer를 꾸며서 반환된 신원의 조직 이메일을 대체할 수 있어요.

packages/backend/src/transformers.ts

export const myVerifiedUserTransformer: UserTransformer = async (user, ctx) => {  const backstageUser = await defaultUserTransformer(user, ctx);  if (backstageUser && user.organizationVerifiedDomainEmails?.length) {    backstageUser.spec.profile!.email =      user.organizationVerifiedDomainEmails[0];  }  return backstageUser;};

이 예시는 위 섹션의 Custom Transformers와 Transformer Examples 문서를 따라 커스텀 트랜스포머를 구현했다고 가정해요.

이메일을 가져온 뒤에는 Custom Resolver를 구축해 사용자를 해석할 수 있어요. 이 커스텀 리졸버에서 다음 예시를 사용해 사용자를 제대로 매칭할 수 있어요.

ctx.signInWithCatalogUser({  filter: {    kind: ['User'],    'spec.profile.email': email as string,  },});

더 알아보기 (Learn more)