0 votes

This is a bit of an advanced question, but can anybody tell me whether it would be possible to use the functionality of the Github REST API from a Godot project, specifically the ability to create files within an existing repository: https://docs.github.com/en/rest/reference/repos#create-or-update-file-contents
Could maybe be related HTTPRequest nodes??

in Engine by (70 points)

So I've gotten to the point where I can send data and get a vague unhelpful error from Github. I suspect the problem might be that Github expects the data in JSON format, but HTTPRequest is incapable of sending anything other than Strings (or potentially PoolByteArrays using request_raw() it seems).
Is there any work around for this?

1 Answer

+2 votes
Best answer

(in response to your comment): JSON is just a regular string formatted like a dictionary, thats not the problem, the problem might be any of these things:

  • Content must be encoded in Base64 (you'll have to make an encoding algorithm yourself, it's not very hard)
  • You need to have a Personal Access token (from here)
  • Authentication must be provided through the headers, not JSON
  • To change an existing file you'll need to have an sha1 token of that file (tbh, i dont know what that means but godot strings have a function with sha1 in the name which looks promising)

Based on my research I came up with this:

extends Node2D

var http: HTTPRequest

# Generate an OAuth token at https://github.com/settings/tokens
const OAUTH_TOKEN: String = "ghp_imnotsharingthatlol"

func _ready() -> void:
    http = HTTPRequest.new()
    add_child(http)

    http.connect("request_completed", self, "response")

    create_or_update_file(
        "Hugo4IT",
        "PreonEngine",
        "test-file.txt",
        "Godot QA test",
        "SGVsbG8sIFdvcmxkIQ==" # I used https://base64.guru/converter/encode to convert "Hello, World!" into Base64
    )

func response(
    result: int,
    response_code: int,
    headers: PoolStringArray,
    body: PoolByteArray
) -> void:
    if response_code >= 200 and response_code < 300:
        print("OK: ", parse_json(body.get_string_from_utf8()))
    else:
        print("ERROR (", response_code, "): ", result)

func create_or_update_file(
    repo_owner: String, # https://github.com/<this>/RepoName
    repo_name: String, # https://github.com/UserName/<this>
    target_file: String, # What file to edit
    commit_message: String, # Commit message
    new_file_content: String, # What to put in the file (MUST BE ENCODED IN BASE64)
    new_file_content_sha: String = "", # Only required when editing an existing file
    commit_on_branch: String = "master" # Very new repos might use "main" as the default branch
) -> void:
    # PUT /repos/{owner}/{repo}/contents/{path}
    var request_url := "https://api.github.com/repos/{owner}/{repo}/contents/{path}".format(
            {"owner": repo_owner, "repo": repo_name, "path": target_file})
    var headers = PoolStringArray([
        "Accept: application/vnd.github.v3+json",
        "Authorization: token " + OAUTH_TOKEN
    ])
    var request_data := {
        "message": commit_message,
        "content": new_file_content,
        "sha": new_file_content_sha,
        "branch": commit_on_branch
    }
    http.request(request_url, headers, true, HTTPClient.METHOD_PUT, to_json(request_data))

Which worked like a charm:

image

by (104 points)
selected by

Thanks a lot finally got it working!
I had done some of this, but I was missing a few key things.
Also found out my acess token didn't have the right scopes... Makes sense retrospectively that it needed "repo", but it wasn't decribed very well on the page for generating.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.