0

Create or Update File Contents

by
Published today

Commit a text file to a branch, creating it or replacing its content. The existing file's SHA is looked up automatically.

Script github Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 1 hour ago
1
//native
2

3
/**
4
 * Create or Update File Contents
5
 * Commit a text file to a branch, creating it or replacing its content. The existing file's SHA is looked up automatically.
6
 */
7
export async function main(
8
  auth: RT.Github,
9
  owner: string,
10
  repo: string,
11
  path: string,
12
  content: string,
13
  message: string,
14
  branch: string | undefined
15
) {
16
  const headers = {
17
    Authorization: `Bearer ${auth.token}`,
18
    Accept: "application/vnd.github+json",
19
    "X-GitHub-Api-Version": "2022-11-28",
20
  }
21
  const url = new URL(
22
    `https://api.github.com/repos/${owner}/${repo}/contents/${path}`
23
  )
24

25
  // Updating needs the current blob SHA; a 404 means the file is new.
26
  const lookup = new URL(url)
27
  if (branch) lookup.searchParams.append("ref", branch)
28
  const existing = await fetch(lookup, { headers })
29
  if (!existing.ok && existing.status !== 404) {
30
    throw new Error(`${existing.status} ${await existing.text()}`)
31
  }
32
  const sha = existing.ok
33
    ? ((await existing.json()) as { sha: string }).sha
34
    : undefined
35

36
  // UTF-8 safe base64
37
  let binary = ""
38
  for (const byte of new TextEncoder().encode(content))
39
    binary += String.fromCharCode(byte)
40

41
  const response = await fetch(url, {
42
    method: "PUT",
43
    headers: { ...headers, "Content-Type": "application/json" },
44
    body: JSON.stringify({ message, content: btoa(binary), branch, sha }),
45
  })
46

47
  if (!response.ok) {
48
    throw new Error(`${response.status} ${await response.text()}`)
49
  }
50

51
  return await response.json()
52
}
53