Merge branch 'master' into bugfix-issue-3728
This commit is contained in:
commit
143bf089c4
|
|
@ -9,3 +9,15 @@ updates:
|
|||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
gomod:
|
||||
patterns:
|
||||
- "*"
|
||||
- package-ecosystem: github-actions
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
groups:
|
||||
actions:
|
||||
patterns:
|
||||
- "*"
|
||||
|
|
|
|||
|
|
@ -123,3 +123,17 @@ jobs:
|
|||
if: steps.list-changed.outputs.changed == 'true'
|
||||
run: |
|
||||
ct install --config charts/.ci/ct-config-gha.yaml
|
||||
test-chart:
|
||||
name: Test Chart
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
cache: false
|
||||
- name: Test gha-runner-scale-set
|
||||
run: go test ./charts/gha-runner-scale-set/...
|
||||
- name: Test gha-runner-scale-set-controller
|
||||
run: go test ./charts/gha-runner-scale-set-controller/...
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -6,7 +6,7 @@ endif
|
|||
DOCKER_USER ?= $(shell echo ${DOCKER_IMAGE_NAME} | cut -d / -f1)
|
||||
VERSION ?= dev
|
||||
COMMIT_SHA = $(shell git rev-parse HEAD)
|
||||
RUNNER_VERSION ?= 2.321.0
|
||||
RUNNER_VERSION ?= 2.322.0
|
||||
TARGETPLATFORM ?= $(shell arch)
|
||||
RUNNER_NAME ?= ${DOCKER_USER}/actions-runner
|
||||
RUNNER_TAG ?= ${VERSION}
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ func TestTemplate_ControllerDeployment_Defaults(t *testing.T) {
|
|||
"--metrics-addr=0",
|
||||
"--listener-metrics-addr=0",
|
||||
"--listener-metrics-endpoint=",
|
||||
"--runner-max-concurrent-reconciles=2",
|
||||
}
|
||||
assert.ElementsMatch(t, expectedArgs, deployment.Spec.Template.Spec.Containers[0].Args)
|
||||
|
||||
|
|
@ -518,6 +519,7 @@ func TestTemplate_ControllerDeployment_Customize(t *testing.T) {
|
|||
"--listener-metrics-addr=0",
|
||||
"--listener-metrics-endpoint=",
|
||||
"--metrics-addr=0",
|
||||
"--runner-max-concurrent-reconciles=2",
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, expectArgs, deployment.Spec.Template.Spec.Containers[0].Args)
|
||||
|
|
@ -646,6 +648,7 @@ func TestTemplate_EnableLeaderElection(t *testing.T) {
|
|||
"--listener-metrics-addr=0",
|
||||
"--listener-metrics-endpoint=",
|
||||
"--metrics-addr=0",
|
||||
"--runner-max-concurrent-reconciles=2",
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, expectedArgs, deployment.Spec.Template.Spec.Containers[0].Args)
|
||||
|
|
@ -686,6 +689,7 @@ func TestTemplate_ControllerDeployment_ForwardImagePullSecrets(t *testing.T) {
|
|||
"--listener-metrics-addr=0",
|
||||
"--listener-metrics-endpoint=",
|
||||
"--metrics-addr=0",
|
||||
"--runner-max-concurrent-reconciles=2",
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, expectedArgs, deployment.Spec.Template.Spec.Containers[0].Args)
|
||||
|
|
@ -776,6 +780,7 @@ func TestTemplate_ControllerDeployment_WatchSingleNamespace(t *testing.T) {
|
|||
"--listener-metrics-addr=0",
|
||||
"--listener-metrics-endpoint=",
|
||||
"--metrics-addr=0",
|
||||
"--runner-max-concurrent-reconciles=2",
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, expectedArgs, deployment.Spec.Template.Spec.Containers[0].Args)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ app.kubernetes.io/instance: {{ include "gha-runner-scale-set.scale-set-name" . }
|
|||
{{- if eq $val.name "runner" }}
|
||||
image: {{ $val.image }}
|
||||
command: ["cp"]
|
||||
args: ["-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||
args: ["-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||
volumeMounts:
|
||||
- name: dind-externals
|
||||
mountPath: /home/runner/tmpDir
|
||||
|
|
@ -218,7 +218,7 @@ env:
|
|||
{{- if eq $env.name "RUNNER_UPDATE_CA_CERTS" }}
|
||||
{{- $setRunnerUpdateCaCerts = 0 }}
|
||||
{{- end }}
|
||||
- {{ $env | toYaml | nindent 4 }}
|
||||
- {{ $env | toYaml | nindent 4 | trim }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $setDockerHost }}
|
||||
|
|
|
|||
|
|
@ -893,7 +893,7 @@ func TestTemplateRenderedAutoScalingRunnerSet_EnableDinD(t *testing.T) {
|
|||
assert.Equal(t, "init-dind-externals", ars.Spec.Template.Spec.InitContainers[0].Name)
|
||||
assert.Equal(t, "ghcr.io/actions/actions-runner:latest", ars.Spec.Template.Spec.InitContainers[0].Image)
|
||||
assert.Equal(t, "cp", ars.Spec.Template.Spec.InitContainers[0].Command[0])
|
||||
assert.Equal(t, "-r -v /home/runner/externals/. /home/runner/tmpDir/", strings.Join(ars.Spec.Template.Spec.InitContainers[0].Args, " "))
|
||||
assert.Equal(t, "-r /home/runner/externals/. /home/runner/tmpDir/", strings.Join(ars.Spec.Template.Spec.InitContainers[0].Args, " "))
|
||||
|
||||
assert.Len(t, ars.Spec.Template.Spec.Containers, 2, "Template.Spec should have 2 container")
|
||||
assert.Equal(t, "runner", ars.Spec.Template.Spec.Containers[0].Name)
|
||||
|
|
|
|||
|
|
@ -2,25 +2,40 @@
|
|||
## ex: https://github.com/myorg/myrepo or https://github.com/myorg
|
||||
githubConfigUrl: ""
|
||||
|
||||
## githubConfigSecret is the k8s secrets to use when auth with GitHub API.
|
||||
## You can choose to use GitHub App or a PAT token
|
||||
## githubConfigSecret is the k8s secret information to use when authenticating via the GitHub API.
|
||||
## You can choose to supply:
|
||||
## A) a PAT token,
|
||||
## B) a GitHub App, or
|
||||
## C) a pre-defined Kubernetes secret.
|
||||
## The syntax for each of these variations is documented below.
|
||||
## (Variation A) When using a PAT token, the syntax is as follows:
|
||||
githubConfigSecret:
|
||||
### GitHub Apps Configuration
|
||||
## NOTE: IDs MUST be strings, use quotes
|
||||
#github_app_id: ""
|
||||
#github_app_installation_id: ""
|
||||
#github_app_private_key: |
|
||||
|
||||
### GitHub PAT Configuration
|
||||
github_token: ""
|
||||
## If you have a pre-define Kubernetes secret in the same namespace the gha-runner-scale-set is going to deploy,
|
||||
## you can also reference it via `githubConfigSecret: pre-defined-secret`.
|
||||
## You need to make sure your predefined secret has all the required secret data set properly.
|
||||
# Example:
|
||||
# github_token: "ghp_sampleSampleSampleSampleSampleSample"
|
||||
github_token: ""
|
||||
#
|
||||
## (Variation B) When using a GitHub App, the syntax is as follows:
|
||||
# githubConfigSecret:
|
||||
# # NOTE: IDs MUST be strings, use quotes
|
||||
# github_app_id: ""
|
||||
# github_app_installation_id: ""
|
||||
# github_app_private_key: |
|
||||
# private key line 1
|
||||
# private key line 2
|
||||
# .
|
||||
# .
|
||||
# .
|
||||
# private key line N
|
||||
#
|
||||
## (Variation C) When using a pre-defined Kubernetes secret in the same namespace that the gha-runner-scale-set is going to deploy,
|
||||
## the syntax is as follows:
|
||||
# githubConfigSecret: pre-defined-secret
|
||||
## Notes on using pre-defined Kubernetes secrets:
|
||||
## You need to make sure your predefined secret has all the required secret data set properly.
|
||||
## For a pre-defined secret using GitHub PAT, the secret needs to be created like this:
|
||||
## > kubectl create secret generic pre-defined-secret --namespace=my_namespace --from-literal=github_token='ghp_your_pat'
|
||||
## For a pre-defined secret using GitHub App, the secret needs to be created like this:
|
||||
## > kubectl create secret generic pre-defined-secret --namespace=my_namespace --from-literal=github_app_id=123456 --from-literal=github_app_installation_id=654321 --from-literal=github_app_private_key='-----BEGIN CERTIFICATE-----*******'
|
||||
# githubConfigSecret: pre-defined-secret
|
||||
|
||||
## proxy can be used to define proxy settings that will be used by the
|
||||
## controller, the listener and the runner of this scale set.
|
||||
|
|
@ -115,7 +130,7 @@ template:
|
|||
## initContainers:
|
||||
## - name: init-dind-externals
|
||||
## image: ghcr.io/actions/actions-runner:latest
|
||||
## command: ["cp", "-r", "-v", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||
## command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
|
||||
## volumeMounts:
|
||||
## - name: dind-externals
|
||||
## mountPath: /home/runner/tmpDir
|
||||
|
|
|
|||
|
|
@ -46,14 +46,15 @@ func Read(path string) (Config, error) {
|
|||
return Config{}, fmt.Errorf("failed to decode config: %w", err)
|
||||
}
|
||||
|
||||
if err := config.validate(); err != nil {
|
||||
if err := config.Validate(); err != nil {
|
||||
return Config{}, fmt.Errorf("failed to validate config: %w", err)
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
func (c *Config) validate() error {
|
||||
// Validate checks the configuration for errors.
|
||||
func (c *Config) Validate() error {
|
||||
if len(c.ConfigureUrl) == 0 {
|
||||
return fmt.Errorf("GitHubConfigUrl is not provided")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func TestConfigValidationMinMax(t *testing.T) {
|
|||
MaxRunners: 2,
|
||||
Token: "token",
|
||||
}
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
assert.ErrorContains(t, err, "MinRunners '5' cannot be greater than MaxRunners '2", "Expected error about MinRunners > MaxRunners")
|
||||
}
|
||||
|
||||
|
|
@ -28,7 +28,7 @@ func TestConfigValidationMissingToken(t *testing.T) {
|
|||
EphemeralRunnerSetName: "deployment",
|
||||
RunnerScaleSetId: 1,
|
||||
}
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
expectedError := fmt.Sprintf("GitHub auth credential is missing, token length: '%d', appId: '%d', installationId: '%d', private key length: '%d", len(config.Token), config.AppID, config.AppInstallationID, len(config.AppPrivateKey))
|
||||
assert.ErrorContains(t, err, expectedError, "Expected error about missing auth")
|
||||
}
|
||||
|
|
@ -42,7 +42,7 @@ func TestConfigValidationAppKey(t *testing.T) {
|
|||
EphemeralRunnerSetName: "deployment",
|
||||
RunnerScaleSetId: 1,
|
||||
}
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
expectedError := fmt.Sprintf("GitHub auth credential is missing, token length: '%d', appId: '%d', installationId: '%d', private key length: '%d", len(config.Token), config.AppID, config.AppInstallationID, len(config.AppPrivateKey))
|
||||
assert.ErrorContains(t, err, expectedError, "Expected error about missing auth")
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ func TestConfigValidationOnlyOneTypeOfCredentials(t *testing.T) {
|
|||
EphemeralRunnerSetName: "deployment",
|
||||
RunnerScaleSetId: 1,
|
||||
}
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
expectedError := fmt.Sprintf("only one GitHub auth method supported at a time. Have both PAT and App auth: token length: '%d', appId: '%d', installationId: '%d', private key length: '%d", len(config.Token), config.AppID, config.AppInstallationID, len(config.AppPrivateKey))
|
||||
assert.ErrorContains(t, err, expectedError, "Expected error about missing auth")
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ func TestConfigValidation(t *testing.T) {
|
|||
Token: "asdf",
|
||||
}
|
||||
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
|
||||
assert.NoError(t, err, "Expected no error")
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ func TestConfigValidationConfigUrl(t *testing.T) {
|
|||
RunnerScaleSetId: 1,
|
||||
}
|
||||
|
||||
err := config.validate()
|
||||
err := config.Validate()
|
||||
|
||||
assert.ErrorContains(t, err, "GitHubConfigUrl is not provided", "Expected error about missing ConfigureUrl")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package metrics
|
|||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/actions/actions-runner-controller/github/actions"
|
||||
|
|
@ -19,11 +18,8 @@ const (
|
|||
labelKeyOrganization = "organization"
|
||||
labelKeyRepository = "repository"
|
||||
labelKeyJobName = "job_name"
|
||||
labelKeyJobWorkflowRef = "job_workflow_ref"
|
||||
labelKeyEventName = "event_name"
|
||||
labelKeyJobResult = "job_result"
|
||||
labelKeyRunnerID = "runner_id"
|
||||
labelKeyRunnerName = "runner_name"
|
||||
)
|
||||
|
||||
const githubScaleSetSubsystem = "gha"
|
||||
|
|
@ -43,14 +39,13 @@ var (
|
|||
labelKeyOrganization,
|
||||
labelKeyEnterprise,
|
||||
labelKeyJobName,
|
||||
labelKeyJobWorkflowRef,
|
||||
labelKeyEventName,
|
||||
}
|
||||
|
||||
completedJobsTotalLabels = append(jobLabels, labelKeyJobResult, labelKeyRunnerID, labelKeyRunnerName)
|
||||
jobExecutionDurationLabels = append(jobLabels, labelKeyJobResult, labelKeyRunnerID, labelKeyRunnerName)
|
||||
startedJobsTotalLabels = append(jobLabels, labelKeyRunnerID, labelKeyRunnerName)
|
||||
jobStartupDurationLabels = append(jobLabels, labelKeyRunnerID, labelKeyRunnerName)
|
||||
completedJobsTotalLabels = append(jobLabels, labelKeyJobResult)
|
||||
jobExecutionDurationLabels = append(jobLabels, labelKeyJobResult)
|
||||
startedJobsTotalLabels = jobLabels
|
||||
jobStartupDurationLabels = jobLabels
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -223,12 +218,11 @@ type baseLabels struct {
|
|||
|
||||
func (b *baseLabels) jobLabels(jobBase *actions.JobMessageBase) prometheus.Labels {
|
||||
return prometheus.Labels{
|
||||
labelKeyEnterprise: b.enterprise,
|
||||
labelKeyOrganization: jobBase.OwnerName,
|
||||
labelKeyRepository: jobBase.RepositoryName,
|
||||
labelKeyJobName: jobBase.JobDisplayName,
|
||||
labelKeyJobWorkflowRef: jobBase.JobWorkflowRef,
|
||||
labelKeyEventName: jobBase.EventName,
|
||||
labelKeyEnterprise: b.enterprise,
|
||||
labelKeyOrganization: jobBase.OwnerName,
|
||||
labelKeyRepository: jobBase.RepositoryName,
|
||||
labelKeyJobName: jobBase.JobDisplayName,
|
||||
labelKeyEventName: jobBase.EventName,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,16 +238,12 @@ func (b *baseLabels) scaleSetLabels() prometheus.Labels {
|
|||
|
||||
func (b *baseLabels) completedJobLabels(msg *actions.JobCompleted) prometheus.Labels {
|
||||
l := b.jobLabels(&msg.JobMessageBase)
|
||||
l[labelKeyRunnerID] = strconv.Itoa(msg.RunnerId)
|
||||
l[labelKeyJobResult] = msg.Result
|
||||
l[labelKeyRunnerName] = msg.RunnerName
|
||||
return l
|
||||
}
|
||||
|
||||
func (b *baseLabels) startedJobLabels(msg *actions.JobStarted) prometheus.Labels {
|
||||
l := b.jobLabels(&msg.JobMessageBase)
|
||||
l[labelKeyRunnerID] = strconv.Itoa(msg.RunnerId)
|
||||
l[labelKeyRunnerName] = msg.RunnerName
|
||||
return l
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -154,15 +154,15 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
|
|||
if autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion] != build.Version {
|
||||
if err := r.Delete(ctx, autoscalingRunnerSet); err != nil {
|
||||
log.Error(err, "Failed to delete autoscaling runner set on version mismatch",
|
||||
"targetVersion", build.Version,
|
||||
"actualVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||
"buildVersion", build.Version,
|
||||
"autoscalingRunnerSetVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||
)
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
log.Info("Autoscaling runner set version doesn't match the build version. Deleting the resource.",
|
||||
"targetVersion", build.Version,
|
||||
"actualVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||
"buildVersion", build.Version,
|
||||
"autoscalingRunnerSetVersion", autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
|
||||
)
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -712,22 +712,41 @@ func (r *EphemeralRunnerReconciler) updateRunStatusFromPod(ctx context.Context,
|
|||
if pod.Status.Phase == corev1.PodSucceeded || pod.Status.Phase == corev1.PodFailed {
|
||||
return nil
|
||||
}
|
||||
if ephemeralRunner.Status.Phase == pod.Status.Phase {
|
||||
|
||||
var ready bool
|
||||
var lastTransitionTime time.Time
|
||||
for _, condition := range pod.Status.Conditions {
|
||||
if condition.Type == corev1.PodReady && condition.LastTransitionTime.After(lastTransitionTime) {
|
||||
ready = condition.Status == corev1.ConditionTrue
|
||||
lastTransitionTime = condition.LastTransitionTime.Time
|
||||
}
|
||||
}
|
||||
|
||||
phaseChanged := ephemeralRunner.Status.Phase != pod.Status.Phase
|
||||
readyChanged := ready != ephemeralRunner.Status.Ready
|
||||
|
||||
if !phaseChanged && !readyChanged {
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Info("Updating ephemeral runner status with pod phase", "statusPhase", pod.Status.Phase, "statusReason", pod.Status.Reason, "statusMessage", pod.Status.Message)
|
||||
log.Info(
|
||||
"Updating ephemeral runner status",
|
||||
"statusPhase", pod.Status.Phase,
|
||||
"statusReason", pod.Status.Reason,
|
||||
"statusMessage", pod.Status.Message,
|
||||
"ready", ready,
|
||||
)
|
||||
err := patchSubResource(ctx, r.Status(), ephemeralRunner, func(obj *v1alpha1.EphemeralRunner) {
|
||||
obj.Status.Phase = pod.Status.Phase
|
||||
obj.Status.Ready = obj.Status.Ready || (pod.Status.Phase == corev1.PodRunning)
|
||||
obj.Status.Ready = ready
|
||||
obj.Status.Reason = pod.Status.Reason
|
||||
obj.Status.Message = pod.Status.Message
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update runner status for Phase/Reason/Message: %v", err)
|
||||
return fmt.Errorf("failed to update runner status for Phase/Reason/Message/Ready: %v", err)
|
||||
}
|
||||
|
||||
log.Info("Updated ephemeral runner status with pod phase")
|
||||
log.Info("Updated ephemeral runner status")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -379,16 +379,21 @@ var _ = Describe("EphemeralRunner", func() {
|
|||
podCopy := pod.DeepCopy()
|
||||
pod.Status.Phase = phase
|
||||
// set container state to force status update
|
||||
pod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{
|
||||
Name: EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{},
|
||||
})
|
||||
pod.Status.ContainerStatuses = append(
|
||||
pod.Status.ContainerStatuses,
|
||||
corev1.ContainerStatus{
|
||||
Name: EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{},
|
||||
},
|
||||
)
|
||||
|
||||
err := k8sClient.Status().Patch(ctx, pod, client.MergeFrom(podCopy))
|
||||
Expect(err).To(BeNil(), "failed to patch pod status")
|
||||
|
||||
var updated *v1alpha1.EphemeralRunner
|
||||
Eventually(
|
||||
func() (corev1.PodPhase, error) {
|
||||
updated := new(v1alpha1.EphemeralRunner)
|
||||
updated = new(v1alpha1.EphemeralRunner)
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, updated)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
@ -401,6 +406,95 @@ var _ = Describe("EphemeralRunner", func() {
|
|||
}
|
||||
})
|
||||
|
||||
It("It should update ready based on the latest condition", func() {
|
||||
pod := new(corev1.Pod)
|
||||
Eventually(func() (bool, error) {
|
||||
if err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod); err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}).Should(BeEquivalentTo(true))
|
||||
|
||||
newPod := pod.DeepCopy()
|
||||
newPod.Status.Conditions = []corev1.PodCondition{
|
||||
{
|
||||
Type: corev1.PodScheduled,
|
||||
Status: corev1.ConditionTrue,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
},
|
||||
{
|
||||
Type: corev1.PodInitialized,
|
||||
Status: corev1.ConditionTrue,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
},
|
||||
{
|
||||
Type: corev1.ContainersReady,
|
||||
Status: corev1.ConditionTrue,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
},
|
||||
{
|
||||
Type: corev1.PodReady,
|
||||
Status: corev1.ConditionTrue,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
},
|
||||
}
|
||||
newPod.Status.ContainerStatuses = append(pod.Status.ContainerStatuses, corev1.ContainerStatus{
|
||||
Name: EphemeralRunnerContainerName,
|
||||
State: corev1.ContainerState{},
|
||||
})
|
||||
err := k8sClient.Status().Patch(ctx, newPod, client.MergeFrom(pod))
|
||||
Expect(err).To(BeNil(), "failed to patch pod status")
|
||||
|
||||
var er *v1alpha1.EphemeralRunner
|
||||
Eventually(
|
||||
func() (bool, error) {
|
||||
er = new(v1alpha1.EphemeralRunner)
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, er)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return er.Status.Ready, nil
|
||||
},
|
||||
ephemeralRunnerTimeout,
|
||||
ephemeralRunnerInterval,
|
||||
).Should(BeEquivalentTo(true))
|
||||
|
||||
// Fetch the pod again
|
||||
Eventually(
|
||||
func() (bool, error) {
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
},
|
||||
ephemeralRunnerTimeout,
|
||||
ephemeralRunnerInterval,
|
||||
).Should(BeEquivalentTo(true))
|
||||
|
||||
newPod = pod.DeepCopy()
|
||||
newPod.Status.Conditions = append(newPod.Status.Conditions, corev1.PodCondition{
|
||||
Type: corev1.PodReady,
|
||||
Status: corev1.ConditionFalse,
|
||||
LastTransitionTime: metav1.Time{Time: metav1.Now().Add(1 * time.Second)},
|
||||
})
|
||||
|
||||
err = k8sClient.Status().Patch(ctx, newPod, client.MergeFrom(pod))
|
||||
Expect(err).To(BeNil(), "expected no errors when updating new pod status")
|
||||
|
||||
Eventually(
|
||||
func() (bool, error) {
|
||||
err := k8sClient.Get(ctx, client.ObjectKey{Name: ephemeralRunner.Name, Namespace: ephemeralRunner.Namespace}, pod)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return ephemeralRunner.Status.Ready, nil
|
||||
},
|
||||
ephemeralRunnerTimeout,
|
||||
ephemeralRunnerInterval,
|
||||
).Should(BeEquivalentTo(false))
|
||||
})
|
||||
|
||||
It("It should not update phase if container state does not exist", func() {
|
||||
pod := new(corev1.Pod)
|
||||
Eventually(
|
||||
|
|
|
|||
|
|
@ -747,7 +747,7 @@ func trimLabelValue(val string) string {
|
|||
if len(val) > 63 {
|
||||
return val[:63-len(trimLabelVauleSuffix)] + trimLabelVauleSuffix
|
||||
}
|
||||
return val
|
||||
return strings.Trim(val, "-_.")
|
||||
}
|
||||
|
||||
func (b *ResourceBuilder) mergeLabels(base, overwrite map[string]string) map[string]string {
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ kubectl set env deploy controller-manager -c manager GITHUB_ENTERPRISE_URL=<GHEC
|
|||
The project supports being deployed on the various cloud Kubernetes platforms (e.g. EKS), it does not however aim to go beyond that. No cloud specific tooling is bundled in the base runner, this is an active decision to keep the overhead of maintaining the solution manageable.
|
||||
|
||||
**Bundled Software**<br />
|
||||
The GitHub hosted runners include a large amount of pre-installed software packages. GitHub maintains a list in README files at <https://github.com/actions/virtual-environments/tree/main/images/linux>.
|
||||
The GitHub hosted runners include a large amount of pre-installed software packages. GitHub maintains a list in README files at <https://github.com/actions/runner-images/blob/main/images/ubuntu/>.
|
||||
|
||||
This solution maintains a few Ubuntu based runner images, these images do not contain all of the software installed on the GitHub runners. The images contain the following subset of packages from the GitHub runners:
|
||||
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ resources:
|
|||
- github.com/actions/actions-runner-controller/config//default?ref=v0.22.2
|
||||
# Add the below!
|
||||
- github.com/actions/actions-runner-controller/config//github-webhook-server?ref=v0.22.2
|
||||
```
|
||||
|
||||
Finally, you will have to configure an ingress so that you may configure the webhook in github. An example of such ingress can be find below:
|
||||
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -25,7 +25,7 @@ require (
|
|||
github.com/teambition/rrule-go v1.8.2
|
||||
go.uber.org/multierr v1.11.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/net v0.25.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/oauth2 v0.19.0
|
||||
golang.org/x/sync v0.10.0
|
||||
gomodules.xyz/jsonpatch/v2 v2.4.0
|
||||
|
|
|
|||
4
go.sum
4
go.sum
|
|
@ -259,8 +259,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.19.0 h1:9+E/EZBCbTLNrbN35fHv/a/d/mOBatymz1zbtQrXpIg=
|
||||
golang.org/x/oauth2 v0.19.0/go.mod h1:vYi7skDa1x015PmRRYZ7+s1cWyPgrPiSYRe4rnsexc8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
|
|||
|
|
@ -21,55 +21,53 @@ func init() {
|
|||
)
|
||||
}
|
||||
|
||||
var (
|
||||
runtimeBuckets []float64 = []float64{
|
||||
0.01,
|
||||
0.05,
|
||||
0.1,
|
||||
0.5,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
12,
|
||||
15,
|
||||
18,
|
||||
20,
|
||||
25,
|
||||
30,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
70,
|
||||
80,
|
||||
90,
|
||||
100,
|
||||
110,
|
||||
120,
|
||||
150,
|
||||
180,
|
||||
210,
|
||||
240,
|
||||
300,
|
||||
360,
|
||||
420,
|
||||
480,
|
||||
540,
|
||||
600,
|
||||
900,
|
||||
1200,
|
||||
1800,
|
||||
2400,
|
||||
3000,
|
||||
3600,
|
||||
}
|
||||
)
|
||||
var runtimeBuckets []float64 = []float64{
|
||||
0.01,
|
||||
0.05,
|
||||
0.1,
|
||||
0.5,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
12,
|
||||
15,
|
||||
18,
|
||||
20,
|
||||
25,
|
||||
30,
|
||||
40,
|
||||
50,
|
||||
60,
|
||||
70,
|
||||
80,
|
||||
90,
|
||||
100,
|
||||
110,
|
||||
120,
|
||||
150,
|
||||
180,
|
||||
210,
|
||||
240,
|
||||
300,
|
||||
360,
|
||||
420,
|
||||
480,
|
||||
540,
|
||||
600,
|
||||
900,
|
||||
1200,
|
||||
1800,
|
||||
2400,
|
||||
3000,
|
||||
3600,
|
||||
}
|
||||
|
||||
func metricLabels(extras ...string) []string {
|
||||
return append(append([]string{}, commonLabels...), extras...)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ DIND_ROOTLESS_RUNNER_NAME ?= ${DOCKER_USER}/actions-runner-dind-rootless
|
|||
OS_IMAGE ?= ubuntu-22.04
|
||||
TARGETPLATFORM ?= $(shell arch)
|
||||
|
||||
RUNNER_VERSION ?= 2.321.0
|
||||
RUNNER_VERSION ?= 2.322.0
|
||||
RUNNER_CONTAINER_HOOKS_VERSION ?= 0.6.2
|
||||
DOCKER_VERSION ?= 24.0.7
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
RUNNER_VERSION=2.321.0
|
||||
RUNNER_VERSION=2.322.0
|
||||
RUNNER_CONTAINER_HOOKS_VERSION=0.6.2
|
||||
|
|
@ -36,7 +36,7 @@ var (
|
|||
|
||||
testResultCMNamePrefix = "test-result-"
|
||||
|
||||
RunnerVersion = "2.321.0"
|
||||
RunnerVersion = "2.322.0"
|
||||
RunnerContainerHooksVersion = "0.6.2"
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue