Skip to content

grokify/gogithub

Repository files navigation

GoGitHub

Go CI Go Lint Go SAST Docs Docs Visualization License

Documentation | API Reference

gogithub is a high-level Go module for interacting with the GitHub API. It wraps go-github with convenience functions organized by operation type.

Installation

go get github.com/grokify/gogithub

Directory Structure

The package is organized into subdirectories by operation type for scalability:

gogithub/
├── gogithub.go           # Client factory, backward-compatible re-exports
├── auth/                 # Authentication utilities
│   └── auth.go           # NewGitHubClient, GetAuthenticatedUser
├── config/               # Configuration utilities
│   └── config.go         # Config struct, FromEnv, GitHub Enterprise support
├── errors/               # Error types and translation
│   └── errors.go         # APIError, Translate, IsNotFound, IsRateLimited
├── graphql/              # GraphQL API for contribution statistics
│   ├── client.go         # NewClient, NewEnterpriseClient
│   ├── contributions.go  # GetContributionStats, GetContributionStatsMultiYear
│   └── commitstats.go    # GetCommitStats, GetCommitStatsByVisibility
├── profile/              # User profile aggregation
│   ├── profile.go        # UserProfile, GetUserProfile
│   ├── calendar.go       # ContributionCalendar, streaks
│   ├── activity.go       # MonthlyActivity, ActivityTimeline, MonthlyStats
│   ├── monthly_output.go # WriteMonthlyFile, WriteMonthlyFiles
│   ├── stats_report.go   # StatsReport, BuildStatsReport, LoadMonthlyFiles
│   ├── stats_render.go   # RenderToMarkdown, RenderToHTML, RenderToText
│   ├── readme/           # README.md generation
│   │   ├── readme.go     # Generate, DefaultConfig
│   │   ├── heatmap.go    # RenderHeatmap (Unicode contribution calendar)
│   │   └── template.go   # Template helpers
│   └── svg/              # SVG visualization generation
│       ├── card.go       # GenerateStatsCard
│       ├── stats.go      # Stats rendering
│       ├── theme.go      # Theme definitions (dark, dracula, nord, etc.)
│       ├── icons.go      # Metric icons
│       └── chart/        # Chart primitives
│           ├── bar.go    # Bar chart rendering
│           └── types.go  # Chart data types
├── pathutil/             # Path validation and normalization
│   └── pathutil.go       # Validate, Normalize, Join, Split
├── search/               # Search API operations
│   ├── search.go         # SearchIssues, SearchIssuesAll
│   ├── query.go          # Query builder, parameter constants
│   └── issues.go         # Issues type, table generation
├── repo/                 # Repository operations
│   ├── fork.go           # EnsureFork, GetDefaultBranch
│   ├── branch.go         # CreateBranch, GetBranchSHA, DeleteBranch
│   ├── commit.go         # CreateCommit (Git tree API), ReadLocalFiles
│   ├── list.go           # ListOrgRepos, ListUserRepos, GetRepo
│   ├── contributors.go   # ListContributorStats, GetContributorSummary
│   └── batch.go          # Batch for atomic multi-file commits
├── pr/                   # Pull request operations
│   └── pullrequest.go    # CreatePR, GetPR, ListPRs, MergePR, ApprovePR, IsMergeable
├── release/              # Release operations
│   └── release.go        # ListReleases, GetLatestRelease, CreateRelease, DeleteRelease
├── checks/               # Check runs operations
│   └── checks.go         # ListCheckRuns, WaitForChecks, AllChecksPassed
├── sarif/                # SARIF upload for GitHub Code Scanning
│   └── sarif.go          # Upload, UploadFile, GetUploadStatus, WaitForProcessing
├── tag/                  # Git tag operations
│   └── tag.go            # ListTags, CreateTag, GetTagSHA, TagExists
├── cliutil/              # CLI utilities
│   └── status.go         # Git status helpers
├── cmd/                  # CLI tools
│   ├── gogithub/         # Main CLI (profile, search-prs, stats-report commands)
│   └── searchuserpr/     # Search user PRs example
└── web/                  # Profile Viewer web application
    └── src/              # TypeScript source (Vite, Chart.js)

Usage

Basic Example

package main

import (
    "context"
    "fmt"

    "github.com/grokify/gogithub/auth"
    "github.com/grokify/gogithub/search"
)

func main() {
    ctx := context.Background()

    // Create authenticated client
    gh := auth.NewGitHubClient(ctx, "your-github-token")

    // Search for open pull requests
    client := search.NewClient(gh)
    issues, err := client.SearchIssuesAll(ctx, search.Query{
        search.ParamUser:  "grokify",
        search.ParamState: search.ParamStateValueOpen,
        search.ParamIs:    search.ParamIsValuePR,
    }, nil)
    if err != nil {
        panic(err)
    }

    fmt.Printf("Found %d open PRs\n", len(issues))
}

Creating a Pull Request

package main

import (
    "context"
    "fmt"

    "github.com/grokify/gogithub/auth"
    "github.com/grokify/gogithub/pr"
    "github.com/grokify/gogithub/repo"
)

func main() {
    ctx := context.Background()
    gh := auth.NewGitHubClient(ctx, "your-github-token")

    // Get branch SHA
    sha, err := repo.GetBranchSHA(ctx, gh, "owner", "repo", "main")
    if err != nil {
        panic(err)
    }

    // Create a new branch
    err = repo.CreateBranch(ctx, gh, "owner", "repo", "feature-branch", sha)
    if err != nil {
        panic(err)
    }

    // Create files and commit
    files := []repo.FileContent{
        {Path: "README.md", Content: []byte("# Hello")},
    }
    _, err = repo.CreateCommit(ctx, gh, "owner", "repo", "feature-branch", "Add README", files)
    if err != nil {
        panic(err)
    }

    // Create pull request
    pullRequest, err := pr.CreatePR(ctx, gh, "upstream-owner", "upstream-repo",
        "fork-owner", "feature-branch", "main", "My PR Title", "PR description")
    if err != nil {
        panic(err)
    }

    fmt.Printf("PR created: %s\n", pullRequest.GetHTMLURL())
}

Waiting for CI Checks

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/grokify/gogithub/auth"
    "github.com/grokify/gogithub/checks"
)

func main() {
    ctx := context.Background()
    gh := auth.NewGitHubClient(ctx, "your-github-token")

    // Wait for all checks to complete (with 10 minute timeout)
    checkRuns, allPassed, err := checks.WaitForChecks(ctx, gh, "owner", "repo", "commit-sha",
        10*time.Minute, 30*time.Second)
    if err != nil {
        panic(err)
    }

    // Get aggregate status
    status := checks.GetChecksStatus(checkRuns)
    fmt.Printf("Checks: %d passed, %d failed, %d pending\n",
        status.Passed, status.Failed, status.Pending)

    if allPassed {
        fmt.Println("All checks passed!")
    }
}

Creating Tags and Releases

package main

import (
    "context"
    "fmt"

    "github.com/grokify/gogithub/auth"
    "github.com/grokify/gogithub/release"
    "github.com/grokify/gogithub/tag"
)

func main() {
    ctx := context.Background()
    gh := auth.NewGitHubClient(ctx, "your-github-token")

    // Create an annotated tag
    err := tag.CreateTag(ctx, gh, "owner", "repo", "v1.0.0", "commit-sha", "Release v1.0.0")
    if err != nil {
        panic(err)
    }

    // Create a release
    rel, err := release.CreateReleaseSimple(ctx, gh, "owner", "repo",
        "v1.0.0",           // tag name
        "Version 1.0.0",    // release name
        "Release notes...", // body
        false,              // draft
        false,              // prerelease
        true,               // generate notes
    )
    if err != nil {
        panic(err)
    }

    fmt.Printf("Release created: %s\n", rel.GetHTMLURL())
}

User Profile Statistics

Get comprehensive contribution statistics similar to GitHub profile pages. See the full documentation for details.

package main

import (
    "context"
    "fmt"
    "time"

    "github.com/google/go-github/v88/github"
    "github.com/grokify/gogithub/graphql"
    "github.com/grokify/gogithub/profile"
)

func main() {
    ctx := context.Background()
    token := "your-github-token"

    restClient, err := github.NewClient(github.WithAuthToken(token))
    if err != nil {
        panic(err)
    }
    gqlClient := graphql.NewClient(ctx, token)

    // Fetch profile for last year
    from := time.Now().AddDate(-1, 0, 0)
    to := time.Now()

    p, err := profile.GetUserProfile(ctx, restClient, gqlClient, "grokify", from, to, nil)
    if err != nil {
        panic(err)
    }

    // Summary
    fmt.Println(p.Summary())
    // grokify: 150 commits (+10000/-3000) in 12 repos, 25 PRs, 10 issues, 50 reviews

    // Calendar stats
    fmt.Printf("Longest streak: %d days\n", p.Calendar.LongestStreak())

    // Monthly activity
    for _, m := range p.Activity.Months {
        if s := m.CommitSummary(); s != "" {
            fmt.Printf("%s %d: %s\n", m.MonthName(), m.Year, s)
        }
    }
}

Profile Output Formats

Generate profile visualizations in multiple formats:

# Generate all outputs
gogithub profile --user grokify --from 2024-01-01 --to 2024-12-31 \
    --output-readme README.md \
    --output-svg stats.svg --svg-theme dracula \
    --output-chart chart.svg \
    --output-chart-json chart.json

README with Contribution Heatmap

Generate a GitHub profile README with a Unicode contribution calendar:

import "github.com/grokify/gogithub/profile/readme"

config := readme.DefaultConfig()
config.ShowHeatmap = true

output, err := readme.Generate(profile, config)

SVG Stats Card

Generate embeddable stats cards with theme support:

import "github.com/grokify/gogithub/profile/svg"

// Available themes: default, dark, dracula, nord, gruvbox, solarized
card, err := svg.GenerateStatsCard(profile, svg.ThemeDracula, "My GitHub Stats")

Monthly Activity Charts

Generate charts as SVG or JSON intermediate representation:

import "github.com/grokify/gogithub/profile/svg"

// SVG chart
chartSVG, err := svg.GenerateMonthlyChart(profile.Timeline, svg.ChartOptions{
    Width:  800,
    Height: 400,
})

// JSON IR for custom rendering
chartJSON, err := svg.GenerateChartJSON(profile.Timeline)

Adding New Functionality

When adding new GitHub API functionality, follow this structure:

  1. Identify the operation category - Determine which subdirectory the functionality belongs to:

    • auth/ - Authentication, user identity
    • config/ - Configuration, environment variables, GitHub Enterprise
    • errors/ - Error types and translation utilities
    • pathutil/ - Path validation and normalization
    • search/ - Search API (issues, PRs, code, commits, etc.)
    • repo/ - Repository operations (forks, branches, commits, batch operations)
    • pr/ - Pull request operations
    • release/ - Release and asset operations
    • Create new directories for distinct API areas (e.g., issues/, actions/, gists/)
  2. Create focused files - Within each subdirectory, organize by specific functionality:

    • One file per logical grouping (e.g., fork.go, branch.go, commit.go)
    • Keep files focused and cohesive
  3. Use consistent patterns:

    • Functions take context.Context and *github.Client as first parameters
    • Return appropriate error types with context
    • Provide both low-level functions and convenience wrappers
  4. Define custom error types when needed:

    type ForkError struct {
        Owner string
        Repo  string
        Err   error
    }
    
    func (e *ForkError) Error() string {
        return "failed to fork " + e.Owner + "/" + e.Repo + ": " + e.Err.Error()
    }
    
    func (e *ForkError) Unwrap() error {
        return e.Err
    }
  5. Add tests in corresponding *_test.go files

Example: Adding Gist Support

gogithub/
└── gist/
    ├── gist.go       # Create, Get, List, Update, Delete
    └── gist_test.go
// gist/gist.go
package gist

import (
    "context"
    "github.com/google/go-github/v88/github"
)

func Create(ctx context.Context, gh *github.Client, description string, public bool, files map[string]string) (*github.Gist, error) {
    // Implementation
}

func Get(ctx context.Context, gh *github.Client, id string) (*github.Gist, error) {
    // Implementation
}

Backward Compatibility

The root gogithub package provides backward-compatible re-exports for existing code:

// Old style (still works)
import "github.com/grokify/gogithub"

c := gogithub.NewClient(httpClient)
issues, _ := c.SearchIssuesAll(ctx, gogithub.Query{...}, nil)

// New style (preferred)
import (
    "github.com/grokify/gogithub/auth"
    "github.com/grokify/gogithub/search"
)

gh := auth.NewGitHubClient(ctx, token)
c := search.NewClient(gh)
issues, _ := c.SearchIssuesAll(ctx, search.Query{...}, nil)

Dependencies

License

MIT License

About

gogithub is a high-level Go module for interacting with the GitHub API. It wraps go-github with convenience functions organized by operation type.

Resources

License

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

1 watching

Forks

Contributors