如何在不使用 import_url 的情况下将特定文件导入到新建的 Gitlab 项目中?

How to import a specific file to a newly created Gitlab project without using import_url?

在创建新项目时,我曾经从仅包含该单个文件的父存储库中导入特定文件,因此它可以作为一个整体导入。

包含单个 POST 请求到 https://gitlab.example.com/api/v4/projects/ 的完整操作,发送负载如:

{
    "name": "The New Great Project III",
    "namespace_id": 12,
    "description": "A Project",
    "import_url": "https://user:users_token@gitlab.example.com/great-projects/0-0_parent_project.git"
}

用于使用从父项目导入的单个文件创建新项目的操作,用户可以立即开始工作。

但是,它变得不可靠:当输入新创建的项目时,用户开始看到挂起的导入作业,这些作业从未完成。最初怀疑是导入父项目的用户权限不够,结果连父项目的所有者都反映无法将父项目导入到新项目中。

所以这是我的问题:是否有任何其他方法可以将文件从模板项目克隆到新项目? Gitlab 服务器上是否有独立的钩子或 cronjobs 运行?

我设法将整个过程分为 3 个步骤:

  1. 创建新项目。
  2. 从现有项目存储库中获取所需文件。
  3. 将文件上传到新项目存储库。

由于这个问题与技术无关,我将 post 一些 JavaScript/Vue.js 风格的伪代码来向读者提供一个总体概述。

这里有一个函数负责调用GitlabAPI:

async callGitLabProjects(url, method, payload, format) {
      const token = this.$store.getters.token
      
      let headers
      if (format === "text") {
          headers = {
            'Private-Token': token
          }
      }
      else {
          headers = {
            'Content-Type': 'application/json',
            'Private-Token': token
          }
      }

      const response = await fetch(url, {
        method: method,
        headers: headers,
        body: JSON.stringify(payload)
      })
      return response.json()
    }

可以通过使用以下有效负载和指令调用 Gitlab API 来创建新项目:

const payload = {
        "name": "newProjectName",
        "namespace_id": 10,
        "description": "Description"
      }

let newRepoUrl = ""

await this.callGitLabProjects("https://gitlab.expl.com/api/v4/projects/", "POST", payload, "json")
        .then(data => {
           newRepoUrl += data._links.self
          }
        .catch((e) => {
           console.error(e)
         })

如您所见,已保存新存储库 URL 以备将来使用。

在第 2 步中,我们获取要导入的原始文件(记得 URL 对文件名进行编码):

let rawFile = await this.callGitLabProjects("https://gitlab.expl.com/api/v4/projects/10705/repository/files/my%2Dfile%2Emd/raw?ref=master", "GET", "", "text")

获取后,您只需将其上传到新项目的存储库即可:

const filePayload = {
          "branch": "master",
          "content": rawFile,
          "commit_message": "Initial file uploaded"
        }

this.callGitLabProjects(newRepoUrl + "/repository/files/my%2Dfile%2Emd", "POST", filePayload, "json")
        .catch((e) => {
          console.log(e)
        })