From 6e632988e97a030186dc547955907b24d5fe1940 Mon Sep 17 00:00:00 2001 From: Mike Trienis Date: Sun, 7 Dec 2025 09:19:08 -0800 Subject: [PATCH] Add GitHub Enterprise support to GithubServiceProviderBasic --- libs/ci/github/github.go | 33 ++++++++++++++++++ libs/ci/github/github_test.go | 66 ++++++++++++++++++++++++++++++++++- 2 files changed, 98 insertions(+), 1 deletion(-) diff --git a/libs/ci/github/github.go b/libs/ci/github/github.go index 26d8388ca..aa08b3526 100644 --- a/libs/ci/github/github.go +++ b/libs/ci/github/github.go @@ -30,6 +30,11 @@ func (_ GithubServiceProviderBasic) NewService(ghToken string, repoName string, client = client.WithAuthToken(ghToken) } + client, err := configureEnterpriseClient(client) + if err != nil { + return GithubService{}, err + } + return GithubService{ Client: client, RepoName: repoName, @@ -37,6 +42,34 @@ func (_ GithubServiceProviderBasic) NewService(ghToken string, repoName string, }, nil } +// configureEnterpriseClient configures the GitHub client for Enterprise if +// DIGGER_GITHUB_HOSTNAME or GITHUB_API_URL environment variables are set. +func configureEnterpriseClient(client *github.Client) (*github.Client, error) { + // Check for DIGGER_GITHUB_HOSTNAME first (explicit configuration) + if hostname := os.Getenv("DIGGER_GITHUB_HOSTNAME"); hostname != "" { + baseURL := fmt.Sprintf("https://%s/api/v3/", hostname) + uploadURL := fmt.Sprintf("https://%s/api/uploads/", hostname) + slog.Info("configuring GitHub Enterprise client", "hostname", hostname) + return client.WithEnterpriseURLs(baseURL, uploadURL) + } + + // Fall back to GITHUB_API_URL (set automatically in GitHub Actions) + if apiURL := os.Getenv("GITHUB_API_URL"); apiURL != "" && apiURL != "https://api.github.com" { + // Derive upload URL from API URL by replacing /api/v3 with /api/uploads + uploadURL := strings.Replace(apiURL, "/api/v3", "/api/uploads", 1) + if !strings.HasSuffix(apiURL, "/") { + apiURL += "/" + } + if !strings.HasSuffix(uploadURL, "/") { + uploadURL += "/" + } + slog.Info("configuring GitHub Enterprise client from GITHUB_API_URL", "apiUrl", apiURL, "uploadUrl", uploadURL) + return client.WithEnterpriseURLs(apiURL, uploadURL) + } + + return client, nil +} + type GithubService struct { Client *github.Client RepoName string diff --git a/libs/ci/github/github_test.go b/libs/ci/github/github_test.go index 238e7441a..a4811011b 100644 --- a/libs/ci/github/github_test.go +++ b/libs/ci/github/github_test.go @@ -1,9 +1,10 @@ package github import ( - "github.com/diggerhq/digger/libs/ci/generic" + "os" "testing" + "github.com/diggerhq/digger/libs/ci/generic" "github.com/diggerhq/digger/libs/digger_config" "github.com/stretchr/testify/assert" ) @@ -121,3 +122,66 @@ func TestFindAllChangedFilesOfPR(t *testing.T) { // 45 changed files including 1 renamed file so the previous filename is included assert.Equal(t, 46, len(files)) } + +func TestConfigureEnterpriseClient_WithDiggerHostname(t *testing.T) { + // Set up + os.Setenv("DIGGER_GITHUB_HOSTNAME", "github.example.com") + defer os.Unsetenv("DIGGER_GITHUB_HOSTNAME") + + svc, err := GithubServiceProviderBasic{}.NewService("test-token", "repo", "owner") + + assert.NoError(t, err) + assert.NotNil(t, svc.Client) + assert.Equal(t, "https://github.example.com/api/v3/", svc.Client.BaseURL.String()) + assert.Equal(t, "https://github.example.com/api/uploads/", svc.Client.UploadURL.String()) +} + +func TestConfigureEnterpriseClient_WithGitHubApiUrl(t *testing.T) { + // Set up - this simulates GitHub Actions environment on Enterprise + os.Setenv("GITHUB_API_URL", "https://github.example.com/api/v3") + defer os.Unsetenv("GITHUB_API_URL") + + svc, err := GithubServiceProviderBasic{}.NewService("test-token", "repo", "owner") + + assert.NoError(t, err) + assert.NotNil(t, svc.Client) + assert.Equal(t, "https://github.example.com/api/v3/", svc.Client.BaseURL.String()) + assert.Equal(t, "https://github.example.com/api/uploads/", svc.Client.UploadURL.String()) +} + +func TestConfigureEnterpriseClient_PublicGitHub(t *testing.T) { + // Ensure no enterprise env vars are set + os.Unsetenv("DIGGER_GITHUB_HOSTNAME") + os.Unsetenv("GITHUB_API_URL") + + svc, err := GithubServiceProviderBasic{}.NewService("test-token", "repo", "owner") + + assert.NoError(t, err) + assert.NotNil(t, svc.Client) + assert.Equal(t, "https://api.github.com/", svc.Client.BaseURL.String()) +} + +func TestConfigureEnterpriseClient_PublicGitHubApiUrl(t *testing.T) { + // GITHUB_API_URL set to public GitHub should not trigger enterprise config + os.Setenv("GITHUB_API_URL", "https://api.github.com") + defer os.Unsetenv("GITHUB_API_URL") + + svc, err := GithubServiceProviderBasic{}.NewService("test-token", "repo", "owner") + + assert.NoError(t, err) + assert.NotNil(t, svc.Client) + assert.Equal(t, "https://api.github.com/", svc.Client.BaseURL.String()) +} + +func TestConfigureEnterpriseClient_DiggerHostnameTakesPrecedence(t *testing.T) { + // Both set - DIGGER_GITHUB_HOSTNAME should take precedence + os.Setenv("DIGGER_GITHUB_HOSTNAME", "digger-enterprise.example.com") + os.Setenv("GITHUB_API_URL", "https://actions-enterprise.example.com/api/v3") + defer os.Unsetenv("DIGGER_GITHUB_HOSTNAME") + defer os.Unsetenv("GITHUB_API_URL") + + svc, err := GithubServiceProviderBasic{}.NewService("test-token", "repo", "owner") + + assert.NoError(t, err) + assert.Equal(t, "https://digger-enterprise.example.com/api/v3/", svc.Client.BaseURL.String()) +}