Help us learn about your current experience with the documentation. Take the survey.

包注册表中的Maven包

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

在项目的包注册表中发布Maven制品。 然后,当您需要将其用作依赖项时,安装这些包。

有关Maven包管理器客户端使用的特定API端点的文档,请参阅Maven API文档

支持的客户端:

  • mvn。了解如何构建Maven包。
  • gradle。了解如何构建Gradle包。
  • sbt

发布到GitLab包注册表

验证包注册表身份

您需要一个令牌来发布包。根据您的目标,有不同类型的令牌可用。更多信息,请查看令牌指南

创建一个令牌并保存,以便稍后在过程中使用。

请不要使用此处未记录的身份验证方法。未来可能会移除未记录的身份验证方法。

编辑客户端配置

更新您的配置,通过HTTP验证Maven仓库的身份。

自定义HTTP头

您必须将身份验证详细信息添加到客户端的配置文件中。

令牌类型 名称必须为 令牌
个人访问令牌 Private-Token 直接粘贴令牌,或定义环境变量来存储令牌
部署令牌 Deploy-Token 直接粘贴令牌,或定义环境变量来存储令牌
CI作业令牌 Job-Token ${CI_JOB_TOKEN}

The <name> field must be named to match the token you chose.

将以下部分添加到您的 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>
令牌类型 名称必须为 令牌
个人访问令牌 Private-Token 直接粘贴令牌,或定义环境变量来存储令牌
部署令牌 Deploy-Token 直接粘贴令牌,或定义环境变量来存储令牌
CI作业令牌 Job-Token System.getenv("CI_JOB_TOKEN")

The <name> field must be named to match the token you chose.

您的 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认证

您也可以使用基本的HTTP认证来认证到Maven包注册表。

| 令牌类型 | 名称必须为 | 令牌 |\n|———————–|——————————|————————————————————————|\n| 个人访问令牌 | 用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| 部署令牌 | 部署令牌的用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| CI作业令牌 | gitlab-ci-token | ${CI_JOB_TOKEN} |\n\n在您的 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>

| 令牌类型 | 名称必须为 | 令牌 |\n|———————–|——————————|————————————————————————|\n| 个人访问令牌 | 用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| 部署令牌 | 部署令牌的用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| CI作业令牌 | gitlab-ci-token | System.getenv("CI_JOB_TOKEN") |\n\n在 您的 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(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)
            }
        }
    }

| 令牌类型 | 名称必须为 | 令牌 |\n|———————–|——————————|————————————————————————|\n| 个人访问令牌 | 用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| 部署令牌 | 部署令牌的用户名 | 直接粘贴令牌,或定义环境变量保存令牌 |\n| CI作业令牌 | gitlab-ci-token | sys.env.get("CI_JOB_TOKEN").get |\n\nSBT 的认证基于 基本HTTP认证。您需要提供名称和密码。\n\n

\n\n名称字段必须与您选择的令牌匹配。\n\n

\n\n要使用 `sbt` 从Maven GitLab包注册表中安装软件包,您必须配置一个 [Maven解析器](https://www.scala-sbt.org/1.x/docs/Resolvers.html#Maven+resolvers)。如果您正在访问私有或内部项目或组,则需要设置 [凭证](https://www.scala-sbt.org/1.x/docs/Publishing.html#Credentials)。配置了解析器和认证后,您可以从项目、组或命名空间安装软件包。\n\n在您的 [`build.sbt`](https://www.scala-sbt.org/1.x/docs/Directories.html#sbt+build+definition+files) 中添加以下行:\n\n```scala resolvers += ("gitlab" at "") ```
credentials += Credentials("GitLab Packages Registry", "<host>", "<name>", "<token>")

在此示例中:

  • <endpoint url> 对应于 endpoint 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。
  • 一个 repositorydistributionManagement 部分。

您的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. 将Gradle插件 maven-publish 添加到plugins部分:

    • 在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/<PROJECT_ID>/packages/maven"
                  credentials(HttpHeaderCredentials) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value = gitLabPrivateToken // 该变量位于 $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      header(HttpHeaderAuthentication)
                  }
              }
          }
      }
    • 在Kotlin DSL中:

      publishing {
          publications {
              create<MavenPublication>("library") {
                  from(components["java"])
              }
          }
          repositories {
              maven {
                  url = uri("https://gitlab.example.com/api/v4/projects/<PROJECT_ID>/packages/maven")
                  credentials(HttpHeaderCredentials::class) {
                      name = "REPLACE_WITH_TOKEN_NAME"
                      value =
                          findProperty("gitLabPrivateToken") as String? // 该变量位于 $GRADLE_USER_HOME/gradle.properties
                  }
                  authentication {
                      create("header", HttpHeaderAuthentication::class)
                  }
              }
          }
      }

发布包

使用 DeployAtEnd 选项可能导致上传被拒绝,返回 400 bad request {"message":"Validation failed: Name has already been taken"}。有关详情,请参见 issue 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

运行发布任务:

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

如果在发布前保护了 Maven 包,该包将被拒绝,并返回 403 Forbidden 错误和 Authorization failed 错误消息。 确保在发布时 Maven 包未被保护。 有关包保护规则的更多信息,请参阅 如何保护包

安装包

要从 GitLab 包注册表安装包,必须配置远程仓库并验证身份
完成此操作后,您可以从项目、群组或命名空间中安装包。

如果有多个包具有相同的名称和版本,则在安装包时,会获取最近发布的包。

若权限不足无法读取最近发布的包,则会返回 403 Forbidden 错误。

要通过 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 文件的路径。

命令中的仓库名称(gitlab-maven)和 settings.xml 文件中的仓库名称必须匹配。

消息应显示正在从包注册表下载包:

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. build.gradle 的 dependencies 部分添加一个 依赖项

    • 使用 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 install

要通过 sbt 安装包:

  1. build.sbt 添加一个 内联依赖项

    libraryDependencies += "com.mycompany.mydepartment" % "my-project" % "8.4"
  2. 在您的项目中,运行以下命令:

    sbt update

Maven 包的代理下载

GitLab Maven 包注册表使用 远程包含校验和
当您下载文件时,注册表会代理该文件,并在单个请求中将文件及其相关校验和发送给 Maven 客户端。

使用最近的 Maven 客户端的远程包含校验和:

  • 减少客户端向 GitLab Maven 包注册表发出的网络请求数量。
  • 降低 GitLab 实例的负载。
  • 提高客户端命令执行时间。

由于技术限制,当您使用对象存储时,Maven 包注册表会忽略对象存储配置中针对 packages代理下载 设置。
相反,Maven 包注册表的下载始终启用代理下载。

如果您不使用对象存储,则此行为对您的实例没有影响。

Maven 包的 CI/CD 集成

您可以使用 CI/CD 自动构建、测试和发布 Maven 包。\n本节中的示例涵盖了以下场景:

  • 多模块项目
  • 版本化发布
  • 条件性发布
  • 与代码质量和安全扫描集成

您可以调整并组合这些示例以适应您的特定项目需求。

请根据项目要求调整 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"

多模块 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
  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"

有用提示

发布同名或同版本的包

当发布一个与现有包同名且同版本的包时,新包文件会被添加到现有包中。您仍然可以通过界面或 API 访问和查看现有包的旧资产。

要删除较旧的包版本,可以考虑使用包 API 或界面。

不允许重复的Maven包

为防止用户发布重复的 Maven 包,您可以使用 GraphQL API 或界面操作。

在界面中:

  1. 左侧边栏选择 搜索或前往 并找到您的组。
  2. 选择 设置 > 包与注册表
  3. 重复包 表格的 Maven 行中,关闭 允许重复 开关。
  4. (可选)在 例外 文本框中输入正则表达式,匹配允许的包名和版本。

允许重复 已开启,您可在 例外 文本框中指定不应出现重复的包名和版本。

您的更改会自动保存。

请求转发到 Maven Central

该功能的可用性由功能标志控制。更多信息请查看历史记录。

当 Maven 包在包注册表中未找到时,请求会被转发至 Maven Central

启用功能标志后,管理员可在 持续集成设置 中禁用此行为。

Maven 转发仅适用于项目级和组级 端点。实例级端点存在命名限制,无法用于不符合约定的包,同时也因供应链攻击风险过高而不适用。

mvn 的额外配置

使用 mvn 时,有多种方式配置 Maven 项目以从 GitLab 请求 Maven Central 的包。Maven 仓库按 特定顺序 查询。默认情况下,Maven Central 通常通过 Super POM 最先被检查,因此需将 GitLab 配置为优先于 maven-central 查询。

为确保所有包请求均发送至 GitLab 而非 Maven Central,可在 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 对中央仓库的代理</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 的 Package Repository 后,你可以配置 GitLab CI/CD 自动构建新包。

每次默认分支更新时,你可以创建一个新包。

  1. 创建一个 ci_settings.xml 文件,作为 Maven 的 settings.xml 文件。

  2. 添加与你在 pom.xml 中定义的相同 ID 的 server 部分。例如,使用 gitlab-maven 作为 ID:

    <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 任务:

    deploy:
      image: maven:3.6-jdk-11
      script:
        - 'mvn deploy -s ci_settings.xml'
      rules:
        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
  5. 将这些文件推送到你的仓库。

下次运行 deploy 任务时,它会将 ci_settings.xml 复制到用户的 home 目录。在此示例中:

  • 用户是 root,因为任务在 Docker 容器中运行。
  • Maven 使用配置好的 CI/CD 变量。

每次默认分支更新时,你可以创建一个包。

  1. 通过Gradle 中的 CI 作业令牌进行身份验证

  2. 向你的 .gitlab-ci.yml 文件添加一个 deploy 任务:

    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 命令行选项

有一些Maven 命令行选项,你可以在使用 GitLab CI/CD 执行任务时使用。

  • 文件传输进度可能会使 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 install:安装Gradle项目指定的包。

故障排除

在使用GitLab中的Maven包时,您可能会遇到问题。
要解决许多常见问题,请尝试以下步骤:

  • 验证身份认证 - 确保您的身份认证令牌正确且未过期。
  • 检查权限 - 确认您拥有发布或安装包所需的必要权限。
  • 验证Maven配置文件 - 仔细检查您的settings.xml文件是否配置正确。
  • 查看GitLab CI/CD日志 - 对于CI/CD问题,仔细检查作业日志中的错误信息。
  • 确保端点URL正确 - 验证您是否使用了项目或组的正确端点URL。
  • 使用mvn命令时添加-s选项 - 始终使用-s选项运行Maven命令,例如mvn package -s settings.xml。如果不使用此选项,身份认证设置不会生效,Maven可能无法找到包。

清除缓存

为提升性能,客户端会缓存与包相关的文件。如果遇到问题,可通过以下命令清除缓存:

rm -rf ~/.m2/repository
rm -rf ~/.gradle/caches # 或将~/.gradle替换为您自定义的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

设置这些选项后,所有网络请求都会被记录,并生成大量输出。

验证您的Maven配置文件

如果在CI/CD中遇到与settings.xml文件相关的问题,尝试添加额外的脚本任务或作业来验证有效配置

帮助插件还可提供系统属性,包括环境变量:

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

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

发布包时出现“401 Unauthorized”错误

这通常表示身份认证问题。请检查:

  • 您的身份认证令牌有效且未过期。
  • 您使用了正确的令牌类型(个人访问令牌、部署令牌或CI作业令牌)。
  • 该令牌具有必要的权限(apiread_apiread_repository)。
  • 对于Maven项目,您在使用mvn命令时添加了-s选项(例如mvn deploy -s settings.xml)。如果不使用此选项,Maven不会应用settings.xml文件中的身份认证设置,导致未经授权的错误。

出现“400 Bad Request”错误,提示“Validation failed: Version is invalid”

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作业令牌)。更多信息请参见向包注册表进行身份认证
  • 该令牌具有必要的权限。只有具备Developer角色或更高角色的用户才能发布包。更多信息请参见GitLab权限
  • 您正在发布的包不受推送保护规则的约束。有关包保护规则的更多信息,请参见如何保护包

发布时出现“工件已存在”错误

当您尝试发布一个已经存在的包版本时会出现此错误。解决方法如下:

  • 在发布前增加包的版本号。
  • 如果您使用的是SNAPSHOT版本,请确保您的配置中允许覆盖SNAPSHOT版本。

已发布的包未显示在UI中

如果您刚发布了包,可能需要几秒钟才会显示。如果仍未显示:

  • 验证您是否有查看包所需的权限。
  • 通过查看CI/CD日志或Maven输出,确认包是否成功发布。
  • 确保您正在查看正确的项目或组。

Maven仓库依赖冲突

可通过以下方式解决依赖冲突:

  • pom.xml中明确指定版本。
  • 使用Maven的依赖管理部分来控制版本。
  • 使用<exclusions>标签排除冲突的传递性依赖项。

“无法找到请求目标的合法证书路径”错误

这通常是SSL证书问题。解决方法如下:

  • 确保您的JDK信任GitLab服务器的SSL证书。
  • 如果使用自签名证书,将其添加到JDK的truststore中。
  • 作为最后的手段,您可以在Maven设置中禁用SSL验证。不建议在生产环境中使用。

“找不到前缀对应的插件”管道错误

这通常表示Maven找不到该插件。修复方法:

  • 确保插件在您的pom.xml中正确定义。
  • 检查您的CI/CD配置是否使用了正确的Maven设置文件。
  • 验证您的管道是否能访问所有必要的仓库。