如何通过 Github API 提交文件夹并打开拉取请求? [英] How to commit a folder and open a Pull Request via 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.
为新文件创建 blob (https://docs.github.com/en/rest/reference/git#create-a-blob).这一步你已经做得很好了.
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.
- 首先创建
^c
树,它基于c
树并添加了main.yml
文件. - 创建
^b
树,它基于b
但包含^c
. - 创建
^a
树,它基于a
但包含^b
.
- Start with creating the
^c
tree, which is based off of thec
tree and has the addedmain.yml
file. - Create the
^b
tree, which is based off ofb
but has^c
in it. - Create the
^a
tree, which is based off ofa
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屋!