Wire runner caches and forge secrets through agenix
Some checks failed
Build Rust / Cargo Test (push) Waiting to run
Build Site / Next.js Build (push) Waiting to run
Build Apple / Build App (iOS Simulator) (push) Failing after 14s
Build Apple / Build App (macOS) (push) Failing after 13s

This commit is contained in:
Conrad Kramer 2026-03-19 00:04:27 -07:00
parent afc3e79eb0
commit ed247b2f5e
20 changed files with 299 additions and 64 deletions

View file

@ -17,19 +17,29 @@ import (
)
type Options struct {
BinaryPath string
DefaultImage string
DefaultMachine string
DefaultDuration time.Duration
WorkDir string
MaxParallel int64
RunnerNamePrefix string
Executor string
Network string
ComputeBaseURL string
MacosBaseImageID string
MacosMachineArch string
Logger *slog.Logger
BinaryPath string
DefaultImage string
DefaultMachine string
DefaultDuration time.Duration
WorkDir string
MaxParallel int64
RunnerNamePrefix string
Executor string
Network string
ComputeBaseURL string
MacosBaseImageID string
MacosMachineArch string
LinuxCachePath string
LinuxCacheVolumes []CacheVolume
MacosCachePath string
MacosCacheVolumes []CacheVolume
Logger *slog.Logger
}
type CacheVolume struct {
Tag string
MountPoint string
SizeGb int64
}
type LaunchRequest struct {
@ -73,6 +83,12 @@ func NewDispatcher(opts Options) (*Dispatcher, error) {
if opts.DefaultDuration == 0 {
opts.DefaultDuration = 30 * time.Minute
}
if opts.LinuxCachePath == "" {
opts.LinuxCachePath = "/var/cache/burrow"
}
if opts.MacosCachePath == "" {
opts.MacosCachePath = "/Users/runner/.cache/burrow"
}
logger := opts.Logger
if logger == nil {
logger = slog.New(slog.NewTextHandler(io.Discard, nil))
@ -104,6 +120,9 @@ func (d *Dispatcher) LaunchRunner(ctx context.Context, req LaunchRequest) (strin
}
machineType := choose(req.MachineType, d.opts.DefaultMachine)
image := choose(req.Image, d.opts.DefaultImage)
if req.ExtraEnv == nil {
req.ExtraEnv = make(map[string]string)
}
if hasWindowsLabel(req.Labels) {
if err := d.launchWindowsRunnerViaWinRM(ctx, runnerName, req, duration, machineType); err != nil {
@ -113,6 +132,9 @@ func (d *Dispatcher) LaunchRunner(ctx context.Context, req LaunchRequest) (strin
}
if hasMacOSLabel(req.Labels) {
if _, ok := req.ExtraEnv["NSC_CACHE_PATH"]; !ok {
req.ExtraEnv["NSC_CACHE_PATH"] = d.opts.MacosCachePath
}
// Compute macOS shapes differ from the Linux "run" defaults. If the request
// didn't specify a machine type, ensure we pick a macOS-valid default.
if machineType == "" || machineType == d.opts.DefaultMachine {
@ -129,6 +151,9 @@ func (d *Dispatcher) LaunchRunner(ctx context.Context, req LaunchRequest) (strin
}
return runnerName, nil
}
if _, ok := req.ExtraEnv["NSC_CACHE_PATH"]; !ok {
req.ExtraEnv["NSC_CACHE_PATH"] = d.opts.LinuxCachePath
}
env := map[string]string{
"FORGEJO_INSTANCE_URL": req.InstanceURL,
@ -140,9 +165,6 @@ func (d *Dispatcher) LaunchRunner(ctx context.Context, req LaunchRequest) (strin
for k, v := range req.ExtraEnv {
env[k] = v
}
if _, ok := env["NSC_CACHE_PATH"]; !ok {
env["NSC_CACHE_PATH"] = "/nix/store"
}
script := d.bootstrapScript()
args := []string{
@ -161,6 +183,7 @@ func (d *Dispatcher) LaunchRunner(ctx context.Context, req LaunchRequest) (strin
if d.opts.Network != "" {
args = append(args, "--network", d.opts.Network)
}
args = appendVolumeArgs(args, d.opts.LinuxCacheVolumes)
for key, value := range env {
if value == "" {
continue
@ -370,6 +393,16 @@ func choose(values ...string) string {
return ""
}
func appendVolumeArgs(args []string, volumes []CacheVolume) []string {
for _, volume := range volumes {
if strings.TrimSpace(volume.Tag) == "" || strings.TrimSpace(volume.MountPoint) == "" || volume.SizeGb <= 0 {
continue
}
args = append(args, "--volume", fmt.Sprintf("cache:%s:%s:%d", volume.Tag, volume.MountPoint, volume.SizeGb))
}
return args
}
func (d *Dispatcher) bootstrapScript() string {
var builder strings.Builder
builder.WriteString(`set -euo pipefail

View file

@ -206,12 +206,8 @@ func (d *Dispatcher) launchMacOSRunner(ctx context.Context, runnerName string, r
for k, v := range req.ExtraEnv {
env[k] = v
}
// Best-effort caching: workflows call Scripts/nscloud-cache.sh, which is a
// no-op unless NSC_CACHE_PATH is set. This may still be skipped if spacectl
// lacks credentials, but setting the path is harmless and keeps behavior
// consistent across macOS / Linux runners.
if _, ok := env["NSC_CACHE_PATH"]; !ok {
env["NSC_CACHE_PATH"] = "/Users/runner/.cache/nscloud"
env["NSC_CACHE_PATH"] = d.opts.MacosCachePath
}
deadline := timestamppb.New(time.Now().Add(ttl))
@ -243,10 +239,15 @@ func (d *Dispatcher) launchMacOSRunner(ctx context.Context, runnerName string, r
},
},
}
experimental := &computev1beta.CreateInstanceRequest_ExperimentalFeatures{}
if imageID := macosComputeBaseImageID(d.opts.MacosBaseImageID); imageID != "" {
createReq.Experimental = &computev1beta.CreateInstanceRequest_ExperimentalFeatures{
MacosBaseImageId: imageID,
}
experimental.MacosBaseImageId = imageID
}
if volumes := computeCacheVolumeRequests(d.opts.MacosCacheVolumes); len(volumes) > 0 {
experimental.Volumes = volumes
}
if experimental.MacosBaseImageId != "" || len(experimental.Volumes) > 0 {
createReq.Experimental = experimental
}
d.log.Info("launching Namespace macos runner",
@ -572,6 +573,22 @@ func (d *Dispatcher) destroyComputeInstance(ctx context.Context, client computev
d.log.Info("macos runner destroyed", "runner", runnerName, "instance", instanceID)
}
func computeCacheVolumeRequests(volumes []CacheVolume) []*computev1beta.VolumeRequest {
var out []*computev1beta.VolumeRequest
for _, volume := range volumes {
if strings.TrimSpace(volume.Tag) == "" || strings.TrimSpace(volume.MountPoint) == "" || volume.SizeGb <= 0 {
continue
}
out = append(out, &computev1beta.VolumeRequest{
MountPoint: volume.MountPoint,
Tag: volume.Tag,
SizeMb: volume.SizeGb * 1024,
PersistencyKind: computev1beta.VolumeRequest_CACHE,
})
}
return out
}
func macosBootstrapScript() string {
// Keep this script self-contained: it runs on a fresh macOS VM base image.
var b strings.Builder

View file

@ -144,6 +144,7 @@ func (d *Dispatcher) launchMacOSRunnerViaNSC(ctx context.Context, runnerName str
"--wait_timeout", a.waitTimeout.String(),
}
args = prependNSCRegionArgs(args, d.opts.ComputeBaseURL)
args = appendVolumeArgs(args, d.opts.MacosCacheVolumes)
createCtx, cancel := context.WithTimeout(ctx, a.createTimeout)
defer cancel()