I'm working on a personal website builder. My goal is to be able to manipulate my page within the browser and then hit a 'Publish' button and have the new HTML file to be mitted to the Github repository where my code is hosted.
I've been able to figure out everything up to generating the updated HTML. However, after going through the GitHub documentation I could not really understand how files should be processed prior or mitted to the repository using the API. Could someone please help me out?
PS: I'd be using JavaScript to generate the HTML and for API calls. Also if there is a better method to achieve my goal I'm open to those too.
I'm working on a personal website builder. My goal is to be able to manipulate my page within the browser and then hit a 'Publish' button and have the new HTML file to be mitted to the Github repository where my code is hosted.
I've been able to figure out everything up to generating the updated HTML. However, after going through the GitHub documentation I could not really understand how files should be processed prior or mitted to the repository using the API. Could someone please help me out?
PS: I'd be using JavaScript to generate the HTML and for API calls. Also if there is a better method to achieve my goal I'm open to those too.
Share Improve this question asked Feb 9, 2022 at 18:33 Kevin EddieKevin Eddie 311 silver badge3 bronze badges2 Answers
Reset to default 7Use GitHub API v3 Repository Content endpoints
You need to take into account the following:
- The content of the file should be in base64 encoding.
- If the file already exists, you need to provide the blob SHA of the file, you can get it via Get repository content endpoint.
Here is a working example with Node.js with Octokit API using createOrUpdateFileContents method. Read more about it here
This endpoint will create a new mit with the new file content, you can even specify the mitter and the author.
Update File Content in GitHub | View in Runme |
---|
// The content of the file should be base64
const content = Buffer.from(`Hello world at ${new Date().toUTCString()}`, 'utf8').toString('base64');
// If the file already exists, you need to provide the sha in order to update the file content.
const file = await octokit.rest.repos.getContent({
owner: owner,
repo: repo,
path: path,
branch: branch,
});
const { sha } = file.data;
const fileContent = await octokit.rest.repos.createOrUpdateFileContents({
owner,
repo,
path,
sha: sha,
message: 'This is the mit message generated via GitHub API',
content,
mitter: {
name: 'demo',
email: '[email protected]'
},
author: {
name: 'demo',
email: '[email protected]'
}
});
const { mit: { html_url } } = fileContent.data;
console.log(`Content updated, see changes at ${html_url}`);
Updating files through the GitHub API is no where as simple as using the CLI. That said, here's a process I used to update the CHANGELOG through the GitHub API instead of through the mand line:
This is in Go, but the API endpoints are the same, so you just need to translate them to JavaScript or the Octokit SDK (look for JavaScript).
This is edited for readability, see the full code here:
package github
import (
"fmt"
"os"
"strings"
"time"
)
// Push Construct a new branch with changes and push to GitHub using the REST
// API. Parameters branch and parent must be fully qualified reference (ie:
// refs/heads/master). If they don't start with 'refs' and have at least two
// slashes, it will be rejected.
func Push(wd, name, parent, mitMessage string, files []string, gh *Client) error {
// Support passing in just the branch name (ie: main),
// the name has to be in the format `head/main`
parentBranch := parent
if !strings.Contains(parent, "heads/") {
parentBranch = "heads/" + parent
}
// We need the GitHub ref of `head/main` for another endpoint.
parentRef, e1 := GetReference(parentBranch, gh)
if e1 != nil {
return e1
}
// Get the tree SHA for the base `head/main` reference.
parentTree, e1 := GetTree(parentBranch, gh)
if e1 != nil {
return e1
}
// Make a new Git tree, based off of a `head/main` tree, with new changes.
// We found out that we had to use a tree instead of just a reference.
// Otherwise, the new branch would not contain any of bases history.
newTree, e2 := NewTree(wd, parentTree.Sha, files, gh)
if e2 != nil {
return e2
}
//...
// Pass in miter info of your choosing.
miterGpg, mitter, e3 := GetCommiter()
if e3 != nil {
return e3
}
// Make a new mit that points to the new tree with changes.
mit, e4 := NewCommit(nil, mitter, mitMessage, miterGpg, newTree.Sha, []string{parentRef.Object.Sha}, gh)
if e4 != nil {
return e4
}
Log.Dbugf("new mit sha: %v", mit.Sha)
Log.Dbugf("new mit tree: %v", mit.Tree)
Log.Dbugf("new mit itter: %v", mit.Committer)
// You could update the main branch to point to the new mit.
// newRef, e5 := UpdateReference(parentRef.Ref, mit.Sha, false,gh)
// I prefer to make PRs.
// Make the new branch based on the main truck.
// The name of the fully qualified reference (ie: refs/heads/my-feature).
// If it doesn't start with 'refs' and have at least two slashes, it will
// be rejected.
newRef, e5 := NewReference(fullRefPrefix+name, mit.Sha, gh)
if e5 != nil {
return e5
}
Log.Dbugf("newRef.Ref: %v", newRef.Ref)
Log.Dbugf("newRef.Sha: %v", newRef.Object.Sha)
return nil
}