Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
with:
distribution: goreleaser
version: "~> v2"
args: release --clean
args: release --clean ${{ github.event_name == 'pull_request' && '--snapshot' || '' }}
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
HOMEBREW_GITHUB_API_TOKEN: ${{ secrets.GH_TOKEN }}
Expand Down
Empty file added .jules/bolt.md
Empty file.
29 changes: 26 additions & 3 deletions internal/run/api/domainmapping/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package domainmapping
import (
"context"
"fmt"
"sync"

"github.com/JulienBreux/run-cli/internal/run/api/client"
"golang.org/x/oauth2/google"
Expand Down Expand Up @@ -59,10 +60,21 @@ type Client interface {
}

// GCPClient is the Google Cloud Platform implementation of the Client interface.
type GCPClient struct{}
type GCPClient struct {
mu sync.Mutex
cachedClient DomainMappingsClientWrapper // Optimization: Cache client to reuse gRPC connections
}

// getOrCreateClient returns a cached client or creates a new one if it doesn't exist.
// This reduces latency by avoiding repeated authentication and connection overhead.
func (c *GCPClient) getOrCreateClient(ctx context.Context) (DomainMappingsClientWrapper, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.cachedClient != nil {
return c.cachedClient, nil
}

// ListDomainMappings lists domain mappings for a given project and region.
func (c *GCPClient) ListDomainMappings(ctx context.Context, project, region string) ([]*run.DomainMapping, error) {
creds, err := client.FindDefaultCredentials(ctx, run.CloudPlatformScope)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
Expand All @@ -73,6 +85,17 @@ func (c *GCPClient) ListDomainMappings(ctx context.Context, project, region stri
return nil, fmt.Errorf("failed to create domain mappings client: %w", err)
}

c.cachedClient = dmClient
return c.cachedClient, nil
}

// ListDomainMappings lists domain mappings for a given project and region.
func (c *GCPClient) ListDomainMappings(ctx context.Context, project, region string) ([]*run.DomainMapping, error) {
dmClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}

parent := fmt.Sprintf("projects/%s/locations/%s", project, region)

var domainMappings []*run.DomainMapping
Expand Down
42 changes: 27 additions & 15 deletions internal/run/api/job/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package job
import (
"context"
"fmt"
"sync"

run "cloud.google.com/go/run/apiv2"
"cloud.google.com/go/run/apiv2/runpb"
Expand Down Expand Up @@ -98,10 +99,21 @@ type Client interface {
var _ Client = (*GCPClient)(nil)

// GCPClient is the Google Cloud Platform implementation of Client.
type GCPClient struct{}
type GCPClient struct {
mu sync.Mutex
cachedClient JobsClientWrapper // Optimization: Cache client to reuse gRPC connections
}

// getOrCreateClient returns a cached client or creates a new one if it doesn't exist.
// This reduces latency by avoiding repeated authentication and connection overhead.
func (c *GCPClient) getOrCreateClient(ctx context.Context) (JobsClientWrapper, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.cachedClient != nil {
return c.cachedClient, nil
}

// ListJobs lists jobs for a project and region.
func (c *GCPClient) ListJobs(ctx context.Context, project, region string) ([]*runpb.Job, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
Expand All @@ -111,9 +123,17 @@ func (c *GCPClient) ListJobs(ctx context.Context, project, region string) ([]*ru
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

c.cachedClient = cClient
return c.cachedClient, nil
}

// ListJobs lists jobs for a project and region.
func (c *GCPClient) ListJobs(ctx context.Context, project, region string) ([]*runpb.Job, error) {
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}

req := &runpb.ListJobsRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", project, region),
Expand All @@ -137,18 +157,10 @@ func (c *GCPClient) ListJobs(ctx context.Context, project, region string) ([]*ru

// RunJob runs a job.
func (c *GCPClient) RunJob(ctx context.Context, name string) (*runpb.Execution, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
}

cClient, err := createJobsClient(ctx, option.WithCredentials(creds))
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

op, err := cClient.RunJob(ctx, &runpb.RunJobRequest{Name: name})
if err != nil {
Expand Down
32 changes: 26 additions & 6 deletions internal/run/api/job/execution/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"context"
"fmt"
"strings"
"sync"

run "cloud.google.com/go/run/apiv2"
"cloud.google.com/go/run/apiv2/runpb"
Expand Down Expand Up @@ -99,10 +100,21 @@ type Client interface {
}

// GCPClient is the Google Cloud Platform implementation of Client.
type GCPClient struct{}
type GCPClient struct {
mu sync.Mutex
cachedClient ExecutionsClientWrapper // Optimization: Cache client to reuse gRPC connections
}

// getOrCreateClient returns a cached client or creates a new one if it doesn't exist.
// This reduces latency by avoiding repeated authentication and connection overhead.
func (c *GCPClient) getOrCreateClient(ctx context.Context) (ExecutionsClientWrapper, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.cachedClient != nil {
return c.cachedClient, nil
}

// ListExecutions lists executions for a project, region and job.
func (c *GCPClient) ListExecutions(ctx context.Context, project, region, jobName string) ([]*runpb.Execution, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
Expand All @@ -112,9 +124,17 @@ func (c *GCPClient) ListExecutions(ctx context.Context, project, region, jobName
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

c.cachedClient = cClient
return c.cachedClient, nil
}

// ListExecutions lists executions for a project, region and job.
func (c *GCPClient) ListExecutions(ctx context.Context, project, region, jobName string) ([]*runpb.Execution, error) {
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}

// Filter by job name
// The parent is the location. We filter by label or just iterate and filter?
Expand Down
52 changes: 28 additions & 24 deletions internal/run/api/service/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package service
import (
"context"
"fmt"
"sync"

run "cloud.google.com/go/run/apiv2"
"cloud.google.com/go/run/apiv2/runpb"
Expand Down Expand Up @@ -105,10 +106,21 @@ type Client interface {
var _ Client = (*GCPClient)(nil)

// GCPClient is the Google Cloud Platform implementation of Client.
type GCPClient struct{}
type GCPClient struct {
mu sync.Mutex
cachedClient ServicesClientWrapper // Optimization: Cache client to reuse gRPC connections
}

// getOrCreateClient returns a cached client or creates a new one if it doesn't exist.
// This reduces latency by avoiding repeated authentication and connection overhead.
func (c *GCPClient) getOrCreateClient(ctx context.Context) (ServicesClientWrapper, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.cachedClient != nil {
return c.cachedClient, nil
}

// ListServices lists services for a project and region.
func (c *GCPClient) ListServices(ctx context.Context, project, region string) ([]*runpb.Service, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
Expand All @@ -118,9 +130,17 @@ func (c *GCPClient) ListServices(ctx context.Context, project, region string) ([
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

c.cachedClient = cClient
return c.cachedClient, nil
}

// ListServices lists services for a project and region.
func (c *GCPClient) ListServices(ctx context.Context, project, region string) ([]*runpb.Service, error) {
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}

req := &runpb.ListServicesRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", project, region),
Expand All @@ -144,36 +164,20 @@ func (c *GCPClient) ListServices(ctx context.Context, project, region string) ([

// GetService gets a single service.
func (c *GCPClient) GetService(ctx context.Context, name string) (*runpb.Service, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
}

cClient, err := createServicesClient(ctx, option.WithCredentials(creds))
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

return cClient.GetService(ctx, &runpb.GetServiceRequest{Name: name})
}

// UpdateService updates a service.
func (c *GCPClient) UpdateService(ctx context.Context, service *runpb.Service) (*runpb.Service, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
}

cClient, err := createServicesClient(ctx, option.WithCredentials(creds))
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

op, err := cClient.UpdateService(ctx, &runpb.UpdateServiceRequest{Service: service})
if err != nil {
Expand Down
52 changes: 28 additions & 24 deletions internal/run/api/workerpool/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package workerpool
import (
"context"
"fmt"
"sync"

run "cloud.google.com/go/run/apiv2"
"cloud.google.com/go/run/apiv2/runpb"
Expand Down Expand Up @@ -104,10 +105,21 @@ type Client interface {
var _ Client = (*GCPClient)(nil)

// GCPClient is the Google Cloud Platform implementation of Client.
type GCPClient struct{}
type GCPClient struct {
mu sync.Mutex
cachedClient WorkerPoolsClientWrapper // Optimization: Cache client to reuse gRPC connections
}

// getOrCreateClient returns a cached client or creates a new one if it doesn't exist.
// This reduces latency by avoiding repeated authentication and connection overhead.
func (c *GCPClient) getOrCreateClient(ctx context.Context) (WorkerPoolsClientWrapper, error) {
c.mu.Lock()
defer c.mu.Unlock()

if c.cachedClient != nil {
return c.cachedClient, nil
}

// ListWorkerPools lists worker pools for a project and region.
func (c *GCPClient) ListWorkerPools(ctx context.Context, project, region string) ([]*runpb.WorkerPool, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
Expand All @@ -117,9 +129,17 @@ func (c *GCPClient) ListWorkerPools(ctx context.Context, project, region string)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

c.cachedClient = cClient
return c.cachedClient, nil
}

// ListWorkerPools lists worker pools for a project and region.
func (c *GCPClient) ListWorkerPools(ctx context.Context, project, region string) ([]*runpb.WorkerPool, error) {
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}

req := &runpb.ListWorkerPoolsRequest{
Parent: fmt.Sprintf("projects/%s/locations/%s", project, region),
Expand All @@ -143,36 +163,20 @@ func (c *GCPClient) ListWorkerPools(ctx context.Context, project, region string)

// GetWorkerPool gets a worker pool.
func (c *GCPClient) GetWorkerPool(ctx context.Context, name string) (*runpb.WorkerPool, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
}

cClient, err := createWorkerPoolsClient(ctx, option.WithCredentials(creds))
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

return cClient.GetWorkerPool(ctx, &runpb.GetWorkerPoolRequest{Name: name})
}

// UpdateWorkerPool updates a worker pool.
func (c *GCPClient) UpdateWorkerPool(ctx context.Context, workerPool *runpb.WorkerPool) (*runpb.WorkerPool, error) {
creds, err := client.FindDefaultCredentials(ctx, run.DefaultAuthScopes()...)
if err != nil {
return nil, fmt.Errorf("failed to find default credentials: %w", err)
}

cClient, err := createWorkerPoolsClient(ctx, option.WithCredentials(creds))
cClient, err := c.getOrCreateClient(ctx)
if err != nil {
return nil, err
}
defer func() {
_ = cClient.Close()
}()

op, err := cClient.UpdateWorkerPool(ctx, &runpb.UpdateWorkerPoolRequest{WorkerPool: workerPool})
if err != nil {
Expand Down
Loading