( token: string, owner: string, repo: string, branch: string, filePath: string, content: string, message: string )
| 268 | * Commit a single file to a branch using the low-level Git Data API. |
| 269 | */ |
| 270 | export async function createFileOnBranch( |
| 271 | token: string, |
| 272 | owner: string, |
| 273 | repo: string, |
| 274 | branch: string, |
| 275 | filePath: string, |
| 276 | content: string, |
| 277 | message: string |
| 278 | ) { |
| 279 | const base = `/repos/${owner}/${repo}`; |
| 280 | const jsonHeaders = { 'Content-Type': 'application/json' }; |
| 281 | |
| 282 | // Step 1: Get the current commit SHA |
| 283 | const refRes = await ghFetch(`${base}/git/ref/heads/${encodeURIComponent(branch)}`, token); |
| 284 | if (!refRes.ok) await handleGitError(refRes, 'Failed to get branch ref'); |
| 285 | const refData = await refRes.json(); |
| 286 | const latestCommitSHA: string = refData.object.sha; |
| 287 | |
| 288 | // Step 2: Get the tree SHA |
| 289 | const commitRes = await ghFetch(`${base}/git/commits/${latestCommitSHA}`, token); |
| 290 | if (!commitRes.ok) await handleGitError(commitRes, 'Failed to get commit'); |
| 291 | const commitData = await commitRes.json(); |
| 292 | const baseTreeSHA: string = commitData.tree.sha; |
| 293 | |
| 294 | // Step 3: Create a blob |
| 295 | const base64Content = utf8ToBase64(content); |
| 296 | const blobRes = await ghFetch(`${base}/git/blobs`, token, { |
| 297 | method: 'POST', |
| 298 | body: JSON.stringify({ content: base64Content, encoding: 'base64' }), |
| 299 | headers: jsonHeaders, |
| 300 | }); |
| 301 | if (!blobRes.ok) await handleGitError(blobRes, 'Failed to create blob'); |
| 302 | const blobData = await blobRes.json(); |
| 303 | |
| 304 | // Step 4: Create a new tree |
| 305 | const treeRes = await ghFetch(`${base}/git/trees`, token, { |
| 306 | method: 'POST', |
| 307 | body: JSON.stringify({ |
| 308 | base_tree: baseTreeSHA, |
| 309 | tree: [{ path: filePath, mode: '100644', type: 'blob', sha: blobData.sha }], |
| 310 | }), |
| 311 | headers: jsonHeaders, |
| 312 | }); |
| 313 | if (!treeRes.ok) await handleGitError(treeRes, 'Failed to create tree'); |
| 314 | const treeData = await treeRes.json(); |
| 315 | |
| 316 | // Step 5: Create a new commit |
| 317 | const newCommitRes = await ghFetch(`${base}/git/commits`, token, { |
| 318 | method: 'POST', |
| 319 | body: JSON.stringify({ message, tree: treeData.sha, parents: [latestCommitSHA] }), |
| 320 | headers: jsonHeaders, |
| 321 | }); |
| 322 | if (!newCommitRes.ok) await handleGitError(newCommitRes, 'Failed to create commit'); |
| 323 | const newCommitData = await newCommitRes.json(); |
| 324 | |
| 325 | // Step 6: Update the branch ref (force: true to avoid "not a fast forward" errors) |
| 326 | const updateRefRes = await ghFetch(`${base}/git/refs/heads/${encodeURIComponent(branch)}`, token, { |
| 327 | method: 'PATCH', |
no test coverage detected