GitLab CI/CD 技术求助:生成附带可执行文件的Release失败问题排查
解决GitLab CI/CD Release生成与资产上传问题
我来帮你搞定这两个CI/CD流水线的问题,咱们一步步拆解修复:
一、Upload阶段:Content-Type不支持错误
问题原因
你遇到的{"error":"The provided content-type '' is not supported."}错误,本质有两个:一是用curl上传文件时没指定Content-Type,GitLab通用包注册表要求明确声明文件MIME类型;二是你当前的上传URL不符合GitLab通用包的路径规范,导致服务器无法识别上传目标。
修复方案
- 构造正确的通用包上传URL:GitLab通用包的标准上传路径是
${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/<包名>/<版本标识>/<文件名>,这里用提交SHA作为版本标识,能保证每次上传的唯一性。 - 给curl添加Content-Type请求头:指定为
application/octet-stream,这是二进制文件的通用MIME类型,适配你的可执行文件。
二、Release阶段:两个错误的修复
错误1:系统尝试打开不存在的文件路径
这是因为release-cli的--description参数默认会把传入值当作文件路径去读取内容,但你实际想传入的是字符串描述。解决办法很简单:改用--description-string参数,直接传递字符串内容即可。
错误2:Links URL被blocked
你当前的URL有两个问题:一是变量在单引号中不会被Shell展开(导致${PACKAGE_REGISTRY_URL}还是原样字符串);二是URL格式不符合GitLab资产链接的合法要求。推荐两种可行的URL方案:
- 方案1:使用通用包的下载URL(和上传路径完全对应)
- 方案2:直接用CI Artifact的访问URL,格式为
${CI_JOB_URL}/artifacts/raw/source/bin/snippet-generator,可以直接引用Build阶段生成的制品,甚至能省略Upload阶段。
另外要注意:资产链接的JSON必须用双引号包裹,确保Shell能正确展开变量。
修改后的完整.gitlab-ci.yml配置
stages: - build - upload - release variables: STACK_ROOT: "${CI_PROJECT_DIR}/.stack-root" # 定义通用包的基础上传/下载路径 GENERIC_PACKAGE_URL: "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/snippet-generator/${CI_COMMIT_SHA}" cache: paths: - .stack-work/ - .stack-root/ build: only: - master stage: build image: haskell:9 artifacts: expire_in: 30 days paths: - source/bin/ script: - cd source - stack update - stack build --copy-bins - stack clean upload: stage: upload image: curlimages/curl:latest cache: {} script: # 上传到GitLab通用包注册表 - | curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" \ --header "Content-Type: application/octet-stream" \ --upload-file "source/bin/snippet-generator" \ "${GENERIC_PACKAGE_URL}/snippet-generator" release: stage: release image: registry.gitlab.com/gitlab-org/release-cli cache: {} only: - master when: manual except: - tags script: - > release-cli create --name "Snippet Generator Release - ${CI_COMMIT_SHORT_SHA}" --description-string "Automated release from CI pipeline - Commit: ${CI_COMMIT_SHA}" --tag-name "release-${CI_COMMIT_SHORT_SHA}" --ref ${CI_COMMIT_SHA} --assets-link "{\"name\":\"Snippet Generator Executable\",\"url\":\"${GENERIC_PACKAGE_URL}/snippet-generator\"}"
额外说明
- 如果你不想用通用包,完全可以省略Upload阶段,把Release中的资产链接URL改成
"${CI_JOB_URL}/artifacts/raw/source/bin/snippet-generator",直接引用Build阶段的制品。 - 标签名我改成了
release-${CI_COMMIT_SHORT_SHA},比之前的job-$CI_JOB_ID更直观,方便关联到具体的代码提交。
内容的提问来源于stack exchange,提问作者Jip W.
相关产品推荐
相关产品推荐

