Add Identifier to actions.Client (#2237)
This commit is contained in:
		
							parent
							
								
									34efb9d585
								
							
						
					
					
						commit
						7414dc6568
					
				|  | @ -165,6 +165,29 @@ func NewClient(githubConfigURL string, creds *ActionsAuth, options ...ClientOpti | ||||||
| 	return ac, nil | 	return ac, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Identifier returns a string to help identify a client uniquely.
 | ||||||
|  | // This is used for caching client instances and understanding when a config
 | ||||||
|  | // change warrants creating a new client. Any changes to Client that would
 | ||||||
|  | // require a new client should be reflected here.
 | ||||||
|  | func (c *Client) Identifier() string { | ||||||
|  | 	identifier := fmt.Sprintf("configURL:%q,", c.config.ConfigURL.String()) | ||||||
|  | 
 | ||||||
|  | 	if c.creds.Token != "" { | ||||||
|  | 		identifier += fmt.Sprintf("token:%q", c.creds.Token) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if c.creds.AppCreds != nil { | ||||||
|  | 		identifier += fmt.Sprintf( | ||||||
|  | 			"appID:%q,installationID:%q,key:%q", | ||||||
|  | 			c.creds.AppCreds.AppID, | ||||||
|  | 			c.creds.AppCreds.AppInstallationID, | ||||||
|  | 			c.creds.AppCreds.AppPrivateKey, | ||||||
|  | 		) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return uuid.NewMD5(uuid.NameSpaceOID, []byte(identifier)).String() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (c *Client) Do(req *http.Request) (*http.Response, error) { | func (c *Client) Do(req *http.Request) (*http.Response, error) { | ||||||
| 	resp, err := c.Client.Do(req) | 	resp, err := c.Client.Do(req) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|  |  | ||||||
|  | @ -91,7 +91,7 @@ func TestGitHubConfig(t *testing.T) { | ||||||
| 		} | 		} | ||||||
| 	}) | 	}) | ||||||
| 
 | 
 | ||||||
| 	t.Run("when given an invalid URL", func(t *testing.T) {}) | 	t.Run("when given an invalid URL", func(t *testing.T) { | ||||||
| 		invalidURLs := []string{ | 		invalidURLs := []string{ | ||||||
| 			"https://github.com/", | 			"https://github.com/", | ||||||
| 			"https://github.com", | 			"https://github.com", | ||||||
|  | @ -103,6 +103,7 @@ func TestGitHubConfig(t *testing.T) { | ||||||
| 			require.Error(t, err) | 			require.Error(t, err) | ||||||
| 			assert.True(t, errors.Is(err, actions.ErrInvalidGitHubConfigURL)) | 			assert.True(t, errors.Is(err, actions.ErrInvalidGitHubConfigURL)) | ||||||
| 		} | 		} | ||||||
|  | 	}) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestGitHubConfig_GitHubAPIURL(t *testing.T) { | func TestGitHubConfig_GitHubAPIURL(t *testing.T) { | ||||||
|  |  | ||||||
|  | @ -0,0 +1,111 @@ | ||||||
|  | package actions_test | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/actions/actions-runner-controller/github/actions" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestClient_Identifier(t *testing.T) { | ||||||
|  | 	t.Run("configURL changes", func(t *testing.T) { | ||||||
|  | 		scenarios := []struct { | ||||||
|  | 			name string | ||||||
|  | 			url  string | ||||||
|  | 		}{ | ||||||
|  | 			{ | ||||||
|  | 				name: "url of a different repo", | ||||||
|  | 				url:  "https://github.com/org/repo2", | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "url of an org", | ||||||
|  | 				url:  "https://github.com/org", | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "url of an enterprise", | ||||||
|  | 				url:  "https://github.com/enterprises/my-enterprise", | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "url of a self-hosted github", | ||||||
|  | 				url:  "https://selfhosted.com/org/repo", | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		configURL := "https://github.com/org/repo" | ||||||
|  | 		defaultCreds := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 		oldClient, err := actions.NewClient(configURL, defaultCreds) | ||||||
|  | 		require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 		for _, scenario := range scenarios { | ||||||
|  | 			t.Run(scenario.name, func(t *testing.T) { | ||||||
|  | 				newClient, err := actions.NewClient(scenario.url, defaultCreds) | ||||||
|  | 				require.NoError(t, err) | ||||||
|  | 				assert.NotEqual(t, oldClient.Identifier(), newClient.Identifier()) | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | 
 | ||||||
|  | 	t.Run("credentials change", func(t *testing.T) { | ||||||
|  | 		defaultTokenCreds := &actions.ActionsAuth{ | ||||||
|  | 			Token: "token", | ||||||
|  | 		} | ||||||
|  | 		defaultAppCreds := &actions.ActionsAuth{ | ||||||
|  | 			AppCreds: &actions.GitHubAppAuth{ | ||||||
|  | 				AppID:             123, | ||||||
|  | 				AppInstallationID: 123, | ||||||
|  | 				AppPrivateKey:     "private key", | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		scenarios := []struct { | ||||||
|  | 			name string | ||||||
|  | 			old  *actions.ActionsAuth | ||||||
|  | 			new  *actions.ActionsAuth | ||||||
|  | 		}{ | ||||||
|  | 			{ | ||||||
|  | 				name: "different token", | ||||||
|  | 				old:  defaultTokenCreds, | ||||||
|  | 				new: &actions.ActionsAuth{ | ||||||
|  | 					Token: "new token", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "changing from token to github app", | ||||||
|  | 				old:  defaultTokenCreds, | ||||||
|  | 				new:  defaultAppCreds, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "changing from github app to token", | ||||||
|  | 				old:  defaultAppCreds, | ||||||
|  | 				new:  defaultTokenCreds, | ||||||
|  | 			}, | ||||||
|  | 			{ | ||||||
|  | 				name: "different github app", | ||||||
|  | 				old:  defaultAppCreds, | ||||||
|  | 				new: &actions.ActionsAuth{ | ||||||
|  | 					AppCreds: &actions.GitHubAppAuth{ | ||||||
|  | 						AppID:             456, | ||||||
|  | 						AppInstallationID: 456, | ||||||
|  | 						AppPrivateKey:     "new private key", | ||||||
|  | 					}, | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		defaultConfigURL := "https://github.com/org/repo" | ||||||
|  | 
 | ||||||
|  | 		for _, scenario := range scenarios { | ||||||
|  | 			t.Run(scenario.name, func(t *testing.T) { | ||||||
|  | 				oldClient, err := actions.NewClient(defaultConfigURL, scenario.old) | ||||||
|  | 				require.NoError(t, err) | ||||||
|  | 
 | ||||||
|  | 				newClient, err := actions.NewClient(defaultConfigURL, scenario.new) | ||||||
|  | 				require.NoError(t, err) | ||||||
|  | 				assert.NotEqual(t, oldClient.Identifier(), newClient.Identifier()) | ||||||
|  | 			}) | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  | } | ||||||
|  | @ -4,7 +4,6 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"crypto/x509" | 	"crypto/x509" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" |  | ||||||
| 	"strconv" | 	"strconv" | ||||||
| 	"sync" | 	"sync" | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +18,7 @@ type MultiClient interface { | ||||||
| type multiClient struct { | type multiClient struct { | ||||||
| 	// To lock adding and removing of individual clients.
 | 	// To lock adding and removing of individual clients.
 | ||||||
| 	mu      sync.Mutex | 	mu      sync.Mutex | ||||||
| 	clients map[ActionsClientKey]*actionsClientWrapper | 	clients map[ActionsClientKey]*Client | ||||||
| 
 | 
 | ||||||
| 	logger    logr.Logger | 	logger    logr.Logger | ||||||
| 	userAgent string | 	userAgent string | ||||||
|  | @ -40,22 +39,14 @@ type ActionsAuth struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type ActionsClientKey struct { | type ActionsClientKey struct { | ||||||
| 	ActionsURL string | 	Identifier string | ||||||
| 	Auth       ActionsAuth |  | ||||||
| 	Namespace  string | 	Namespace  string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type actionsClientWrapper struct { |  | ||||||
| 	// To lock client usage when tokens are being refreshed.
 |  | ||||||
| 	mu sync.Mutex |  | ||||||
| 
 |  | ||||||
| 	client ActionsService |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func NewMultiClient(userAgent string, logger logr.Logger) MultiClient { | func NewMultiClient(userAgent string, logger logr.Logger) MultiClient { | ||||||
| 	return &multiClient{ | 	return &multiClient{ | ||||||
| 		mu:        sync.Mutex{}, | 		mu:        sync.Mutex{}, | ||||||
| 		clients:   make(map[ActionsClientKey]*actionsClientWrapper), | 		clients:   make(map[ActionsClientKey]*Client), | ||||||
| 		logger:    logger, | 		logger:    logger, | ||||||
| 		userAgent: userAgent, | 		userAgent: userAgent, | ||||||
| 	} | 	} | ||||||
|  | @ -64,11 +55,6 @@ func NewMultiClient(userAgent string, logger logr.Logger) MultiClient { | ||||||
| func (m *multiClient) GetClientFor(ctx context.Context, githubConfigURL string, creds ActionsAuth, namespace string) (ActionsService, error) { | func (m *multiClient) GetClientFor(ctx context.Context, githubConfigURL string, creds ActionsAuth, namespace string) (ActionsService, error) { | ||||||
| 	m.logger.Info("retrieve actions client", "githubConfigURL", githubConfigURL, "namespace", namespace) | 	m.logger.Info("retrieve actions client", "githubConfigURL", githubConfigURL, "namespace", namespace) | ||||||
| 
 | 
 | ||||||
| 	parsedGitHubURL, err := url.Parse(githubConfigURL) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if creds.Token == "" && creds.AppCreds == nil { | 	if creds.Token == "" && creds.AppCreds == nil { | ||||||
| 		return nil, fmt.Errorf("no credentials provided. either a PAT or GitHub App credentials should be provided") | 		return nil, fmt.Errorf("no credentials provided. either a PAT or GitHub App credentials should be provided") | ||||||
| 	} | 	} | ||||||
|  | @ -77,34 +63,6 @@ func (m *multiClient) GetClientFor(ctx context.Context, githubConfigURL string, | ||||||
| 		return nil, fmt.Errorf("both PAT and GitHub App credentials provided. should only provide one") | 		return nil, fmt.Errorf("both PAT and GitHub App credentials provided. should only provide one") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	key := ActionsClientKey{ |  | ||||||
| 		ActionsURL: parsedGitHubURL.String(), |  | ||||||
| 		Namespace:  namespace, |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if creds.AppCreds != nil { |  | ||||||
| 		key.Auth = ActionsAuth{ |  | ||||||
| 			AppCreds: creds.AppCreds, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if creds.Token != "" { |  | ||||||
| 		key.Auth = ActionsAuth{ |  | ||||||
| 			Token: creds.Token, |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	m.mu.Lock() |  | ||||||
| 	defer m.mu.Unlock() |  | ||||||
| 
 |  | ||||||
| 	clientWrapper, has := m.clients[key] |  | ||||||
| 	if has { |  | ||||||
| 		m.logger.Info("using cache client", "githubConfigURL", githubConfigURL, "namespace", namespace) |  | ||||||
| 		return clientWrapper.client, nil |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	m.logger.Info("creating new client", "githubConfigURL", githubConfigURL, "namespace", namespace) |  | ||||||
| 
 |  | ||||||
| 	client, err := NewClient( | 	client, err := NewClient( | ||||||
| 		githubConfigURL, | 		githubConfigURL, | ||||||
| 		&creds, | 		&creds, | ||||||
|  | @ -115,11 +73,24 @@ func (m *multiClient) GetClientFor(ctx context.Context, githubConfigURL string, | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	m.clients[key] = &actionsClientWrapper{ | 	m.mu.Lock() | ||||||
| 		mu:     sync.Mutex{}, | 	defer m.mu.Unlock() | ||||||
| 		client: client, | 
 | ||||||
|  | 	key := ActionsClientKey{ | ||||||
|  | 		Identifier: client.Identifier(), | ||||||
|  | 		Namespace:  namespace, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	cachedClient, has := m.clients[key] | ||||||
|  | 	if has { | ||||||
|  | 		m.logger.Info("using cache client", "githubConfigURL", githubConfigURL, "namespace", namespace) | ||||||
|  | 		return cachedClient, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	m.logger.Info("creating new client", "githubConfigURL", githubConfigURL, "namespace", namespace) | ||||||
|  | 
 | ||||||
|  | 	m.clients[key] = client | ||||||
|  | 
 | ||||||
| 	m.logger.Info("successfully created new client", "githubConfigURL", githubConfigURL, "namespace", namespace) | 	m.logger.Info("successfully created new client", "githubConfigURL", githubConfigURL, "namespace", namespace) | ||||||
| 
 | 
 | ||||||
| 	return client, nil | 	return client, nil | ||||||
|  |  | ||||||
|  | @ -2,131 +2,51 @@ package actions | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"encoding/json" |  | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/http" |  | ||||||
| 	"net/http/httptest" |  | ||||||
| 	"strings" |  | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/go-logr/logr" | 	"github.com/go-logr/logr" | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| func TestAddClient(t *testing.T) { | func TestMultiClientCaching(t *testing.T) { | ||||||
| 	logger := logr.Discard() | 	logger := logr.Discard() | ||||||
|  | 	ctx := context.Background() | ||||||
| 	multiClient := NewMultiClient("test-user-agent", logger).(*multiClient) | 	multiClient := NewMultiClient("test-user-agent", logger).(*multiClient) | ||||||
| 
 | 
 | ||||||
| 	ctx := context.Background() | 	defaultNamespace := "default" | ||||||
|  | 	defaultConfigURL := "https://github.com/org/repo" | ||||||
|  | 	defaultCreds := &ActionsAuth{ | ||||||
|  | 		Token: "token", | ||||||
|  | 	} | ||||||
|  | 	client, err := NewClient(defaultConfigURL, defaultCreds) | ||||||
|  | 	require.NoError(t, err) | ||||||
| 
 | 
 | ||||||
| 	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | 	multiClient.clients[ActionsClientKey{client.Identifier(), defaultNamespace}] = client | ||||||
| 		if strings.HasSuffix(r.URL.Path, "actions/runners/registration-token") { |  | ||||||
| 			w.WriteHeader(http.StatusCreated) |  | ||||||
| 			w.Header().Set("Content-Type", "application/json") |  | ||||||
| 
 | 
 | ||||||
| 			token := "abc-123" | 	// Verify that the client is cached
 | ||||||
| 			rt := ®istrationToken{Token: &token} | 	cachedClient, err := multiClient.GetClientFor( | ||||||
|  | 		ctx, | ||||||
|  | 		defaultConfigURL, | ||||||
|  | 		*defaultCreds, | ||||||
|  | 		defaultNamespace, | ||||||
|  | 	) | ||||||
|  | 	require.NoError(t, err) | ||||||
|  | 	assert.Equal(t, client, cachedClient) | ||||||
|  | 	assert.Len(t, multiClient.clients, 1) | ||||||
| 
 | 
 | ||||||
| 			if err := json.NewEncoder(w).Encode(rt); err != nil { | 	// Asking for a different client results in creating and caching a new client
 | ||||||
| 				http.Error(w, err.Error(), http.StatusInternalServerError) | 	otherNamespace := "other" | ||||||
| 				return | 	newClient, err := multiClient.GetClientFor( | ||||||
| 			} | 		ctx, | ||||||
| 		} | 		defaultConfigURL, | ||||||
| 		if strings.HasSuffix(r.URL.Path, "actions/runner-registration") { | 		*defaultCreds, | ||||||
| 			w.Header().Set("Content-Type", "application/json") | 		otherNamespace, | ||||||
| 
 | 	) | ||||||
| 			url := "actions.github.com/abc" | 	require.NoError(t, err) | ||||||
| 			jwt := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjI1MTYyMzkwMjJ9.tlrHslTmDkoqnc4Kk9ISoKoUNDfHo-kjlH-ByISBqzE" | 	assert.NotEqual(t, client, newClient) | ||||||
| 			adminConnInfo := &ActionsServiceAdminConnection{ActionsServiceUrl: &url, AdminToken: &jwt} | 	assert.Len(t, multiClient.clients, 2) | ||||||
| 
 |  | ||||||
| 			if err := json.NewEncoder(w).Encode(adminConnInfo); err != nil { |  | ||||||
| 				http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if strings.HasSuffix(r.URL.Path, "/access_tokens") { |  | ||||||
| 			w.Header().Set("Content-Type", "application/vnd.github+json") |  | ||||||
| 
 |  | ||||||
| 			t, _ := time.Parse(time.RFC3339, "2006-01-02T15:04:05Z07:00") |  | ||||||
| 			accessToken := &accessToken{ |  | ||||||
| 				Token:     "abc-123", |  | ||||||
| 				ExpiresAt: t, |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if err := json.NewEncoder(w).Encode(accessToken); err != nil { |  | ||||||
| 				http.Error(w, err.Error(), http.StatusInternalServerError) |  | ||||||
| 				return |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	})) |  | ||||||
| 	defer srv.Close() |  | ||||||
| 
 |  | ||||||
| 	want := 1 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{Token: "PAT"}, "namespace"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	want++ // New repo
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/actions", srv.URL), ActionsAuth{Token: "PAT"}, "namespace"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Repeat
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{Token: "PAT"}, "namespace"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	want++ // New namespace
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{Token: "PAT"}, "other"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	want++ // New pat
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{Token: "other"}, "other"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	want++ // New org
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github", srv.URL), ActionsAuth{Token: "PAT"}, "other"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// No org, repo, enterprise
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v", srv.URL), ActionsAuth{Token: "PAT"}, "other"); err == nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	want++ // Test keying on GitHub App
 |  | ||||||
| 	appAuth := &GitHubAppAuth{ |  | ||||||
| 		AppID: 1, |  | ||||||
| 		AppPrivateKey: `-----BEGIN RSA PRIVATE KEY----- |  | ||||||
| MIICWgIBAAKBgHXfRT9cv9UY9fAAD4+1RshpfSSZe277urfEmPfX3/Og9zJYRk//
 |  | ||||||
| CZrJVD1CaBZDiIyQsNEzjta7r4UsqWdFOggiNN2E7ZTFQjMSaFkVgrzHqWuiaCBf |  | ||||||
| /BjbKPn4SMDmTzHvIe7Nel76hBdCaVgu6mYCW5jmuSH5qz/yR1U1J/WJAgMBAAEC |  | ||||||
| gYARWGWsSU3BYgbu5lNj5l0gKMXNmPhdAJYdbMTF0/KUu18k/XB7XSBgsre+vALt |  | ||||||
| I8r4RGKApoGif8P4aPYUyE8dqA1bh0X3Fj1TCz28qoUL5//dA+pigCRS20H7HM3C
 |  | ||||||
| ojoqF7+F+4F2sXmzFNd1NgY5RxFPYosTT7OnUiFuu2IisQJBALnMLe09LBnjuHXR |  | ||||||
| xxR65DDNxWPQLBjW3dL+ubLcwr7922l6ZIQsVjdeE0ItEUVRjjJ9/B/Jq9VJ/Lw4 |  | ||||||
| g9LCkkMCQQCiaM2f7nYmGivPo9hlAbq5lcGJ5CCYFfeeYzTxMqum7Mbqe4kk5lgb |  | ||||||
| X6gWd0Izg2nGdAEe/97DClO6VpKcPbpDAkBTR/JOJN1fvXMxXJaf13XxakrQMr+R |  | ||||||
| Yr6LlSInykyAz8lJvlLP7A+5QbHgN9NF/wh+GXqpxPwA3ukqdSqhjhWBAkBn6mDv |  | ||||||
| HPgR5xrzL6XM8y9TgaOlJAdK6HtYp6d/UOmN0+Butf6JUq07TphRT5tXNJVgemch |  | ||||||
| O5x/9UKfbrc+KyzbAkAo97TfFC+mZhU1N5fFelaRu4ikPxlp642KRUSkOh8GEkNf |  | ||||||
| jQ97eJWiWtDcsMUhcZgoB5ydHcFlrBIn6oBcpge5 |  | ||||||
| -----END RSA PRIVATE KEY-----`, |  | ||||||
| 	} |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{AppCreds: appAuth}, "other"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	// Repeat last to verify GitHub App keys are mapped together
 |  | ||||||
| 	if _, err := multiClient.GetClientFor(ctx, fmt.Sprintf("%v/github/github", srv.URL), ActionsAuth{AppCreds: appAuth}, "other"); err != nil { |  | ||||||
| 		t.Fatal(err) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if len(multiClient.clients) != want { |  | ||||||
| 		t.Fatalf("GetClientFor: unexpected number of clients: got=%v want=%v", len(multiClient.clients), want) |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestCreateJWT(t *testing.T) { | func TestCreateJWT(t *testing.T) { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue