Compare commits

...

10 Commits

Author SHA1 Message Date
Yusuke Kuoka
67c7b7a228 Bump chart version to 0.13.1 with controller 0.20.1 2021-09-24 00:40:08 +00:00
Yusuke Kuoka
2e325fa176 Merge pull request #843 from tyrken/add-preserve-unknown-false-crds
Add preserveUnknown=false to crds
2021-09-24 09:25:02 +09:00
Tristan Keen
5e3f89bdc5 Correct test to append docker container (#837)
Fixes #835
2021-09-24 09:18:20 +09:00
Tristan Keen
9f4f5ec951 Added preserveUnknownFields:false to CRDs 2021-09-23 22:00:18 +01:00
Tristan Keen
1fafd0d139 Force CRDs to have preserveUnknownFields: false 2021-09-23 22:00:18 +01:00
Renovate Bot
24602ff3ee chore(deps): update dependency actions/runner to v2.283.1 2021-09-20 17:41:07 +00:00
Callum Tait
cf75d24def ci: updating triggers (#827)
* ci: updating triggers
2021-09-17 09:21:00 +09:00
Renovate Bot
ac3721d0d5 chore(deps): update dependency actions/runner to v2.282.1 2021-09-15 20:09:19 +00:00
Callum Tait
594b086674 docs: adding election details (#821)
* docs: adding election details

* use consistent case
2021-09-15 12:44:31 +01:00
Yusuke Kuoka
58d2591f09 Bump chart version to 0.13.0 for actions-runner-controller 0.20.0 2021-09-15 00:38:43 +00:00
19 changed files with 37860 additions and 61248 deletions

View File

@@ -19,7 +19,7 @@ on:
- .github/workflows/build-and-release-runners.yml - .github/workflows/build-and-release-runners.yml
env: env:
RUNNER_VERSION: 2.282.0 RUNNER_VERSION: 2.283.1
DOCKER_VERSION: 20.10.8 DOCKER_VERSION: 20.10.8
DOCKERHUB_USERNAME: summerwind DOCKERHUB_USERNAME: summerwind

View File

@@ -4,10 +4,9 @@ on:
push: push:
paths: paths:
- 'charts/**' - 'charts/**'
- '.github/workflows/on-push-lint-charts.yml'
- '!charts/actions-runner-controller/docs/**' - '!charts/actions-runner-controller/docs/**'
- '!charts/actions-runner-controller/*.md' - '!**.md'
- '.github/**'
- '!.github/*.md'
workflow_dispatch: workflow_dispatch:
env: env:
KUBE_SCORE_VERSION: 1.10.0 KUBE_SCORE_VERSION: 1.10.0

View File

@@ -4,11 +4,10 @@ on:
push: push:
branches: branches:
- master - master
- main # assume that the branch name may change in future
paths: paths:
- 'charts/**' - 'charts/**'
- '.github/workflows/on-push-master-publish-chart.yml'
- '!charts/actions-runner-controller/docs/**' - '!charts/actions-runner-controller/docs/**'
- '.github/**'
- '!**.md' - '!**.md'
workflow_dispatch: workflow_dispatch:

View File

@@ -86,8 +86,11 @@ deploy: manifests
# Generate manifests e.g. CRD, RBAC etc. # Generate manifests e.g. CRD, RBAC etc.
manifests: manifests-gen-crds chart-crds manifests: manifests-gen-crds chart-crds
manifests-gen-crds: controller-gen manifests-gen-crds: controller-gen yq
$(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases $(CONTROLLER_GEN) $(CRD_OPTIONS) rbac:roleName=manager-role webhook paths="./..." output:crd:artifacts:config=config/crd/bases
for YAMLFILE in config/crd/bases/actions*.yaml; do \
$(YQ) write --inplace "$$YAMLFILE" spec.preserveUnknownFields false; \
done
chart-crds: chart-crds:
cp config/crd/bases/*.yaml charts/actions-runner-controller/crds/ cp config/crd/bases/*.yaml charts/actions-runner-controller/crds/
@@ -227,6 +230,23 @@ else
CONTROLLER_GEN=$(shell which controller-gen) CONTROLLER_GEN=$(shell which controller-gen)
endif endif
# find or download yq
# download yq if necessary
# Use always go-version to get consistent line wraps etc.
yq:
ifeq (, $(wildcard $(GOBIN)/yq))
echo "Downloading yq"
@{ \
set -e ;\
YQ_TMP_DIR=$$(mktemp -d) ;\
cd $$YQ_TMP_DIR ;\
go mod init tmp ;\
go get github.com/mikefarah/yq/v3@3.4.0 ;\
rm -rf $$YQ_TMP_DIR ;\
}
endif
YQ=$(GOBIN)/yq
OS_NAME := $(shell uname -s | tr A-Z a-z) OS_NAME := $(shell uname -s | tr A-Z a-z)
# find or download etcd # find or download etcd

View File

@@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.12.8 version: 0.13.1
# Used as the default manager tag value when no tag property is provided in the values.yaml # Used as the default manager tag value when no tag property is provided in the values.yaml
appVersion: 0.19.0 appVersion: 0.20.1
home: https://github.com/actions-runner-controller/actions-runner-controller home: https://github.com/actions-runner-controller/actions-runner-controller

View File

@@ -4,15 +4,17 @@ All additional docs are kept in the `docs/` folder, this README is solely for do
## Values ## Values
_The values are documented as of HEAD_ **_The values are documented as of HEAD, to review the configuration options for your chart version ensure you view this file at the relevent [tag](https://github.com/actions-runner-controller/actions-runner-controller/tags)_**
_Default values are the defaults set in the charts values.yaml, some properties have default configurations in the code for when the property is omitted or invalid_ > _Default values are the defaults set in the charts values.yaml, some properties have default configurations in the code for when the property is omitted or invalid_
| Key | Description | Default | | Key | Description | Default |
|----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------| |----------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------|
| `labels` | Set labels to apply to all resources in the chart | | | `labels` | Set labels to apply to all resources in the chart | |
| `replicaCount` | Set the number of controller pods | 1 | | `replicaCount` | Set the number of controller pods | 1 |
| `syncPeriod` | Set the period in which the controler reconciles the desired runners count | 10m | | `syncPeriod` | Set the period in which the controler reconciles the desired runners count | 10m |
| `enableLeaderElection` | Enable election configuration | true |
| `leaderElectionId` | Set the election ID for the controller group | |
| `githubAPICacheDuration` | Set the cache period for API calls | | | `githubAPICacheDuration` | Set the cache period for API calls | |
| `githubEnterpriseServerURL` | Set the URL for a self-hosted GitHub Enterprise Server | | | `githubEnterpriseServerURL` | Set the URL for a self-hosted GitHub Enterprise Server | |
| `logLevel` | Set the log level of the controller container | | | `logLevel` | Set the log level of the controller container | |
@@ -22,7 +24,7 @@ _Default values are the defaults set in the charts values.yaml, some properties
| `authSecret.github_app_installation_id` | The ID of your GitHub App installation. **This can't be set at the same time as `authSecret.github_token`** | | | `authSecret.github_app_installation_id` | The ID of your GitHub App installation. **This can't be set at the same time as `authSecret.github_token`** | |
| `authSecret.github_app_private_key` | The multiline string of your GitHub App's private key. **This can't be set at the same time as `authSecret.github_token`** | | | `authSecret.github_app_private_key` | The multiline string of your GitHub App's private key. **This can't be set at the same time as `authSecret.github_token`** | |
| `authSecret.github_token` | Your chosen GitHub PAT token. **This can't be set at the same time as the `authSecret.github_app_*`** | | | `authSecret.github_token` | Your chosen GitHub PAT token. **This can't be set at the same time as the `authSecret.github_app_*`** | |
| `dockerRegistryMirror` | The default Docker Registry Mirror used by runners. | | `dockerRegistryMirror` | The default Docker Registry Mirror used by runners. | |
| `image.repository` | The "repository/image" of the controller container | summerwind/actions-runner-controller | | `image.repository` | The "repository/image" of the controller container | summerwind/actions-runner-controller |
| `image.tag` | The tag of the controller container | | | `image.tag` | The tag of the controller container | |
| `image.actionsRunnerRepositoryAndTag` | The "repository/image" of the actions runner container | summerwind/actions-runner:latest | | `image.actionsRunnerRepositoryAndTag` | The "repository/image" of the actions runner container | summerwind/actions-runner:latest |

View File

@@ -1,5 +1,3 @@
---
apiVersion: apiextensions.k8s.io/v1 apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition kind: CustomResourceDefinition
metadata: metadata:
@@ -34,29 +32,22 @@ spec:
name: v1alpha1 name: v1alpha1
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: HorizontalRunnerAutoscaler is the Schema for the horizontalrunnerautoscaler description: HorizontalRunnerAutoscaler is the Schema for the horizontalrunnerautoscaler API
API
properties: properties:
apiVersion: apiVersion:
description: 'APIVersion defines the versioned schema of this representation description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string type: string
kind: kind:
description: 'Kind is a string value representing the REST resource this description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string type: string
metadata: metadata:
type: object type: object
spec: spec:
description: HorizontalRunnerAutoscalerSpec defines the desired state description: HorizontalRunnerAutoscalerSpec defines the desired state of HorizontalRunnerAutoscaler
of HorizontalRunnerAutoscaler
properties: properties:
capacityReservations: capacityReservations:
items: items:
description: CapacityReservation specifies the number of replicas description: CapacityReservation specifies the number of replicas temporarily added to the scale target until ExpirationTime.
temporarily added to the scale target until ExpirationTime.
properties: properties:
expirationTime: expirationTime:
format: date-time format: date-time
@@ -68,68 +59,48 @@ spec:
type: object type: object
type: array type: array
maxReplicas: maxReplicas:
description: MinReplicas is the maximum number of replicas the deployment description: MinReplicas is the maximum number of replicas the deployment is allowed to scale
is allowed to scale
type: integer type: integer
metrics: metrics:
description: Metrics is the collection of various metric targets to description: Metrics is the collection of various metric targets to calculate desired number of runners
calculate desired number of runners
items: items:
properties: properties:
repositoryNames: repositoryNames:
description: RepositoryNames is the list of repository names description: RepositoryNames is the list of repository names to be used for calculating the metric. For example, a repository name is the REPO part of `github.com/USER/REPO`.
to be used for calculating the metric. For example, a repository
name is the REPO part of `github.com/USER/REPO`.
items: items:
type: string type: string
type: array type: array
scaleDownAdjustment: scaleDownAdjustment:
description: ScaleDownAdjustment is the number of runners removed description: ScaleDownAdjustment is the number of runners removed on scale-down. You can only specify either ScaleDownFactor or ScaleDownAdjustment.
on scale-down. You can only specify either ScaleDownFactor
or ScaleDownAdjustment.
type: integer type: integer
scaleDownFactor: scaleDownFactor:
description: ScaleDownFactor is the multiplicative factor applied description: ScaleDownFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be removed.
to the current number of runners used to determine how many
pods should be removed.
type: string type: string
scaleDownThreshold: scaleDownThreshold:
description: ScaleDownThreshold is the percentage of busy runners description: ScaleDownThreshold is the percentage of busy runners less than which will trigger the hpa to scale the runners down.
less than which will trigger the hpa to scale the runners
down.
type: string type: string
scaleUpAdjustment: scaleUpAdjustment:
description: ScaleUpAdjustment is the number of runners added description: ScaleUpAdjustment is the number of runners added on scale-up. You can only specify either ScaleUpFactor or ScaleUpAdjustment.
on scale-up. You can only specify either ScaleUpFactor or
ScaleUpAdjustment.
type: integer type: integer
scaleUpFactor: scaleUpFactor:
description: ScaleUpFactor is the multiplicative factor applied description: ScaleUpFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be added.
to the current number of runners used to determine how many
pods should be added.
type: string type: string
scaleUpThreshold: scaleUpThreshold:
description: ScaleUpThreshold is the percentage of busy runners description: ScaleUpThreshold is the percentage of busy runners greater than which will trigger the hpa to scale runners up.
greater than which will trigger the hpa to scale runners up.
type: string type: string
type: type:
description: Type is the type of metric to be used for autoscaling. description: Type is the type of metric to be used for autoscaling. The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
type: string type: string
type: object type: object
type: array type: array
minReplicas: minReplicas:
description: MinReplicas is the minimum number of replicas the deployment description: MinReplicas is the minimum number of replicas the deployment is allowed to scale
is allowed to scale
type: integer type: integer
scaleDownDelaySecondsAfterScaleOut: scaleDownDelaySecondsAfterScaleOut:
description: ScaleDownDelaySecondsAfterScaleUp is the approximate description: ScaleDownDelaySecondsAfterScaleUp is the approximate delay for a scale down followed by a scale up Used to prevent flapping (down->up->down->... loop)
delay for a scale down followed by a scale up Used to prevent flapping
(down->up->down->... loop)
type: integer type: integer
scaleTargetRef: scaleTargetRef:
description: ScaleTargetRef sis the reference to scaled resource like description: ScaleTargetRef sis the reference to scaled resource like RunnerDeployment
RunnerDeployment
properties: properties:
kind: kind:
description: Kind is the type of resource being referenced description: Kind is the type of resource being referenced
@@ -142,15 +113,7 @@ spec:
type: string type: string
type: object type: object
scaleUpTriggers: scaleUpTriggers:
description: "ScaleUpTriggers is an experimental feature to increase description: "ScaleUpTriggers is an experimental feature to increase the desired replicas by 1 on each webhook requested received by the webhookBasedAutoscaler. \n This feature requires you to also enable and deploy the webhookBasedAutoscaler onto your cluster. \n Note that the added runners remain until the next sync period at least, and they may or may not be used by GitHub Actions depending on the timing. They are intended to be used to gain \"resource slack\" immediately after you receive a webhook from GitHub, so that you can loosely expect MinReplicas runners to be always available."
the desired replicas by 1 on each webhook requested received by
the webhookBasedAutoscaler. \n This feature requires you to also
enable and deploy the webhookBasedAutoscaler onto your cluster.
\n Note that the added runners remain until the next sync period
at least, and they may or may not be used by GitHub Actions depending
on the timing. They are intended to be used to gain \"resource slack\"
immediately after you receive a webhook from GitHub, so that you
can loosely expect MinReplicas runners to be always available."
items: items:
properties: properties:
amount: amount:
@@ -163,20 +126,12 @@ spec:
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
properties: properties:
names: names:
description: Names is a list of GitHub Actions glob description: Names is a list of GitHub Actions glob patterns. Any check_run event whose name matches one of patterns in the list can trigger autoscaling. Note that check_run name seem to equal to the job name you've defined in your actions workflow yaml file. So it is very likely that you can utilize this to trigger depending on the job.
patterns. Any check_run event whose name matches one
of patterns in the list can trigger autoscaling. Note
that check_run name seem to equal to the job name
you've defined in your actions workflow yaml file.
So it is very likely that you can utilize this to
trigger depending on the job.
items: items:
type: string type: string
type: array type: array
repositories: repositories:
description: Repositories is a list of GitHub repositories. description: Repositories is a list of GitHub repositories. Any check_run event whose repository matches one of repositories in the list can trigger autoscaling.
Any check_run event whose repository matches one of
repositories in the list can trigger autoscaling.
items: items:
type: string type: string
type: array type: array
@@ -200,41 +155,29 @@ spec:
type: array type: array
type: object type: object
push: push:
description: PushSpec is the condition for triggering scale-up description: PushSpec is the condition for triggering scale-up on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
type: object type: object
type: object type: object
type: object type: object
type: array type: array
scheduledOverrides: scheduledOverrides:
description: ScheduledOverrides is the list of ScheduledOverride. description: ScheduledOverrides is the list of ScheduledOverride. It can be used to override a few fields of HorizontalRunnerAutoscalerSpec on schedule. The earlier a scheduled override is, the higher it is prioritized.
It can be used to override a few fields of HorizontalRunnerAutoscalerSpec
on schedule. The earlier a scheduled override is, the higher it
is prioritized.
items: items:
description: ScheduledOverride can be used to override a few fields description: ScheduledOverride can be used to override a few fields of HorizontalRunnerAutoscalerSpec on schedule. A schedule can optionally be recurring, so that the correspoding override happens every day, week, month, or year.
of HorizontalRunnerAutoscalerSpec on schedule. A schedule can
optionally be recurring, so that the correspoding override happens
every day, week, month, or year.
properties: properties:
endTime: endTime:
description: EndTime is the time at which the first override description: EndTime is the time at which the first override ends.
ends.
format: date-time format: date-time
type: string type: string
minReplicas: minReplicas:
description: MinReplicas is the number of runners while overriding. description: MinReplicas is the number of runners while overriding. If omitted, it doesn't override minReplicas.
If omitted, it doesn't override minReplicas.
minimum: 0 minimum: 0
nullable: true nullable: true
type: integer type: integer
recurrenceRule: recurrenceRule:
properties: properties:
frequency: frequency:
description: Frequency is the name of a predefined interval description: Frequency is the name of a predefined interval of each recurrence. The valid values are "Daily", "Weekly", "Monthly", and "Yearly". If empty, the corresponding override happens only once.
of each recurrence. The valid values are "Daily", "Weekly",
"Monthly", and "Yearly". If empty, the corresponding override
happens only once.
enum: enum:
- Daily - Daily
- Weekly - Weekly
@@ -242,14 +185,12 @@ spec:
- Yearly - Yearly
type: string type: string
untilTime: untilTime:
description: UntilTime is the time of the final recurrence. description: UntilTime is the time of the final recurrence. If empty, the schedule recurs forever.
If empty, the schedule recurs forever.
format: date-time format: date-time
type: string type: string
type: object type: object
startTime: startTime:
description: StartTime is the time at which the first override description: StartTime is the time at which the first override starts.
starts.
format: date-time format: date-time
type: string type: string
required: required:
@@ -273,25 +214,18 @@ spec:
type: object type: object
type: array type: array
desiredReplicas: desiredReplicas:
description: DesiredReplicas is the total number of desired, non-terminated description: DesiredReplicas is the total number of desired, non-terminated and latest pods to be set for the primary RunnerSet This doesn't include outdated pods while upgrading the deployment and replacing the runnerset.
and latest pods to be set for the primary RunnerSet This doesn't
include outdated pods while upgrading the deployment and replacing
the runnerset.
type: integer type: integer
lastSuccessfulScaleOutTime: lastSuccessfulScaleOutTime:
format: date-time format: date-time
nullable: true nullable: true
type: string type: string
observedGeneration: observedGeneration:
description: ObservedGeneration is the most recent generation observed description: ObservedGeneration is the most recent generation observed for the target. It corresponds to e.g. RunnerDeployment's generation, which is updated on mutation by the API Server.
for the target. It corresponds to e.g. RunnerDeployment's generation,
which is updated on mutation by the API Server.
format: int64 format: int64
type: integer type: integer
scheduledOverridesSummary: scheduledOverridesSummary:
description: ScheduledOverridesSummary is the summary of active and description: ScheduledOverridesSummary is the summary of active and upcoming scheduled overrides to be shown in e.g. a column of a `kubectl get hra` output for observability.
upcoming scheduled overrides to be shown in e.g. a column of a `kubectl
get hra` output for observability.
type: string type: string
type: object type: object
type: object type: object
@@ -299,6 +233,7 @@ spec:
storage: true storage: true
subresources: subresources:
status: {} status: {}
preserveUnknownFields: false
status: status:
acceptedNames: acceptedNames:
kind: "" kind: ""

View File

@@ -1,5 +1,3 @@
---
apiVersion: apiextensions.k8s.io/v1 apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition kind: CustomResourceDefinition
metadata: metadata:
@@ -34,29 +32,22 @@ spec:
name: v1alpha1 name: v1alpha1
schema: schema:
openAPIV3Schema: openAPIV3Schema:
description: HorizontalRunnerAutoscaler is the Schema for the horizontalrunnerautoscaler description: HorizontalRunnerAutoscaler is the Schema for the horizontalrunnerautoscaler API
API
properties: properties:
apiVersion: apiVersion:
description: 'APIVersion defines the versioned schema of this representation description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string type: string
kind: kind:
description: 'Kind is a string value representing the REST resource this description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string type: string
metadata: metadata:
type: object type: object
spec: spec:
description: HorizontalRunnerAutoscalerSpec defines the desired state description: HorizontalRunnerAutoscalerSpec defines the desired state of HorizontalRunnerAutoscaler
of HorizontalRunnerAutoscaler
properties: properties:
capacityReservations: capacityReservations:
items: items:
description: CapacityReservation specifies the number of replicas description: CapacityReservation specifies the number of replicas temporarily added to the scale target until ExpirationTime.
temporarily added to the scale target until ExpirationTime.
properties: properties:
expirationTime: expirationTime:
format: date-time format: date-time
@@ -68,68 +59,48 @@ spec:
type: object type: object
type: array type: array
maxReplicas: maxReplicas:
description: MinReplicas is the maximum number of replicas the deployment description: MinReplicas is the maximum number of replicas the deployment is allowed to scale
is allowed to scale
type: integer type: integer
metrics: metrics:
description: Metrics is the collection of various metric targets to description: Metrics is the collection of various metric targets to calculate desired number of runners
calculate desired number of runners
items: items:
properties: properties:
repositoryNames: repositoryNames:
description: RepositoryNames is the list of repository names description: RepositoryNames is the list of repository names to be used for calculating the metric. For example, a repository name is the REPO part of `github.com/USER/REPO`.
to be used for calculating the metric. For example, a repository
name is the REPO part of `github.com/USER/REPO`.
items: items:
type: string type: string
type: array type: array
scaleDownAdjustment: scaleDownAdjustment:
description: ScaleDownAdjustment is the number of runners removed description: ScaleDownAdjustment is the number of runners removed on scale-down. You can only specify either ScaleDownFactor or ScaleDownAdjustment.
on scale-down. You can only specify either ScaleDownFactor
or ScaleDownAdjustment.
type: integer type: integer
scaleDownFactor: scaleDownFactor:
description: ScaleDownFactor is the multiplicative factor applied description: ScaleDownFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be removed.
to the current number of runners used to determine how many
pods should be removed.
type: string type: string
scaleDownThreshold: scaleDownThreshold:
description: ScaleDownThreshold is the percentage of busy runners description: ScaleDownThreshold is the percentage of busy runners less than which will trigger the hpa to scale the runners down.
less than which will trigger the hpa to scale the runners
down.
type: string type: string
scaleUpAdjustment: scaleUpAdjustment:
description: ScaleUpAdjustment is the number of runners added description: ScaleUpAdjustment is the number of runners added on scale-up. You can only specify either ScaleUpFactor or ScaleUpAdjustment.
on scale-up. You can only specify either ScaleUpFactor or
ScaleUpAdjustment.
type: integer type: integer
scaleUpFactor: scaleUpFactor:
description: ScaleUpFactor is the multiplicative factor applied description: ScaleUpFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be added.
to the current number of runners used to determine how many
pods should be added.
type: string type: string
scaleUpThreshold: scaleUpThreshold:
description: ScaleUpThreshold is the percentage of busy runners description: ScaleUpThreshold is the percentage of busy runners greater than which will trigger the hpa to scale runners up.
greater than which will trigger the hpa to scale runners up.
type: string type: string
type: type:
description: Type is the type of metric to be used for autoscaling. description: Type is the type of metric to be used for autoscaling. The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
type: string type: string
type: object type: object
type: array type: array
minReplicas: minReplicas:
description: MinReplicas is the minimum number of replicas the deployment description: MinReplicas is the minimum number of replicas the deployment is allowed to scale
is allowed to scale
type: integer type: integer
scaleDownDelaySecondsAfterScaleOut: scaleDownDelaySecondsAfterScaleOut:
description: ScaleDownDelaySecondsAfterScaleUp is the approximate description: ScaleDownDelaySecondsAfterScaleUp is the approximate delay for a scale down followed by a scale up Used to prevent flapping (down->up->down->... loop)
delay for a scale down followed by a scale up Used to prevent flapping
(down->up->down->... loop)
type: integer type: integer
scaleTargetRef: scaleTargetRef:
description: ScaleTargetRef sis the reference to scaled resource like description: ScaleTargetRef sis the reference to scaled resource like RunnerDeployment
RunnerDeployment
properties: properties:
kind: kind:
description: Kind is the type of resource being referenced description: Kind is the type of resource being referenced
@@ -142,15 +113,7 @@ spec:
type: string type: string
type: object type: object
scaleUpTriggers: scaleUpTriggers:
description: "ScaleUpTriggers is an experimental feature to increase description: "ScaleUpTriggers is an experimental feature to increase the desired replicas by 1 on each webhook requested received by the webhookBasedAutoscaler. \n This feature requires you to also enable and deploy the webhookBasedAutoscaler onto your cluster. \n Note that the added runners remain until the next sync period at least, and they may or may not be used by GitHub Actions depending on the timing. They are intended to be used to gain \"resource slack\" immediately after you receive a webhook from GitHub, so that you can loosely expect MinReplicas runners to be always available."
the desired replicas by 1 on each webhook requested received by
the webhookBasedAutoscaler. \n This feature requires you to also
enable and deploy the webhookBasedAutoscaler onto your cluster.
\n Note that the added runners remain until the next sync period
at least, and they may or may not be used by GitHub Actions depending
on the timing. They are intended to be used to gain \"resource slack\"
immediately after you receive a webhook from GitHub, so that you
can loosely expect MinReplicas runners to be always available."
items: items:
properties: properties:
amount: amount:
@@ -163,20 +126,12 @@ spec:
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
properties: properties:
names: names:
description: Names is a list of GitHub Actions glob description: Names is a list of GitHub Actions glob patterns. Any check_run event whose name matches one of patterns in the list can trigger autoscaling. Note that check_run name seem to equal to the job name you've defined in your actions workflow yaml file. So it is very likely that you can utilize this to trigger depending on the job.
patterns. Any check_run event whose name matches one
of patterns in the list can trigger autoscaling. Note
that check_run name seem to equal to the job name
you've defined in your actions workflow yaml file.
So it is very likely that you can utilize this to
trigger depending on the job.
items: items:
type: string type: string
type: array type: array
repositories: repositories:
description: Repositories is a list of GitHub repositories. description: Repositories is a list of GitHub repositories. Any check_run event whose repository matches one of repositories in the list can trigger autoscaling.
Any check_run event whose repository matches one of
repositories in the list can trigger autoscaling.
items: items:
type: string type: string
type: array type: array
@@ -200,41 +155,29 @@ spec:
type: array type: array
type: object type: object
push: push:
description: PushSpec is the condition for triggering scale-up description: PushSpec is the condition for triggering scale-up on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
type: object type: object
type: object type: object
type: object type: object
type: array type: array
scheduledOverrides: scheduledOverrides:
description: ScheduledOverrides is the list of ScheduledOverride. description: ScheduledOverrides is the list of ScheduledOverride. It can be used to override a few fields of HorizontalRunnerAutoscalerSpec on schedule. The earlier a scheduled override is, the higher it is prioritized.
It can be used to override a few fields of HorizontalRunnerAutoscalerSpec
on schedule. The earlier a scheduled override is, the higher it
is prioritized.
items: items:
description: ScheduledOverride can be used to override a few fields description: ScheduledOverride can be used to override a few fields of HorizontalRunnerAutoscalerSpec on schedule. A schedule can optionally be recurring, so that the correspoding override happens every day, week, month, or year.
of HorizontalRunnerAutoscalerSpec on schedule. A schedule can
optionally be recurring, so that the correspoding override happens
every day, week, month, or year.
properties: properties:
endTime: endTime:
description: EndTime is the time at which the first override description: EndTime is the time at which the first override ends.
ends.
format: date-time format: date-time
type: string type: string
minReplicas: minReplicas:
description: MinReplicas is the number of runners while overriding. description: MinReplicas is the number of runners while overriding. If omitted, it doesn't override minReplicas.
If omitted, it doesn't override minReplicas.
minimum: 0 minimum: 0
nullable: true nullable: true
type: integer type: integer
recurrenceRule: recurrenceRule:
properties: properties:
frequency: frequency:
description: Frequency is the name of a predefined interval description: Frequency is the name of a predefined interval of each recurrence. The valid values are "Daily", "Weekly", "Monthly", and "Yearly". If empty, the corresponding override happens only once.
of each recurrence. The valid values are "Daily", "Weekly",
"Monthly", and "Yearly". If empty, the corresponding override
happens only once.
enum: enum:
- Daily - Daily
- Weekly - Weekly
@@ -242,14 +185,12 @@ spec:
- Yearly - Yearly
type: string type: string
untilTime: untilTime:
description: UntilTime is the time of the final recurrence. description: UntilTime is the time of the final recurrence. If empty, the schedule recurs forever.
If empty, the schedule recurs forever.
format: date-time format: date-time
type: string type: string
type: object type: object
startTime: startTime:
description: StartTime is the time at which the first override description: StartTime is the time at which the first override starts.
starts.
format: date-time format: date-time
type: string type: string
required: required:
@@ -273,25 +214,18 @@ spec:
type: object type: object
type: array type: array
desiredReplicas: desiredReplicas:
description: DesiredReplicas is the total number of desired, non-terminated description: DesiredReplicas is the total number of desired, non-terminated and latest pods to be set for the primary RunnerSet This doesn't include outdated pods while upgrading the deployment and replacing the runnerset.
and latest pods to be set for the primary RunnerSet This doesn't
include outdated pods while upgrading the deployment and replacing
the runnerset.
type: integer type: integer
lastSuccessfulScaleOutTime: lastSuccessfulScaleOutTime:
format: date-time format: date-time
nullable: true nullable: true
type: string type: string
observedGeneration: observedGeneration:
description: ObservedGeneration is the most recent generation observed description: ObservedGeneration is the most recent generation observed for the target. It corresponds to e.g. RunnerDeployment's generation, which is updated on mutation by the API Server.
for the target. It corresponds to e.g. RunnerDeployment's generation,
which is updated on mutation by the API Server.
format: int64 format: int64
type: integer type: integer
scheduledOverridesSummary: scheduledOverridesSummary:
description: ScheduledOverridesSummary is the summary of active and description: ScheduledOverridesSummary is the summary of active and upcoming scheduled overrides to be shown in e.g. a column of a `kubectl get hra` output for observability.
upcoming scheduled overrides to be shown in e.g. a column of a `kubectl
get hra` output for observability.
type: string type: string
type: object type: object
type: object type: object
@@ -299,6 +233,7 @@ spec:
storage: true storage: true
subresources: subresources:
status: {} status: {}
preserveUnknownFields: false
status: status:
acceptedNames: acceptedNames:
kind: "" kind: ""

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -619,7 +619,7 @@ func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
Resources: runner.Spec.Resources, Resources: runner.Spec.Resources,
}) })
if runner.Spec.DockerdWithinRunnerContainer == nil || !*runner.Spec.DockerdWithinRunnerContainer { if (runner.Spec.DockerEnabled == nil || *runner.Spec.DockerEnabled) && (runner.Spec.DockerdWithinRunnerContainer == nil || !*runner.Spec.DockerdWithinRunnerContainer) {
template.Spec.Containers = append(template.Spec.Containers, corev1.Container{ template.Spec.Containers = append(template.Spec.Containers, corev1.Container{
Name: "docker", Name: "docker",
VolumeMounts: runner.Spec.DockerVolumeMounts, VolumeMounts: runner.Spec.DockerVolumeMounts,

View File

@@ -0,0 +1,136 @@
package main
import (
"context"
"errors"
"flag"
"fmt"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"github.com/actions-runner-controller/actions-runner-controller/github"
"github.com/actions-runner-controller/actions-runner-controller/pkg/githubwebhookdeliveryforwarder"
"github.com/kelseyhightower/envconfig"
)
func main() {
var (
metricsAddr string
target string
repo string
)
var c github.Config
if err := envconfig.Process("github", &c); err != nil {
fmt.Fprintln(os.Stderr, "Error: Environment variable read failed.")
}
flag.StringVar(&metricsAddr, "metrics-addr", ":8000", "The address the metric endpoint binds to.")
flag.StringVar(&repo, "repo", "", "The owner/name of the repository that has the target hook. If specified, the forwarder will use the first hook configured on the repository as the source.")
flag.StringVar(&target, "target", "", "The URL of the forwarding target that receives all the forwarded webhooks.")
flag.StringVar(&c.Token, "github-token", c.Token, "The personal access token of GitHub.")
flag.Int64Var(&c.AppID, "github-app-id", c.AppID, "The application ID of GitHub App.")
flag.Int64Var(&c.AppInstallationID, "github-app-installation-id", c.AppInstallationID, "The installation ID of GitHub App.")
flag.StringVar(&c.AppPrivateKey, "github-app-private-key", c.AppPrivateKey, "The path of a private key file to authenticate as a GitHub App")
flag.Parse()
ghClient, err := c.NewClient()
if err != nil {
fmt.Fprintln(os.Stderr, "Error: Client creation failed.", err)
os.Exit(1)
}
var wg sync.WaitGroup
ctx, cancel := context.WithCancel(context.Background())
fwd := githubwebhookdeliveryforwarder.New(ghClient, target)
fwd.Repo = repo
mux := http.NewServeMux()
mux.HandleFunc("/readyz", fwd.HandleReadyz)
srv := http.Server{
Addr: metricsAddr,
Handler: mux,
}
wg.Add(1)
go func() {
defer cancel()
defer wg.Done()
if err := fwd.Run(ctx); err != nil {
fmt.Fprintf(os.Stderr, "problem running forwarder: %v\n", err)
}
}()
wg.Add(1)
go func() {
defer cancel()
defer wg.Done()
go func() {
<-ctx.Done()
srv.Shutdown(context.Background())
}()
if err := srv.ListenAndServe(); err != nil {
if !errors.Is(err, http.ErrServerClosed) {
fmt.Fprintf(os.Stderr, "problem running http server: %v\n", err)
}
}
}()
go func() {
<-SetupSignalHandler().Done()
cancel()
}()
wg.Wait()
}
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var onlyOneSignalHandler = make(chan struct{})
var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM}
// SetupSignalHandler registers for SIGTERM and SIGINT. A stop channel is returned
// which is closed on one of these signals. If a second signal is caught, the program
// is terminated with exit code 1.
func SetupSignalHandler() context.Context {
close(onlyOneSignalHandler) // panics when called twice
ctx, cancel := context.WithCancel(context.Background())
c := make(chan os.Signal, 2)
signal.Notify(c, shutdownSignals...)
go func() {
<-c
cancel()
<-c
os.Exit(1) // second signal. Exit directly.
}()
return ctx
}

View File

@@ -0,0 +1,202 @@
package githubwebhookdeliveryforwarder
import (
"bytes"
"context"
"fmt"
"net/http"
"os"
"sort"
"strings"
"time"
"github.com/actions-runner-controller/actions-runner-controller/github"
gogithub "github.com/google/go-github/v36/github"
)
type server struct {
target string
Repo string
client *github.Client
}
func New(client *github.Client, target string) *server {
var srv server
srv.target = target
srv.client = client
return &srv
}
func (s *server) Run(ctx context.Context) error {
segments := strings.Split(s.Repo, "/")
if len(segments) != 2 {
return fmt.Errorf("repository must be in a form of OWNER/REPO: got %q", s.Repo)
}
owner, repo := segments[0], segments[1]
hooks, _, err := s.client.Repositories.ListHooks(ctx, owner, repo, nil)
if err != nil {
s.Errorf("Failed listing hooks: %v", err)
return err
}
var hook *gogithub.Hook
for i := range hooks {
hook = hooks[i]
break
}
cur := &cursor{}
cur.deliveredAt = time.Now()
for {
var (
err error
payloads [][]byte
)
payloads, cur, err = s.getUnprocessedDeliveries(ctx, owner, repo, hook.GetID(), *cur)
if err != nil {
s.Errorf("failed getting unprocessed deliveries: %v", err)
}
for _, p := range payloads {
if _, err := http.Post(s.target, "application/json", bytes.NewReader(p)); err != nil {
s.Errorf("failed forwarding delivery: %v", err)
}
}
time.Sleep(10 * time.Second)
}
}
type cursor struct {
deliveredAt time.Time
id int64
}
func (s *server) getUnprocessedDeliveries(ctx context.Context, owner, repo string, hookID int64, pos cursor) ([][]byte, *cursor, error) {
var (
opts gogithub.ListCursorOptions
)
opts.PerPage = 2
var deliveries []*gogithub.HookDelivery
OUTER:
for {
ds, resp, err := s.client.Repositories.ListHookDeliveries(ctx, owner, repo, hookID, &opts)
if err != nil {
return nil, nil, err
}
opts.Cursor = resp.Cursor
for _, d := range ds {
d, _, err := s.client.Repositories.GetHookDelivery(ctx, owner, repo, hookID, d.GetID())
if err != nil {
return nil, nil, err
}
payload, err := d.ParseRequestPayload()
if err != nil {
return nil, nil, err
}
id := d.GetID()
deliveredAt := d.GetDeliveredAt()
if !pos.deliveredAt.IsZero() && deliveredAt.Before(pos.deliveredAt) {
s.Logf("%s is before %s so skipping all the remaining deliveries", deliveredAt, pos.deliveredAt)
break OUTER
}
if pos.id != 0 && id <= pos.id {
break OUTER
}
s.Logf("Received %T at %s: %v", payload, deliveredAt, payload)
if deliveredAt.After(pos.deliveredAt) {
pos.deliveredAt = deliveredAt
}
if id > pos.id {
pos.id = id
}
}
if opts.Cursor == "" {
break
}
time.Sleep(1 * time.Second)
}
sort.Slice(deliveries, func(a, b int) bool {
return deliveries[b].GetDeliveredAt().After(deliveries[a].GetDeliveredAt())
})
var payloads [][]byte
for _, d := range deliveries {
payloads = append(payloads, *d.Request.RawPayload)
}
return payloads, &pos, nil
}
func (s *server) HandleReadyz(w http.ResponseWriter, r *http.Request) {
var (
ok bool
err error
)
defer func() {
if !ok {
w.WriteHeader(http.StatusInternalServerError)
if err != nil {
msg := err.Error()
if _, err := w.Write([]byte(msg)); err != nil {
s.Errorf("failed writing http error response: %v", err)
}
}
}
}()
defer func() {
if r.Body != nil {
r.Body.Close()
}
}()
// respond ok to GET / e.g. for health check
if r.Method == http.MethodGet {
fmt.Fprintln(w, "webhook server is running")
return
}
w.WriteHeader(http.StatusOK)
if _, err := w.Write([]byte("ok")); err != nil {
s.Errorf("failed writing http response: %v", err)
}
}
func (s *server) Logf(format string, args ...interface{}) {
fmt.Fprintf(os.Stdout, format+"\n", args...)
}
func (s *server) Errorf(format string, args ...interface{}) {
fmt.Fprintf(os.Stderr, format+"\n", args...)
}