GitLab 파일 리포지터리

파일 업로드, 저장 및 검색을 처리하기 위해 CarrierWave gem을 사용합니다.

파일 업로드는 workhorse에 의해 가속화되어야 하며 자세한 내용은 uploads 개발 문서를 참조하십시오.

파일 업로드가 사용되는 여러 곳이 있으며 이는 상황에 따라 다릅니다.

  • 시스템
    • 인스턴스 로고 (로그인/가입 페이지에 표시되는 로고)
    • 헤더 로고 (내비게이션 바에 표시되는 로고)
  • 그룹
    • 그룹 아바타
  • 사용자
    • 사용자 아바타
    • 사용자 스니펫 첨부 파일
  • 프로젝트
    • 프로젝트 아바타
    • 이슈/MR/노트 마크다운 첨부 파일
    • 이슈/MR/노트 레거시 마크다운 첨부 파일
    • CI 아티팩트 (아카이브, 메타데이터, 추적)
    • LFS 객체
    • Merge Request 차이
    • 디자인 관리 디자인 섬네일
  • 주제
    • 주제 아바타

디스크 리포지터리

GitLab은 모든 것을 로컬 디스크에 저장하기 시작했습니다. 이전 버전에서 디렉터리 위치가 변경되었지만, 아직 100% 표준화되지는 않았습니다. 아래에서 확인할 수 있습니다.

설명 DB 내 존재 여부 CarrierWave.root로부터의 상대 경로 업로더 클래스 모델 타입
인스턴스 로고 yes uploads/-/system/appearance/logo/:id/:filename AttachmentUploader Appearance
헤더 로고 yes uploads/-/system/appearance/header_logo/:id/:filename AttachmentUploader Appearance
그룹 아바타 yes uploads/-/system/group/avatar/:id/:filename AvatarUploader Group
사용자 아바타 yes uploads/-/system/user/avatar/:id/:filename AvatarUploader User
사용자 스니펫 첨부 파일 yes uploads/-/system/personal_snippet/:id/:random_hex/:filename PersonalFileUploader Snippet
프로젝트 아바타 yes uploads/-/system/project/avatar/:id/:filename AvatarUploader Project
주제 아바타 yes uploads/-/system/projects/topic/avatar/:id/:filename AvatarUploader Topic
이슈/MR/노트 마크다운 첨부 파일 yes uploads/:project_path_with_namespace/:random_hex/:filename FileUploader Project
이슈/MR/노트 레거시 마크다운 첨부 파일 no uploads/-/system/note/attachment/:id/:filename AttachmentUploader Note
디자인 관리 디자인 섬네일 yes uploads/-/system/design_management/action/image_v432x230/:id/:filename DesignManagement::DesignV432x230Uploader DesignManagement::Action
CI 아티팩트 (CE) yes shared/artifacts/:disk_hash[0..1]/:disk_hash[2..3]/:disk_hash/:year_:month_:date/:job_id/:job_artifact_id (:disk_hashproject_id의 SHA256 다이제스트임) JobArtifactUploader Ci::JobArtifact
LFS 객체 (CE) yes shared/lfs-objects/:hex/:hex/:object_hash LfsObjectUploader LfsObject
외부 Merge Request 차이 yes shared/external-diffs/merge_request_diffs/mr-:parent_id/diff-:id ExternalDiffUploader MergeRequestDiff
이슈 미터릭 이미지 yes uploads/-/system/issuable_metric_image/file/:id/:filename IssuableMetricImageUploader IssuableMetricImage

CI 아티팩트 및 LFS 객체는 CE와 EE에서 다르게 작동합니다. CE에서는 GitlabUploader를 상속받지만, EE에서는 ObjectStorage를 상속받아 S3 API 호환 객체 리포지터리에 파일을 저장합니다.

이슈/MR/노트 마크다운 첨부 파일의 경우, Hashed Storage 레이아웃을 사용하여 경로를 기반으로 하는 대신 가변 변수 :project_path_with_namespace로 경로를 기반으로하는 대신 프로젝트 ID의 해시를 사용할 수 있습니다(10.2에서 도입).

모든 업로드를 한 번에 객체 리포지터리로 마이그레이션하려면 올인원 Rake 작업을 제공합니다. 새로운 업로더 클래스나 모델 타입이 도입된 경우 해당하는 Rake 작업 호출을 카테고리 디렉터리에 추가해야 합니다.

경로 세그먼트

파일은 여러 위치에 저장되며 다양한 경로 체계를 사용합니다. 모든 GitlabUploader 파생 클래스는 이 경로 세그먼트 스키마를 준수해야 합니다.

|   GitlabUploader
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `<gitlab_root>/public/` | `uploads/-/system/`       | `user/avatar/:id/`                | `:filename`                      |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root`      | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`  | `CarrierWave::Uploader#filename` |
|                         | `CarrierWave::Uploader#store_dir`                             |                                  |

|   FileUploader
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `<gitlab_root>/shared/` | `artifacts/`              | `:year_:month/:id`                | `:filename`                      |
| `<gitlab_root>/shared/` | `snippets/`               | `:secret/`                        | `:filename`                      |
| ----------------------- + ------------------------- + --------------------------------- + -------------------------------- |
| `CarrierWave.root`      | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`  | `CarrierWave::Uploader#filename` |
|                         | `CarrierWave::Uploader#store_dir`                             |                                  |
|                         |                           | `FileUploader#upload_path`                                           |

|   ObjectStore::Concern (store = remote)
| ----------------------- + ------------------------- + ----------------------------------- + -------------------------------- |
| `<bucket_name>`         | <ignored>                 | `user/avatar/:id/`                  | `:filename`                      |
| ----------------------- + ------------------------- + ----------------------------------- + -------------------------------- |
| `#fog_dir`              | `GitlabUploader.base_dir` | `GitlabUploader#dynamic_segment`    | `CarrierWave::Uploader#filename` |
|                         |                           | `ObjectStorage::Concern#store_dir`  |                                  |
|                         |                           | `ObjectStorage::Concern#upload_path`                                   |

RecordsUploads::ConcernGitlabUploader에 의해 저장된 모든 파일에 대해 GitlabUploader#dynamic_path를 유지하는 Upload 항목을 생성합니다. 그런 다음 Upload#build_uploader 메서드를 사용하여 파일을 조작할 수 있습니다.

객체 리포지터리

GitlabUploader 파생 클래스에 ObjectStorage::Concern을 포함시킴으로써 해당 업로더에 대해 객체 리포지터리를 활성화할 수 있습니다. 업로더에 객체 리포지터리를 활성화하려면 1) RecordsUpload::Concern을 포함하고 ObjectStorage::Extension::RecordsUploads를 먼저 삽입하거나 2) 업로더를 마운트하고 새로운 필드 <mount>_store를 만들어야 합니다.

CarrierWave::Uploader#store_dir는 다음을 대체하여 사용됩니다.

  • 로컬 리포지터리인 경우 GitlabUploader.base_dir + GitlabUploader.dynamic_segment
  • 원격 리포지터리인 경우 GitlabUploader.dynamic_segment (버킷 이름은 네임스페이스로 사용됨)

ObjectStorage::Extension::RecordsUploads 사용하기

이 관심은 이미 포함되어 있지 않다면 RecordsUploads::Concern를 포함합니다.

ObjectStorage::Concern 업로더는 일치하는 Upload를 찾아 올바른 객체 리포지터리를 선택합니다. 각 리포지터리(LOCAL/REMOTE)마다 #store_dirs + identifier를 사용하여 Upload가 매핑됩니다.

class SongUploader < GitlabUploader
  include RecordsUploads::Concern
  include ObjectStorage::Concern
  prepend ObjectStorage::Extension::RecordsUploads
  
  ...
end

class Thing < ActiveRecord::Base
  mount :theme, SongUploader # 멋진 테마 송이 있어요!
  
  ...
end

업로더 장착하기

ObjectStorage::Concern은 올바른 객체 리포지터리를 선택하기 위해 model.<mount>_store 속성을 쿼리합니다. 이 컬럼은 모델 스키마에 존재해야 합니다.

class SongUploader < GitlabUploader
  include ObjectStorage::Concern
  
  ...
end

class Thing < ActiveRecord::Base
  attr_reader :theme_store # 이것은 ActiveRecord 속성입니다.
  mount :theme, SongUploader # 멋진 테마 송이 있어요!
  
  def theme_store
    super || ObjectStorage::Store::LOCAL
  end
  
  ...
end