InfoGrab DocsInfoGrab Docs

패키지 레지스트리의 Maven 패키지

요약

프로젝트의 패키지 레지스트리에 Maven 아티팩트를 게시합니다. Maven 패키지 관리자 클라이언트가 사용하는 구체적인 API 엔드포인트 문서는 Maven API 문서를 참고합니다. 패키지를 게시하려면 토큰이 필요합니다.

프로젝트의 패키지 레지스트리에 Maven 아티팩트를 게시합니다. 그런 다음 의존성으로 사용해야 할 때마다 패키지를 설치합니다.

Maven 패키지 관리자 클라이언트가 사용하는 구체적인 API 엔드포인트 문서는 Maven API 문서를 참고합니다.

지원되는 클라이언트:

  • mvn. Maven 패키지를 빌드하는 방법을 확인합니다.
  • gradle. Gradle 패키지를 빌드하는 방법을 확인합니다.
  • sbt.

GitLab 패키지 레지스트리에 게시#

패키지 레지스트리 인증#

패키지를 게시하려면 토큰이 필요합니다. 목적에 따라 사용할 수 있는 토큰이 다릅니다. 자세한 내용은 토큰 관련 안내를 참고합니다.

토큰을 생성하고 이후 과정에서 사용할 수 있도록 저장합니다.

여기에 문서화된 방법 외의 인증 방법은 사용하지 않습니다. 문서화되지 않은 인증 방법은 향후 제거될 수 있습니다.

클라이언트 설정 편집#

HTTP로 Maven 리포지터리에 인증하도록 설정을 업데이트합니다.

커스텀 HTTP 헤더#

클라이언트의 설정 파일에 인증 정보를 추가해야 합니다.

토큰 유형 이름 토큰
Personal access token Private-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token Deploy-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token Job-Token ${CI_JOB_TOKEN}
OAuth token Authorization 토큰 앞에 Bearer를 붙입니다(예: Bearer <oauth_token>)
Note

<name> 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

다음 섹션을 settings.xml 파일에 추가합니다.

<settings>
  <servers>
    <server>
      <id>gitlab-maven</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>REPLACE_WITH_NAME</name>
            <value>REPLACE_WITH_TOKEN</value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
  </servers>
</settings>
토큰 유형 이름 토큰
Personal access token Private-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token Deploy-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token Job-Token System.getenv("CI_JOB_TOKEN")
OAuth token Authorization 토큰 앞에 Bearer를 붙입니다(예: Bearer <oauth_token>)
Note

<name> 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

GRADLE_USER_HOME 디렉터리에 다음 내용으로 gradle.properties 파일을 생성합니다.

gitLabPrivateToken=REPLACE_WITH_YOUR_TOKEN

build.gradle 파일에 repositories 섹션을 추가합니다.

  • Groovy DSL:

    repositories {
        maven {
            url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
            name "GitLab"
            credentials(HttpHeaderCredentials) {
                name = 'REPLACE_WITH_NAME'
                value = gitLabPrivateToken
            }
            authentication {
                header(HttpHeaderAuthentication)
            }
        }
    }
    
  • Kotlin DSL:

    repositories {
        maven {
            url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
            name = "GitLab"
            credentials(HttpHeaderCredentials::class) {
                name = "REPLACE_WITH_NAME"
                value = findProperty("gitLabPrivateToken") as String?
            }
            authentication {
                create("header", HttpHeaderAuthentication::class)
            }
        }
    }
    
기본 HTTP 인증#

Maven 패키지 레지스트리 인증에 기본 HTTP 인증을 사용할 수도 있습니다.

토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token ${CI_JOB_TOKEN}

다음 섹션을 settings.xml 파일에 추가합니다.

<settings>
  <servers>
    <server>
      <id>gitlab-maven</id>
      <username>REPLACE_WITH_NAME</username>
      <password>REPLACE_WITH_TOKEN</password>
      <configuration>
        <authenticationInfo>
          <userName>REPLACE_WITH_NAME</userName>
          <password>REPLACE_WITH_TOKEN</password>
        </authenticationInfo>
      </configuration>
    </server>
  </servers>
</settings>
토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token System.getenv("CI_JOB_TOKEN")

GRADLE_USER_HOME 디렉터리에 다음 내용으로 gradle.properties 파일을 생성합니다.

gitLabPrivateToken=REPLACE_WITH_YOUR_TOKEN

repositories 섹션을 build.gradle에 추가합니다.

  • Groovy DSL:

    repositories {
        maven {
            url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
            name "GitLab"
            credentials(PasswordCredentials) {
                username = 'REPLACE_WITH_NAME'
                password = gitLabPrivateToken
            }
            authentication {
                basic(BasicAuthentication)
            }
        }
    }
    
  • Kotlin DSL:

    repositories {
        maven {
            url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
            name = "GitLab"
            credentials(BasicAuthentication::class) {
                username = "REPLACE_WITH_NAME"
                password = findProperty("gitLabPrivateToken") as String?
            }
            authentication {
                create("basic", BasicAuthentication::class)
            }
        }
    }
    
토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token sys.env.get("CI_JOB_TOKEN").get

SBT 인증은 기본 HTTP 인증을 기반으로 합니다. 이름과 비밀번호를 제공해야 합니다.

Note

name 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

sbt로 Maven GitLab 패키지 레지스트리에서 패키지를 설치하려면 Maven 리졸버를 설정해야 합니다. 비공개 또는 내부 프로젝트나 그룹에 접근한다면 자격 증명을 설정해야 합니다. 리졸버와 인증을 설정한 뒤에는 프로젝트, 그룹, 네임스페이스에서 패키지를 설치할 수 있습니다.

build.sbt에 다음 줄을 추가합니다.

resolvers += ("gitlab" at "<endpoint url>")

credentials += Credentials("GitLab Packages Registry", "<host>", "<name>", "<token>")

이 예시에서:

  • <endpoint url>은 엔드포인트 URL입니다. 예: https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven.
  • <host>는 <endpoint url>에 있는 호스트로, 프로토콜 스킴과 포트는 제외합니다. 예: gitlab.example.com.
  • <name>과 <token>은 앞의 표에서 설명했습니다.

명명 규칙#

Maven 패키지를 설치할 때는 세 가지 엔드포인트 중 하나를 사용할 수 있습니다. 패키지는 프로젝트에 게시해야 하지만, 선택한 엔드포인트에 따라 게시를 위해 pom.xml 파일에 추가하는 설정이 달라집니다.

세 가지 엔드포인트는 다음과 같습니다.

  • 프로젝트: Maven 패키지가 몇 개 없고 같은 GitLab 그룹에 있지 않을 때 사용합니다.
  • 그룹: 같은 GitLab 그룹의 여러 프로젝트에서 패키지를 설치하려 할 때 사용합니다. GitLab은 그룹 안에서 패키지 이름의 고유성을 보장하지 않습니다. 같은 패키지 이름과 패키지 버전을 가진 프로젝트가 두 개 있을 수 있으며, 이 경우 GitLab은 더 최근 것을 제공합니다.
  • 인스턴스: 여러 GitLab 그룹이나 각자의 네임스페이스에 패키지가 많을 때 사용합니다.

인스턴스 레벨 엔드포인트의 경우, Maven의 pom.xml에서 관련 섹션이 다음과 같은지 확인합니다.

  <groupId>group-slug.subgroup-slug</groupId>
  <artifactId>project-slug</artifactId>

프로젝트와 경로가 같은 패키지만 인스턴스 레벨 엔드포인트로 노출됩니다.

프로젝트 패키지 인스턴스 레벨 엔드포인트 사용 가능
foo/bar foo/bar/1.0-SNAPSHOT 예
gitlab-org/gitlab foo/bar/1.0-SNAPSHOT 아니요
gitlab-org/gitlab gitlab-org/gitlab/1.0-SNAPSHOT 예

엔드포인트 URL#

엔드포인트 pom.xml용 엔드포인트 URL 추가 정보
프로젝트 https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다. <project_id>는 프로젝트 개요 페이지에서 확인할 수 있는 프로젝트 ID로 바꿉니다.
그룹 https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다. <group_id>는 그룹 홈페이지에서 확인할 수 있는 그룹 ID로 바꿉니다.
인스턴스 https://gitlab.example.com/api/v4/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다.

게시용 설정 파일 편집#

클라이언트의 설정 파일에 게시 정보를 추가해야 합니다.

어떤 엔드포인트를 선택하든 다음이 있어야 합니다.

  • distributionManagement 섹션의 프로젝트별 URL.
  • repository 및 distributionManagement 섹션.

Maven의 pom.xml에서 관련 repository 섹션은 다음과 같아야 합니다.

<repositories>
  <repository>
    <id>gitlab-maven</id>
    <url><your_endpoint_url></url>
  </repository>
</repositories>
<distributionManagement>
  <repository>
    <id>gitlab-maven</id>
    <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
  </repository>
  <snapshotRepository>
    <id>gitlab-maven</id>
    <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
  </snapshotRepository>
</distributionManagement>

Gradle로 패키지를 게시하려면 다음 절차를 따릅니다.

  1. plugins 섹션에 Gradle 플러그인 maven-publish를 추가합니다.

    • Groovy DSL:

      plugins {
          id 'java'
          id 'maven-publish'
      }
      
    • Kotlin DSL:

      plugins {
          java
          `maven-publish`
      }
      
  2. publishing 섹션을 추가합니다.

    • Groovy DSL:

      publishing {
          publications {
              library(MavenPublication) {
                  from components.java
              }
          }
          repositories {
              maven {
                  url "https://gitlab.example.com/api/v4/projects//packages/maven"
                  credentials(HttpHeaderCredentials) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value = gitLabPrivateToken // the variable resides in $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      header(HttpHeaderAuthentication)
                  }
              }
          }
      }
      
    • Kotlin DSL:

      publishing {
          publications {
              create("library") {
                  from(components["java"])
              }
          }
          repositories {
              maven {
                  url = uri("https://gitlab.example.com/api/v4/projects//packages/maven")
                  credentials(HttpHeaderCredentials::class) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value =
                          findProperty("gitLabPrivateToken") as String? // the variable resides in $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      create("header", HttpHeaderAuthentication::class)
                  }
              }
          }
      }
      

패키지 게시#

Warning

DeployAtEnd 옵션을 사용하면 업로드가 400 bad request {"message":"Validation failed: Name has already been taken"}로 거부될 수 있습니다. 자세한 내용은 이슈 424238을 참고합니다.

인증을 설정하고 게시할 엔드포인트를 선택한 뒤에는 프로젝트에 Maven 패키지를 게시합니다.

Maven으로 패키지를 게시하려면 다음을 실행합니다.

mvn deploy

배포에 성공하면 빌드 성공 메시지가 표시됩니다.

...
[INFO] BUILD SUCCESS
...

이 메시지에는 패키지가 올바른 위치에 게시되었다는 내용도 함께 표시됩니다.

Uploading to gitlab-maven: https://example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar

publish 태스크를 실행합니다.

gradle publish

프로젝트의 Packages and registries 페이지로 이동해 게시된 패키지를 확인합니다.

build.sbt 파일에서 publishTo 설정을 구성합니다.

publishTo := Some("gitlab" at "<endpoint url>")

자격 증명이 올바르게 참조되는지 확인합니다. 자세한 내용은 sbt 문서를 참고합니다.

sbt로 패키지를 게시하려면 다음을 실행합니다.

sbt publish

배포에 성공하면 빌드 성공 메시지가 표시됩니다.

[success] Total time: 1 s, completed Jan 28, 2020 12:08:57 PM

성공 메시지를 확인해 패키지가 올바른 위치에 게시되었는지 확인합니다.

[info]  published my-project_2.12 to https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/my-project_2.12/0.1.1-SNAPSHOT/my-project_2.12-0.1.1-SNAPSHOT.pom
Note

Maven 패키지를 게시하기 전에 보호하면 패키지가 403 Forbidden 오류와 Authorization failed 오류 메시지와 함께 거부됩니다. 게시할 때는 Maven 패키지가 보호되어 있지 않은지 확인합니다. 패키지 보호 규칙에 대한 자세한 내용은 패키지 보호 방법을 참고합니다.

패키지 설치#

GitLab 패키지 레지스트리에서 패키지를 설치하려면 리모트와 인증을 설정해야 합니다. 설정이 끝나면 프로젝트, 그룹, 네임스페이스에서 패키지를 설치할 수 있습니다.

같은 이름과 버전의 패키지가 여러 개 있으면 패키지를 설치할 때 가장 최근에 게시된 패키지를 가져옵니다.

mvn install로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. 프로젝트의 pom.xml 파일에 의존성을 직접 추가합니다. 앞에서 만든 예시를 추가하면 XML은 다음과 같습니다.

    <dependency>
      <groupId>com.mycompany.mydepartment</groupId>
      <artifactId>my-project</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    
  2. 프로젝트에서 다음을 실행합니다.

    mvn install
    

패키지가 패키지 레지스트리에서 다운로드된다는 메시지가 표시됩니다.

Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom

Maven dependency:get 명령을 직접 사용해 패키지를 설치할 수도 있습니다.

  1. 프로젝트 디렉터리에서 다음을 실행합니다.

    mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT -DremoteRepositories=gitlab-maven::::<gitlab endpoint url>  -s <path to settings.xml>
    
    • <gitlab endpoint url>은 GitLab 엔드포인트의 URL입니다.
    • <path to settings.xml>은 인증 정보가 들어 있는 settings.xml 파일의 경로입니다.
Note

gitlab-maven 명령의 리포지터리 ID와 settings.xml 파일의 리포지터리 ID는 일치해야 합니다.

패키지가 패키지 레지스트리에서 다운로드된다는 메시지가 표시됩니다.

Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom

gradle로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. dependencies 섹션에서 build.gradle에 의존성을 추가합니다.

    • Groovy DSL:

      dependencies {
          implementation 'com.mycompany.mydepartment:my-project:1.0-SNAPSHOT'
      }
      
    • Kotlin DSL:

      dependencies {
          implementation("com.mycompany.mydepartment:my-project:1.0-SNAPSHOT")
      }
      
  2. 프로젝트에서 다음을 실행합니다.

    gradle build
    

sbt로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. build.sbt에 인라인 의존성을 추가합니다.

    libraryDependencies += "com.mycompany.mydepartment" % "my-project" % "8.4"
    
  2. 프로젝트에서 다음을 실행합니다.

    sbt update
    

Maven 패키지 프록시 다운로드#

히스토리
  • GitLab 17.8에서 도입되었습니다.

GitLab Maven 패키지 레지스트리는 원격 포함 체크섬을 사용합니다. 파일을 다운로드하면 레지스트리가 파일을 프록시해 파일과 관련 체크섬을 한 번의 요청으로 Maven 클라이언트에 전송합니다.

최신 Maven 클라이언트에서 원격 포함 체크섬을 사용하면 다음과 같은 효과가 있습니다.

  • 클라이언트가 GitLab Maven 패키지 레지스트리에 보내는 웹 요청 수가 줄어듭니다.
  • GitLab 인스턴스의 부하가 줄어듭니다.
  • 클라이언트 명령 실행 시간이 단축됩니다.

기술적인 제약 때문에 오브젝트 스토리지를 사용할 때 Maven 패키지 레지스트리는 packages의 오브젝트 스토리지 설정에 있는 프록시 다운로드 설정을 무시합니다. 대신 Maven 패키지 레지스트리 다운로드에서는 프록시 다운로드가 항상 활성화됩니다.

Note

오브젝트 스토리지를 사용하지 않는다면 이 동작은 인스턴스에 영향을 주지 않습니다.

Maven 패키지를 위한 CI/CD 통합#

CI/CD를 사용해 Maven 패키지를 자동으로 빌드하고 테스트하고 게시할 수 있습니다. 이 섹션의 예시는 다음과 같은 시나리오를 다룹니다.

  • 멀티 모듈 프로젝트
  • 버전이 지정된 릴리스
  • 조건부 게시
  • 코드 품질 및 보안 스캔과의 통합

이 예시들은 프로젝트의 필요에 맞게 수정하고 조합할 수 있습니다.

프로젝트 요구 사항에 맞춰 Maven 버전, Java 버전, 그 밖의 세부 사항을 조정합니다. 또한 GitLab 패키지 레지스트리에 게시하는 데 필요한 자격 증명과 설정이 올바르게 구성되어 있는지 확인합니다.

기본 Maven 패키지 빌드 및 게시#

이 예시는 Maven 패키지를 빌드하고 게시하는 파이프라인을 구성합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

병렬 job을 사용한 멀티 모듈 Maven 프로젝트#

모듈이 여러 개인 대규모 프로젝트에서는 병렬 job으로 빌드 과정을 단축할 수 있습니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  parallel:
    matrix:
      - MODULE: [module1, module2, module3]
  script:
    - mvn $MAVEN_CLI_OPTS test -pl $MODULE

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

태그를 사용한 버전 릴리스#

이 예시는 태그를 푸시하면 버전이 지정된 릴리스를 만듭니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish
  - release

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

release:
  stage: release
  script:
    - mvn versions:set -DnewVersion=${CI_COMMIT_TAG}
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_TAG

변경 사항에 따른 조건부 게시#

이 예시는 특정 파일이 변경될 때만 패키지를 게시합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - pom.xml
        - src/**/*

코드 품질 및 보안 스캔과의 통합#

이 예시는 코드 품질 검사와 보안 스캔을 파이프라인에 통합합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Code-Quality.gitlab-ci.yml

stages:
  - build
  - test
  - quality
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

code_quality:
  stage: quality

sast:
  stage: quality

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

유용한 힌트#

같은 이름이나 버전의 패키지 게시#

기존 패키지와 이름과 버전이 같은 패키지를 게시하면 새 패키지 파일이 기존 패키지에 추가됩니다. UI나 API로 기존 패키지의 이전 자산에 계속 접근하고 확인할 수 있습니다.

이전 패키지 버전을 삭제하려면 Packages API나 UI를 사용합니다.

중복 Maven 패키지 허용 안 함#

히스토리
  • GitLab 15.0에서 필요한 권한이 Developer에서 Maintainer로 변경되었습니다.
  • GitLab 17.0에서 필요한 권한이 Maintainer에서 Owner로 변경되었습니다.

사용자가 중복 Maven 패키지를 게시하지 못하게 하려면 GraphQL API나 UI를 사용할 수 있습니다.

UI에서는 다음 절차를 따릅니다.

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Packages and registries를 선택합니다.
  3. Duplicate packages 표의 Maven 행에서 Allow duplicates 토글을 끕니다.
  4. 선택 사항. Exceptions 텍스트 상자에 허용할 패키지의 이름 및 버전과 일치하는 정규 표현식을 입력합니다.
Note

Allow duplicates가 켜져 있으면 Exceptions 텍스트 상자에 중복을 허용하지 않을 패키지 이름과 버전을 지정할 수 있습니다.

변경 사항은 자동으로 저장됩니다.

Maven Central로 요청 전달#

히스토리
  • GitLab 15.4에서 maven_central_request_forwarding이라는 피처 플래그와 함께 도입되었습니다. 기본적으로 비활성화되어 있습니다.
  • GitLab 17.0에서 필요한 권한이 Maintainer에서 Owner로 변경되었습니다.
Feature flag

이 기능의 제공 여부는 피처 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

패키지 레지스트리에서 Maven 패키지를 찾지 못하면 요청이 Maven Central로 전달됩니다.

피처 플래그가 활성화되어 있으면 관리자는 Continuous Integration 설정에서 이 동작을 비활성화할 수 있습니다.

Maven 전달은 프로젝트 레벨과 그룹 레벨 엔드포인트로만 제한됩니다. 인스턴스 레벨 엔드포인트는 해당 규칙을 따르지 않는 패키지에 사용할 수 없도록 하는 명명 제한이 있고, 공급망 방식 공격에 대한 보안 위험도 너무 큽니다.

mvn을 위한 추가 설정#

mvn을 사용할 때 Maven Central의 패키지를 GitLab에 요청하도록 Maven 프로젝트를 구성하는 방법은 여러 가지가 있습니다. Maven 리포지터리는 정해진 순서로 조회됩니다. 기본적으로 Maven Central이 Super POM을 통해 먼저 조회되는 경우가 많으므로, GitLab이 maven-central보다 먼저 조회되도록 구성해야 합니다.

모든 패키지 요청이 Maven Central 대신 GitLab으로 전송되게 하려면 settings.xml에 <mirror> 섹션을 추가해 중앙 리포지터리로서의 Maven Central을 재정의할 수 있습니다.

<settings>
  <servers>
    <server>
      <id>central-proxy</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>Private-Token</name>
            <value><personal_access_token></value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
  </servers>
  <mirrors>
    <mirror>
      <id>central-proxy</id>
      <name>GitLab proxy of central repo</name>
      <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
</settings>

GitLab CI/CD로 Maven 패키지 생성#

Maven용 패키지 리포지터리를 사용하도록 리포지터리를 구성한 뒤에는 새 패키지를 자동으로 빌드하도록 GitLab CI/CD를 구성할 수 있습니다.

기본 브랜치가 업데이트될 때마다 새 패키지를 생성할 수 있습니다.

  1. Maven의 settings.xml 역할을 하는 ci_settings.xml 파일을 생성합니다.

  2. pom.xml 파일에서 정의한 것과 같은 ID로 server 섹션을 추가합니다. 예를 들어 ID로 gitlab-maven을 사용합니다.

    <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
      <servers>
        <server>
          <id>gitlab-maven</id>
          <configuration>
            <httpHeaders>
              <property>
                <name>Job-Token</name>
                <value>${CI_JOB_TOKEN}</value>
              </property>
            </httpHeaders>
          </configuration>
        </server>
      </servers>
    </settings>
    
  3. pom.xml 파일에 다음 내용이 포함되어 있는지 확인합니다. 이 예시처럼 Maven이 사전 정의된 CI/CD 변수를 사용하게 하거나, 서버 호스트명과 프로젝트 ID를 직접 입력할 수 있습니다.

    <repositories>
      <repository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </repository>
    </repositories>
    <distributionManagement>
      <repository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </repository>
      <snapshotRepository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </snapshotRepository>
    </distributionManagement>
    
  4. .gitlab-ci.yml 파일에 deploy job을 추가합니다.

    deploy:
      image: maven:3.6-jdk-11
      script:
        - 'mvn deploy -s ci_settings.xml'
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  5. 이 파일들을 리포지터리에 푸시합니다.

다음에 deploy job이 실행되면 ci_settings.xml이 사용자 홈 위치로 복사됩니다. 이 예시에서는 다음과 같습니다.

  • job이 Docker 컨테이너에서 실행되므로 사용자는 root입니다.
  • Maven은 구성된 CI/CD 변수를 사용합니다.

기본 브랜치가 업데이트될 때마다 패키지를 생성할 수 있습니다.

  1. Gradle의 CI job 토큰으로 인증합니다.

  2. .gitlab-ci.yml 파일에 deploy job을 추가합니다.

    deploy:
      image: gradle:6.5-jdk11
      script:
        - 'gradle publish'
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  3. 파일을 리포지터리에 커밋합니다.

파이프라인이 성공하면 Maven 패키지가 생성됩니다.

버전 유효성 검사#

버전 문자열은 다음 정규 표현식으로 검증합니다.

\A(?!.*\.\.)[\w+.-]+\z

이 정규 표현식 편집기에서 정규 표현식을 시험하고 버전 문자열을 확인할 수 있습니다.

스냅샷 배포와 릴리스 배포에 다른 설정 사용#

스냅샷과 릴리스에 서로 다른 URL이나 설정을 사용하려면 다음과 같이 합니다.

  • pom.xml 파일의 <distributionManagement> 섹션에서 <repository> 요소와 <snapshotRepository> 요소를 따로 정의합니다.

유용한 Maven 명령줄 옵션#

GitLab CI/CD로 작업을 수행할 때 사용할 수 있는 Maven 명령줄 옵션이 몇 가지 있습니다.

  • 파일 전송 진행 상황 때문에 CI 로그를 읽기 어려울 수 있습니다. -ntp,--no-transfer-progress 옵션은 3.6.1에서 추가되었습니다. 또는 -B,--batch-mode나 더 낮은 수준의 로깅 변경을 확인합니다.

  • pom.xml 파일의 위치를 지정합니다(-f,--file).

    package:
      script:
        - 'mvn --no-transfer-progress -f helloworld/pom.xml package'
    
  • 사용자 설정의 위치를 지정합니다(-s,--settings). 기본 위치 대신 사용하며, -gs,--global-settings 옵션도 있습니다.

    package:
      script:
        - 'mvn -s settings/ci.xml package'
    

지원되는 CLI 명령#

GitLab Maven 리포지터리는 다음 CLI 명령을 지원합니다.

  • mvn deploy: 패키지를 패키지 레지스트리에 게시합니다.
  • mvn install: Maven 프로젝트에 지정된 패키지를 설치합니다.
  • mvn dependency:get: 특정 패키지를 설치합니다.
  • gradle publish: 패키지를 패키지 레지스트리에 게시합니다.
  • gradle build: 이 프로젝트를 빌드하고 테스트합니다.

문제 해결#

GitLab에서 Maven 패키지를 다루다 보면 문제가 발생할 수 있습니다. 자주 발생하는 문제는 다음 단계로 해결할 수 있습니다.

  • 인증 확인 - 인증 토큰이 올바르고 만료되지 않았는지 확인합니다.
  • 권한 확인 - 패키지를 게시하거나 설치하는 데 필요한 권한이 있는지 확인합니다.
  • Maven 설정 검증 - settings.xml 파일의 설정이 올바른지 다시 확인합니다.
  • GitLab CI/CD 로그 검토 - CI/CD 문제라면 job 로그에서 오류 메시지를 자세히 살펴봅니다.
  • 엔드포인트 URL 확인 - 프로젝트나 그룹에 맞는 엔드포인트 URL을 사용하고 있는지 확인합니다.
  • mvn 명령에 -s 옵션 사용 - Maven 명령은 항상 -s 옵션과 함께 실행합니다. 예를 들면 mvn package -s settings.xml입니다. 이 옵션이 없으면 인증 설정이 적용되지 않아 Maven이 패키지를 찾지 못할 수 있습니다.

캐시 지우기#

성능을 높이기 위해 클라이언트는 패키지 관련 파일을 캐시합니다. 문제가 발생하면 다음 명령으로 캐시를 지웁니다.

rm -rf ~/.m2/repository
rm -rf ~/.gradle/caches # Or replace ~/.gradle with your custom GRADLE_USER_HOME

네트워크 추적 로그 검토#

Maven 리포지터리에 문제가 있다면 네트워크 추적 로그를 검토할 수 있습니다. 네트워크 추적 로그에는 Maven 클라이언트가 기본적으로 제공하지 않는 더 자세한 오류 메시지가 담깁니다.

예를 들어 PAT 토큰으로 로컬에서 mvn deploy를 실행하면서 다음 옵션을 사용합니다.

mvn deploy \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.wagon.providers.http.httpclient=trace \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.wagon.providers.http.httpclient.wire=trace
Warning

이 옵션을 설정하면 모든 네트워크 요청이 기록되어 많은 양의 출력이 생성됩니다.

Maven 설정 확인#

CI/CD에서 settings.xml 파일과 관련된 문제가 발생하면 스크립트 태스크나 job을 추가해 유효 설정을 확인해 볼 수 있습니다.

help 플러그인은 환경 변수를 포함한 시스템 속성도 제공합니다.

mvn-settings:
  script:
    - 'mvn help:effective-settings'

package:
  script:
    - 'mvn help:system'
    - 'mvn package'

패키지 게시 시 401 Unauthorized 오류#

대개 인증 문제를 의미합니다. 다음을 확인합니다.

  • 인증 토큰이 유효하고 만료되지 않았습니다.
  • 올바른 토큰 유형(개인 액세스 토큰, 배포 토큰, CI job 토큰)을 사용하고 있습니다.
  • 토큰에 필요한 권한(api, read_api, read_repository)이 있습니다.
  • Maven 프로젝트라면 mvn 명령에 -s 옵션을 사용하고 있습니다(예: mvn deploy -s settings.xml). 이 옵션이 없으면 Maven이 settings.xml 파일의 인증 설정을 적용하지 않아 권한 오류가 발생합니다.

"Validation failed: Version is invalid" 메시지와 함께 발생하는 400 Bad Request 오류#

GitLab은 버전 문자열에 특정 요구 사항을 둡니다. 버전이 다음 형식을 따르는지 확인합니다.

^(?!.*\.\.)(?!.*\.$)[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*(\+[0-9A-Za-z-]+)?$

예를 들어 "1.0.0", "1.0-SNAPSHOT", "1.0.0-alpha"는 유효하지만 "1..0"이나 "1.0."은 유효하지 않습니다.

패키지 게시 시 403 Forbidden 오류#

Authorization failed 메시지와 함께 발생하는 403 Forbidden 오류는 대개 인증 문제이거나 권한 문제입니다. 다음을 확인합니다.

  • 올바른 토큰 유형(개인 액세스 토큰, 배포 토큰, CI/CD job 토큰)을 사용하고 있습니다. 자세한 내용은 패키지 레지스트리 인증을 참고합니다.
  • 토큰에 필요한 권한이 있습니다. Developer, Maintainer, Owner 권한이 있는 사용자만 패키지를 게시할 수 있습니다. 자세한 내용은 GitLab 권한을 참고합니다.
  • 게시하려는 패키지가 푸시 보호 규칙으로 보호되어 있지 않습니다. 패키지 보호 규칙에 대한 자세한 내용은 패키지 보호 방법을 참고합니다.

게시할 때 발생하는 Artifact already exists 오류#

이미 존재하는 패키지 버전을 게시하려고 할 때 이 오류가 발생합니다. 해결 방법은 다음과 같습니다.

  • 게시하기 전에 패키지 버전을 올립니다.
  • SNAPSHOT 버전을 사용한다면 설정에서 SNAPSHOT 덮어쓰기를 허용하고 있는지 확인합니다.

게시한 패키지가 UI에 표시되지 않음#

패키지를 방금 게시했다면 표시되기까지 잠시 걸릴 수 있습니다. 계속 표시되지 않으면 다음을 확인합니다.

  • 패키지를 볼 수 있는 권한이 있는지 확인합니다.
  • CI/CD 로그나 Maven 출력을 검토해 패키지가 정상적으로 게시되었는지 확인합니다.
  • 올바른 프로젝트나 그룹에서 찾고 있는지 확인합니다.

Maven 리포지터리 의존성 충돌#

의존성 충돌은 다음 방법으로 해결할 수 있습니다.

  • pom.xml에 버전을 명시적으로 정의합니다.
  • Maven의 dependency management 섹션으로 버전을 제어합니다.
  • <exclusions> 태그로 충돌하는 전이 의존성을 제외합니다.

Unable to find valid certification path to requested target 오류#

대개 SSL 인증서 문제입니다. 해결 방법은 다음과 같습니다.

  • JDK가 GitLab 서버의 SSL 인증서를 신뢰하는지 확인합니다.
  • 자체 서명 인증서를 사용한다면 JDK의 truststore에 추가합니다.
  • 최후의 수단으로 Maven 설정에서 SSL 검증을 비활성화할 수 있습니다. 프로덕션에서는 권장하지 않습니다.

No plugin found for prefix 파이프라인 오류#

대개 Maven이 플러그인을 찾지 못한다는 뜻입니다. 해결 방법은 다음과 같습니다.

  • 플러그인이 pom.xml에 올바르게 정의되어 있는지 확인합니다.
  • CI/CD 설정이 올바른 Maven 설정 파일을 사용하는지 확인합니다.
  • 파이프라인이 필요한 모든 리포지터리에 접근할 수 있는지 확인합니다.

패키지 레지스트리의 Maven 패키지

GitLab v19.4
Tier: Free, Premium, Ultimate
Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
원문 보기

요약

프로젝트의 패키지 레지스트리에 Maven 아티팩트를 게시합니다. Maven 패키지 관리자 클라이언트가 사용하는 구체적인 API 엔드포인트 문서는 Maven API 문서를 참고합니다. 패키지를 게시하려면 토큰이 필요합니다.

프로젝트의 패키지 레지스트리에 Maven 아티팩트를 게시합니다. 그런 다음 의존성으로 사용해야 할 때마다 패키지를 설치합니다.

Maven 패키지 관리자 클라이언트가 사용하는 구체적인 API 엔드포인트 문서는 Maven API 문서를 참고합니다.

지원되는 클라이언트:

  • mvn. Maven 패키지를 빌드하는 방법을 확인합니다.
  • gradle. Gradle 패키지를 빌드하는 방법을 확인합니다.
  • sbt.

GitLab 패키지 레지스트리에 게시#

패키지 레지스트리 인증#

패키지를 게시하려면 토큰이 필요합니다. 목적에 따라 사용할 수 있는 토큰이 다릅니다. 자세한 내용은 토큰 관련 안내를 참고합니다.

토큰을 생성하고 이후 과정에서 사용할 수 있도록 저장합니다.

여기에 문서화된 방법 외의 인증 방법은 사용하지 않습니다. 문서화되지 않은 인증 방법은 향후 제거될 수 있습니다.

클라이언트 설정 편집#

HTTP로 Maven 리포지터리에 인증하도록 설정을 업데이트합니다.

커스텀 HTTP 헤더#

클라이언트의 설정 파일에 인증 정보를 추가해야 합니다.

토큰 유형 이름 토큰
Personal access token Private-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token Deploy-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token Job-Token ${CI_JOB_TOKEN}
OAuth token Authorization 토큰 앞에 Bearer를 붙입니다(예: Bearer <oauth_token>)
Note

<name> 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

다음 섹션을 settings.xml 파일에 추가합니다.

<settings>
  <servers>
    <server>
      <id>gitlab-maven</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>REPLACE_WITH_NAME</name>
            <value>REPLACE_WITH_TOKEN</value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
  </servers>
</settings>
토큰 유형 이름 토큰
Personal access token Private-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token Deploy-Token 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token Job-Token System.getenv("CI_JOB_TOKEN")
OAuth token Authorization 토큰 앞에 Bearer를 붙입니다(예: Bearer <oauth_token>)
Note

<name> 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

GRADLE_USER_HOME 디렉터리에 다음 내용으로 gradle.properties 파일을 생성합니다.

gitLabPrivateToken=REPLACE_WITH_YOUR_TOKEN

build.gradle 파일에 repositories 섹션을 추가합니다.

  • Groovy DSL:

    repositories {
        maven {
            url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
            name "GitLab"
            credentials(HttpHeaderCredentials) {
                name = 'REPLACE_WITH_NAME'
                value = gitLabPrivateToken
            }
            authentication {
                header(HttpHeaderAuthentication)
            }
        }
    }
    
  • Kotlin DSL:

    repositories {
        maven {
            url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
            name = "GitLab"
            credentials(HttpHeaderCredentials::class) {
                name = "REPLACE_WITH_NAME"
                value = findProperty("gitLabPrivateToken") as String?
            }
            authentication {
                create("header", HttpHeaderAuthentication::class)
            }
        }
    }
    
기본 HTTP 인증#

Maven 패키지 레지스트리 인증에 기본 HTTP 인증을 사용할 수도 있습니다.

토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token ${CI_JOB_TOKEN}

다음 섹션을 settings.xml 파일에 추가합니다.

<settings>
  <servers>
    <server>
      <id>gitlab-maven</id>
      <username>REPLACE_WITH_NAME</username>
      <password>REPLACE_WITH_TOKEN</password>
      <configuration>
        <authenticationInfo>
          <userName>REPLACE_WITH_NAME</userName>
          <password>REPLACE_WITH_TOKEN</password>
        </authenticationInfo>
      </configuration>
    </server>
  </servers>
</settings>
토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token System.getenv("CI_JOB_TOKEN")

GRADLE_USER_HOME 디렉터리에 다음 내용으로 gradle.properties 파일을 생성합니다.

gitLabPrivateToken=REPLACE_WITH_YOUR_TOKEN

repositories 섹션을 build.gradle에 추가합니다.

  • Groovy DSL:

    repositories {
        maven {
            url "https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven"
            name "GitLab"
            credentials(PasswordCredentials) {
                username = 'REPLACE_WITH_NAME'
                password = gitLabPrivateToken
            }
            authentication {
                basic(BasicAuthentication)
            }
        }
    }
    
  • Kotlin DSL:

    repositories {
        maven {
            url = uri("https://gitlab.example.com/api/v4/groups/<group>/-/packages/maven")
            name = "GitLab"
            credentials(BasicAuthentication::class) {
                username = "REPLACE_WITH_NAME"
                password = findProperty("gitLabPrivateToken") as String?
            }
            authentication {
                create("basic", BasicAuthentication::class)
            }
        }
    }
    
토큰 유형 이름 토큰
Personal access token 사용자의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
Deploy token 배포 토큰의 사용자명 토큰을 그대로 붙여넣거나 토큰을 저장할 환경 변수를 정의합니다
CI Job token gitlab-ci-token sys.env.get("CI_JOB_TOKEN").get

SBT 인증은 기본 HTTP 인증을 기반으로 합니다. 이름과 비밀번호를 제공해야 합니다.

Note

name 필드의 이름은 선택한 토큰에 맞춰 지정해야 합니다.

sbt로 Maven GitLab 패키지 레지스트리에서 패키지를 설치하려면 Maven 리졸버를 설정해야 합니다. 비공개 또는 내부 프로젝트나 그룹에 접근한다면 자격 증명을 설정해야 합니다. 리졸버와 인증을 설정한 뒤에는 프로젝트, 그룹, 네임스페이스에서 패키지를 설치할 수 있습니다.

build.sbt에 다음 줄을 추가합니다.

resolvers += ("gitlab" at "<endpoint url>")

credentials += Credentials("GitLab Packages Registry", "<host>", "<name>", "<token>")

이 예시에서:

  • <endpoint url>은 엔드포인트 URL입니다. 예: https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven.
  • <host>는 <endpoint url>에 있는 호스트로, 프로토콜 스킴과 포트는 제외합니다. 예: gitlab.example.com.
  • <name>과 <token>은 앞의 표에서 설명했습니다.

명명 규칙#

Maven 패키지를 설치할 때는 세 가지 엔드포인트 중 하나를 사용할 수 있습니다. 패키지는 프로젝트에 게시해야 하지만, 선택한 엔드포인트에 따라 게시를 위해 pom.xml 파일에 추가하는 설정이 달라집니다.

세 가지 엔드포인트는 다음과 같습니다.

  • 프로젝트: Maven 패키지가 몇 개 없고 같은 GitLab 그룹에 있지 않을 때 사용합니다.
  • 그룹: 같은 GitLab 그룹의 여러 프로젝트에서 패키지를 설치하려 할 때 사용합니다. GitLab은 그룹 안에서 패키지 이름의 고유성을 보장하지 않습니다. 같은 패키지 이름과 패키지 버전을 가진 프로젝트가 두 개 있을 수 있으며, 이 경우 GitLab은 더 최근 것을 제공합니다.
  • 인스턴스: 여러 GitLab 그룹이나 각자의 네임스페이스에 패키지가 많을 때 사용합니다.

인스턴스 레벨 엔드포인트의 경우, Maven의 pom.xml에서 관련 섹션이 다음과 같은지 확인합니다.

  <groupId>group-slug.subgroup-slug</groupId>
  <artifactId>project-slug</artifactId>

프로젝트와 경로가 같은 패키지만 인스턴스 레벨 엔드포인트로 노출됩니다.

프로젝트 패키지 인스턴스 레벨 엔드포인트 사용 가능
foo/bar foo/bar/1.0-SNAPSHOT 예
gitlab-org/gitlab foo/bar/1.0-SNAPSHOT 아니요
gitlab-org/gitlab gitlab-org/gitlab/1.0-SNAPSHOT 예

엔드포인트 URL#

엔드포인트 pom.xml용 엔드포인트 URL 추가 정보
프로젝트 https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다. <project_id>는 프로젝트 개요 페이지에서 확인할 수 있는 프로젝트 ID로 바꿉니다.
그룹 https://gitlab.example.com/api/v4/groups/<group_id>/-/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다. <group_id>는 그룹 홈페이지에서 확인할 수 있는 그룹 ID로 바꿉니다.
인스턴스 https://gitlab.example.com/api/v4/packages/maven gitlab.example.com은 사용 중인 도메인 이름으로 바꿉니다.

게시용 설정 파일 편집#

클라이언트의 설정 파일에 게시 정보를 추가해야 합니다.

어떤 엔드포인트를 선택하든 다음이 있어야 합니다.

  • distributionManagement 섹션의 프로젝트별 URL.
  • repository 및 distributionManagement 섹션.

Maven의 pom.xml에서 관련 repository 섹션은 다음과 같아야 합니다.

<repositories>
  <repository>
    <id>gitlab-maven</id>
    <url><your_endpoint_url></url>
  </repository>
</repositories>
<distributionManagement>
  <repository>
    <id>gitlab-maven</id>
    <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
  </repository>
  <snapshotRepository>
    <id>gitlab-maven</id>
    <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
  </snapshotRepository>
</distributionManagement>

Gradle로 패키지를 게시하려면 다음 절차를 따릅니다.

  1. plugins 섹션에 Gradle 플러그인 maven-publish를 추가합니다.

    • Groovy DSL:

      plugins {
          id 'java'
          id 'maven-publish'
      }
      
    • Kotlin DSL:

      plugins {
          java
          `maven-publish`
      }
      
  2. publishing 섹션을 추가합니다.

    • Groovy DSL:

      publishing {
          publications {
              library(MavenPublication) {
                  from components.java
              }
          }
          repositories {
              maven {
                  url "https://gitlab.example.com/api/v4/projects//packages/maven"
                  credentials(HttpHeaderCredentials) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value = gitLabPrivateToken // the variable resides in $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      header(HttpHeaderAuthentication)
                  }
              }
          }
      }
      
    • Kotlin DSL:

      publishing {
          publications {
              create("library") {
                  from(components["java"])
              }
          }
          repositories {
              maven {
                  url = uri("https://gitlab.example.com/api/v4/projects//packages/maven")
                  credentials(HttpHeaderCredentials::class) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value =
                          findProperty("gitLabPrivateToken") as String? // the variable resides in $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      create("header", HttpHeaderAuthentication::class)
                  }
              }
          }
      }
      

패키지 게시#

Warning

DeployAtEnd 옵션을 사용하면 업로드가 400 bad request {"message":"Validation failed: Name has already been taken"}로 거부될 수 있습니다. 자세한 내용은 이슈 424238을 참고합니다.

인증을 설정하고 게시할 엔드포인트를 선택한 뒤에는 프로젝트에 Maven 패키지를 게시합니다.

Maven으로 패키지를 게시하려면 다음을 실행합니다.

mvn deploy

배포에 성공하면 빌드 성공 메시지가 표시됩니다.

...
[INFO] BUILD SUCCESS
...

이 메시지에는 패키지가 올바른 위치에 게시되었다는 내용도 함께 표시됩니다.

Uploading to gitlab-maven: https://example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.jar

publish 태스크를 실행합니다.

gradle publish

프로젝트의 Packages and registries 페이지로 이동해 게시된 패키지를 확인합니다.

build.sbt 파일에서 publishTo 설정을 구성합니다.

publishTo := Some("gitlab" at "<endpoint url>")

자격 증명이 올바르게 참조되는지 확인합니다. 자세한 내용은 sbt 문서를 참고합니다.

sbt로 패키지를 게시하려면 다음을 실행합니다.

sbt publish

배포에 성공하면 빌드 성공 메시지가 표시됩니다.

[success] Total time: 1 s, completed Jan 28, 2020 12:08:57 PM

성공 메시지를 확인해 패키지가 올바른 위치에 게시되었는지 확인합니다.

[info]  published my-project_2.12 to https://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/my-project_2.12/0.1.1-SNAPSHOT/my-project_2.12-0.1.1-SNAPSHOT.pom
Note

Maven 패키지를 게시하기 전에 보호하면 패키지가 403 Forbidden 오류와 Authorization failed 오류 메시지와 함께 거부됩니다. 게시할 때는 Maven 패키지가 보호되어 있지 않은지 확인합니다. 패키지 보호 규칙에 대한 자세한 내용은 패키지 보호 방법을 참고합니다.

패키지 설치#

GitLab 패키지 레지스트리에서 패키지를 설치하려면 리모트와 인증을 설정해야 합니다. 설정이 끝나면 프로젝트, 그룹, 네임스페이스에서 패키지를 설치할 수 있습니다.

같은 이름과 버전의 패키지가 여러 개 있으면 패키지를 설치할 때 가장 최근에 게시된 패키지를 가져옵니다.

mvn install로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. 프로젝트의 pom.xml 파일에 의존성을 직접 추가합니다. 앞에서 만든 예시를 추가하면 XML은 다음과 같습니다.

    <dependency>
      <groupId>com.mycompany.mydepartment</groupId>
      <artifactId>my-project</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    
  2. 프로젝트에서 다음을 실행합니다.

    mvn install
    

패키지가 패키지 레지스트리에서 다운로드된다는 메시지가 표시됩니다.

Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom

Maven dependency:get 명령을 직접 사용해 패키지를 설치할 수도 있습니다.

  1. 프로젝트 디렉터리에서 다음을 실행합니다.

    mvn dependency:get -Dartifact=com.nickkipling.app:nick-test-app:1.1-SNAPSHOT -DremoteRepositories=gitlab-maven::::<gitlab endpoint url>  -s <path to settings.xml>
    
    • <gitlab endpoint url>은 GitLab 엔드포인트의 URL입니다.
    • <path to settings.xml>은 인증 정보가 들어 있는 settings.xml 파일의 경로입니다.
Note

gitlab-maven 명령의 리포지터리 ID와 settings.xml 파일의 리포지터리 ID는 일치해야 합니다.

패키지가 패키지 레지스트리에서 다운로드된다는 메시지가 표시됩니다.

Downloading from gitlab-maven: http://gitlab.example.com/api/v4/projects/PROJECT_ID/packages/maven/com/mycompany/mydepartment/my-project/1.0-SNAPSHOT/my-project-1.0-20200128.120857-1.pom

gradle로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. dependencies 섹션에서 build.gradle에 의존성을 추가합니다.

    • Groovy DSL:

      dependencies {
          implementation 'com.mycompany.mydepartment:my-project:1.0-SNAPSHOT'
      }
      
    • Kotlin DSL:

      dependencies {
          implementation("com.mycompany.mydepartment:my-project:1.0-SNAPSHOT")
      }
      
  2. 프로젝트에서 다음을 실행합니다.

    gradle build
    

sbt로 패키지를 설치하려면 다음 절차를 따릅니다.

  1. build.sbt에 인라인 의존성을 추가합니다.

    libraryDependencies += "com.mycompany.mydepartment" % "my-project" % "8.4"
    
  2. 프로젝트에서 다음을 실행합니다.

    sbt update
    

Maven 패키지 프록시 다운로드#

히스토리
  • GitLab 17.8에서 도입되었습니다.

GitLab Maven 패키지 레지스트리는 원격 포함 체크섬을 사용합니다. 파일을 다운로드하면 레지스트리가 파일을 프록시해 파일과 관련 체크섬을 한 번의 요청으로 Maven 클라이언트에 전송합니다.

최신 Maven 클라이언트에서 원격 포함 체크섬을 사용하면 다음과 같은 효과가 있습니다.

  • 클라이언트가 GitLab Maven 패키지 레지스트리에 보내는 웹 요청 수가 줄어듭니다.
  • GitLab 인스턴스의 부하가 줄어듭니다.
  • 클라이언트 명령 실행 시간이 단축됩니다.

기술적인 제약 때문에 오브젝트 스토리지를 사용할 때 Maven 패키지 레지스트리는 packages의 오브젝트 스토리지 설정에 있는 프록시 다운로드 설정을 무시합니다. 대신 Maven 패키지 레지스트리 다운로드에서는 프록시 다운로드가 항상 활성화됩니다.

Note

오브젝트 스토리지를 사용하지 않는다면 이 동작은 인스턴스에 영향을 주지 않습니다.

Maven 패키지를 위한 CI/CD 통합#

CI/CD를 사용해 Maven 패키지를 자동으로 빌드하고 테스트하고 게시할 수 있습니다. 이 섹션의 예시는 다음과 같은 시나리오를 다룹니다.

  • 멀티 모듈 프로젝트
  • 버전이 지정된 릴리스
  • 조건부 게시
  • 코드 품질 및 보안 스캔과의 통합

이 예시들은 프로젝트의 필요에 맞게 수정하고 조합할 수 있습니다.

프로젝트 요구 사항에 맞춰 Maven 버전, Java 버전, 그 밖의 세부 사항을 조정합니다. 또한 GitLab 패키지 레지스트리에 게시하는 데 필요한 자격 증명과 설정이 올바르게 구성되어 있는지 확인합니다.

기본 Maven 패키지 빌드 및 게시#

이 예시는 Maven 패키지를 빌드하고 게시하는 파이프라인을 구성합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

병렬 job을 사용한 멀티 모듈 Maven 프로젝트#

모듈이 여러 개인 대규모 프로젝트에서는 병렬 job으로 빌드 과정을 단축할 수 있습니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  parallel:
    matrix:
      - MODULE: [module1, module2, module3]
  script:
    - mvn $MAVEN_CLI_OPTS test -pl $MODULE

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

태그를 사용한 버전 릴리스#

이 예시는 태그를 푸시하면 버전이 지정된 릴리스를 만듭니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish
  - release

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

release:
  stage: release
  script:
    - mvn versions:set -DnewVersion=${CI_COMMIT_TAG}
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_TAG

변경 사항에 따른 조건부 게시#

이 예시는 특정 파일이 변경될 때만 패키지를 게시합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

stages:
  - build
  - test
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - pom.xml
        - src/**/*

코드 품질 및 보안 스캔과의 통합#

이 예시는 코드 품질 검사와 보안 스캔을 파이프라인에 통합합니다.

default:
  image: maven:3.8.5-openjdk-17
  cache:
    paths:
      - .m2/repository/
      - target/

variables:
  MAVEN_CLI_OPTS: "-s .m2/settings.xml --batch-mode"
  MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

include:
  - template: Security/SAST.gitlab-ci.yml
  - template: Code-Quality.gitlab-ci.yml

stages:
  - build
  - test
  - quality
  - publish

build:
  stage: build
  script:
    - mvn $MAVEN_CLI_OPTS compile

test:
  stage: test
  script:
    - mvn $MAVEN_CLI_OPTS test

code_quality:
  stage: quality

sast:
  stage: quality

publish:
  stage: publish
  script:
    - mvn $MAVEN_CLI_OPTS deploy
  rules:
    - if: $CI_COMMIT_BRANCH == "main"

유용한 힌트#

같은 이름이나 버전의 패키지 게시#

기존 패키지와 이름과 버전이 같은 패키지를 게시하면 새 패키지 파일이 기존 패키지에 추가됩니다. UI나 API로 기존 패키지의 이전 자산에 계속 접근하고 확인할 수 있습니다.

이전 패키지 버전을 삭제하려면 Packages API나 UI를 사용합니다.

중복 Maven 패키지 허용 안 함#

히스토리
  • GitLab 15.0에서 필요한 권한이 Developer에서 Maintainer로 변경되었습니다.
  • GitLab 17.0에서 필요한 권한이 Maintainer에서 Owner로 변경되었습니다.

사용자가 중복 Maven 패키지를 게시하지 못하게 하려면 GraphQL API나 UI를 사용할 수 있습니다.

UI에서는 다음 절차를 따릅니다.

  1. 상단 바에서 Search or go to를 선택하고 그룹을 찾습니다.
  2. 왼쪽 사이드바에서 Settings > Packages and registries를 선택합니다.
  3. Duplicate packages 표의 Maven 행에서 Allow duplicates 토글을 끕니다.
  4. 선택 사항. Exceptions 텍스트 상자에 허용할 패키지의 이름 및 버전과 일치하는 정규 표현식을 입력합니다.
Note

Allow duplicates가 켜져 있으면 Exceptions 텍스트 상자에 중복을 허용하지 않을 패키지 이름과 버전을 지정할 수 있습니다.

변경 사항은 자동으로 저장됩니다.

Maven Central로 요청 전달#

히스토리
  • GitLab 15.4에서 maven_central_request_forwarding이라는 피처 플래그와 함께 도입되었습니다. 기본적으로 비활성화되어 있습니다.
  • GitLab 17.0에서 필요한 권한이 Maintainer에서 Owner로 변경되었습니다.
Feature flag

이 기능의 제공 여부는 피처 플래그로 제어됩니다. 자세한 내용은 히스토리를 참고합니다.

패키지 레지스트리에서 Maven 패키지를 찾지 못하면 요청이 Maven Central로 전달됩니다.

피처 플래그가 활성화되어 있으면 관리자는 Continuous Integration 설정에서 이 동작을 비활성화할 수 있습니다.

Maven 전달은 프로젝트 레벨과 그룹 레벨 엔드포인트로만 제한됩니다. 인스턴스 레벨 엔드포인트는 해당 규칙을 따르지 않는 패키지에 사용할 수 없도록 하는 명명 제한이 있고, 공급망 방식 공격에 대한 보안 위험도 너무 큽니다.

mvn을 위한 추가 설정#

mvn을 사용할 때 Maven Central의 패키지를 GitLab에 요청하도록 Maven 프로젝트를 구성하는 방법은 여러 가지가 있습니다. Maven 리포지터리는 정해진 순서로 조회됩니다. 기본적으로 Maven Central이 Super POM을 통해 먼저 조회되는 경우가 많으므로, GitLab이 maven-central보다 먼저 조회되도록 구성해야 합니다.

모든 패키지 요청이 Maven Central 대신 GitLab으로 전송되게 하려면 settings.xml에 <mirror> 섹션을 추가해 중앙 리포지터리로서의 Maven Central을 재정의할 수 있습니다.

<settings>
  <servers>
    <server>
      <id>central-proxy</id>
      <configuration>
        <httpHeaders>
          <property>
            <name>Private-Token</name>
            <value><personal_access_token></value>
          </property>
        </httpHeaders>
      </configuration>
    </server>
  </servers>
  <mirrors>
    <mirror>
      <id>central-proxy</id>
      <name>GitLab proxy of central repo</name>
      <url>https://gitlab.example.com/api/v4/projects/<project_id>/packages/maven</url>
      <mirrorOf>central</mirrorOf>
    </mirror>
  </mirrors>
</settings>

GitLab CI/CD로 Maven 패키지 생성#

Maven용 패키지 리포지터리를 사용하도록 리포지터리를 구성한 뒤에는 새 패키지를 자동으로 빌드하도록 GitLab CI/CD를 구성할 수 있습니다.

기본 브랜치가 업데이트될 때마다 새 패키지를 생성할 수 있습니다.

  1. Maven의 settings.xml 역할을 하는 ci_settings.xml 파일을 생성합니다.

  2. pom.xml 파일에서 정의한 것과 같은 ID로 server 섹션을 추가합니다. 예를 들어 ID로 gitlab-maven을 사용합니다.

    <settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
      <servers>
        <server>
          <id>gitlab-maven</id>
          <configuration>
            <httpHeaders>
              <property>
                <name>Job-Token</name>
                <value>${CI_JOB_TOKEN}</value>
              </property>
            </httpHeaders>
          </configuration>
        </server>
      </servers>
    </settings>
    
  3. pom.xml 파일에 다음 내용이 포함되어 있는지 확인합니다. 이 예시처럼 Maven이 사전 정의된 CI/CD 변수를 사용하게 하거나, 서버 호스트명과 프로젝트 ID를 직접 입력할 수 있습니다.

    <repositories>
      <repository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </repository>
    </repositories>
    <distributionManagement>
      <repository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </repository>
      <snapshotRepository>
        <id>gitlab-maven</id>
        <url>${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/maven</url>
      </snapshotRepository>
    </distributionManagement>
    
  4. .gitlab-ci.yml 파일에 deploy job을 추가합니다.

    deploy:
      image: maven:3.6-jdk-11
      script:
        - 'mvn deploy -s ci_settings.xml'
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  5. 이 파일들을 리포지터리에 푸시합니다.

다음에 deploy job이 실행되면 ci_settings.xml이 사용자 홈 위치로 복사됩니다. 이 예시에서는 다음과 같습니다.

  • job이 Docker 컨테이너에서 실행되므로 사용자는 root입니다.
  • Maven은 구성된 CI/CD 변수를 사용합니다.

기본 브랜치가 업데이트될 때마다 패키지를 생성할 수 있습니다.

  1. Gradle의 CI job 토큰으로 인증합니다.

  2. .gitlab-ci.yml 파일에 deploy job을 추가합니다.

    deploy:
      image: gradle:6.5-jdk11
      script:
        - 'gradle publish'
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    
  3. 파일을 리포지터리에 커밋합니다.

파이프라인이 성공하면 Maven 패키지가 생성됩니다.

버전 유효성 검사#

버전 문자열은 다음 정규 표현식으로 검증합니다.

\A(?!.*\.\.)[\w+.-]+\z

이 정규 표현식 편집기에서 정규 표현식을 시험하고 버전 문자열을 확인할 수 있습니다.

스냅샷 배포와 릴리스 배포에 다른 설정 사용#

스냅샷과 릴리스에 서로 다른 URL이나 설정을 사용하려면 다음과 같이 합니다.

  • pom.xml 파일의 <distributionManagement> 섹션에서 <repository> 요소와 <snapshotRepository> 요소를 따로 정의합니다.

유용한 Maven 명령줄 옵션#

GitLab CI/CD로 작업을 수행할 때 사용할 수 있는 Maven 명령줄 옵션이 몇 가지 있습니다.

  • 파일 전송 진행 상황 때문에 CI 로그를 읽기 어려울 수 있습니다. -ntp,--no-transfer-progress 옵션은 3.6.1에서 추가되었습니다. 또는 -B,--batch-mode나 더 낮은 수준의 로깅 변경을 확인합니다.

  • pom.xml 파일의 위치를 지정합니다(-f,--file).

    package:
      script:
        - 'mvn --no-transfer-progress -f helloworld/pom.xml package'
    
  • 사용자 설정의 위치를 지정합니다(-s,--settings). 기본 위치 대신 사용하며, -gs,--global-settings 옵션도 있습니다.

    package:
      script:
        - 'mvn -s settings/ci.xml package'
    

지원되는 CLI 명령#

GitLab Maven 리포지터리는 다음 CLI 명령을 지원합니다.

  • mvn deploy: 패키지를 패키지 레지스트리에 게시합니다.
  • mvn install: Maven 프로젝트에 지정된 패키지를 설치합니다.
  • mvn dependency:get: 특정 패키지를 설치합니다.
  • gradle publish: 패키지를 패키지 레지스트리에 게시합니다.
  • gradle build: 이 프로젝트를 빌드하고 테스트합니다.

문제 해결#

GitLab에서 Maven 패키지를 다루다 보면 문제가 발생할 수 있습니다. 자주 발생하는 문제는 다음 단계로 해결할 수 있습니다.

  • 인증 확인 - 인증 토큰이 올바르고 만료되지 않았는지 확인합니다.
  • 권한 확인 - 패키지를 게시하거나 설치하는 데 필요한 권한이 있는지 확인합니다.
  • Maven 설정 검증 - settings.xml 파일의 설정이 올바른지 다시 확인합니다.
  • GitLab CI/CD 로그 검토 - CI/CD 문제라면 job 로그에서 오류 메시지를 자세히 살펴봅니다.
  • 엔드포인트 URL 확인 - 프로젝트나 그룹에 맞는 엔드포인트 URL을 사용하고 있는지 확인합니다.
  • mvn 명령에 -s 옵션 사용 - Maven 명령은 항상 -s 옵션과 함께 실행합니다. 예를 들면 mvn package -s settings.xml입니다. 이 옵션이 없으면 인증 설정이 적용되지 않아 Maven이 패키지를 찾지 못할 수 있습니다.

캐시 지우기#

성능을 높이기 위해 클라이언트는 패키지 관련 파일을 캐시합니다. 문제가 발생하면 다음 명령으로 캐시를 지웁니다.

rm -rf ~/.m2/repository
rm -rf ~/.gradle/caches # Or replace ~/.gradle with your custom GRADLE_USER_HOME

네트워크 추적 로그 검토#

Maven 리포지터리에 문제가 있다면 네트워크 추적 로그를 검토할 수 있습니다. 네트워크 추적 로그에는 Maven 클라이언트가 기본적으로 제공하지 않는 더 자세한 오류 메시지가 담깁니다.

예를 들어 PAT 토큰으로 로컬에서 mvn deploy를 실행하면서 다음 옵션을 사용합니다.

mvn deploy \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.wagon.providers.http.httpclient=trace \
-Dorg.slf4j.simpleLogger.log.org.apache.maven.wagon.providers.http.httpclient.wire=trace
Warning

이 옵션을 설정하면 모든 네트워크 요청이 기록되어 많은 양의 출력이 생성됩니다.

Maven 설정 확인#

CI/CD에서 settings.xml 파일과 관련된 문제가 발생하면 스크립트 태스크나 job을 추가해 유효 설정을 확인해 볼 수 있습니다.

help 플러그인은 환경 변수를 포함한 시스템 속성도 제공합니다.

mvn-settings:
  script:
    - 'mvn help:effective-settings'

package:
  script:
    - 'mvn help:system'
    - 'mvn package'

패키지 게시 시 401 Unauthorized 오류#

대개 인증 문제를 의미합니다. 다음을 확인합니다.

  • 인증 토큰이 유효하고 만료되지 않았습니다.
  • 올바른 토큰 유형(개인 액세스 토큰, 배포 토큰, CI job 토큰)을 사용하고 있습니다.
  • 토큰에 필요한 권한(api, read_api, read_repository)이 있습니다.
  • Maven 프로젝트라면 mvn 명령에 -s 옵션을 사용하고 있습니다(예: mvn deploy -s settings.xml). 이 옵션이 없으면 Maven이 settings.xml 파일의 인증 설정을 적용하지 않아 권한 오류가 발생합니다.

"Validation failed: Version is invalid" 메시지와 함께 발생하는 400 Bad Request 오류#

GitLab은 버전 문자열에 특정 요구 사항을 둡니다. 버전이 다음 형식을 따르는지 확인합니다.

^(?!.*\.\.)(?!.*\.$)[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*(\+[0-9A-Za-z-]+)?$

예를 들어 "1.0.0", "1.0-SNAPSHOT", "1.0.0-alpha"는 유효하지만 "1..0"이나 "1.0."은 유효하지 않습니다.

패키지 게시 시 403 Forbidden 오류#

Authorization failed 메시지와 함께 발생하는 403 Forbidden 오류는 대개 인증 문제이거나 권한 문제입니다. 다음을 확인합니다.

  • 올바른 토큰 유형(개인 액세스 토큰, 배포 토큰, CI/CD job 토큰)을 사용하고 있습니다. 자세한 내용은 패키지 레지스트리 인증을 참고합니다.
  • 토큰에 필요한 권한이 있습니다. Developer, Maintainer, Owner 권한이 있는 사용자만 패키지를 게시할 수 있습니다. 자세한 내용은 GitLab 권한을 참고합니다.
  • 게시하려는 패키지가 푸시 보호 규칙으로 보호되어 있지 않습니다. 패키지 보호 규칙에 대한 자세한 내용은 패키지 보호 방법을 참고합니다.

게시할 때 발생하는 Artifact already exists 오류#

이미 존재하는 패키지 버전을 게시하려고 할 때 이 오류가 발생합니다. 해결 방법은 다음과 같습니다.

  • 게시하기 전에 패키지 버전을 올립니다.
  • SNAPSHOT 버전을 사용한다면 설정에서 SNAPSHOT 덮어쓰기를 허용하고 있는지 확인합니다.

게시한 패키지가 UI에 표시되지 않음#

패키지를 방금 게시했다면 표시되기까지 잠시 걸릴 수 있습니다. 계속 표시되지 않으면 다음을 확인합니다.

  • 패키지를 볼 수 있는 권한이 있는지 확인합니다.
  • CI/CD 로그나 Maven 출력을 검토해 패키지가 정상적으로 게시되었는지 확인합니다.
  • 올바른 프로젝트나 그룹에서 찾고 있는지 확인합니다.

Maven 리포지터리 의존성 충돌#

의존성 충돌은 다음 방법으로 해결할 수 있습니다.

  • pom.xml에 버전을 명시적으로 정의합니다.
  • Maven의 dependency management 섹션으로 버전을 제어합니다.
  • <exclusions> 태그로 충돌하는 전이 의존성을 제외합니다.

Unable to find valid certification path to requested target 오류#

대개 SSL 인증서 문제입니다. 해결 방법은 다음과 같습니다.

  • JDK가 GitLab 서버의 SSL 인증서를 신뢰하는지 확인합니다.
  • 자체 서명 인증서를 사용한다면 JDK의 truststore에 추가합니다.
  • 최후의 수단으로 Maven 설정에서 SSL 검증을 비활성화할 수 있습니다. 프로덕션에서는 권장하지 않습니다.

No plugin found for prefix 파이프라인 오류#

대개 Maven이 플러그인을 찾지 못한다는 뜻입니다. 해결 방법은 다음과 같습니다.

  • 플러그인이 pom.xml에 올바르게 정의되어 있는지 확인합니다.
  • CI/CD 설정이 올바른 Maven 설정 파일을 사용하는지 확인합니다.
  • 파이프라인이 필요한 모든 리포지터리에 접근할 수 있는지 확인합니다.