如何通过 Github API 提交文件夹并打开拉取请求? [英] How to commit a folder and open a Pull Request via Github API?

查看:157
本文介绍了如何通过 Github API 提交文件夹并打开拉取请求?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想通过 Github API 为用户提交管道配置.

I want to commit a pipeline config for a user via the Github API.

到目前为止,我只能将一个名为 main.yaml 的文件提交到 repo 的根目录中,但我需要将该文件放在 .github/workflows/main.yaml 中.

So far I am able to commit just a file named main.yaml into the root directory of the repo but I need the file to sit within .github/workflows/main.yaml.

我目前的代码是这样的:

The code I have so far is this:

const commitWorkflowConfig = async ({
  ownerName,
  repoName
}) => {

  const pipelineConfig = fs.readFileSync(__dirname + '/../../../templates/main.yaml', { encoding: "utf-8" })

  // Create Blob from the content
  const blob = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/blobs`, {
    content: pipelineConfig,
    encoding: "utf-8"
  })

  // Get last commit hash of Master
  const {
    commit: {
      sha: masterSha
    }
  } = await axios.get(`https://api.github.com/repos/${ownerName}/${repoName}/branches/master`)

  // Create new branch from master
  const branch = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/refs`, 
  {
    "ref": "refs/heads/workflow-pipeline",
    "sha": masterSha
  })

  // Create commit to new branch
  const commit = await axios.put(`https://api.github.com/repos/${ownerName}/${repoName}/contents/main.yaml`, {
    message: "New commit",
    content: pipelineConfig,
    sha: blob.sha,
    branch: "workflow-pipeline"
  })

  // Open Pull Request
  const response = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/pulls`, {
    title: "New PR",
    head: "workflow-pipeline",
    base: "master"
  })
  
}    const commitWorkflowConfig = async ({
  ownerName,
  repoName
}) => {

  const pipelineConfig = fs.readFileSync(__dirname + '/../../../templates/main.yaml', { encoding: "utf-8" })

  // Create Blob from the content
  const blob = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/blobs`, {
    content: pipelineConfig,
    encoding: "utf-8"
  })

  // Get last commit hash of Master
  const {
    commit: {
      sha: masterSha
    }
  } = await axios.get(`https://api.github.com/repos/${ownerName}/${repoName}/branches/master`)

  // Create new branch from master
  const branch = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/refs`, 
  {
    "ref": "refs/heads/workflow-pipeline",
    "sha": masterSha
  })

  // Create commit to new branch
  const commit = await axios.put(`https://api.github.com/repos/${ownerName}/${repoName}/contents/main.yaml`, {
    message: "New commit",
    content: pipelineConfig,
    sha: blob.sha,
    branch: "workflow-pipeline"
  })

  // Open Pull Request
  const response = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/pulls`, {
    title: "New PR",
    head: "workflow-pipeline",
    base: "master"
  })
  
}

这感觉就像很多 API 调用都是为了提交一个文件并打开 PR,我怀疑我做错了什么?

This feels like a lot of API calls all for just committing one file and opening a PR, I suspect I am doing something wrong?

当我创建新提交时,它不允许我添加任何路径或将 .github/workflows/main.yaml 添加到 URL 的末尾,因为我收到 404.是有什么方法可以更新此提交以提交到文件夹而不是根目录?

When I create the new commit, it doesn't allow me to add any path or add .github/workflows/main.yaml to the end of the URL as I get a 404. Is there any way I can update this commit to commit to a folder instead of the root directory?

总而言之,如何将 .github/workflows/main.yaml 简单提交到新分支并为其打开 PR?

To summarise, How can I make a simple commit of .github/workflows/main.yaml to a new branch and open a PR for it?

const tree = await this.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/trees`, {
  base_tree: masterSha,
  tree: [
    {
      path: ".github",
      mode: "040000",
      type: "tree"
    },
    {
      path: ".github/workflow",
      mode: "040000",
      type: "tree"
    },
    {
      path: ".github/workflow/main.yaml",
      mode: "100755",
      type: "tree",
      content: pipelineConfig
    },
  ]
})

创建树

const { tree } = await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/trees`, {
  base_tree: masterSha,
  tree: [
    {
      path: "workflows/main.yaml",
      mode: "100644", 
      type: "blob",
      sha
    }
  ]
})

const workflowTree = tree.find(t => t.path === "workflows");

await axios.post(`https://api.github.com/repos/${ownerName}/${repoName}/git/trees`, {
  base_tree: masterSha,
  tree: [
    {
      path: ".github/workflows",
      mode: workflowTree.mode, // "040000"
      type: workflowTree.type, // "tree"
      sha: workflowTree.sha 
    }
  ]
})

推荐答案

以下代码没有正确使用 GitHub API

The following code does not use the GitHub API properly

// Create commit to new branch
  const commit = await axios.put(`https://api.github.com/repos/${ownerName}/${repoName}/contents/main.yaml`, {
    message: "New commit",
    content: pipelineConfig,
    sha: blob.sha,
    branch: "workflow-pipeline"
  })

您不能直接编辑文件的内容.您需要使用树 API 基于原始树创建一个全新的树.

You cannot directly edit the contents of a file. You need to use the trees API to create an entirely new tree based off of the original tree.

  1. 为新文件创建 blob (https://docs.github.com/en/rest/reference/git#create-a-blob).这一步你已经做得很好了.

  1. Create the blob for the new file (https://docs.github.com/en/rest/reference/git#create-a-blob). You already did this step good job.

根据 (https://docs.github.com/en/rest/reference/repos#get-a-branch).请注意,您必须获得 tree sha,而不是 commit sha.

Get the tree that you want to make your new branch based off of (https://docs.github.com/en/rest/reference/repos#get-a-branch). Note that you have to get the tree sha, not the commit sha.

创建一个添加该文件的新树(https://docs.github.com/en/rest/reference/git#create-a-tree).我认为这一步将是最复杂的,因为对于创建的每个文件夹"树,还需要创建一个父文件夹"树来包含新创建的文件夹"树.因此,如果您想修改.github/workflows 文件夹,您首先必须基于.github/workflows 创建一个新树.假设树 sha 是 abc....然后你需要基于 .github 文件夹创建一个新树,并使 workflows dir abc...,而不是旧的.

Create a new tree with that file added (https://docs.github.com/en/rest/reference/git#create-a-tree). I think this step will be the most complicated, because for each 'folder' tree created, a parent 'folder' tree will also need to be created to contain the newly created 'folder' tree. So if you want to modify the .github/workflows folder, you'll first have to create a new tree based on.github/workflows. Let's say that tree sha was abc.... Then you'll need to create a new tree based on the .github folder, and make the workflows dir abc..., and not the old one.

创建提交(https://docs.github.com/en/rest/reference/git#create-a-commit).使用您在上一步中创建的根树的 sha.

Create a commit (https://docs.github.com/en/rest/reference/git#create-a-commit). Use the sha of the root tree you created in the previous step.

创建一个新分支(https://docs.github.com/en/rest/reference/git#create-a-reference).在问题代码中,您创建提交之前创建了它,这没有意义.您需要在创建提交之后 创建它,以便它的头部指向您创建的提交的 sha.

Create a new branch (https://docs.github.com/en/rest/reference/git#create-a-reference). In the question code, you created it before you created the commit, which doesn't make sense. You need to create it after you create the commit, so that it's head will point to the sha of the commit you created.

创建拉取请求(https://docs.github.com/en/rest/reference/pulls#create-a-pull-request).您的代码中已包含此步骤.

Create the pull request (https://docs.github.com/en/rest/reference/pulls#create-a-pull-request). You already have this step in your code.

这是一个视觉效果,解释了将 main.yml 文件添加到 .github/workflows 的第 2 步和第 3 步:

Here is a visual that explains the steps 2 and 3 for adding a main.yml file to .github/workflows:

Original tree        | New Tree (but the '.github' tree references ^b, not b)
- sha: a           --> - sha: ^a
- files:               - files:
  - .github        -->   - .github (but the 'workflows' tree references ^c, not c)
    - sha: b               - sha: ^b
    - files:               - files
      - workflows  -->       - workflows (but with the main.yml)
        - sha: c               - sha: ^c
        - files:               - files:
                                 - main.yml (reference the sha of the blob you created)
          ...
      ...
  ...

视觉对象中有三个 --> .每个 --> 都是一个请求.

There are three -->s in the visual. Each --> is a request to make.

  1. 首先创建 ^c 树,它基于 c 树并添加了 main.yml 文件.
  2. 创建 ^b 树,它基于 b 但包含 ^c.
  3. 创建 ^a 树,它基于 a 但包含 ^b.
  1. Start with creating the ^c tree, which is based off of the c tree and has the added main.yml file.
  2. Create the ^b tree, which is based off of b but has ^c in it.
  3. Create the ^a tree, which is based off of a but has ^b in it.

这些是创建simple的步骤,创建拉取请求很简单,但创建请求很复杂.

And those are the steps to creating a simple simple, but complicated to create pull request.

令人惊讶的是,为此需要调用多少 API.5 + {你要添加的文件有多深}

It's surprising how many API calls are needed for this. 5 + {how deep the file you want to add is}

这篇关于如何通过 Github API 提交文件夹并打开拉取请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆