DEV Community

Evan Lin
Evan Lin

Posted on • Originally published at evanlin.com on

[Learning Notes][Golang] Using GitHub Issues as a Database

title: [Learning Notes][Golang] Using Github Issues as a Database
published: false
date: 2023-02-15 00:00:00 UTC
tags: 
canonical_url: http://www.evanlin.com/go-github-issue/
Enter fullscreen mode Exit fullscreen mode

x-cellent technologies GmbH

Preface

I've mentioned before that many databases have started charging fees, so it's actually quite troublesome to find a free database to use. Whether using Heroku or Render databases, it's a significant expense. Therefore, I often come up with strange ideas to use some unusual storage methods as databases. Today's article will use the Github Golang API to use your personal (Private Repository) issues as a database.

Open Source Package https://github.com/google/go-github

How to Obtain a Github Token

First, to use the Github API, you need to obtain a Github Token. Here's the process:

image-20230216161642112

Open Settings

image-20230216161706554

Select Developer settings

image-20230216161756251

Here, select Personal Access Token, and remember to choose Tokens (Classic)

This allows you to obtain a developer Access Token. Remember not to lose it (or don't store it on github).

Prerequisites and Methods for Using Github Issues as a Database

API Rate Limit

If you want to use this method as a database, you must first ensure that your data format is quite simple. Or, your data access has relatively low traffic. Because the Github API has Rate Limit information, which may be as follows:

  • Core:
    • Limit: 5000 (60mins)
  • Search:
    • Limit: 30 (60mins)
  • GraphQL:
    • Limit: 5000 (60mins)

Data Placement Suggestions

  • Title: Database Name
  • Each comment can be considered a record
  • Each Comment can be separated by csv (comma-separated), or by other methods.
  • Tags can help you quickly find similar Titles

These are just some suggestions; the following code example is simpler. It's just a Key -> Value method of storage. The Key is placed in the Title, and the Value is placed directly in the first Comment.

Related Code:

Basic Structure

type GithubDB struct {
    Name string // github owner name
    Repo string // repo name (can be private)
    Token string // the Access Token just obtained
    Client *github.Client
}

Enter fullscreen mode Exit fullscreen mode

Initialize Github Client

func createGithubClient(token string) *github.Client {
    ctx := context.Background()
    ts := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: token},
    )
    tc := oauth2.NewClient(ctx, ts)
    return github.NewClient(tc)
}

Enter fullscreen mode Exit fullscreen mode

Save Github Issue (Create)

At this time, you need to provide the username Name and Repo name.

func (u *GithubDB) saveIssue(title, body string) error {
    input := &github.IssueRequest{
        Title: String(title),
        Body: String(body),
        Assignee: String(""),
    }

    _, _, err := u.Client.Issues.Create(context.Background(), u.Name, u.Repo, input)
    if err != nil {
        fmt.Printf("Issues.Create returned error: %v", err)
        return err
    }
    return nil
}

Enter fullscreen mode Exit fullscreen mode

Find Title (key) Get by Title

func (u *GithubDB) getIssue(title string) (string, int, error) {
    ret, _, err := u.Client.Search.Issues(context.Background(), title, nil)
    if err != nil {
        fmt.Printf("Issues.search returned error: %v", err)
        return "", 0, err
    }

    log.Println("issue ret:", ret)
    for _, v := range ret.Issues {
        log.Println("return issue:", v)
        log.Println("Issue Num:", v.Number)
        log.Println("Body:", v.Body)
        log.Println("Comments:", v.Comments)
    }
    return *ret.Issues[0].Body, *ret.Issues[0].Number, nil
}

Enter fullscreen mode Exit fullscreen mode

Update the data inside (Update)

func (u *GithubDB) updateIssue(number int, title string, updatedCnt string) error {
    updateIssue := &github.IssueRequest{
        Title: String(title),
        Body: String(updatedCnt),
        Assignee: String(""),
    }
    ret, _, err := u.Client.Issues.Edit(context.Background(), u.Name, u.Repo, number, updateIssue)
    if err != nil {
        fmt.Printf("Issues.edit returned error: %v", err)
        return err
    }

    log.Println("Issue updated:", ret)
    return nil
}

Enter fullscreen mode Exit fullscreen mode

Future Development

In fact, when doing some simple example programs, if your database itself doesn't have too many field requirements, and the amount of access itself isn't very large, you might consider storing your data through Github Issues. Firstly, your database is "visualized," and you can also save some unnecessary extra costs.

Top comments (0)