-
I'm trying to use octokit/rest to remove a directory programaticcaly. I have the following code import {Octokit as Github} from '@octokit/rest';
type GitCreateTreeParamsTree = {
content?: string
mode?: "100644" | "100755" | "040000" | "160000" | "120000"
path?: string
sha?: string | null
type?: "blob" | "tree" | "commit"
}
type Blob = { sha?: string | null, url?: string }
const githubToken = "read from vault"
const getCurrentCommit = async (
github: Github,
org: string,
repo: string,
branch: string = 'main'
) => {
const {data: refData} = await github.git.getRef({
owner: org,
repo,
ref: `heads/${branch}`,
})
const commitSha = refData.object.sha
const {data: commitData} = await github.git.getCommit({
owner: org,
repo,
commit_sha: commitSha,
})
return {
commitSha,
treeSha: commitData.tree.sha,
}
}
const createNewTree = async (
github: Github,
owner: string,
repo: string,
blobs: Blob[],
parentTreeSha: string
) => {
const tree: GitCreateTreeParamsTree[] = blobs.map(({sha, url: path}, index) => ({
path: path,
mode: `100644`,
type: `blob`,
sha
}))
const {data} = await github.git.createTree({
owner,
repo,
tree,
base_tree: parentTreeSha,
});
return data
}
const setBranchToCommit = (
github: Github,
org: string,
repo: string,
commitSha: string,
branch: string = `main`
) => github.git.updateRef({
owner: org,
repo,
ref: `heads/${branch}`,
sha: commitSha,
});
const getdirectorySha = async (
tree: { path?: string, sha?: string }[],
directoryName: string
) => {
return tree
.filter(({path: directoryPath}) => directoryPath ? directoryPath.includes(directoryName) : false)
.map(({sha}) => sha)
.filter(sha => sha !== undefined).values().next().value
};
const deleteFromRepo = async (
github: Github,
org: string,
repo: string,
directoryName: string,
branch: string = `main`
) => {
const currentCommit = await getCurrentCommit(github, org, repo, branch);
const {data: treeData} = await github.git.getTree({
owner: org,
repo,
tree_sha: currentCommit.treeSha
})
const directorySha = await getdirectorySha(treeData.tree, directoryName);
if (!directorySha) {
throw new Error(`Could not find an directory '${directoryName}'`)
}
// Skip the files in the directory I need to remove
treeData.tree = treeData.tree
.filter(({path: directoryPath}) => directoryPath && !(directoryPath.includes(directoryName)))
.map(({path: directoryPath, sha}) => {
return {path: directoryPath, sha}
});
// For some reason, this repopulates the files I just skipped
const commitMessage = `Deleting '${directoryName}' files.`
const newCommit = await createNewCommit(
github,
org,
repo,
commitMessage,
treeData.sha,
currentCommit.commitSha
)
await setBranchToCommit(github, org, repo, newCommit.sha, branch)
}
const checkRepositoryExists = (
organisationRepos: any,
repoName: string) => {
if (!organisationRepos.data.map((repo: { name: any }) => repo.name).includes(repoName)) {
let errorMessage = `Repo '${repoName}' does not exist`;
console.log(errorMessage);
throw new Error(errorMessage);
}
};
export const deletedirectoryFromGithubRepo = async (
directoryName: string
) => {
const github = new Github({auth: githubToken})
const organization = `myOrg`
const repoName = `myRepo`
const organisationRepos = await github.repos.listForOrg({org: organization})
checkRepositoryExists(organisationRepos, repoName);
await deleteFromRepo(github, organization, repoName, directoryName)
} When I call I read that passing the current commit might be repopulating the deleted files. But removing it results in an error Full reponse from github
I'm using Any idea how to fix this? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
Hey there! It looks like your question here is more about how deleting a file works in the GitHub API than how Octokit works - but I’ll try to help anyway 😊 You are filtering I believe the step you’re missing is to create a tree which deletes the files you want to delete. I think the instructions at https://stackoverflow.com/a/67101960 will help. Let me know how you get on! |
Beta Was this translation helpful? Give feedback.
-
Thank you ! I will give this solution a try |
Beta Was this translation helpful? Give feedback.
-
@timrogers Thanks again for your suggestion, it worked. const deleteFromRepo = async (
github: Github,
org: string,
repo: string,
directoryName: string
) => {
const currentCommit = await getCurrentCommit(github, org, repo);
const {data: repoTree} = await github.git.getTree({
owner: org,
repo,
tree_sha: currentCommit.treeSha
})
const directorySha = await getDirectorySha(repoTree.tree, directoryName);
if (!directorySha) {
throw new Error(`Could not find an directory '${directoryName}'`)
}
const {data: directoryTree} = await github.git.getTree({
owner: org,
repo,
tree_sha: directorySha
})
const blobs: Blob[] = directoryTree.tree.map((blob) => {
return {'url': `${directoryName}/${blob.path}`, 'sha': null}
});
const newTree = await createNewTree(
github,
org,
repo,
blobs,
currentCommit.treeSha
)
const commitMessage = `Deleting '${directoryName}' files.`
const newCommit = await createNewCommit(
github,
org,
repo,
commitMessage,
newTree.sha,
currentCommit.commitSha
)
await setBranchToCommit(github, org, repo, newCommit.sha)
} |
Beta Was this translation helpful? Give feedback.
-
Deleting all files in a directory deletes the directory. |
Beta Was this translation helpful? Give feedback.
Hey there! It looks like your question here is more about how deleting a file works in the GitHub API than how Octokit works - but I’ll try to help anyway 😊
You are filtering
treeData.tree
but then you don’t ever use that value - you only refer totreeData.sha
which you haven’t changed.I believe the step you’re missing is to create a tree which deletes the files you want to delete. I think the instructions at https://stackoverflow.com/a/67101960 will help. Let me know how you get on!