如何在GitLab中存储发布/二进制文件?

83

我正在使用GitlabJenkins和-可能-Nexus(需要一个工件存储)构建工作流。我希望GitLab可以方便地存储发行版/二进制文件,这是否可行?

我不想再使用另一个服务来下载发布(和文档),而是希望将其与代码库管理器整合,就像在GitHub中处理发布一样。有什么线索吗?


2
像Nexus和Artifactory这样的构件仓库是为了管理具有版本控制、缓存、清理策略和访问控制的二进制文件而建立的。Git仓库不会自动清理,它们会随着时间的推移而增长。 - bbaassssiiee
1
不是你想要的答案,但是一个非常简陋的方法是在readme.md或wiki中链接到Jenkins最新的稳定构建工件。 - KCD
5个回答

72

2020年10月更新:

GitLab 13.5 现在提供了:

将二进制文件附加到发行版

如果您因为无法将二进制文件附加到发布版而没有使用GitLab,那么您的工作流程就变得简单多了。

现在,您可以从 gitlab.ci-yml 将二进制文件附加到发布标签。这扩展了发布资产的支持,包括二进制文件,而不仅仅是资产链接或源代码。这使得您的开发团队更容易采用GitLab并使用它来自动化您的发布过程。

https://about.gitlab.com/images/13_5/release_assets.png -- Attach binary assets to Releases

请参阅 文档问题


2015年11月更新: GitLab 8.2 现在支持发布版

通过其API,您现在可以创建和更新与标签相关联的发布版
目前,仅能够将发布说明(Markdown文本和附件)添加到git标签(也称为发布版)中。

2019年5月更新:GitLab 1.11 引入了一个有趣的 "访客可访问发布版" 功能:

现在,您项目的访客用户可以查看您在发布页面上发布的版本。
他们将能够下载您发布的工件,但不允许下载源代码,也无法查看仓库信息,例如标签和提交


原始回答于2015年3月

这是一个正在进行的项目,建议采用Ciro的最小提案
  1. 对于https://github.com/cirosantilli/test/releases/tag/3.0下的每个存储库标签,允许上传和下载文件列表。
  2. 可以直接从标签列表视图中进行上传和下载。
  3. 如果删除了标签,则上传的内容也会被删除。 (我们不接受最近评论中提到的标记消息编辑)

该建议的评论包括:

更有趣的是下一步。
我真的很想让公共用户从“发布”中下载工件,而不必访问源代码(即使其他内容如维基百科、“发布”、问题跟踪器仅限于项目团队私人使用)。

然而,这种额外的功能看起来更加通用,我已经提交了一个单独的功能请求

尽管如此,我在这里重申我的观点:
虽然“发布”的简化版本仍然不错,但许多人可以轻松地设置外部文件服务器,并将URL指向GitLab之外的此服务器在发布/标记说明中。
换句话说,“发布”可能现在看起来并不吸引人,需要一些未来的集成方案。


你能够像在GitHub上一样在发布中附加大于10Mb的文件吗?它是否可以在本地配置? - Ciro Santilli OurBigBook.com
2
访客访问发布版是一个非常有趣的功能! - Kajsa Gauza

28

这个答案基本上与VonC的答案相同,只是为了不那么有经验的CI用户以逐步方式进行描述。

所以,假设你有一个非常酷的提交30728cab,并且你想将这个版本的代码作为新版本发布...

1)为您的提交创建标记

git tag -a MY_TAG_NAME 30728cab

输入此命令后,您将被要求填写描述,就像提交新代码更改时一样。

2)将标签推送到远程存储库

标签不会随着您的提交自动推送! 您需要手动将它们推送到远程存储库。

git push REMOTE_REPO_NAME REMOTE_BRANCH_NAME MY_TAG_NAME

3)上传文件

现在您可以选择a)将文件上传到GitLab存储库,b)将其上传到其他任何地方并在两种情况下保存链接。

警告:上传到GitLab存储库的文件很难删除,并且稍后无法查看其链接!

虽然我不建议将二进制文件上传到存储库,因为上述原因,但您要求这样做,所以这是方法:

curl --request POST --header "Private-Token: YOUR_PRIVATE_TOKEN" --form "file=@/PATH/TO/THE/FILE/file.txt" "https://MY_GITLAB_HOSTING.COM/api/v4/projects/MY_PROJECT_ID/uploads"

私有令牌可以在用户设置->访问令牌中创建。

此外,如果您真的需要删除文件,您可以导出项目,手动从下载的存档中删除更新文件夹,删除原来的远程存储库,并通过导入下载和修改的存档创建一个新的存储库

4) 创建发布

现在我们可以使用发布将所有内容终于联系在一起。

curl --request POST --header 'Content-Type: application/json' --header "Private-Token: YOUR_PRIVATE_TOKEN" --data '{"name": "MY_RELEASE_NAME", "tag_name": "MY_TAG_NAME", "description": "Release with the binary LINK_TO_YOUR_BINARY"}' "https://MY_GITLAB_HOSTING.COM/api/v4/projects/MY_PROJECT_ID/releases"

你可以看到,发布与特定标签紧密相关,随后与特定提交相关联。连接二进制文件只需提供这些文件的链接即可。
有趣的是,你的描述支持Markdown,但在如此繁琐的一行中写一些较大的* .md文档确实很困难。因此,我编写了一个简短的Bash脚本,它允许我们将Markdown文件放在一边,然后自动读取并发送它:
#!/bin/bash

RELEASE_NAME="$1"
TAG_NAME="$2"
PROJECT_ID="$3"
DESCRIPTION_FILE_PATH="$4"
PRIVATE_TOKEN="$5"

if [ "$5" == "" ]; then
    echo "Missing parameter! Parameters are RELEASE_NAME, TAG_NAME, PROJECT_ID, DESCRIPTION_FILE_PATH and PRIVATE_TOKEN.";
    exit 1;
fi

DESCRIPTION=''

# Load data from file
while read -r line; do
    DESCRIPTION="${DESCRIPTION}${line}\n";
done < "${DESCRIPTION_FILE_PATH}"

curl --request POST\
     --header 'Content-Type: application/json'\
     --header "Private-Token: ${PRIVATE_TOKEN}"\
     --data-binary "{\"name\": \"${RELEASE_NAME}\", \"tag_name\": \"${TAG_NAME}\", \"description\": \"${DESCRIPTION}\"}"\
     "https://MY_GITLAB_HOSTING.com/api/v4/projects/${PROJECT_ID}/releases" 

echo

所以你可以像这样使用它

./upload_release.sh MY_RELEASE_NAME MY_TAG_NAME MY_PROJECT_ID MY_MARKDOWN_FILE_PATH MY_PRIVATE_TOKEN

现在就是这样!您拥有了第一个完整的发布版!

直到你意识到,在发布描述的标题中犯了一个可怕的错字......

5) 删除发布版(如果需要)

在这里,你很幸运!与上传的二进制文件不同,您也可以使用REST API删除您的发布版!

curl --request DELETE --header "Private-Token: MY_PRIVATE_TOKEN" "https://MY_GITLAB_HOSTING.com/api/v4/projects/MY_PROJECT_ID/releases/MY_TAG_NAME"

由于多次输入这个命令还是很烦人的,所以我又写了一个Bash脚本:

#!/bin/bash

PROJECT_ID=$1
TAG_NAME=$2
PRIVATE_TOKEN=$3

if [ "$3" == "" ]; then
    echo "Missing parameter! Parameters are PROJECT_ID, TAG_NAME and PRIVATE_TOKEN.";
    exit 1;
fi

curl --request DELETE --header "Private-Token: ${PRIVATE_TOKEN}" "https://MY_GITLAB_HOSTING.com/api/v4/projects/${PROJECT_ID}/releases/${TAG_NAME}"

echo

这可以像这样使用:./delete_release.sh MY_PROJECT_ID MY_TAG_NAME MY_PRIVATE_TOKEN


我曾经成功地使用这个脚本创建一个版本发布,但现在我试图做完全相同的事情,但脚本无法完整运行。当将DESCRIPTION变量附加到curl命令时,它会退出。至少使用`bash -x release.sh'时是这样的。 - James Mak
@JamesMak 你通常如何启动脚本? - Eenoku
1
@Eonoku 我使用的是WSL。结果发现将文件存储到变量中的循环并没有正常执行。像#和*这样的特殊字符一直在搞乱curl命令。我仍然不知道为什么会发生这种情况(我对bash还比较陌生)。但是,我使用了这个命令sed -zE 's/\r\n|\n/\\n/g' < ${DESCRIPTION_FILE_PATH}来读取文件,解决了我的问题。 - James Mak

2
我正在使用我用Python编写的命令行工具作为快捷方式。执行了先前答案中描述的API方法的一些步骤(上传、发布、删除发布)。
你可以检查源代码或者自己使用它。
如果有人对使用Python和requests.py进行这些操作感兴趣,那么更简单的版本也很容易实现。

上传

import requests
secret_token = "<your secret token>"
project_id = "<your project id>"
file_path = "your_file.txt"
api_root = "https://gitlab.com/api/v4"

headers = {
    'PRIVATE-TOKEN': secret_token,
}

uri = '{}/projects/{}/uploads'.format(api_root, project_id)

files = {
    'file': open(file_path, 'rb')
}


r_upload = requests.post(uri, headers=headers, files=files)
if(r_upload.status_code != 201 and r_upload.status_code != 200):
    raise ValueError(f"Upload API responded with unvalid status {r_upload.status_code}")  # noqa: E501

upload = r_upload.json()

上传后会返回一个JSON,其中包含链接和Markdown格式的链接。我发现Markdown格式的链接对于发布说明非常有用,因为你必须自己将链接添加到说明中。

创建发布版本

import requests
secret_token = "<your secret token>"
project_id = "<your project id>"
api_root = "https://gitlab.com/api/v4"

desc = """
Your release description. **You can use markdown !**
Don't forget to add download link here.
"""

headers = {
    'PRIVATE-TOKEN': secret_token,
}

data = {
    "description": desc
}

r_new_release = requests.post(uri, data=data, headers=headers)
if(r_new_release.status_code != 201 and r_new_release.status_code != 200):
    raise ValueError(f"Releases API responded with invalid status {r_new_release.status_code}")

new_release = r_new_release.json()

JSON响应是发布版
其他步骤基本上遵循API指南并进行调整。它们都非常相似。

请问您能提供一个下载发布资产的代码片段吗?我正在尝试做这件事,但是我一点都不清楚(我是Python的新手)。提前感谢。 - Willy

1
我们正在使用scp复制在GitlabCI中生成的二进制文件或报告等文件。
# capture test exit code
set +e
bash build/ci/test.sh; TESTS_EXIT_CODE=$?
set -e

# copy reports
sshpass -p "$SFTP_PASS" ssh -o StrictHostKeyChecking=no sftp@192.168.1.60 "mkdir -p ${CI_REPORTS_PATH}"
sshpass -p "$SFTP_PASS" scp -r ${CI_APP_VOLUME}/tests/_output/* sftp@192.168.23.17:${CI_REPORTS_PATH}

# return test exit-code
exit ${TESTS_EXIT_CODE}

-2

Gitlab(服务器)本身是用于git存储库的。您不应该在git中存储二进制文件。Nexus将是正确的选择。您可以在存储库描述或readme文件中添加指向nexus的链接(就像您也可以将其指向jenkins构建一样)。

您可能想要查看与Gitlab集成的GitLab持续集成。那似乎更像Jenkins。我不知道它是否带有像Nexus这样的数据存储。


嗯,是的和不是的,git annex 允许在 git 中处理二进制文件。GitLab CI 不在考虑范围内,我只能在 Jenkins 和 TeamCity 之间选择。 - Kajsa Gauza
git annex是带有修改后端的git的一个例外。虽然您可以随时黑客攻击CI和CD环境,但我认为将发布版本推送到git-annex并不可行(即使它可以删除旧版本,这是Nexus等工具的好处)。与从Nexus / FTP / HTTP(S)/ S3等获取请求相比,检出过程会更加复杂。 - volker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接