InfoGrab DocsInfoGrab Docs

Orbit 내부 API

요약

GitLab Orbit 내부 API는 knowledge graph 서비스가 사용합니다. API 엔드포인트는 적절한 인증과 인가를 갖추고 기본적으로 외부에서 접근할 수 있어야 합니다. GitLab Orbit API가 내부 엔드포인트를 사용하는 이유는 요청이 사용자 토큰이 아니라 서비스 수준 JWT 토큰으로 인증되며, 내부 로드 밸런서를 통해서만 접근할 수 있어야 하기 때문입니다.

GitLab Orbit 내부 API는 knowledge graph 서비스가 사용합니다. 다른 소비자는 이 API를 사용할 수 없습니다. 이 문서는 GitLab 코드베이스에서 작업하는 사람을 대상으로 합니다.

새 엔드포인트 추가#

API 엔드포인트는 적절한 인증과 인가를 갖추고 기본적으로 외부에서 접근할 수 있어야 합니다. 새 내부 엔드포인트를 추가하기 전에, 해당 API가 더 넓은 GitLab 커뮤니티에 도움이 되고 외부에서 접근할 수 있게 만들 수 있는지 검토합니다.

GitLab Orbit API가 내부 엔드포인트를 사용하는 이유는 요청이 사용자 토큰이 아니라 서비스 수준 JWT 토큰으로 인증되며, 내부 로드 밸런서를 통해서만 접근할 수 있어야 하기 때문입니다.

인증#

이 엔드포인트는 모두 knowledge graph에서 발급한 JWT 인증을 사용합니다.

JWT로 인증하려면 클라이언트는 다음 단계를 수행합니다.

  1. knowledge graph JWT 서명 시크릿을 읽습니다.
  2. 서명 키로 gkg-indexer: 주체 접두사를 가진 JSON Web Token(JWT)을 생성합니다.
  3. Gitlab-Orbit-Api-Request 헤더에 JWT를 전달합니다.

프로젝트 엔드포인트에는 Workhorse 내부 API 인증과 유효한 Knowledge Graph JWT가 모두 필요합니다. JWT는 GitLab 사용자가 아니라 서비스를 식별합니다. Rails API 요청 로그에서는 인증된 인덱서 트래픽을 엔드포인트의 meta.caller_id와 함께 meta.client_service=orbit-indexer로 식별합니다. 이 요청은 Rails나 Gitaly 로그에 사용자 이름을 기록하지 않습니다.

리포지터리 아카이브 감사 이벤트는 사용자가 아니라 GitLab Orbit Indexer 감사 작성자를 사용합니다. Workhorse가 지원하는 아카이브, 변경된 경로, blob, raw diff 요청에서 Gitaly는 client_name=orbit-indexer를 받습니다. Rails가 Gitaly를 직접 호출하는 경우에는 대신 Rails 클라이언트 이름을 사용합니다.

내부 엔드포인트#

Cloud Connector#

Cloud Connector 토큰 가져오기#

워크로드 ID 인증을 사용할 수 없는 Self-Managed 및 Dedicated 인스턴스에서 청구 이벤트 전송을 인증하는 Cloud Connector 토큰을 가져오려면 GET 요청을 사용합니다.

GET /internal/orbit/cloud_connector_token

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/cloud_connector_token"

응답 예시:

{
  "token": "<json-web-token>"
}

이 토큰에는 자체 exp 클레임이 포함되어 있습니다. 만료 시점이 필요한 호출자는 별도 필드에 의존하지 않고 토큰을 디코딩하여 확인합니다.

Cloud Connector 토큰을 사용할 수 없거나 토큰 형식이 잘못되면 엔드포인트는 503을 반환합니다.

Note

이 엔드포인트를 성공적으로 호출하면 직접적인 사용자 작업이 아니라 인스턴스 범위의 Orbit 인덱서에 귀속되는 orbit_cloud_connector_token_issued 감사 이벤트로 기록됩니다.

프로젝트#

프로젝트 정보 조회#

GET 명령으로 프로젝트의 기본 브랜치와 그 브랜치의 현재 커밋 SHA를 가져옵니다.

GET /internal/orbit/project/:project_id/info

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/info"

응답 예시:

{
  "project_id": 1,
  "default_branch": "main",
  "default_branch_head_sha": "abc123def456"
}

리포지터리#

리포지터리 브랜치 목록 조회#

GET 명령으로 리포지터리 브랜치와 그 커밋을 나열합니다.

GET /internal/orbit/project/:project_id/repository/branches
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
page_token string no 이전 응답의 Link 헤더에서 받은 불투명 커서입니다. 유효하지 않은 커서는 400을 반환합니다.
pagination string no 페이지네이션 방식입니다. keyset만 지원하며 기본값입니다.
per_page integer no 페이지당 브랜치 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다.
sort string no 브랜치를 name_asc, updated_asc, updated_desc 중 하나로 정렬합니다. 기본값은 name_asc 입니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/branches?pagination=keyset&per_page=20"

응답 예시:

[
  {
    "name": "main",
    "commit": {
      "id": "abc123def456",
      "title": "Update README"
    }
  }
]

다른 keyset 페이지가 있으면 응답에 다음 요청에 사용할 page_token 이 담긴 Link 헤더가 포함됩니다.

리포지터리 트리 항목 목록 조회#

GET 명령으로 지정한 ref와 경로의 리포지터리 파일과 디렉터리를 나열합니다.

GET /internal/orbit/project/:project_id/repository/tree
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
page integer no 페이지 번호입니다. 기본값은 1 입니다. legacy 페이지네이션과 함께 사용합니다.
page_token string no 이전 응답의 Link 헤더에서 받은 불투명 커서입니다. keyset 페이지네이션과 함께 사용합니다. 유효하지 않은 커서는 400을 반환합니다.
pagination string no 페이지네이션 방식으로 legacy, keyset, none 중 하나입니다. 기본값은 keyset 입니다. none은 recursive=true를 요구합니다.
path string no 리포지터리 트리 내 경로입니다.
per_page integer no 페이지당 항목 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다. pagination=none에서는 검증은 되지만 사용되지 않습니다.
recursive boolean no 항목을 재귀적으로 반환합니다. 기본값은 false 입니다.
ref string no 브랜치, 태그 또는 SHA 입니다. 기본값은 기본 브랜치입니다.
with_last_commit boolean no 각 항목의 마지막 커밋을 포함합니다. recursive=true와 함께 사용할 수 없습니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/tree?ref=main&recursive=true&pagination=none"

응답 예시:

[
  {
    "id": "a1e8f8d745cc87e3a9248358d9352bb7f9a0aeba",
    "name": "README.md",
    "type": "blob",
    "path": "README.md",
    "mode": "100644"
  }
]

다른 keyset 페이지가 있으면 응답에 다음 요청에 사용할 page_token 이 담긴 Link 헤더가 포함됩니다.

리포지터리 아카이브 다운로드#

GET 명령으로 지정한 ref 시점의 프로젝트 리포지터리를 tar.gz 아카이브로 다운로드합니다.

GET /internal/orbit/project/:project_id/repository/archive
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
ref string no 아카이브할 Git ref(브랜치, 태그 또는 SHA)입니다. 기본값은 기본 브랜치입니다.
include_lfs_blobs boolean no Git LFS 포인터를 해당 객체 내용으로 해석합니다. 기본값은 true 입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/archive?ref=main&include_lfs_blobs=false"

응답 예시:

200

응답 본문은 Workhorse를 통해 스트리밍되는 바이너리 tar.gz 아카이브입니다.

include_lfs_blobs는 아카이브에 LFS 콘텐츠를 포함할지 제어합니다.

Note

이 엔드포인트를 호출하면 repository_download_operation 감사 이벤트가 발생하며, 이 이벤트는 직접적인 사용자 동작이 아니라 인덱서가 대행하는 인증된 사용자에게 귀속됩니다.

변경된 파일 경로 스트리밍#

GET 명령으로 두 트리 리비전 사이에서 변경된 파일 경로를 Workhorse를 통해 줄바꿈 구분 JSON으로 스트리밍합니다. Gitaly FindChangedPaths RPC로 프록시합니다. 이 경로는 fast-forward만 지원합니다. left_tree_revision 이 right_tree_revision의 조상이 아니면 400을 반환합니다.

GET /internal/orbit/project/:project_id/repository/changed_paths
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
left_tree_revision string yes 기준 트리 리비전(커밋 SHA)입니다. 최초 인덱싱에는 빈 SHA(0000...0000)를 사용합니다.
right_tree_revision string yes 대상 트리 리비전(커밋 SHA)

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/changed_paths?left_tree_revision=0123456789abcdef0123456789abcdef01234567&right_tree_revision=89abcdef0123456789abcdef0123456789abcdef"

응답 예시(Workhorse를 통해 스트리밍되는 줄바꿈 구분 JSON):

{"path":"app/models/user.rb","status":"MODIFIED","old_path":"","old_mode":33188,"new_mode":33188,"old_blob_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","new_blob_id":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
{"path":"README.md","status":"ADDED","old_path":"","old_mode":0,"new_mode":33188,"old_blob_id":"","new_blob_id":"cccccccccccccccccccccccccccccccccccccccc"}
{"path":"old_file.rb","status":"DELETED","old_path":"","old_mode":33188,"new_mode":0,"old_blob_id":"dddddddddddddddddddddddddddddddddddddddd","new_blob_id":""}
{"path":"vendor/lib","status":"DELETED","old_path":"","old_mode":57344,"new_mode":0,"old_blob_id":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee","new_blob_id":""}

old_mode와 new_mode는 10진수로 표현한 Git 트리 항목 모드입니다. 모드 57344(0160000)는 서브모듈이고 16384(040000)는 디렉터리이므로, 이들의 blob ID는 blob 이 아니며 가져오면 안 됩니다.

POST 명령으로 하나 이상의 커밋 비교에 대한 변경된 파일 경로를 Workhorse를 통해 줄바꿈 구분 JSON으로 스트리밍합니다. 반복되는 CommitRequest 항목을 담은 단일 Gitaly FindChangedPaths RPC로 프록시합니다. 각 비교는 base_revision을 명시적 부모로, target_revision을 검사할 커밋으로 사용합니다. 이 경로는 갈라진 이력을 허용하며 조상 관계를 요구하지 않습니다.

POST /internal/orbit/project/:project_id/repository/changed_paths
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
comparisons array yes 1 개에서 1,000 개까지의 비교 객체

각 비교 객체에는 base_revision과 target_revision 이 필요합니다. 두 필드 모두 40자 또는 64자 전체 커밋 SHA 여야 하며 비어 있을 수 없습니다. API는 Gitaly로 보내기 전에 이 값을 소문자로 변환합니다. target_revision은 대소문자가 달라도 요청 안에서 고유해야 합니다.

요청 예시:

curl --request POST \
  --header "Content-Type: application/json" \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/changed_paths" \
  --data '{"comparisons":[{"base_revision":"0123456789abcdef0123456789abcdef01234567","target_revision":"89abcdef0123456789abcdef0123456789abcdef"}]}'

응답 예시(Workhorse를 통해 스트리밍되는 줄바꿈 구분 JSON):

{"commit_id":"89abcdef0123456789abcdef0123456789abcdef","path":"app/models/user.rb","status":"MODIFIED","old_path":"","old_mode":33188,"new_mode":33188,"old_blob_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","new_blob_id":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
{"commit_id":"89abcdef0123456789abcdef0123456789abcdef","path":"README.md","status":"ADDED","old_path":"","old_mode":0,"new_mode":33188,"old_blob_id":"","new_blob_id":"cccccccccccccccccccccccccccccccccccccccc"}

GET 응답에는 commit_id가 포함되지 않습니다. POST 행에는 대상 리비전에 해당하는 commit_id가 포함됩니다. 대상 리비전에 변경된 경로가 없으면 해당 비교에 대해 스트림이 아무 행도 내보내지 않습니다. target_revision 마다 빈 버킷을 초기화하고, 스트림이 성공적으로 끝난 뒤에만 그 버킷을 받아들입니다.

스트림 실패#

changed-paths 스트림과 list-blobs 스트림은 모두 Workhorse가 성공적으로 끝나면 EOF로 종료됩니다. Workhorse가 응답 바이트를 쓰기 전에 Gitaly가 리비전을 알 수 없는 객체로 거부하면, Workhorse는 Gitaly 오류 메시지를 일반 텍스트 본문으로 담아 404를 반환합니다. Git은 리비전 하나라도 알 수 없으면 요청 전체를 거부하므로, 나머지 blob 이 필요한 클라이언트는 알 수 없는 리비전을 빼고 다시 시도해야 합니다. Workhorse가 응답 바이트를 쓰기 전에 다른 이유로 백엔드가 실패하면 Workhorse는 500을 반환합니다. 본문이 시작된 뒤에 백엔드가 실패하면 Workhorse는 HTTP 응답을 완결하지 않고 중단합니다. 클라이언트는 부분 데이터를 폐기해야 합니다.

Blob 목록 조회#

POST 명령으로 지정한 리비전의 blob 내용을 길이 접두사가 붙은 protobuf 프레임으로 Workhorse를 통해 스트리밍합니다. Gitaly ListBlobs RPC로 프록시합니다. 응답 본문은 ListBlobsResponse protobuf 프레임의 바이너리 스트림으로 유지됩니다. 각 프레임 앞에는 뒤따르는 protobuf 메시지의 크기를 나타내는 4바이트 빅엔디언 길이 접두사가 붙습니다.

POST /internal/orbit/project/:project_id/repository/list_blobs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
revisions string[] yes blob을 나열할 Git 리비전입니다. 예를 들면 SHA, --not, 범위 제외입니다. 비어 있을 수 없습니다.
bytes_limit integer no 바이트 단위 요청 한도입니다. 유효한 값은 1에서 1,048,576 까지입니다. 기본값은 1,048,576 바이트(1 MiB)입니다. 이 범위를 벗어난 요청은 400을 반환합니다.

요청 예시:

curl --request POST \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --header "Content-Type: application/json" \
  --data '{"revisions":["0123456789abcdef0123456789abcdef01234567","--not","89abcdef0123456789abcdef0123456789abcdef"],"bytes_limit":1048576}' \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/list_blobs"

size 필드는 원본 blob 크기를 보고합니다. 서버는 bytes_limit을 Gitaly로 전달하며, Gitaly는 한도를 넘는 blob을 거부하지 않고 잘라냅니다. 클라이언트 코드는 원본 크기가 선택한 한도를 넘는 blob을 제외해야 하며, 잘린 페이로드 길이를 사용해서는 안 됩니다. 기본 한도에서는 1,048,576 바이트 blob은 허용되고 1,048,577 바이트 blob은 클라이언트 코드에서 제외됩니다.

리포지터리 커밋 목록 조회#

GET 명령으로 지정한 ref의 커밋 목록을 페이지 단위로 가져옵니다.

GET /internal/orbit/project/:project_id/repository/commits
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
all boolean no 단일 ref가 아니라 모든 ref의 커밋을 반환합니다.
author string no 커밋 작성자로 커밋을 검색합니다.
first_parent boolean no 머지 커밋의 첫 번째 부모만 따라갑니다.
order string no 커밋 순회 순서로 default 또는 topo 입니다. 기본값은 default 입니다.
page_token string no 이전 응답의 X-Next-Page-Token 헤더에서 받은 불투명 커서입니다.
path string no 커밋을 필터링하는 데 사용하는 파일 경로입니다.
per_page integer no 페이지당 커밋 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다.
ref string no ref_name의 별칭입니다. ref_name과 함께 사용할 수 없습니다.
ref_name string no 브랜치, 태그 또는 SHA 입니다. 기본값은 기본 브랜치입니다.
since datetime no ISO 8601 형식의 이 날짜 이후 또는 당일 커밋만 반환합니다.
until datetime no ISO 8601 형식의 이 날짜 이전 또는 당일 커밋만 반환합니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/commits?ref_name=main&per_page=2"

응답 예시:

[
  {
    "id": "abc123def456",
    "short_id": "abc123d",
    "title": "Update README",
    "message": "Update README with new instructions",
    "author_name": "Jane Smith",
    "author_email": "jane@example.com",
    "authored_date": "2025-01-15T10:30:00.000Z",
    "committed_date": "2025-01-15T10:30:00.000Z"
  }
]

다른 페이지가 있으면 응답에 X-Next-Page-Token 헤더가 포함됩니다. 다음 요청에서 그 값을 page_token으로 전달합니다.

머지 리퀘스트#

diff 엔드포인트는 두 가지 형식으로 제공됩니다.

  • 파일별 JSON diff(merge_request_diffs/:diff_id)는 변경된 각 파일을 diff 내용과 메타데이터(경로, 모드, 이름 변경·삭제 상태)와 함께 반환합니다. 이 데이터는 MergeRequestDiffFile 레코드에서 읽습니다. 특정 파일만 요청하려면 paths 파라미터를 사용합니다.
  • raw 통합 패치(merge_requests/:iid/raw_diffs 또는 merge_request_diffs/:diff_id/raw_diffs)는 Gitaly가 계산해 Workhorse로 스트리밍한 전체 diff를 text/plain으로 반환합니다.

머지 리퀘스트 최신 버전의 raw diff 조회#

GET 명령으로 머지 리퀘스트의 최신 diff 버전에 대한 전체 통합 패치를 가져옵니다. 응답은 Workhorse를 통해 text/plain으로 스트리밍됩니다.

GET /internal/orbit/project/:project_id/merge_requests/:merge_request_iid/raw_diffs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
merge_request_iid integer yes 머지 리퀘스트의 IID(프로젝트 범위)입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_requests/42/raw_diffs"

응답은 Workhorse를 통해 스트리밍되는 text/plain 통합 패치입니다.

머지 리퀘스트 diff#

이 엔드포인트는 데이터베이스 ID로 특정 MergeRequestDiff 버전을 지정합니다.

머지 리퀘스트 diff의 파일별 diff 조회#

GET 명령으로 MergeRequestDiff 레코드의 파일별 diff를 가져옵니다.

GET /internal/orbit/project/:project_id/merge_request_diffs/:diff_id
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
diff_id integer yes MergeRequestDiff 레코드의 ID 입니다.
paths string[] no 이 파일 경로(new_path 또는 old_path)로 필터링합니다. 최대 100 개입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_request_diffs/42"

응답 예시:

{
  "id": 42,
  "head_commit_sha": "abc123def456",
  "base_commit_sha": "789fed012cba",
  "start_commit_sha": "456abc789def",
  "diffs": [
    {
      "diff": "@@ -1,3 +1,4 @@\n...",
      "collapsed": false,
      "too_large": false,
      "new_path": "app/models/user.rb",
      "old_path": "app/models/user.rb",
      "a_mode": "100644",
      "b_mode": "100644",
      "new_file": false,
      "renamed_file": false,
      "deleted_file": false,
      "generated_file": false
    }
  ]
}

머지 리퀘스트 diff의 raw 통합 패치 조회#

GET 명령으로 MergeRequestDiff 레코드의 전체 통합 패치를 Workhorse를 통해 스트리밍되는 text/plain으로 가져옵니다.

GET /internal/orbit/project/:project_id/merge_request_diffs/:diff_id/raw_diffs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
diff_id integer yes MergeRequestDiff 레코드의 ID 입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_request_diffs/42/raw_diffs"

응답은 Workhorse를 통해 스트리밍되는 text/plain 통합 패치입니다.

Orbit 내부 API

GitLab v19.5
원문 보기

요약

GitLab Orbit 내부 API는 knowledge graph 서비스가 사용합니다. API 엔드포인트는 적절한 인증과 인가를 갖추고 기본적으로 외부에서 접근할 수 있어야 합니다. GitLab Orbit API가 내부 엔드포인트를 사용하는 이유는 요청이 사용자 토큰이 아니라 서비스 수준 JWT 토큰으로 인증되며, 내부 로드 밸런서를 통해서만 접근할 수 있어야 하기 때문입니다.

GitLab Orbit 내부 API는 knowledge graph 서비스가 사용합니다. 다른 소비자는 이 API를 사용할 수 없습니다. 이 문서는 GitLab 코드베이스에서 작업하는 사람을 대상으로 합니다.

새 엔드포인트 추가#

API 엔드포인트는 적절한 인증과 인가를 갖추고 기본적으로 외부에서 접근할 수 있어야 합니다. 새 내부 엔드포인트를 추가하기 전에, 해당 API가 더 넓은 GitLab 커뮤니티에 도움이 되고 외부에서 접근할 수 있게 만들 수 있는지 검토합니다.

GitLab Orbit API가 내부 엔드포인트를 사용하는 이유는 요청이 사용자 토큰이 아니라 서비스 수준 JWT 토큰으로 인증되며, 내부 로드 밸런서를 통해서만 접근할 수 있어야 하기 때문입니다.

인증#

이 엔드포인트는 모두 knowledge graph에서 발급한 JWT 인증을 사용합니다.

JWT로 인증하려면 클라이언트는 다음 단계를 수행합니다.

  1. knowledge graph JWT 서명 시크릿을 읽습니다.
  2. 서명 키로 gkg-indexer: 주체 접두사를 가진 JSON Web Token(JWT)을 생성합니다.
  3. Gitlab-Orbit-Api-Request 헤더에 JWT를 전달합니다.

프로젝트 엔드포인트에는 Workhorse 내부 API 인증과 유효한 Knowledge Graph JWT가 모두 필요합니다. JWT는 GitLab 사용자가 아니라 서비스를 식별합니다. Rails API 요청 로그에서는 인증된 인덱서 트래픽을 엔드포인트의 meta.caller_id와 함께 meta.client_service=orbit-indexer로 식별합니다. 이 요청은 Rails나 Gitaly 로그에 사용자 이름을 기록하지 않습니다.

리포지터리 아카이브 감사 이벤트는 사용자가 아니라 GitLab Orbit Indexer 감사 작성자를 사용합니다. Workhorse가 지원하는 아카이브, 변경된 경로, blob, raw diff 요청에서 Gitaly는 client_name=orbit-indexer를 받습니다. Rails가 Gitaly를 직접 호출하는 경우에는 대신 Rails 클라이언트 이름을 사용합니다.

내부 엔드포인트#

Cloud Connector#

Cloud Connector 토큰 가져오기#

워크로드 ID 인증을 사용할 수 없는 Self-Managed 및 Dedicated 인스턴스에서 청구 이벤트 전송을 인증하는 Cloud Connector 토큰을 가져오려면 GET 요청을 사용합니다.

GET /internal/orbit/cloud_connector_token

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/cloud_connector_token"

응답 예시:

{
  "token": "<json-web-token>"
}

이 토큰에는 자체 exp 클레임이 포함되어 있습니다. 만료 시점이 필요한 호출자는 별도 필드에 의존하지 않고 토큰을 디코딩하여 확인합니다.

Cloud Connector 토큰을 사용할 수 없거나 토큰 형식이 잘못되면 엔드포인트는 503을 반환합니다.

Note

이 엔드포인트를 성공적으로 호출하면 직접적인 사용자 작업이 아니라 인스턴스 범위의 Orbit 인덱서에 귀속되는 orbit_cloud_connector_token_issued 감사 이벤트로 기록됩니다.

프로젝트#

프로젝트 정보 조회#

GET 명령으로 프로젝트의 기본 브랜치와 그 브랜치의 현재 커밋 SHA를 가져옵니다.

GET /internal/orbit/project/:project_id/info

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/info"

응답 예시:

{
  "project_id": 1,
  "default_branch": "main",
  "default_branch_head_sha": "abc123def456"
}

리포지터리#

리포지터리 브랜치 목록 조회#

GET 명령으로 리포지터리 브랜치와 그 커밋을 나열합니다.

GET /internal/orbit/project/:project_id/repository/branches
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
page_token string no 이전 응답의 Link 헤더에서 받은 불투명 커서입니다. 유효하지 않은 커서는 400을 반환합니다.
pagination string no 페이지네이션 방식입니다. keyset만 지원하며 기본값입니다.
per_page integer no 페이지당 브랜치 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다.
sort string no 브랜치를 name_asc, updated_asc, updated_desc 중 하나로 정렬합니다. 기본값은 name_asc 입니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/branches?pagination=keyset&per_page=20"

응답 예시:

[
  {
    "name": "main",
    "commit": {
      "id": "abc123def456",
      "title": "Update README"
    }
  }
]

다른 keyset 페이지가 있으면 응답에 다음 요청에 사용할 page_token 이 담긴 Link 헤더가 포함됩니다.

리포지터리 트리 항목 목록 조회#

GET 명령으로 지정한 ref와 경로의 리포지터리 파일과 디렉터리를 나열합니다.

GET /internal/orbit/project/:project_id/repository/tree
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
page integer no 페이지 번호입니다. 기본값은 1 입니다. legacy 페이지네이션과 함께 사용합니다.
page_token string no 이전 응답의 Link 헤더에서 받은 불투명 커서입니다. keyset 페이지네이션과 함께 사용합니다. 유효하지 않은 커서는 400을 반환합니다.
pagination string no 페이지네이션 방식으로 legacy, keyset, none 중 하나입니다. 기본값은 keyset 입니다. none은 recursive=true를 요구합니다.
path string no 리포지터리 트리 내 경로입니다.
per_page integer no 페이지당 항목 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다. pagination=none에서는 검증은 되지만 사용되지 않습니다.
recursive boolean no 항목을 재귀적으로 반환합니다. 기본값은 false 입니다.
ref string no 브랜치, 태그 또는 SHA 입니다. 기본값은 기본 브랜치입니다.
with_last_commit boolean no 각 항목의 마지막 커밋을 포함합니다. recursive=true와 함께 사용할 수 없습니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/tree?ref=main&recursive=true&pagination=none"

응답 예시:

[
  {
    "id": "a1e8f8d745cc87e3a9248358d9352bb7f9a0aeba",
    "name": "README.md",
    "type": "blob",
    "path": "README.md",
    "mode": "100644"
  }
]

다른 keyset 페이지가 있으면 응답에 다음 요청에 사용할 page_token 이 담긴 Link 헤더가 포함됩니다.

리포지터리 아카이브 다운로드#

GET 명령으로 지정한 ref 시점의 프로젝트 리포지터리를 tar.gz 아카이브로 다운로드합니다.

GET /internal/orbit/project/:project_id/repository/archive
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
ref string no 아카이브할 Git ref(브랜치, 태그 또는 SHA)입니다. 기본값은 기본 브랜치입니다.
include_lfs_blobs boolean no Git LFS 포인터를 해당 객체 내용으로 해석합니다. 기본값은 true 입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/archive?ref=main&include_lfs_blobs=false"

응답 예시:

200

응답 본문은 Workhorse를 통해 스트리밍되는 바이너리 tar.gz 아카이브입니다.

include_lfs_blobs는 아카이브에 LFS 콘텐츠를 포함할지 제어합니다.

Note

이 엔드포인트를 호출하면 repository_download_operation 감사 이벤트가 발생하며, 이 이벤트는 직접적인 사용자 동작이 아니라 인덱서가 대행하는 인증된 사용자에게 귀속됩니다.

변경된 파일 경로 스트리밍#

GET 명령으로 두 트리 리비전 사이에서 변경된 파일 경로를 Workhorse를 통해 줄바꿈 구분 JSON으로 스트리밍합니다. Gitaly FindChangedPaths RPC로 프록시합니다. 이 경로는 fast-forward만 지원합니다. left_tree_revision 이 right_tree_revision의 조상이 아니면 400을 반환합니다.

GET /internal/orbit/project/:project_id/repository/changed_paths
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
left_tree_revision string yes 기준 트리 리비전(커밋 SHA)입니다. 최초 인덱싱에는 빈 SHA(0000...0000)를 사용합니다.
right_tree_revision string yes 대상 트리 리비전(커밋 SHA)

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/changed_paths?left_tree_revision=0123456789abcdef0123456789abcdef01234567&right_tree_revision=89abcdef0123456789abcdef0123456789abcdef"

응답 예시(Workhorse를 통해 스트리밍되는 줄바꿈 구분 JSON):

{"path":"app/models/user.rb","status":"MODIFIED","old_path":"","old_mode":33188,"new_mode":33188,"old_blob_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","new_blob_id":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
{"path":"README.md","status":"ADDED","old_path":"","old_mode":0,"new_mode":33188,"old_blob_id":"","new_blob_id":"cccccccccccccccccccccccccccccccccccccccc"}
{"path":"old_file.rb","status":"DELETED","old_path":"","old_mode":33188,"new_mode":0,"old_blob_id":"dddddddddddddddddddddddddddddddddddddddd","new_blob_id":""}
{"path":"vendor/lib","status":"DELETED","old_path":"","old_mode":57344,"new_mode":0,"old_blob_id":"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee","new_blob_id":""}

old_mode와 new_mode는 10진수로 표현한 Git 트리 항목 모드입니다. 모드 57344(0160000)는 서브모듈이고 16384(040000)는 디렉터리이므로, 이들의 blob ID는 blob 이 아니며 가져오면 안 됩니다.

POST 명령으로 하나 이상의 커밋 비교에 대한 변경된 파일 경로를 Workhorse를 통해 줄바꿈 구분 JSON으로 스트리밍합니다. 반복되는 CommitRequest 항목을 담은 단일 Gitaly FindChangedPaths RPC로 프록시합니다. 각 비교는 base_revision을 명시적 부모로, target_revision을 검사할 커밋으로 사용합니다. 이 경로는 갈라진 이력을 허용하며 조상 관계를 요구하지 않습니다.

POST /internal/orbit/project/:project_id/repository/changed_paths
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
comparisons array yes 1 개에서 1,000 개까지의 비교 객체

각 비교 객체에는 base_revision과 target_revision 이 필요합니다. 두 필드 모두 40자 또는 64자 전체 커밋 SHA 여야 하며 비어 있을 수 없습니다. API는 Gitaly로 보내기 전에 이 값을 소문자로 변환합니다. target_revision은 대소문자가 달라도 요청 안에서 고유해야 합니다.

요청 예시:

curl --request POST \
  --header "Content-Type: application/json" \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/changed_paths" \
  --data '{"comparisons":[{"base_revision":"0123456789abcdef0123456789abcdef01234567","target_revision":"89abcdef0123456789abcdef0123456789abcdef"}]}'

응답 예시(Workhorse를 통해 스트리밍되는 줄바꿈 구분 JSON):

{"commit_id":"89abcdef0123456789abcdef0123456789abcdef","path":"app/models/user.rb","status":"MODIFIED","old_path":"","old_mode":33188,"new_mode":33188,"old_blob_id":"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","new_blob_id":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"}
{"commit_id":"89abcdef0123456789abcdef0123456789abcdef","path":"README.md","status":"ADDED","old_path":"","old_mode":0,"new_mode":33188,"old_blob_id":"","new_blob_id":"cccccccccccccccccccccccccccccccccccccccc"}

GET 응답에는 commit_id가 포함되지 않습니다. POST 행에는 대상 리비전에 해당하는 commit_id가 포함됩니다. 대상 리비전에 변경된 경로가 없으면 해당 비교에 대해 스트림이 아무 행도 내보내지 않습니다. target_revision 마다 빈 버킷을 초기화하고, 스트림이 성공적으로 끝난 뒤에만 그 버킷을 받아들입니다.

스트림 실패#

changed-paths 스트림과 list-blobs 스트림은 모두 Workhorse가 성공적으로 끝나면 EOF로 종료됩니다. Workhorse가 응답 바이트를 쓰기 전에 Gitaly가 리비전을 알 수 없는 객체로 거부하면, Workhorse는 Gitaly 오류 메시지를 일반 텍스트 본문으로 담아 404를 반환합니다. Git은 리비전 하나라도 알 수 없으면 요청 전체를 거부하므로, 나머지 blob 이 필요한 클라이언트는 알 수 없는 리비전을 빼고 다시 시도해야 합니다. Workhorse가 응답 바이트를 쓰기 전에 다른 이유로 백엔드가 실패하면 Workhorse는 500을 반환합니다. 본문이 시작된 뒤에 백엔드가 실패하면 Workhorse는 HTTP 응답을 완결하지 않고 중단합니다. 클라이언트는 부분 데이터를 폐기해야 합니다.

Blob 목록 조회#

POST 명령으로 지정한 리비전의 blob 내용을 길이 접두사가 붙은 protobuf 프레임으로 Workhorse를 통해 스트리밍합니다. Gitaly ListBlobs RPC로 프록시합니다. 응답 본문은 ListBlobsResponse protobuf 프레임의 바이너리 스트림으로 유지됩니다. 각 프레임 앞에는 뒤따르는 protobuf 메시지의 크기를 나타내는 4바이트 빅엔디언 길이 접두사가 붙습니다.

POST /internal/orbit/project/:project_id/repository/list_blobs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID
revisions string[] yes blob을 나열할 Git 리비전입니다. 예를 들면 SHA, --not, 범위 제외입니다. 비어 있을 수 없습니다.
bytes_limit integer no 바이트 단위 요청 한도입니다. 유효한 값은 1에서 1,048,576 까지입니다. 기본값은 1,048,576 바이트(1 MiB)입니다. 이 범위를 벗어난 요청은 400을 반환합니다.

요청 예시:

curl --request POST \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --header "Content-Type: application/json" \
  --data '{"revisions":["0123456789abcdef0123456789abcdef01234567","--not","89abcdef0123456789abcdef0123456789abcdef"],"bytes_limit":1048576}' \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/list_blobs"

size 필드는 원본 blob 크기를 보고합니다. 서버는 bytes_limit을 Gitaly로 전달하며, Gitaly는 한도를 넘는 blob을 거부하지 않고 잘라냅니다. 클라이언트 코드는 원본 크기가 선택한 한도를 넘는 blob을 제외해야 하며, 잘린 페이로드 길이를 사용해서는 안 됩니다. 기본 한도에서는 1,048,576 바이트 blob은 허용되고 1,048,577 바이트 blob은 클라이언트 코드에서 제외됩니다.

리포지터리 커밋 목록 조회#

GET 명령으로 지정한 ref의 커밋 목록을 페이지 단위로 가져옵니다.

GET /internal/orbit/project/:project_id/repository/commits
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
all boolean no 단일 ref가 아니라 모든 ref의 커밋을 반환합니다.
author string no 커밋 작성자로 커밋을 검색합니다.
first_parent boolean no 머지 커밋의 첫 번째 부모만 따라갑니다.
order string no 커밋 순회 순서로 default 또는 topo 입니다. 기본값은 default 입니다.
page_token string no 이전 응답의 X-Next-Page-Token 헤더에서 받은 불투명 커서입니다.
path string no 커밋을 필터링하는 데 사용하는 파일 경로입니다.
per_page integer no 페이지당 커밋 수입니다. 생략하거나 null 이면 기본값은 20 입니다. 100을 넘는 값은 100으로 제한됩니다. 1 미만의 값은 400을 반환합니다.
ref string no ref_name의 별칭입니다. ref_name과 함께 사용할 수 없습니다.
ref_name string no 브랜치, 태그 또는 SHA 입니다. 기본값은 기본 브랜치입니다.
since datetime no ISO 8601 형식의 이 날짜 이후 또는 당일 커밋만 반환합니다.
until datetime no ISO 8601 형식의 이 날짜 이전 또는 당일 커밋만 반환합니다.

요청 예시:

curl --request GET \
  --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  --url "https://gitlab.example.com/api/v4/internal/orbit/project/1/repository/commits?ref_name=main&per_page=2"

응답 예시:

[
  {
    "id": "abc123def456",
    "short_id": "abc123d",
    "title": "Update README",
    "message": "Update README with new instructions",
    "author_name": "Jane Smith",
    "author_email": "jane@example.com",
    "authored_date": "2025-01-15T10:30:00.000Z",
    "committed_date": "2025-01-15T10:30:00.000Z"
  }
]

다른 페이지가 있으면 응답에 X-Next-Page-Token 헤더가 포함됩니다. 다음 요청에서 그 값을 page_token으로 전달합니다.

머지 리퀘스트#

diff 엔드포인트는 두 가지 형식으로 제공됩니다.

  • 파일별 JSON diff(merge_request_diffs/:diff_id)는 변경된 각 파일을 diff 내용과 메타데이터(경로, 모드, 이름 변경·삭제 상태)와 함께 반환합니다. 이 데이터는 MergeRequestDiffFile 레코드에서 읽습니다. 특정 파일만 요청하려면 paths 파라미터를 사용합니다.
  • raw 통합 패치(merge_requests/:iid/raw_diffs 또는 merge_request_diffs/:diff_id/raw_diffs)는 Gitaly가 계산해 Workhorse로 스트리밍한 전체 diff를 text/plain으로 반환합니다.

머지 리퀘스트 최신 버전의 raw diff 조회#

GET 명령으로 머지 리퀘스트의 최신 diff 버전에 대한 전체 통합 패치를 가져옵니다. 응답은 Workhorse를 통해 text/plain으로 스트리밍됩니다.

GET /internal/orbit/project/:project_id/merge_requests/:merge_request_iid/raw_diffs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
merge_request_iid integer yes 머지 리퀘스트의 IID(프로젝트 범위)입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_requests/42/raw_diffs"

응답은 Workhorse를 통해 스트리밍되는 text/plain 통합 패치입니다.

머지 리퀘스트 diff#

이 엔드포인트는 데이터베이스 ID로 특정 MergeRequestDiff 버전을 지정합니다.

머지 리퀘스트 diff의 파일별 diff 조회#

GET 명령으로 MergeRequestDiff 레코드의 파일별 diff를 가져옵니다.

GET /internal/orbit/project/:project_id/merge_request_diffs/:diff_id
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
diff_id integer yes MergeRequestDiff 레코드의 ID 입니다.
paths string[] no 이 파일 경로(new_path 또는 old_path)로 필터링합니다. 최대 100 개입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_request_diffs/42"

응답 예시:

{
  "id": 42,
  "head_commit_sha": "abc123def456",
  "base_commit_sha": "789fed012cba",
  "start_commit_sha": "456abc789def",
  "diffs": [
    {
      "diff": "@@ -1,3 +1,4 @@\n...",
      "collapsed": false,
      "too_large": false,
      "new_path": "app/models/user.rb",
      "old_path": "app/models/user.rb",
      "a_mode": "100644",
      "b_mode": "100644",
      "new_file": false,
      "renamed_file": false,
      "deleted_file": false,
      "generated_file": false
    }
  ]
}

머지 리퀘스트 diff의 raw 통합 패치 조회#

GET 명령으로 MergeRequestDiff 레코드의 전체 통합 패치를 Workhorse를 통해 스트리밍되는 text/plain으로 가져옵니다.

GET /internal/orbit/project/:project_id/merge_request_diffs/:diff_id/raw_diffs
Attribute Type Required Description
project_id integer yes 프로젝트의 ID 입니다.
diff_id integer yes MergeRequestDiff 레코드의 ID 입니다.

요청 예시:

curl --header "Gitlab-Orbit-Api-Request: <json-web-token>" \
  "https://gitlab.example.com/api/v4/internal/orbit/project/1/merge_request_diffs/42/raw_diffs"

응답은 Workhorse를 통해 스트리밍되는 text/plain 통합 패치입니다.