Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,103 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v1.5.0] - 2025-10-28

### 🚨 Breaking Changes

This release removes the `github.com/google/go-github/v74` dependency and implements a lightweight internal GitHub API client. While most users will experience no breaking changes, some API adjustments have been made:

#### API Changes

1. **Enterprise Configuration Simplified**
- **Before**: `WithEnterpriseURLs(baseURL, uploadURL string)` - required both base and upload URLs
- **After**: `WithEnterpriseURL(baseURL string)` - single base URL parameter
- **Migration**: Remove the redundant upload URL parameter

2. **Type Changes** (if you were using these types directly)
- `github.InstallationTokenOptions` → `githubauth.InstallationTokenOptions`
- `github.InstallationPermissions` → `githubauth.InstallationPermissions`
- `github.InstallationToken` → `githubauth.InstallationToken`
- `github.Repository` → `githubauth.Repository`

### Added

- **Internal GitHub API Client**: New `github.go` file with minimal GitHub API implementation
- Direct HTTP API calls to GitHub's REST API
- `InstallationTokenOptions` type for configuring installation token requests
- `InstallationPermissions` type with comprehensive permission structure
- `InstallationToken` response type from GitHub API
- `Repository` type for minimal repository representation
- **Public Helper Function**: Added `Ptr[T]()` generic helper for creating pointers to any type (useful for InstallationTokenOptions)

### Changed

- **Removed Dependency**: Eliminated `github.com/google/go-github/v74` dependency
- **Removed Dependency**: Eliminated `github.com/google/go-querystring` indirect dependency
- **Simplified Enterprise Support**: Streamlined from `WithEnterpriseURLs()` to `WithEnterpriseURL()`
- **Updated Documentation**: Package docs now reflect that the library is built only on `golang.org/x/oauth2`
- **Binary Size Reduction**: Smaller binaries without unused go-github code

### Fixed

- **Documentation**: Fixed GitHub API documentation link for installation token generation

### Migration Guide

#### For Most Users

No action required - if you only use the public `TokenSource` functions, your code will continue to work without changes.

#### For Enterprise GitHub Users

```go
// Before (v1.4.x)
installationTokenSource := githubauth.NewInstallationTokenSource(
installationID,
appTokenSource,
githubauth.WithEnterpriseURLs("https://github.example.com", "https://github.example.com"),
)

// After (v1.5.0)
installationTokenSource := githubauth.NewInstallationTokenSource(
installationID,
appTokenSource,
githubauth.WithEnterpriseURL("https://github.example.com"),
)
```

#### For Direct Type Users

```go
// Before (v1.4.x)
import "github.com/google/go-github/v74/github"
opts := &github.InstallationTokenOptions{
Repositories: []string{"repo1", "repo2"},
Permissions: &github.InstallationPermissions{
Contents: github.Ptr("read"),
},
}

// After (v1.5.0)
import "github.com/jferrl/go-githubauth"
opts := &githubauth.InstallationTokenOptions{
Repositories: []string{"repo1", "repo2"},
Permissions: &githubauth.InstallationPermissions{
Contents: githubauth.Ptr("read"), // Use the new Ptr() helper
},
}
```

### Benefits

- ✅ **Reduced Dependencies**: 2 fewer dependencies (from 3 to 2 total)
- ✅ **Smaller Binary Size**: No unused go-github code included
- ✅ **Better Control**: Full ownership of GitHub API integration
- ✅ **Easier Debugging**: Simpler code path for troubleshooting
- ✅ **Same Performance**: All token caching and performance optimizations maintained

**Full Changelog**: <https://github.com/jferrl/go-githubauth/compare/v1.4.2...v1.5.0>

## [v1.4.2] - 2025-09-19

### Changed
Expand Down
63 changes: 55 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

`go-githubauth` is a Go package that provides utilities for GitHub authentication, including generating and using GitHub App tokens, installation tokens, and personal access tokens.

**v1.4.x** introduces personal access token support and significant performance optimizations with intelligent token caching and high-performance HTTP clients.
**v1.5.0** removes the `go-github` dependency, implementing a lightweight internal GitHub API client. This reduces external dependencies while maintaining full compatibility with the OAuth2 token source interface.

---

Expand All @@ -26,15 +26,17 @@

`go-githubauth` package provides implementations of the `TokenSource` interface from the `golang.org/x/oauth2` package. This interface has a single method, Token, which returns an *oauth2.Token.

### v1.4.0 Features
### v1.5.0 Features

- **📦 Zero External Dependencies**: Removed `go-github` dependency - lightweight internal implementation
- **🔐 Personal Access Token Support**: Native support for both classic and fine-grained personal access tokens
- **⚡ Token Caching**: Dual-layer caching system for optimal performance
- JWT tokens cached until expiration (up to 10 minutes)
- Installation tokens cached until expiration (defined by GitHub response)
- **🚀 Pooled HTTP Client**: Production-ready HTTP client with connection pooling
- **📈 Performance Optimizations**: Up to 99% reduction in unnecessary GitHub API calls
- **🏗️ Production Ready**: Optimized for high-throughput and enterprise applications
- **🌐 Simplified Enterprise Support**: Streamlined configuration with single base URL parameter

### Core Capabilities

Expand All @@ -48,7 +50,9 @@

### Requirements

- Go 1.21 or higher (for generics support)
- This package is designed to be used with the `golang.org/x/oauth2` package
- No external GitHub SDK dependencies required

## Installation

Expand All @@ -60,7 +64,9 @@ go get -u github.com/jferrl/go-githubauth

## Usage

### Usage with [go-github](https://github.com/google/go-github) and [oauth2](golang.org/x/oauth2)
### Usage with [oauth2](golang.org/x/oauth2)

You can use this package standalone with any HTTP client, or integrate it with the [go-github](https://github.com/google/go-github) SDK if you need additional GitHub API functionality.

#### Client ID (Recommended)

Expand All @@ -73,7 +79,7 @@ import (
"os"
"strconv"

"github.com/google/go-github/v74/github"
"github.com/google/go-github/v76/github"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -117,7 +123,7 @@ import (
"os"
"strconv"

"github.com/google/go-github/v74/github"
"github.com/google/go-github/v76/github"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -274,7 +280,48 @@ func main() {

GitHub Personal Access Tokens provide direct authentication for users and organizations. This package supports both classic personal access tokens and fine-grained personal access tokens.

#### Using Personal Access Tokens with [go-github](https://github.com/google/go-github)
#### Using Personal Access Tokens

##### With oauth2 Client (Standalone)

```go
package main

import (
"context"
"fmt"
"io"
"net/http"
"os"

"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)

func main() {
// Personal access token from environment variable
token := os.Getenv("GITHUB_TOKEN") // e.g., "ghp_..." or "github_pat_..."

// Create token source
tokenSource := githubauth.NewPersonalAccessTokenSource(token)

// Create HTTP client with OAuth2 transport
httpClient := oauth2.NewClient(context.Background(), tokenSource)

// Use the HTTP client for GitHub API calls
resp, err := httpClient.Get("https://api.github.com/user")
if err != nil {
fmt.Println("Error getting user:", err)
return
}
defer resp.Body.Close()

body, _ := io.ReadAll(resp.Body)
fmt.Printf("User info: %s\n", body)
}
```

##### With go-github SDK (Optional)

```go
package main
Expand All @@ -284,7 +331,7 @@ import (
"fmt"
"os"

"github.com/google/go-github/v74/github"
"github.com/google/go-github/v76/github"
"github.com/jferrl/go-githubauth"
"golang.org/x/oauth2"
)
Expand Down Expand Up @@ -316,7 +363,7 @@ func main() {
1. **Classic Personal Access Token**: Visit [GitHub Settings > Developer settings > Personal access tokens > Tokens (classic)](https://github.com/settings/tokens)
2. **Fine-grained Personal Access Token**: Visit [GitHub Settings > Developer settings > Personal access tokens > Fine-grained tokens](https://github.com/settings/personal-access-tokens/new)

** 🔐 Security Note **: Store your personal access tokens securely and never commit them to version control. Use environment variables or secure credential management systems.
**🔐 Security Note**: Store your personal access tokens securely and never commit them to version control. Use environment variables or secure credential management systems.

## Contributing

Expand Down
29 changes: 14 additions & 15 deletions auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//
// This package implements oauth2.TokenSource interfaces for GitHub App
// authentication and GitHub App installation token generation. It is built
// on top of the go-github and golang.org/x/oauth2 libraries.
// on top of the golang.org/x/oauth2 library.
package githubauth

import (
Expand All @@ -15,7 +15,6 @@ import (
"time"

jwt "github.com/golang-jwt/jwt/v5"
"github.com/google/go-github/v74/github"
"golang.org/x/oauth2"
)

Expand Down Expand Up @@ -135,7 +134,7 @@ func (t *applicationTokenSource) Token() (*oauth2.Token, error) {
type InstallationTokenSourceOpt func(*installationTokenSource)

// WithInstallationTokenOptions sets the options for the GitHub App installation token.
func WithInstallationTokenOptions(opts *github.InstallationTokenOptions) InstallationTokenSourceOpt {
func WithInstallationTokenOptions(opts *InstallationTokenOptions) InstallationTokenSourceOpt {
return func(i *installationTokenSource) {
i.opts = opts
}
Expand All @@ -149,16 +148,16 @@ func WithHTTPClient(client *http.Client) InstallationTokenSourceOpt {
Base: client.Transport,
}

i.client = github.NewClient(client)
i.client = newGitHubClient(client)
}
}

// WithEnterpriseURLs sets the base URL and upload URL for GitHub Enterprise Server.
// WithEnterpriseURL sets the base URL for GitHub Enterprise Server.
// This option should be used after WithHTTPClient to ensure the HTTP client is properly configured.
// If the provided URLs are invalid, the option is ignored and default GitHub URLs are used.
func WithEnterpriseURLs(baseURL, uploadURL string) InstallationTokenSourceOpt {
// If the provided base URL is invalid, the option is ignored and default GitHub base URL is used.
func WithEnterpriseURL(baseURL string) InstallationTokenSourceOpt {
return func(i *installationTokenSource) {
enterpriseClient, err := i.client.WithEnterpriseURLs(baseURL, uploadURL)
enterpriseClient, err := i.client.withEnterpriseURL(baseURL)
if err != nil {
return
}
Expand All @@ -182,8 +181,8 @@ type installationTokenSource struct {
id int64
ctx context.Context
src oauth2.TokenSource
client *github.Client
opts *github.InstallationTokenOptions
client *githubClient
opts *InstallationTokenOptions
}

// NewInstallationTokenSource creates a GitHub App installation token source.
Expand All @@ -193,7 +192,7 @@ type installationTokenSource struct {
// token regeneration. Don't worry about wrapping the result again since ReuseTokenSource
// prevents re-wrapping automatically.
//
// See https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token
// See https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app
func NewInstallationTokenSource(id int64, src oauth2.TokenSource, opts ...InstallationTokenSourceOpt) oauth2.TokenSource {
ctx := context.Background()

Expand All @@ -207,7 +206,7 @@ func NewInstallationTokenSource(id int64, src oauth2.TokenSource, opts ...Instal
id: id,
ctx: ctx,
src: src,
client: github.NewClient(httpClient),
client: newGitHubClient(httpClient),
}

for _, opt := range opts {
Expand All @@ -219,15 +218,15 @@ func NewInstallationTokenSource(id int64, src oauth2.TokenSource, opts ...Instal

// Token generates a new GitHub App installation token for authenticating as a GitHub App installation.
func (t *installationTokenSource) Token() (*oauth2.Token, error) {
token, _, err := t.client.Apps.CreateInstallationToken(t.ctx, t.id, t.opts)
token, err := t.client.createInstallationToken(t.ctx, t.id, t.opts)
if err != nil {
return nil, err
}

return &oauth2.Token{
AccessToken: token.GetToken(),
AccessToken: token.Token,
TokenType: bearerTokenType,
Expiry: token.GetExpiresAt().Time,
Expiry: token.ExpiresAt,
}, nil
}

Expand Down
Loading
Loading