Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| efa922e8dd | |||
| ff25a89ba7 | |||
| 2f9b84ee5a | |||
| 63a0a32683 | |||
| e4a017ce06 |
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 GitHub
|
||||
Copyright GitHub, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GitHub Actions Runner Scale Set Client (Private Preview)
|
||||
# GitHub Actions Runner Scale Set Client (Public Preview)
|
||||
|
||||
> Status: **Private Preview** – While the API is stable, interfaces and examples in this repository may change.
|
||||
> Status: **Public Preview** – While the API is stable, interfaces and examples in this repository may change.
|
||||
|
||||
This repository provides a standalone Go client for the GitHub Actions **Runner Scale Set** APIs. It is extracted from the `actions-runner-controller` project so that platform teams, integrators, and infrastructure providers can build **their own custom autoscaling solutions** for GitHub Actions runners.
|
||||
|
||||
@@ -12,7 +12,7 @@ You do *not* need to adopt the full controller (and Kubernetes) to take advantag
|
||||
|
||||
A runner scale set is a group of self-hosted runners that autoscales based on workflow demand. Here's how it works:
|
||||
|
||||
1. **Registration**: You create a scale set with a name, which also serves as the label workflows use to target it (e.g., `runs-on: my-scale-set`). Like regular self-hosted runners, scale sets can be registered at the repository, organization, or enterprise level.
|
||||
1. **Registration**: You create a scale set with a name, which also serves as the label workflows use to target it (e.g., `runs-on: my-scale-set`). Multiple labels can be assigned per scale set. Like regular self-hosted runners, scale sets can be registered at the repository, organization, or enterprise level.
|
||||
2. **Polling**: Your scale set client continuously polls the API, reporting its maximum capacity (how many runners it can produce).
|
||||
3. **Job matching**: GitHub matches jobs to your scale set based on the label and runner group policies, just like regular self-hosted runners.
|
||||
4. **Scaling signal**: The API responds with how many runners your scale set needs online (`statistics.TotalAssignedJobs`).
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"maps"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -127,9 +126,9 @@ type ProxyFunc func(req *http.Request) (*url.URL, error)
|
||||
type SystemInfo struct {
|
||||
// System is the name of the scale set implementation
|
||||
System string `json:"system"`
|
||||
// Version is the version of the controller
|
||||
// Version is the version of the client
|
||||
Version string `json:"version"`
|
||||
// CommitSHA is the git commit SHA of the controller
|
||||
// CommitSHA is the git commit SHA of the client
|
||||
CommitSHA string `json:"commit_sha"`
|
||||
// ScaleSetID is the ID of the scale set
|
||||
ScaleSetID int `json:"scale_set_id"`
|
||||
@@ -223,6 +222,7 @@ type userAgent struct {
|
||||
SystemInfo
|
||||
BuildVersion string `json:"build_version"`
|
||||
BuildCommitSHA string `json:"build_commit_sha"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
|
||||
func (c *Client) newGitHubAPIRequest(ctx context.Context, method, path string, body io.Reader) (*http.Request, error) {
|
||||
@@ -836,8 +836,6 @@ func (c *Client) getActionsServiceAdminConnection(ctx context.Context, rt *regis
|
||||
return nil, fmt.Errorf("failed to get actions service admin connection: %w", err)
|
||||
}
|
||||
|
||||
slog.Info("got admin connection", *adminConnection.ActionsServiceURL)
|
||||
|
||||
return adminConnection, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -137,6 +137,7 @@ func (c *commonClient) setUserAgent() {
|
||||
SystemInfo: c.systemInfo,
|
||||
BuildVersion: buildInfo.version,
|
||||
BuildCommitSHA: buildInfo.commitSHA,
|
||||
Kind: "scaleset",
|
||||
})
|
||||
c.userAgent = string(b)
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ func TestUserAgent(t *testing.T) {
|
||||
SystemInfo: testSystemInfo,
|
||||
BuildCommitSHA: sha,
|
||||
BuildVersion: version,
|
||||
Kind: "scaleset",
|
||||
}
|
||||
b, err := json.Marshal(wantInfo)
|
||||
require.NoError(t, err, "failed to marshal expected user agent")
|
||||
@@ -144,6 +145,7 @@ func TestUserAgent(t *testing.T) {
|
||||
SystemInfo: userAgentInfo,
|
||||
BuildCommitSHA: sha,
|
||||
BuildVersion: version,
|
||||
Kind: "scaleset",
|
||||
}
|
||||
b, err = json.Marshal(wantInfo)
|
||||
require.NoError(t, err, "failed to marshal expected user agent after SetSystemInfo")
|
||||
|
||||
@@ -74,40 +74,35 @@ func run(ctx context.Context, c Config) error {
|
||||
runnerGroupID = runnerGroup.ID
|
||||
}
|
||||
|
||||
slog.Info("creating scale set")
|
||||
|
||||
// Create the runner scale set
|
||||
scaleSet, err := scalesetClient.CreateRunnerScaleSet(ctx, &scaleset.RunnerScaleSet{
|
||||
Name: c.ScaleSetName,
|
||||
RunnerGroupID: runnerGroupID,
|
||||
Labels: []scaleset.Label{},
|
||||
Labels: c.BuildLabels(),
|
||||
RunnerSetting: scaleset.RunnerSetting{
|
||||
DisableUpdate: true,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
slog.Error("failed to create", err)
|
||||
return fmt.Errorf("failed to create runner scale set: %w", err)
|
||||
}
|
||||
|
||||
slog.Info("created")
|
||||
|
||||
// Set the user agent for the scaleset client now that we have the scale set ID
|
||||
scalesetClient.SetSystemInfo(systemInfo(scaleSet.ID))
|
||||
|
||||
// defer func() {
|
||||
// logger.Info(
|
||||
// "Deleting runner scale set",
|
||||
// slog.Int("scaleSetID", scaleSet.ID),
|
||||
// )
|
||||
// if err := scalesetClient.DeleteRunnerScaleSet(context.WithoutCancel(ctx), scaleSet.ID); err != nil {
|
||||
// slog.Error(
|
||||
// "Failed to delete runner scale set",
|
||||
// slog.Int("scaleSetID", scaleSet.ID),
|
||||
// slog.String("error", err.Error()),
|
||||
// )
|
||||
// }
|
||||
// }()
|
||||
defer func() {
|
||||
logger.Info(
|
||||
"Deleting runner scale set",
|
||||
slog.Int("scaleSetID", scaleSet.ID),
|
||||
)
|
||||
if err := scalesetClient.DeleteRunnerScaleSet(context.WithoutCancel(ctx), scaleSet.ID); err != nil {
|
||||
slog.Error(
|
||||
"Failed to delete runner scale set",
|
||||
slog.Int("scaleSetID", scaleSet.ID),
|
||||
slog.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}()
|
||||
|
||||
dockerClient, err := dockerclient.NewClientWithOpts(dockerclient.FromEnv, dockerclient.WithAPIVersionNegotiation())
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user