InfoGrab DocsInfoGrab Docs

HTTP 라우터

요약

HTTP Router는 클러스터 안으로 들어오는 요청을 어느 cell 이 처리할지 결정하는 서비스입니다. 예를 들어 cell-2 안의 프로젝트를 찾는 요청은 cell-2로 라우팅됩니다. HTTP Router에 대해 더 알아보려면 설계 문서와 프로젝트 리포지터리를 참고합니다.

HTTP Router#

HTTP Router는 클러스터 안으로 들어오는 요청을 어느 cell 이 처리할지 결정하는 서비스입니다. 이 결정은 일반적으로 요청이 요구하는 리소스에 따라 정해집니다.

예를 들어 cell-2 안의 프로젝트를 찾는 요청은 cell-2로 라우팅됩니다.

HTTP Router에 대해 더 알아보려면 설계 문서와 프로젝트 리포지터리를 참고합니다.

라우팅 규칙#

라우팅 규칙은 요청을 어떻게 디코딩하고 라우팅을 결정할지 정의합니다.

규칙은 룰셋 단위로 구성됩니다(예: session_token). 규칙은 정적이며 HTTP Router 배포 전에 룰셋 단위로 선택됩니다.

라우팅 결정은 위에서 아래로 평가됩니다. 처음 일치하는 시점에 즉시 중단됩니다.

규칙에 대한 더 자세한 설명과 들어오는 요청이 라우팅 규칙에 매칭되는 실행 예시는 http-router 문서의 rules를 참고합니다.

라우팅 가능 토큰 기반 라우팅#

라우팅 가능 토큰은 라우팅 정보를 토큰 안에 직접 인코딩합니다. 요청이 라우팅 가능 토큰을 담고 있으면 HTTP Router는 토큰을 디코딩해 요청을 올바른 cell로 라우팅합니다. 라우터는 리소스를 소유한 cell을 찾기 위해 다른 서비스에 질의할 필요가 없습니다.

이 방식은 Routable Tokens 설계 문서를 따릅니다.

라우팅 가능 토큰 기반 라우팅에는 두 측면이 있습니다.

  • GitLab 이 토큰을 생성할 때 라우팅 정보를 인코딩합니다.
  • HTTP Router가 그 정보를 디코딩해 요청을 라우팅합니다.

토큰에 라우팅 정보 인코딩#

routable_token은 가능한 한 빨리 도입합니다. 이렇게 하면 처음부터 라우팅 정보를 포함한 토큰이 생성됩니다. HTTP Router 디코더 변경은 나중에 진행해도 됩니다. 라우터가 요청을 어디로 보낼지 알지 못하면 레거시 cell로 폴백합니다.

GitLab은 TokenAuthenticatable concern의 routable_token: 옵션을 통해 토큰에 라우팅 정보를 인코딩합니다. 자세한 내용은 TokenAuthenticatable concern 사용을 참고합니다.

예를 들어 Ci::Runner#token은 라우팅 가능합니다. 러너 토큰은 그룹 타입과 프로젝트 타입 러너에 대해 조직, 그룹, 프로젝트, 사용자 키를 인코딩합니다.

add_authentication_token_field :token,
  encrypted: :optional,
  expires_at: :compute_token_expiration,
  format_with_prefix: :prefix_for_new_and_legacy_runner,
  routable_token: {
    if: ->(token_owner_record) {
      (token_owner_record.group_type? || token_owner_record.project_type?) &&
        token_owner_record.owner &&
        Feature.enabled?(:routable_runner_token, token_owner_record.owner)
    },
    payload: {
      o: ->(token_owner_record) { token_owner_record.owner.organization_id },
      g: ->(token_owner_record) { token_owner_record.group_type? ? token_owner_record.sharding_key_id : nil },
      p: ->(token_owner_record) { token_owner_record.project_type? ? token_owner_record.sharding_key_id : nil },
      u: ->(token_owner_record) { token_owner_record.creator_id }
    }
  }

토큰 디코딩 및 요청 라우팅#

HTTP Router는 토큰을 규칙과 매칭하고, 페이로드를 디코딩하고, 요청을 cell 기준으로 분류합니다.

토큰 타입마다 HTTP Router에 새 규칙이 필요합니다.

러너 토큰을 라우팅하는 규칙은 다음과 같습니다.

{
  "id": "session_token_header_runner_token",
  "match": {
    "type": "header",
    "name": "runner-token",
    "regexValue": "^glrtr?-(?<payload>[0-9A-Za-z_-]{27,300})\\.01\\.(?<payload_length>[0-9a-z]{2})[0-9a-z]{7}$"
  },
  "transform": {
    "type": "routable-token-payload",
    "input": [
      "${payload}",
      "${payload_length}"
    ],
    "output": "decoded"
  },
  "action": "classify",
  "classify": {
    "type": "CELL_ID",
    "value": "${decoded.c}"
  },
  "validate": {
    "exist": [
      "${decoded.c}"
    ]
  }
}

라우터는 규칙을 다음 단계로 처리합니다.

  1. Match: match.regexValue가 토큰에서 payload와 payload_length를 캡처합니다. payload_length는 페이로드를 어디까지 읽을지 디코더에 알려 주며, 토큰 전체를 디코딩하지 않아도 되게 합니다.
  2. Transform: routable-token-payload 변환이 Base64 페이로드를 디코딩하고 그 결과를 decoded 아래에 붙입니다. 예를 들어 decoded.c는 cell을 담습니다.
  3. Validate: 라우터가 decoded.c의 존재를 확인합니다.
  4. Classify: 라우터가 decoded.c 값으로 Topology Service에 CELL_ID 분류 요청을 보내고, Topology Service가 반환한 cell로 요청을 프록시합니다.

샘플 요청으로 이 규칙을 단계별로 살펴보려면 http-router 문서의 러너 토큰 예시 를 참고합니다.

리소스 경로 기반 라우팅#

준비 중입니다

리소스 ID 기반 라우팅#

준비 중입니다

라우트 스냅샷#

HTTP Router가 분류할 수 있어야 하는 라우트 목록의 진실 공급원은 GitLab 입니다. config/routing/gitlab_routes.json 파일은 모든 Rails 및 Grape 라우트를 template로 담고, 각각에 구체적인 example URL을 짝지어 둡니다. HTTP Router는 이 파일을 내려받아 각 예시를 자체 라우팅 테이블에 대해 다시 실행하는 스냅샷 테스트 로 GitLab 라우트 변경이 라우팅에 영향을 주는 시점을 탐지합니다.

각 항목은 선택 필드 두 개를 추가로 가질 수 있습니다. 라우터는 이 필드들도 같은 방식으로 다시 실행하며, example과 동일하게 분류해야 합니다.

  • acceptsFormat: Rails 포맷 세그먼트(.:format)를 허용하는 라우트에만 존재하며 true로 설정됩니다. 스냅샷은 .json 예시를 직접 만들어 두지 않으며, 소비 측에서 example + .json 형태로 직접 구성합니다.
  • dottedExample: 파라미터나 와일드카드를 포함하는 템플릿에만 존재합니다. 값은 각 파라미터 값을 john.doe로 바꿔 example을 다시 만든 것입니다. 사용자 이름과 네임스페이스 경로에는 점이 올 수 있으므로, 점을 접미사 구분자로 읽어 값을 잘라 버리는 코드를 이 항목으로 잡아냅니다.

두 필드가 모두 있으면 소비 측은 dottedExample + .json도 함께 구성합니다 (예: /users/john.doe.json). 이 조합은 요청을 잘못된 cell로 보내는 버그에 가장 가까운 입력입니다. 점이 포함된 식별자 뒤에 실제 포맷 접미사가 붙은 형태입니다. 클레임 추출은 마지막 점에서 정확히 접미사 하나만 제거해야 합니다. 두 필드를 각각 따로 처리하는 파서도 이 조합에서는 여전히 틀릴 수 있습니다.

두 필드는 해당하지 않으면 생략됩니다.

GitLab과 HTTP Router를 동기 상태로 유지하기 위해, 라우트는 HTTP Router 리포지터리가 아니라 GitLab에서 생성하고 커밋합니다. 이렇게 하면 둘이 어긋나 요청이 잘못된 cell로 라우팅되는 일을 막을 수 있습니다.

스냅샷 재생성#

라우트를 추가·변경·제거할 때는 파일을 다시 생성해 같은 머지 리퀘스트에 커밋합니다.

bundle exec rake gitlab:cells:routes:generate

cells-routes:up-to-date CI job은 파일을 다시 생성해 커밋된 사본과 다르면 실패하므로, 스냅샷을 갱신하지 않은 라우트 변경은 머지될 수 없습니다. pre-push Git 훅이 본인 변경에 대해 같은 검사를 실행하므로 대부분의 어긋남은 푸시 전에 잡힙니다.

이 CI job은 머지된 결과에서 실행되므로, 스냅샷을 생성한 뒤 다른 사람이 라우트를 추가한 경우에는 라우트를 전혀 건드리지 않은 머지 리퀘스트에서도 실패할 수 있습니다. 이때는 다시 생성해도 변경 사항이 없다고 보고되며, 먼저 리베이스해야 합니다.

git fetch origin master && git rebase origin/master
bundle exec rake gitlab:cells:routes:generate

생성 환경#

Rails 라우트 테이블은 고정돼 있지 않습니다. Rails 환경과 로컬 설정에 따라 달라지므로, 서로 다른 두 머신에서 스냅샷을 생성하면 서로 다른 파일이 나올 수 있습니다. 출력을 재현 가능하게 유지하기 위해 Rake 태스크는 환경을 고정하고, 환경이 이미 일치하지 않으면 자기 자신을 다시 실행합니다.

  • RAILS_ENV=test - development 환경과 test 환경은 각각 자체 라우트를 마운트합니다.
  • CI=true - config/environments/test.rb는 CI가 설정돼 있으면 Sprockets /assets 마운트를 건너뜁니다.
  • GITLAB_CONFIG=config/gitlab.yml.example - 일부 라우트는 로컬 설정에서 그려집니다. /users/auth/ 아래의 OmniAuth 및 LDAP 공급자 콜백 라우트는 config/gitlab.yml에서 오므로, 공급자를 추가로 설정한 GDK에서는 항목이 더 생성됩니다. CI는 scripts/prepare_build.sh가 준비하는 config/gitlab.yml.example을 사용하므로 이 태스크도 같은 파일을 사용합니다.

이 태스크는 FOSS_ONLY가 설정돼 있으면 중단됩니다. FOSS_ONLY에서는 ee/ 라우트가 그려지지 않아 스냅샷에 EE 라우트가 전혀 없는 상태로 기록됩니다. 이는 생성된 JavaScript 경로 헬퍼에 대해 Gitlab::JsRoutes.match_ci_env!가 수행하는 동작과 같습니다.

스냅샷은 RAILS_ENV=test로 생성되므로 프로덕션 라우트 테이블에 가깝기는 하지만 정확히 같지는 않습니다. 템플릿이 더 있는 것은 무해합니다. 라우터 쪽에 예약어 가드가 하나 더 추가될 뿐입니다. 위험한 방향은 템플릿이 빠지는 쪽인데, 그 경우 실제 라우트가 더 넓은 분류 규칙으로 흘러가기 때문입니다. test 환경에만 존재하는 라우트는 생성기의 Gitlab::Cells::HttpRouter::RoutesSnapshot::TEST_ONLY_TEMPLATES에서 명시적으로 제외됩니다.

HTTP Router 업데이트#

HTTP Router는 GitLab에서 config/routing/gitlab_routes.json을 내려받습니다. GitLab 머지 리퀘스트가 라우트를 변경하면, 해당 GitLab 브랜치에서 파일을 내려받는 짝 머지 리퀘스트로 HTTP Router 스냅샷을 업데이트합니다. 명령어, 새 라우트에 라우팅 변경이 필요한지에 대한 판단, 그리고 두 가지 실제 예시는 HTTP Router에 GitLab 라우트 추가를 참고합니다. 별도의 CI job 이 이 다운로드가 최신 상태인지 확인합니다. 자세한 내용은 HTTP Router 동기 상태 확인을 참고합니다.

HTTP Router는 src/generated_route_guards.ts의 예약어 라우트 가드를 이 스냅샷 파일에서 도출합니다. 스냅샷은 RAILS_ENV=test로 생성되므로 Lookbook, letter_opener, 메일러 프리뷰 같은 development 전용 /rails/* 라우트가 스냅샷에 없고, 따라서 가드를 다시 생성하면 /rails/* 가드가 사라집니다. 이는 문제가 되지 않습니다. 해당 라우트는 development 에만 존재하므로 프로덕션 가드는 의미가 없고, 라우터에는 변경이 필요 없습니다. GDK 동작도 어느 쪽이든 동일합니다. 가드가 있으면 /rails/*는 곧바로 JSON 규칙 엔진으로 갑니다. 가드가 없으면 요청은 최상위 /:ROUTE/* 분류 규칙으로 흘러가 rails를 네임스페이스 라우트로 분류하지 못하고, 핸들러가 그 실패를 잡아 같은 JSON 규칙 엔진으로 폴백합니다. 대가는 development에서 Topology Service 호출이 한 번 추가되는 것입니다.

HTTP Router 동기 상태 확인#

cells-routes:router-in-sync CI job은 HTTP Router 리포지터리의 main 브랜치에서 test/routes/gitlab_routes.json을 내려받아 사용자 브랜치의 config/routing/gitlab_routes.json에 있는 모든 라우트 템플릿이 포함되어 있는지 확인합니다. cells-routes:up-to-date가 GitLab의 파일을 Rails 라우트 테이블과 대조한다면, cells-routes:router-in-sync는 HTTP Router의 사본을 GitLab의 파일과 대조합니다.

이 job은 머지 리퀘스트 파이프라인에서만, 그리고 머지 리퀘스트가 config/routing/gitlab_routes.json을 변경할 때만 실행됩니다. 다운로드 실패와 라우트 어긋남을 구분해 보고하므로, HTTP Router에서 파일을 가져오는 중의 네트워크 문제가 라우트 변경으로 오인되지 않습니다. 이 job은 allow_failure: true로 설정돼 있어 현재는 머지 리퀘스트를 막지 않습니다. 이를 대체할 검사가 작업 항목 954에 제안돼 있습니다.

라우트 어긋남으로 job 이 실패하면, 사용자 GitLab 브랜치에서 라우트를 내려받는 짝 머지 리퀘스트를 HTTP Router에 엽니다.

npm run download-gitlab-routes -- <your-gitlab-branch-name>

vitest 스냅샷을 업데이트하고, 새 라우트가 올바르게 매칭되지 않으면 라우팅 규칙도 업데이트한 뒤, 그 머지 리퀘스트를 머지하고 GitLab 파이프라인을 다시 실행합니다. 대부분의 새 라우트는 기존 규칙에 매칭되며 스냅샷 갱신만 필요합니다. 두 경우를 구분하는 방법과 전체 절차는 HTTP Router에 GitLab 라우트 추가를 참고합니다.

짝 머지 리퀘스트가 준비되기 전에 반드시 머지해야 한다면, pipeline:skip-router-sync 레이블을 적용해 job을 건너뛰고 그 이유를 머지 리퀘스트 설명에 적습니다.

HTTP 라우터

GitLab v19.5
원문 보기

요약

HTTP Router는 클러스터 안으로 들어오는 요청을 어느 cell 이 처리할지 결정하는 서비스입니다. 예를 들어 cell-2 안의 프로젝트를 찾는 요청은 cell-2로 라우팅됩니다. HTTP Router에 대해 더 알아보려면 설계 문서와 프로젝트 리포지터리를 참고합니다.

HTTP Router#

HTTP Router는 클러스터 안으로 들어오는 요청을 어느 cell 이 처리할지 결정하는 서비스입니다. 이 결정은 일반적으로 요청이 요구하는 리소스에 따라 정해집니다.

예를 들어 cell-2 안의 프로젝트를 찾는 요청은 cell-2로 라우팅됩니다.

HTTP Router에 대해 더 알아보려면 설계 문서와 프로젝트 리포지터리를 참고합니다.

라우팅 규칙#

라우팅 규칙은 요청을 어떻게 디코딩하고 라우팅을 결정할지 정의합니다.

규칙은 룰셋 단위로 구성됩니다(예: session_token). 규칙은 정적이며 HTTP Router 배포 전에 룰셋 단위로 선택됩니다.

라우팅 결정은 위에서 아래로 평가됩니다. 처음 일치하는 시점에 즉시 중단됩니다.

규칙에 대한 더 자세한 설명과 들어오는 요청이 라우팅 규칙에 매칭되는 실행 예시는 http-router 문서의 rules를 참고합니다.

라우팅 가능 토큰 기반 라우팅#

라우팅 가능 토큰은 라우팅 정보를 토큰 안에 직접 인코딩합니다. 요청이 라우팅 가능 토큰을 담고 있으면 HTTP Router는 토큰을 디코딩해 요청을 올바른 cell로 라우팅합니다. 라우터는 리소스를 소유한 cell을 찾기 위해 다른 서비스에 질의할 필요가 없습니다.

이 방식은 Routable Tokens 설계 문서를 따릅니다.

라우팅 가능 토큰 기반 라우팅에는 두 측면이 있습니다.

  • GitLab 이 토큰을 생성할 때 라우팅 정보를 인코딩합니다.
  • HTTP Router가 그 정보를 디코딩해 요청을 라우팅합니다.

토큰에 라우팅 정보 인코딩#

routable_token은 가능한 한 빨리 도입합니다. 이렇게 하면 처음부터 라우팅 정보를 포함한 토큰이 생성됩니다. HTTP Router 디코더 변경은 나중에 진행해도 됩니다. 라우터가 요청을 어디로 보낼지 알지 못하면 레거시 cell로 폴백합니다.

GitLab은 TokenAuthenticatable concern의 routable_token: 옵션을 통해 토큰에 라우팅 정보를 인코딩합니다. 자세한 내용은 TokenAuthenticatable concern 사용을 참고합니다.

예를 들어 Ci::Runner#token은 라우팅 가능합니다. 러너 토큰은 그룹 타입과 프로젝트 타입 러너에 대해 조직, 그룹, 프로젝트, 사용자 키를 인코딩합니다.

add_authentication_token_field :token,
  encrypted: :optional,
  expires_at: :compute_token_expiration,
  format_with_prefix: :prefix_for_new_and_legacy_runner,
  routable_token: {
    if: ->(token_owner_record) {
      (token_owner_record.group_type? || token_owner_record.project_type?) &&
        token_owner_record.owner &&
        Feature.enabled?(:routable_runner_token, token_owner_record.owner)
    },
    payload: {
      o: ->(token_owner_record) { token_owner_record.owner.organization_id },
      g: ->(token_owner_record) { token_owner_record.group_type? ? token_owner_record.sharding_key_id : nil },
      p: ->(token_owner_record) { token_owner_record.project_type? ? token_owner_record.sharding_key_id : nil },
      u: ->(token_owner_record) { token_owner_record.creator_id }
    }
  }

토큰 디코딩 및 요청 라우팅#

HTTP Router는 토큰을 규칙과 매칭하고, 페이로드를 디코딩하고, 요청을 cell 기준으로 분류합니다.

토큰 타입마다 HTTP Router에 새 규칙이 필요합니다.

러너 토큰을 라우팅하는 규칙은 다음과 같습니다.

{
  "id": "session_token_header_runner_token",
  "match": {
    "type": "header",
    "name": "runner-token",
    "regexValue": "^glrtr?-(?<payload>[0-9A-Za-z_-]{27,300})\\.01\\.(?<payload_length>[0-9a-z]{2})[0-9a-z]{7}$"
  },
  "transform": {
    "type": "routable-token-payload",
    "input": [
      "${payload}",
      "${payload_length}"
    ],
    "output": "decoded"
  },
  "action": "classify",
  "classify": {
    "type": "CELL_ID",
    "value": "${decoded.c}"
  },
  "validate": {
    "exist": [
      "${decoded.c}"
    ]
  }
}

라우터는 규칙을 다음 단계로 처리합니다.

  1. Match: match.regexValue가 토큰에서 payload와 payload_length를 캡처합니다. payload_length는 페이로드를 어디까지 읽을지 디코더에 알려 주며, 토큰 전체를 디코딩하지 않아도 되게 합니다.
  2. Transform: routable-token-payload 변환이 Base64 페이로드를 디코딩하고 그 결과를 decoded 아래에 붙입니다. 예를 들어 decoded.c는 cell을 담습니다.
  3. Validate: 라우터가 decoded.c의 존재를 확인합니다.
  4. Classify: 라우터가 decoded.c 값으로 Topology Service에 CELL_ID 분류 요청을 보내고, Topology Service가 반환한 cell로 요청을 프록시합니다.

샘플 요청으로 이 규칙을 단계별로 살펴보려면 http-router 문서의 러너 토큰 예시 를 참고합니다.

리소스 경로 기반 라우팅#

준비 중입니다

리소스 ID 기반 라우팅#

준비 중입니다

라우트 스냅샷#

HTTP Router가 분류할 수 있어야 하는 라우트 목록의 진실 공급원은 GitLab 입니다. config/routing/gitlab_routes.json 파일은 모든 Rails 및 Grape 라우트를 template로 담고, 각각에 구체적인 example URL을 짝지어 둡니다. HTTP Router는 이 파일을 내려받아 각 예시를 자체 라우팅 테이블에 대해 다시 실행하는 스냅샷 테스트 로 GitLab 라우트 변경이 라우팅에 영향을 주는 시점을 탐지합니다.

각 항목은 선택 필드 두 개를 추가로 가질 수 있습니다. 라우터는 이 필드들도 같은 방식으로 다시 실행하며, example과 동일하게 분류해야 합니다.

  • acceptsFormat: Rails 포맷 세그먼트(.:format)를 허용하는 라우트에만 존재하며 true로 설정됩니다. 스냅샷은 .json 예시를 직접 만들어 두지 않으며, 소비 측에서 example + .json 형태로 직접 구성합니다.
  • dottedExample: 파라미터나 와일드카드를 포함하는 템플릿에만 존재합니다. 값은 각 파라미터 값을 john.doe로 바꿔 example을 다시 만든 것입니다. 사용자 이름과 네임스페이스 경로에는 점이 올 수 있으므로, 점을 접미사 구분자로 읽어 값을 잘라 버리는 코드를 이 항목으로 잡아냅니다.

두 필드가 모두 있으면 소비 측은 dottedExample + .json도 함께 구성합니다 (예: /users/john.doe.json). 이 조합은 요청을 잘못된 cell로 보내는 버그에 가장 가까운 입력입니다. 점이 포함된 식별자 뒤에 실제 포맷 접미사가 붙은 형태입니다. 클레임 추출은 마지막 점에서 정확히 접미사 하나만 제거해야 합니다. 두 필드를 각각 따로 처리하는 파서도 이 조합에서는 여전히 틀릴 수 있습니다.

두 필드는 해당하지 않으면 생략됩니다.

GitLab과 HTTP Router를 동기 상태로 유지하기 위해, 라우트는 HTTP Router 리포지터리가 아니라 GitLab에서 생성하고 커밋합니다. 이렇게 하면 둘이 어긋나 요청이 잘못된 cell로 라우팅되는 일을 막을 수 있습니다.

스냅샷 재생성#

라우트를 추가·변경·제거할 때는 파일을 다시 생성해 같은 머지 리퀘스트에 커밋합니다.

bundle exec rake gitlab:cells:routes:generate

cells-routes:up-to-date CI job은 파일을 다시 생성해 커밋된 사본과 다르면 실패하므로, 스냅샷을 갱신하지 않은 라우트 변경은 머지될 수 없습니다. pre-push Git 훅이 본인 변경에 대해 같은 검사를 실행하므로 대부분의 어긋남은 푸시 전에 잡힙니다.

이 CI job은 머지된 결과에서 실행되므로, 스냅샷을 생성한 뒤 다른 사람이 라우트를 추가한 경우에는 라우트를 전혀 건드리지 않은 머지 리퀘스트에서도 실패할 수 있습니다. 이때는 다시 생성해도 변경 사항이 없다고 보고되며, 먼저 리베이스해야 합니다.

git fetch origin master && git rebase origin/master
bundle exec rake gitlab:cells:routes:generate

생성 환경#

Rails 라우트 테이블은 고정돼 있지 않습니다. Rails 환경과 로컬 설정에 따라 달라지므로, 서로 다른 두 머신에서 스냅샷을 생성하면 서로 다른 파일이 나올 수 있습니다. 출력을 재현 가능하게 유지하기 위해 Rake 태스크는 환경을 고정하고, 환경이 이미 일치하지 않으면 자기 자신을 다시 실행합니다.

  • RAILS_ENV=test - development 환경과 test 환경은 각각 자체 라우트를 마운트합니다.
  • CI=true - config/environments/test.rb는 CI가 설정돼 있으면 Sprockets /assets 마운트를 건너뜁니다.
  • GITLAB_CONFIG=config/gitlab.yml.example - 일부 라우트는 로컬 설정에서 그려집니다. /users/auth/ 아래의 OmniAuth 및 LDAP 공급자 콜백 라우트는 config/gitlab.yml에서 오므로, 공급자를 추가로 설정한 GDK에서는 항목이 더 생성됩니다. CI는 scripts/prepare_build.sh가 준비하는 config/gitlab.yml.example을 사용하므로 이 태스크도 같은 파일을 사용합니다.

이 태스크는 FOSS_ONLY가 설정돼 있으면 중단됩니다. FOSS_ONLY에서는 ee/ 라우트가 그려지지 않아 스냅샷에 EE 라우트가 전혀 없는 상태로 기록됩니다. 이는 생성된 JavaScript 경로 헬퍼에 대해 Gitlab::JsRoutes.match_ci_env!가 수행하는 동작과 같습니다.

스냅샷은 RAILS_ENV=test로 생성되므로 프로덕션 라우트 테이블에 가깝기는 하지만 정확히 같지는 않습니다. 템플릿이 더 있는 것은 무해합니다. 라우터 쪽에 예약어 가드가 하나 더 추가될 뿐입니다. 위험한 방향은 템플릿이 빠지는 쪽인데, 그 경우 실제 라우트가 더 넓은 분류 규칙으로 흘러가기 때문입니다. test 환경에만 존재하는 라우트는 생성기의 Gitlab::Cells::HttpRouter::RoutesSnapshot::TEST_ONLY_TEMPLATES에서 명시적으로 제외됩니다.

HTTP Router 업데이트#

HTTP Router는 GitLab에서 config/routing/gitlab_routes.json을 내려받습니다. GitLab 머지 리퀘스트가 라우트를 변경하면, 해당 GitLab 브랜치에서 파일을 내려받는 짝 머지 리퀘스트로 HTTP Router 스냅샷을 업데이트합니다. 명령어, 새 라우트에 라우팅 변경이 필요한지에 대한 판단, 그리고 두 가지 실제 예시는 HTTP Router에 GitLab 라우트 추가를 참고합니다. 별도의 CI job 이 이 다운로드가 최신 상태인지 확인합니다. 자세한 내용은 HTTP Router 동기 상태 확인을 참고합니다.

HTTP Router는 src/generated_route_guards.ts의 예약어 라우트 가드를 이 스냅샷 파일에서 도출합니다. 스냅샷은 RAILS_ENV=test로 생성되므로 Lookbook, letter_opener, 메일러 프리뷰 같은 development 전용 /rails/* 라우트가 스냅샷에 없고, 따라서 가드를 다시 생성하면 /rails/* 가드가 사라집니다. 이는 문제가 되지 않습니다. 해당 라우트는 development 에만 존재하므로 프로덕션 가드는 의미가 없고, 라우터에는 변경이 필요 없습니다. GDK 동작도 어느 쪽이든 동일합니다. 가드가 있으면 /rails/*는 곧바로 JSON 규칙 엔진으로 갑니다. 가드가 없으면 요청은 최상위 /:ROUTE/* 분류 규칙으로 흘러가 rails를 네임스페이스 라우트로 분류하지 못하고, 핸들러가 그 실패를 잡아 같은 JSON 규칙 엔진으로 폴백합니다. 대가는 development에서 Topology Service 호출이 한 번 추가되는 것입니다.

HTTP Router 동기 상태 확인#

cells-routes:router-in-sync CI job은 HTTP Router 리포지터리의 main 브랜치에서 test/routes/gitlab_routes.json을 내려받아 사용자 브랜치의 config/routing/gitlab_routes.json에 있는 모든 라우트 템플릿이 포함되어 있는지 확인합니다. cells-routes:up-to-date가 GitLab의 파일을 Rails 라우트 테이블과 대조한다면, cells-routes:router-in-sync는 HTTP Router의 사본을 GitLab의 파일과 대조합니다.

이 job은 머지 리퀘스트 파이프라인에서만, 그리고 머지 리퀘스트가 config/routing/gitlab_routes.json을 변경할 때만 실행됩니다. 다운로드 실패와 라우트 어긋남을 구분해 보고하므로, HTTP Router에서 파일을 가져오는 중의 네트워크 문제가 라우트 변경으로 오인되지 않습니다. 이 job은 allow_failure: true로 설정돼 있어 현재는 머지 리퀘스트를 막지 않습니다. 이를 대체할 검사가 작업 항목 954에 제안돼 있습니다.

라우트 어긋남으로 job 이 실패하면, 사용자 GitLab 브랜치에서 라우트를 내려받는 짝 머지 리퀘스트를 HTTP Router에 엽니다.

npm run download-gitlab-routes -- <your-gitlab-branch-name>

vitest 스냅샷을 업데이트하고, 새 라우트가 올바르게 매칭되지 않으면 라우팅 규칙도 업데이트한 뒤, 그 머지 리퀘스트를 머지하고 GitLab 파이프라인을 다시 실행합니다. 대부분의 새 라우트는 기존 규칙에 매칭되며 스냅샷 갱신만 필요합니다. 두 경우를 구분하는 방법과 전체 절차는 HTTP Router에 GitLab 라우트 추가를 참고합니다.

짝 머지 리퀘스트가 준비되기 전에 반드시 머지해야 한다면, pipeline:skip-router-sync 레이블을 적용해 job을 건너뛰고 그 이유를 머지 리퀘스트 설명에 적습니다.