mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Compare commits
70 Commits
actions-ru
...
actions-ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62995fec5b | ||
|
|
7ee1d6bcdb | ||
|
|
b87e6e3966 | ||
|
|
88b8871830 | ||
|
|
2191617eb5 | ||
|
|
b305e38b17 | ||
|
|
b6c33cee32 | ||
|
|
46da4a6b6e | ||
|
|
f7e14e06e8 | ||
|
|
09e6b1839b | ||
|
|
0416a9272f | ||
|
|
c33578a041 | ||
|
|
49566aaebd | ||
|
|
f66e6a00fa | ||
|
|
431c1ed04a | ||
|
|
0d3de9ee2a | ||
|
|
79d63acded | ||
|
|
271a4dcd9d | ||
|
|
0401b2d786 | ||
|
|
43141cb751 | ||
|
|
b805cfada7 | ||
|
|
c4e97d600d | ||
|
|
fce7d6d2a7 | ||
|
|
5805e39e1f | ||
|
|
d36d47fe66 | ||
|
|
8657a34f32 | ||
|
|
b01e193aab | ||
|
|
0a3d2b686e | ||
|
|
2bc050a62d | ||
|
|
0725e72ae0 | ||
|
|
5f9fcaf016 | ||
|
|
e4e0b45933 | ||
|
|
2937173101 | ||
|
|
fccf29970b | ||
|
|
ea06001819 | ||
|
|
1bc1712519 | ||
|
|
24224613f3 | ||
|
|
3f331e9a39 | ||
|
|
67c7b7a228 | ||
|
|
2e325fa176 | ||
|
|
5e3f89bdc5 | ||
|
|
9f4f5ec951 | ||
|
|
1fafd0d139 | ||
|
|
24602ff3ee | ||
|
|
cf75d24def | ||
|
|
ac3721d0d5 | ||
|
|
594b086674 | ||
|
|
58d2591f09 | ||
|
|
1a75b4558b | ||
|
|
40c88eb490 | ||
|
|
fe64850d3d | ||
|
|
4320e0e5e1 | ||
|
|
4a61c2f3aa | ||
|
|
1eb135cace | ||
|
|
d918c91bea | ||
|
|
bf35c51440 | ||
|
|
b679a54196 | ||
|
|
5da808af96 | ||
|
|
e5b5ee6f1d | ||
|
|
cf3abcc7d6 | ||
|
|
cffc2585f9 | ||
|
|
01928863b9 | ||
|
|
a98729b08b | ||
|
|
ec0915ce7c | ||
|
|
d355f05ac0 | ||
|
|
6f27b4920e | ||
|
|
f8959f973f | ||
|
|
37955fa267 | ||
|
|
63fe89b7aa | ||
|
|
3f801af72a |
1
.github/renovate.json5
vendored
1
.github/renovate.json5
vendored
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"extends": ["config:base"],
|
"extends": ["config:base"],
|
||||||
|
"labels": ["dependencies"],
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
// automatically merge an update of runner
|
// automatically merge an update of runner
|
||||||
|
|||||||
3
.github/stale.yml
vendored
3
.github/stale.yml
vendored
@@ -18,8 +18,9 @@ exemptLabels:
|
|||||||
- refactor
|
- refactor
|
||||||
- documentation
|
- documentation
|
||||||
- chore
|
- chore
|
||||||
- needs-investigation
|
|
||||||
- bug
|
- bug
|
||||||
|
- dependencies
|
||||||
|
- needs-investigation
|
||||||
|
|
||||||
# Set to true to ignore issues in a project (defaults to false)
|
# Set to true to ignore issues in a project (defaults to false)
|
||||||
exemptProjects: false
|
exemptProjects: false
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'runner/**'
|
- 'runner/**'
|
||||||
- .github/workflows/build-and-release-runners.yml
|
- .github/workflows/build-and-release-runners.yml
|
||||||
|
- '!**.md'
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
@@ -17,9 +18,10 @@ on:
|
|||||||
- runner/Dockerfile.dindrunner
|
- runner/Dockerfile.dindrunner
|
||||||
- runner/entrypoint.sh
|
- runner/entrypoint.sh
|
||||||
- .github/workflows/build-and-release-runners.yml
|
- .github/workflows/build-and-release-runners.yml
|
||||||
|
- '!**.md'
|
||||||
|
|
||||||
env:
|
env:
|
||||||
RUNNER_VERSION: 2.281.0
|
RUNNER_VERSION: 2.284.0
|
||||||
DOCKER_VERSION: 20.10.8
|
DOCKER_VERSION: 20.10.8
|
||||||
DOCKERHUB_USERNAME: summerwind
|
DOCKERHUB_USERNAME: summerwind
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/on-push-lint-charts.yml
vendored
6
.github/workflows/on-push-lint-charts.yml
vendored
@@ -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
|
||||||
@@ -16,6 +15,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
lint-test:
|
lint-test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
name: Lint Chart
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|
||||||
@@ -19,6 +18,9 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
lint-chart:
|
lint-chart:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
name: Lint Chart
|
||||||
|
outputs:
|
||||||
|
publish-chart: ${{ steps.publish-chart-step.outputs.publish }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v2
|
||||||
@@ -80,10 +82,25 @@ jobs:
|
|||||||
run: ct install --config charts/.ci/ct-config.yaml
|
run: ct install --config charts/.ci/ct-config.yaml
|
||||||
if: steps.list-changed.outputs.changed == 'true'
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
|
||||||
publish-chart:
|
# WARNING: This relies on the latest release being inat the top of the JSON from GitHub and a clean chart.yaml
|
||||||
|
- name: Check if Chart Publish is Needed
|
||||||
|
id: publish-chart-step
|
||||||
|
run: |
|
||||||
|
CHART_TEXT=$(curl -fs https://raw.githubusercontent.com/actions-runner-controller/actions-runner-controller/master/charts/actions-runner-controller/Chart.yaml)
|
||||||
|
NEW_CHART_VERSION=$(echo "$CHART_TEXT" | grep version: | cut -d ' ' -f 2)
|
||||||
|
RELEASE_LIST=$(curl -fs https://api.github.com/repos/actions-runner-controller/actions-runner-controller/releases | jq .[].tag_name | grep actions-runner-controller | cut -d '"' -f 2 | cut -d '-' -f 4)
|
||||||
|
LATEST_RELEASED_CHART_VERSION=$(echo $RELEASE_LIST | cut -d ' ' -f 1)
|
||||||
|
echo "Chart version in master : $NEW_CHART_VERSION"
|
||||||
|
echo "Latest release chart version : $LATEST_RELEASED_CHART_VERSION"
|
||||||
|
if [[ $NEW_CHART_VERSION != $LATEST_RELEASED_CHART_VERSION ]]; then
|
||||||
|
echo "::set-output name=publish::true"
|
||||||
|
fi
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
publish-chart:
|
||||||
|
if: needs.lint-chart.outputs.publish-chart == 'true'
|
||||||
needs: lint-chart
|
needs: lint-chart
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Publish Chart
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
|
|||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
name: Publish Controller Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
|
|||||||
22
.github/workflows/test-entrypoint.yaml
vendored
Normal file
22
.github/workflows/test-entrypoint.yaml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
name: Unit tests for entrypoint
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
paths:
|
||||||
|
- 'runner/**'
|
||||||
|
- 'test/entrypoint/**'
|
||||||
|
- '!**.md'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Test entrypoint
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
- name: Run unit tests for entrypoint.sh
|
||||||
|
run: |
|
||||||
|
cd test/entrypoint
|
||||||
|
bash entrypoint_unittest.sh
|
||||||
13
.github/workflows/test.yaml
vendored
13
.github/workflows/test.yaml
vendored
@@ -5,10 +5,15 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'runner/**'
|
- .github/workflows/build-and-release-runners.yml
|
||||||
- .github/workflows/build-and-release-runners.yml
|
- .github/workflows/on-push-lint-charts.yml
|
||||||
- '*.md'
|
- .github/workflows/on-push-master-publish-chart.yml
|
||||||
- '.gitignore'
|
- .github/workflows/release.yml
|
||||||
|
- .github/workflows/test-entrypoint.yml
|
||||||
|
- .github/workflows/wip.yml
|
||||||
|
- 'runner/**'
|
||||||
|
- '**.md'
|
||||||
|
- '.gitignore'
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
|||||||
9
.github/workflows/wip.yml
vendored
9
.github/workflows/wip.yml
vendored
@@ -1,8 +1,15 @@
|
|||||||
|
name: Publish Canary Image
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
|
- .github/workflows/build-and-release-runners.yml
|
||||||
|
- .github/workflows/on-push-lint-charts.yml
|
||||||
|
- .github/workflows/on-push-master-publish-chart.yml
|
||||||
|
- .github/workflows/release.yml
|
||||||
|
- .github/workflows/test-entrypoint.yml
|
||||||
- "runner/**"
|
- "runner/**"
|
||||||
- "**.md"
|
- "**.md"
|
||||||
- ".gitignore"
|
- ".gitignore"
|
||||||
@@ -10,7 +17,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: release-latest
|
name: Build and Publish Canary Image
|
||||||
env:
|
env:
|
||||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USER }}
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USER }}
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -1,10 +1,25 @@
|
|||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
### Testing Controller Built from a Pull Request
|
||||||
|
|
||||||
|
We always appreciate your help in testing open pull requests by deploying custom builds of actions-runner-controller onto your own environment, so that we are extra sure we didn't break anything.
|
||||||
|
|
||||||
|
It is especially true when the pull request is about GitHub Enterprise, both GHEC and GHES, as [maintainers don't have GitHub Enterprise environments for testing](/README.md#github-enterprise-support).
|
||||||
|
|
||||||
|
The process would look like the below:
|
||||||
|
|
||||||
|
- Clone this repository locally
|
||||||
|
- Checkout the branch. If you use the `gh` command, run `gh pr checkout $PR_NUMBER`
|
||||||
|
- Run `NAME=$DOCKER_USER/actions-runner-controller VERSION=canary make docker-build docker-push` for a custom container image build
|
||||||
|
- Update your actions-runner-controller's controller-manager deployment to use the new image, `$DOCKER_USER/actions-runner-controller:canary`
|
||||||
|
|
||||||
|
Please also note that you need to replace `$DOCKER_USER` with your own DockerHub account name.
|
||||||
|
|
||||||
### How to Contribute a Patch
|
### How to Contribute a Patch
|
||||||
|
|
||||||
Depending on what you are patching depends on how you should go about it. Below are some guides on how to test patches locally as well as develop the controller and runners.
|
Depending on what you are patching depends on how you should go about it. Below are some guides on how to test patches locally as well as develop the controller and runners.
|
||||||
|
|
||||||
When sumitting a PR for a change please provide evidence that your change works as we still need to work on improving the CI of the project. Some resources are provided for helping achieve this, see this guide for details.
|
When submitting a PR for a change please provide evidence that your change works as we still need to work on improving the CI of the project. Some resources are provided for helping achieve this, see this guide for details.
|
||||||
|
|
||||||
#### Running an End to End Test
|
#### Running an End to End Test
|
||||||
|
|
||||||
@@ -136,7 +151,4 @@ GINKGO_FOCUS='[It] should create a new Runner resource from the specified templa
|
|||||||
|
|
||||||
#### Helm Version Bumps
|
#### Helm Version Bumps
|
||||||
|
|
||||||
**Chart Version :** When bumping the chart version follow semantic versioning https://semver.org/<br />
|
In general we ask you not to bump the version in your PR, the maintainers in general manage the publishing of a new chart.
|
||||||
**App Version :** When bumping the app version you will also need to bump the chart version too. Again, follow semantic versioning when bumping the chart.
|
|
||||||
|
|
||||||
To determine if you need to bump the MAJOR, MINOR or PATCH versions you will need to review the changes between the previous app version and the new app version and / or ask for a maintainer to advise.
|
|
||||||
|
|||||||
34
Makefile
34
Makefile
@@ -18,13 +18,6 @@ KUBECONTEXT ?= kind-acceptance
|
|||||||
CLUSTER ?= acceptance
|
CLUSTER ?= acceptance
|
||||||
CERT_MANAGER_VERSION ?= v1.1.1
|
CERT_MANAGER_VERSION ?= v1.1.1
|
||||||
|
|
||||||
# From https://github.com/VictoriaMetrics/operator/pull/44
|
|
||||||
YAML_DROP=$(YQ) delete --inplace
|
|
||||||
|
|
||||||
# If you encounter errors like the below, you are very likely to update this to follow e.g. CRD version change:
|
|
||||||
# CustomResourceDefinition.apiextensions.k8s.io "runners.actions.summerwind.dev" is invalid: spec.preserveUnknownFields: Invalid value: true: must be false in order to use defaults in the schema
|
|
||||||
YAML_DROP_PREFIX=spec.versions[0].schema.openAPIV3Schema.properties.spec.properties
|
|
||||||
|
|
||||||
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
|
# Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
|
||||||
CRD_OPTIONS ?= "crd:trivialVersions=true,generateEmbeddedObjectMeta=true"
|
CRD_OPTIONS ?= "crd:trivialVersions=true,generateEmbeddedObjectMeta=true"
|
||||||
|
|
||||||
@@ -91,10 +84,13 @@ deploy: manifests
|
|||||||
kustomize build config/default | kubectl apply -f -
|
kustomize build config/default | kubectl apply -f -
|
||||||
|
|
||||||
# Generate manifests e.g. CRD, RBAC etc.
|
# Generate manifests e.g. CRD, RBAC etc.
|
||||||
manifests: manifests-118 fix118 chart-crds
|
manifests: manifests-gen-crds chart-crds
|
||||||
|
|
||||||
manifests-118: 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/
|
||||||
@@ -107,30 +103,14 @@ fmt:
|
|||||||
vet:
|
vet:
|
||||||
go vet ./...
|
go vet ./...
|
||||||
|
|
||||||
# workaround for CRD issue with k8s 1.18 & controller-gen
|
|
||||||
# ref: https://github.com/kubernetes/kubernetes/issues/91395
|
|
||||||
fix118: yq
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.containers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.initContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.sidecarContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerreplicasets.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.ephemeralContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.containers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.initContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.sidecarContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runnerdeployments.yaml $(YAML_DROP_PREFIX).template.properties.spec.properties.ephemeralContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runners.yaml $(YAML_DROP_PREFIX).containers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runners.yaml $(YAML_DROP_PREFIX).initContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runners.yaml $(YAML_DROP_PREFIX).sidecarContainers.items.properties
|
|
||||||
$(YAML_DROP) config/crd/bases/actions.summerwind.dev_runners.yaml $(YAML_DROP_PREFIX).ephemeralContainers.items.properties
|
|
||||||
|
|
||||||
# Generate code
|
# Generate code
|
||||||
generate: controller-gen
|
generate: controller-gen
|
||||||
$(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths="./..."
|
$(CONTROLLER_GEN) object:headerFile=./hack/boilerplate.go.txt paths="./..."
|
||||||
|
|
||||||
# Build the docker image
|
# Build the docker image
|
||||||
docker-build:
|
docker-build:
|
||||||
docker build . -t ${NAME}:${VERSION}
|
docker build -t ${NAME}:${VERSION} .
|
||||||
docker build runner -t ${RUNNER_NAME}:${RUNNER_TAG} --build-arg TARGETPLATFORM=$(shell arch)
|
docker build -t ${RUNNER_NAME}:${RUNNER_TAG} --build-arg TARGETPLATFORM=$(shell arch) runner
|
||||||
|
|
||||||
docker-buildx:
|
docker-buildx:
|
||||||
export DOCKER_CLI_EXPERIMENTAL=enabled
|
export DOCKER_CLI_EXPERIMENTAL=enabled
|
||||||
|
|||||||
464
README.md
464
README.md
@@ -12,14 +12,16 @@ ToC:
|
|||||||
- [Setting Up Authentication with GitHub API](#setting-up-authentication-with-github-api)
|
- [Setting Up Authentication with GitHub API](#setting-up-authentication-with-github-api)
|
||||||
- [Deploying Using GitHub App Authentication](#deploying-using-github-app-authentication)
|
- [Deploying Using GitHub App Authentication](#deploying-using-github-app-authentication)
|
||||||
- [Deploying Using PAT Authentication](#deploying-using-pat-authentication)
|
- [Deploying Using PAT Authentication](#deploying-using-pat-authentication)
|
||||||
|
- [Deploying Multiple Controllers](#deploying-multiple-controllers)
|
||||||
- [Usage](#usage)
|
- [Usage](#usage)
|
||||||
- [Repository Runners](#repository-runners)
|
- [Repository Runners](#repository-runners)
|
||||||
- [Organization Runners](#organization-runners)
|
- [Organization Runners](#organization-runners)
|
||||||
- [Enterprise Runners](#enterprise-runners)
|
- [Enterprise Runners](#enterprise-runners)
|
||||||
- [Runner Deployments](#runnerdeployments)
|
- [RunnerDeployments](#runnerdeployments)
|
||||||
- [Note on scaling to/from 0](#note-on-scaling-tofrom-0)
|
|
||||||
- [Autoscaling](#autoscaling)
|
- [Autoscaling](#autoscaling)
|
||||||
- [Faster Autoscaling with GitHub Webhook](#faster-autoscaling-with-github-webhook)
|
- [Anti-Flapping Configuration](#anti-flapping-configuration)
|
||||||
|
- [Pull Driven Scaling](#pull-driven-scaling)
|
||||||
|
- [Webhook Driven Scaling](#webhook-driven-scaling)
|
||||||
- [Autoscaling to/from 0](#autoscaling-tofrom-0)
|
- [Autoscaling to/from 0](#autoscaling-tofrom-0)
|
||||||
- [Scheduled Overrides](#scheduled-overrides)
|
- [Scheduled Overrides](#scheduled-overrides)
|
||||||
- [Runner with DinD](#runner-with-dind)
|
- [Runner with DinD](#runner-with-dind)
|
||||||
@@ -45,18 +47,18 @@ actions-runner-controller uses [cert-manager](https://cert-manager.io/docs/insta
|
|||||||
|
|
||||||
- [Installing cert-manager on Kubernetes](https://cert-manager.io/docs/installation/kubernetes/)
|
- [Installing cert-manager on Kubernetes](https://cert-manager.io/docs/installation/kubernetes/)
|
||||||
|
|
||||||
Install the custom resource and actions-runner-controller with `kubectl` or `helm`. This will create actions-runner-system namespace in your Kubernetes and deploy the required resources.
|
Subsequent to this, install the custom resource definitions and actions-runner-controller with `kubectl` or `helm`. This will create actions-runner-system namespace in your Kubernetes and deploy the required resources.
|
||||||
|
|
||||||
**Kubectl Deployment:**
|
**Kubectl Deployment:**
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# REPLACE "v0.18.2" with the version you wish to deploy
|
# REPLACE "v0.20.2" with the version you wish to deploy
|
||||||
kubectl apply -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.18.2/actions-runner-controller.yaml
|
kubectl apply -f https://github.com/actions-runner-controller/actions-runner-controller/releases/download/v0.20.2/actions-runner-controller.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
**Helm Deployment:**
|
**Helm Deployment:**
|
||||||
|
|
||||||
**Note: For all configuration options for the Helm chart see the chart's [README](./charts/actions-runner-controller/README.md)**
|
Configure your values.yaml, see the chart's [README](./charts/actions-runner-controller/README.md) for the values documentation
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
|
helm repo add actions-runner-controller https://actions-runner-controller.github.io/actions-runner-controller
|
||||||
@@ -76,7 +78,7 @@ When deploying the solution for a GitHub Enterprise Server environment you need
|
|||||||
kubectl set env deploy controller-manager -c manager GITHUB_ENTERPRISE_URL=<GHEC/S URL> --namespace actions-runner-system
|
kubectl set env deploy controller-manager -c manager GITHUB_ENTERPRISE_URL=<GHEC/S URL> --namespace actions-runner-system
|
||||||
```
|
```
|
||||||
|
|
||||||
__**Note: The repository maintainers do not have an enterprise environment (cloud or server). Support for the enterprise specific feature set is community driven and on a best effort basis. PRs from the community are welcomed to add features and maintain support.**__
|
**_Note: The repository maintainers do not have an enterprise environment (cloud or server). Support for the enterprise specific feature set is community driven and on a best effort basis. PRs from the community are welcomed to add features and maintain support._**
|
||||||
|
|
||||||
## Setting Up Authentication with GitHub API
|
## Setting Up Authentication with GitHub API
|
||||||
|
|
||||||
@@ -93,17 +95,17 @@ If you are deploying the solution for a GitHub Enterprise Server environment you
|
|||||||
|
|
||||||
You can create a GitHub App for either your user account or any organization, below are the app permissions required for each supported type of runner:
|
You can create a GitHub App for either your user account or any organization, below are the app permissions required for each supported type of runner:
|
||||||
|
|
||||||
_Note: Links are provided further down to create an app for your logged in user account or an organisation with the permissions for all runner types set in each link's query string_
|
_Note: Links are provided further down to create an app for your logged in user account or an organization with the permissions for all runner types set in each link's query string_
|
||||||
|
|
||||||
**Required Permissions for Repository Runners:**<br />
|
**Required Permissions for Repository Runners:**<br />
|
||||||
**Repository Permissions**
|
**Repository Permissions**
|
||||||
|
|
||||||
* Actions (read)
|
* Actions (read)
|
||||||
* Administration (read / write)
|
* Administration (read / write)
|
||||||
* Checks (read) (if you are going to use [Faster Autoscaling with GitHub Webhook](#faster-autoscaling-with-github-webhook))
|
* Checks (read) (if you are going to use [Webhook Driven Scaling](#webhook-driven-scaling))
|
||||||
* Metadata (read)
|
* Metadata (read)
|
||||||
|
|
||||||
**Required Permissions for Organisation Runners:**<br />
|
**Required Permissions for Organization Runners:**<br />
|
||||||
**Repository Permissions**
|
**Repository Permissions**
|
||||||
|
|
||||||
* Actions (read)
|
* Actions (read)
|
||||||
@@ -112,11 +114,15 @@ _Note: Links are provided further down to create an app for your logged in user
|
|||||||
**Organization Permissions**
|
**Organization Permissions**
|
||||||
* Self-hosted runners (read / write)
|
* Self-hosted runners (read / write)
|
||||||
|
|
||||||
**Subscribe to events**
|
|
||||||
* Check run (if you are going to use [Faster Autoscaling with GitHub Webhook](#faster-autoscaling-with-github-webhook))
|
|
||||||
|
|
||||||
_Note: All API routes mapped to their permissions can be found [here](https://docs.github.com/en/rest/reference/permissions-required-for-github-apps) if you wish to review_
|
_Note: All API routes mapped to their permissions can be found [here](https://docs.github.com/en/rest/reference/permissions-required-for-github-apps) if you wish to review_
|
||||||
|
|
||||||
|
**Subscribe to events**
|
||||||
|
|
||||||
|
At this point you have a choice of configuring a webhook, a webhook is needed if you are going to use [webhook driven scaling](#webhook-driven-scaling). The webhook can be configured centrally in the GitHub app itself or separately. In either case the event details are:
|
||||||
|
|
||||||
|
* Check run (required for all webhook driven scaling events)
|
||||||
|
* Workflow job (optionally) (required for [webhook driven scaling with workflow_job events](https://github.com/actions-runner-controller/actions-runner-controller#example-1-scale-on-each-workflow_job-event)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Setup Steps**
|
**Setup Steps**
|
||||||
@@ -185,9 +191,11 @@ Log-in to a GitHub account that has `admin` privileges for the repository, and [
|
|||||||
|
|
||||||
**Required Scopes for Enterprise Runners**
|
**Required Scopes for Enterprise Runners**
|
||||||
|
|
||||||
* admin:enterprise (Full control)
|
* admin:enterprise (manage_runners:enterprise)
|
||||||
|
|
||||||
_Note: When you deploy enterprise runners they will get access to organisations, however, access to the repositories themselves is **NOT** allowed by default. Each GitHub organisation must allow enterprise runner groups to be used in repositories as an initial one time configuration step, this only needs to be done once after which it is permanent for that runner group._
|
_Note: When you deploy enterprise runners they will get access to organizations, however, access to the repositories themselves is **NOT** allowed by default. Each GitHub organization must allow enterprise runner groups to be used in repositories as an initial one time configuration step, this only needs to be done once after which it is permanent for that runner group._
|
||||||
|
|
||||||
|
_Note: GitHub do not document exactly what permissions you get with each PAT scope beyond a vague description. The best documentation they provide on the topic can be found [here](https://docs.github.com/en/developers/apps/building-oauth-apps/scopes-for-oauth-apps) if you wish to review. The docs target OAuth apps and so are incomplete and amy not be 100% accurate._
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -205,6 +213,25 @@ kubectl create secret generic controller-manager \
|
|||||||
|
|
||||||
Configure your values.yaml, see the chart's [README](./charts/actions-runner-controller/README.md) for deploying the secret via Helm
|
Configure your values.yaml, see the chart's [README](./charts/actions-runner-controller/README.md) for deploying the secret via Helm
|
||||||
|
|
||||||
|
### Deploying Multiple Controllers
|
||||||
|
|
||||||
|
> This feature requires controller version => [v0.18.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.18.0)
|
||||||
|
|
||||||
|
**_Note: Be aware when using this feature that CRDs are cluster wide and so you should upgrade all of your controllers (and your CRDs) as the same time if you are doing an upgrade. Do not mix and match CRD versions with different controller versions. Doing so risks out of control scaling._**
|
||||||
|
|
||||||
|
By default the controller will look for runners in all namespaces, the watch namespace feature allows you to restrict the controller to monitoring a single namespace. This then lets you deploy multiple controllers in a single cluster. You may want to do this either because you wish to scale beyond the API rate limit of a single PAT / GitHub App configuration or you wish to support multiple GitHub organizations with runners installed at the organization level in a single cluster.
|
||||||
|
|
||||||
|
This feature is configured via the controller's `--watch-namespace` flag. When a namespace is provided via this flag, the controller will only monitor runners in that namespace.
|
||||||
|
|
||||||
|
If you plan on installing all instances of the controller stack into a single namespace you will need to make the names of the resources unique to each stack. In the case of Helm this can be done by giving each install a unique release name, or via the `fullnameOverride` properties.
|
||||||
|
|
||||||
|
Alternatively, you can install each controller stack into its own unique namespace (relative to other controller stacks in the cluster), avoiding the need to uniquely prefix resources.
|
||||||
|
|
||||||
|
When you go to the route of sharing the namespace while giving each a unique Helm release name, you must also ensure the following values are configured correctly:
|
||||||
|
|
||||||
|
- `authSecret.name` needs be unique per stack when each stack is tied to runners in different GitHub organizations and repositories AND you want your GitHub credentials to narrowly scoped.
|
||||||
|
- `leaderElectionId` needs to be unique per stack. If this is not unique to the stack the controller tries to race onto the leader election lock and resulting in only one stack working concurrently.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
[GitHub self-hosted runners can be deployed at various levels in a management hierarchy](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners#about-self-hosted-runners):
|
[GitHub self-hosted runners can be deployed at various levels in a management hierarchy](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners#about-self-hosted-runners):
|
||||||
@@ -228,7 +255,7 @@ kind: Runner
|
|||||||
metadata:
|
metadata:
|
||||||
name: example-runner
|
name: example-runner
|
||||||
spec:
|
spec:
|
||||||
repository: actions-runner-controller/actions-runner-controller
|
repository: example/myrepo
|
||||||
env: []
|
env: []
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -295,9 +322,11 @@ Now you can see the runner on the enterprise level (if you have enterprise acces
|
|||||||
|
|
||||||
### RunnerDeployments
|
### RunnerDeployments
|
||||||
|
|
||||||
There are `RunnerReplicaSet` and `RunnerDeployment` that corresponds to `ReplicaSet` and `Deployment` but for `Runner`.
|
You can manage sets of runners instead of individually through the `RunnerDeployment` kind and its `replicas:` attribute. This kind is required for many of the advanced features.
|
||||||
|
|
||||||
You usually need only `RunnerDeployment` rather than `RunnerReplicaSet` as the former is for managing the latter.
|
There are `RunnerReplicaSet` and `RunnerDeployment` kinds that corresponds to the `ReplicaSet` and `Deployment` kinds but for the `Runner` kind.
|
||||||
|
|
||||||
|
You typically only need `RunnerDeployment` rather than `RunnerReplicaSet` as the former is for managing the latter.
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
# runnerdeployment.yaml
|
# runnerdeployment.yaml
|
||||||
@@ -329,63 +358,19 @@ example-runnerdeploy2475h595fr mumoshu/actions-runner-controller-ci Running
|
|||||||
example-runnerdeploy2475ht2qbr mumoshu/actions-runner-controller-ci Running
|
example-runnerdeploy2475ht2qbr mumoshu/actions-runner-controller-ci Running
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Note on scaling to/from 0
|
|
||||||
|
|
||||||
> This feature is available since actions-runner-controller v0.19.0
|
|
||||||
|
|
||||||
You can either delete the runner deployment, or update it to have `replicas: 0`, so that there will be 0 runner pods in the cluster. This, in combination with e.g. `cluster-autoscaler`, enables you to save your infrastructure cost when there's no need to run Actions jobs.
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
# runnerdeployment.yaml
|
|
||||||
apiVersion: actions.summerwind.dev/v1alpha1
|
|
||||||
kind: RunnerDeployment
|
|
||||||
metadata:
|
|
||||||
name: example-runnerdeploy
|
|
||||||
spec:
|
|
||||||
replicas: 0
|
|
||||||
```
|
|
||||||
|
|
||||||
The implication of setting `replicas: 0` instead of deleting the runner deployment is that you can let GitHub Actions queue jobs until there will be one or more runners. See [#465](https://github.com/actions-runner-controller/actions-runner-controller/pull/465) for more information.
|
|
||||||
|
|
||||||
Also note that the controller creates a "registration-only" runner per RunnerReplicaSet on it's being scaled to zero,
|
|
||||||
and retains it until there are one or more runners available.
|
|
||||||
|
|
||||||
This, in combination with a correctly configured HorizontalRunnerAutoscaler, allows you to automatically [scale to/from 0](#autoscaling-tofrom-0)
|
|
||||||
|
|
||||||
### Autoscaling
|
### Autoscaling
|
||||||
|
|
||||||
__**IMPORTANT : Due to limitations / a bug with GitHub's [routing engine](https://docs.github.com/en/actions/hosting-your-own-runners/using-self-hosted-runners-in-a-workflow#routing-precedence-for-self-hosted-runners) autoscaling does NOT work correctly with RunnerDeployments that target the enterprise level. Scaling activity works as expected however jobs fail to get assigned to the scaled out replicas. This was explored in issue [#470](https://github.com/actions-runner-controller/actions-runner-controller/issues/470). Once GitHub resolves the issue with their backend service we expect the solution to be able to support autoscaled enterprise runnerdeploments without any additional changes.**__
|
> Since the release of GitHub's [`workflow_job` webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#workflow_job), webhook driven scaling is the preferred way of autoscaling as it enables targeted scaling of your `RunnerDeployments` / `RunnerSets` as it includes the `runs-on` information needed to scale the appropriate runners for that workflow run. More broadly, webhook driven scaling is the preferred scaling option as it is far quicker compared to the pull driven scaling and is easy to setup.
|
||||||
|
|
||||||
**NOTE: Once `workflow_job` webhook events are released on GitHub, the webhook-based autoscaling is the preferred way of autoscaling, because it is easy to configure and has the ability to accurately detect which runners to scale. See [Example 3: Scale on each `workflow_job` event](#example-3-scale-on-each-workflow_job-event)**
|
A `RunnerDeployment` or `RunnerSet` (see [stateful runners](#stateful-runners) for more details on this kind) can scale the number of runners between `minReplicas` and `maxReplicas` fields driven by either pull based scaling metrics or via a webhook event (see limitations section of [stateful runners](#stateful-runners) for cavaets of this kind). Whether the autoscaling is driven from a webhook event or pull based metrics it is implemented by backing a `RunnerDeployment` or `RunnerSet` kind with a `HorizontalRunnerAutoscaler` kind.
|
||||||
|
|
||||||
A `RunnerDeployment` (excluding enterprise runners) can scale the number of runners between `minReplicas` and `maxReplicas` fields based the chosen scaling metric as defined in the `metrics` attribute
|
#### Anti-Flapping Configuration
|
||||||
|
|
||||||
**Scaling Metrics**
|
For both pull driven or webhook driven scaling an anti-flapping implementation is included, by default a runner won't be scaled down within 10 minutes of it having been scaled up. This delay is configurable by including the attribute `scaleDownDelaySecondsAfterScaleOut:` in a `HorizontalRunnerAutoscaler` kind's `spec:`.
|
||||||
|
|
||||||
**TotalNumberOfQueuedAndInProgressWorkflowRuns**
|
This configuration has the final say on if a runner can be scaled down or not regardless of the chosen scaling method. Depending on your requirements, you may want to consider adjusting this by setting the `scaleDownDelaySecondsAfterScaleOut:` attribute.
|
||||||
|
|
||||||
In the below example, `actions-runner` will poll GitHub for all pending workflows with the poll period defined by the sync period configuration. It will then scale to e.g. 3 if there're 3 pending jobs at sync time.
|
Below is a complete basic example with one of the pull driven scaling metrics.
|
||||||
With this scaling metric we are required to define a list of repositories within our metric.
|
|
||||||
|
|
||||||
The scale out performance is controlled via the manager containers startup `--sync-period` argument. The default value is set to 10 minutes to prevent default deployments rate limiting themselves from the GitHub API.
|
|
||||||
|
|
||||||
**Kustomize Config :** The period can be customised in the `config/default/manager_auth_proxy_patch.yaml` patch<br />
|
|
||||||
|
|
||||||
**Benefits of this metric**
|
|
||||||
1. Supports named repositories allowing you to restrict the runner to a specified set of repositories server side.
|
|
||||||
2. Scales the runner count based on the actual queue depth of the jobs meaning a more 1:1 scaling of runners to queued jobs (caveat, see drawback #4)
|
|
||||||
3. Like all scaling metrics, you can manage workflow allocation to the RunnerDeployment through the use of [GitHub labels](#runner-labels).
|
|
||||||
|
|
||||||
**Drawbacks of this metric**
|
|
||||||
1. Repositories must be named within the scaling metric, maintaining a list of repositories may not be viable in larger environments or self-serve environments.
|
|
||||||
2. May not scale quick enough for some users needs. This metric is pull based and so the queue depth is polled as configured by the sync period, as a result scaling performance is bound by this sync period meaning there is a lag to scaling activity.
|
|
||||||
3. Relatively large amounts of API requests required to maintain this metric, you may run in API rate limit issues depending on the size of your environment and how aggressive your sync period configuration is
|
|
||||||
4. The GitHub API doesn't provide a way to filter workflow jobs to just those targeting self-hosted runners. If your environment's workflows target both self-hosted and GitHub hosted runners then the queue depth this metric scales against isn't a true 1:1 mapping of queue depth to required runner count. As a result of this, this metric may scale too aggressively for your actual self-hosted runner count needs.
|
|
||||||
|
|
||||||
|
|
||||||
Example `RunnerDeployment` backed by a `HorizontalRunnerAutoscaler`:
|
|
||||||
|
|
||||||
_Important!!! We no longer include the attribute `replicas` in our `RunnerDeployment` if we are configuring autoscaling!_
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: actions.summerwind.dev/v1alpha1
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
@@ -395,7 +380,78 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
template:
|
template:
|
||||||
spec:
|
spec:
|
||||||
repository: actions-runner-controller/actions-runner-controller
|
repository: example/myrepo
|
||||||
|
---
|
||||||
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
|
kind: HorizontalRunnerAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: example-runner-deployment-autoscaler
|
||||||
|
spec:
|
||||||
|
# Runners in the targeted RunnerDeployment won't be scaled down for 5 minutes instead of the default 10 minutes now
|
||||||
|
scaleDownDelaySecondsAfterScaleOut: 300
|
||||||
|
scaleTargetRef:
|
||||||
|
name: example-runner-deployment
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 5
|
||||||
|
metrics:
|
||||||
|
- type: PercentageRunnersBusy
|
||||||
|
scaleUpThreshold: '0.75'
|
||||||
|
scaleDownThreshold: '0.25'
|
||||||
|
scaleUpFactor: '2'
|
||||||
|
scaleDownFactor: '0.5'
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Pull Driven Scaling
|
||||||
|
|
||||||
|
> To configure webhook driven scaling see the [Webhook Driven Scaling](#webhook-driven-scaling) section
|
||||||
|
|
||||||
|
The pull based metrics are configured in the `metrics` attribute of a HRA (see snippet below). The period between polls is defined by the controller's `--sync-period` flag. If this flag isn't provided then the controller defaults to a sync period of 10 minutes. The default value is set to 10 minutes to prevent default deployments rate limiting themselves from the GitHub API, you will most likely want to adjust this.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
|
kind: HorizontalRunnerAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: example-runner-deployment-autoscaler
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
# Your RunnerDeployment Here
|
||||||
|
name: example-runner-deployment
|
||||||
|
minReplicas: 1
|
||||||
|
maxReplicas: 5
|
||||||
|
# Your chosen scaling metrics here
|
||||||
|
metrics: []
|
||||||
|
```
|
||||||
|
|
||||||
|
**Metric Options:**
|
||||||
|
|
||||||
|
**TotalNumberOfQueuedAndInProgressWorkflowRuns**
|
||||||
|
|
||||||
|
The `TotalNumberOfQueuedAndInProgressWorkflowRuns` metric polls GitHub for all pending workflow runs against a given set of repositories. The metric will scale the runner count up to the total number of pending jobs at the sync time up to the `maxReplicas` configuration.
|
||||||
|
|
||||||
|
**Benefits of this metric**
|
||||||
|
1. Supports named repositories allowing you to restrict the runner to a specified set of repositories server-side.
|
||||||
|
2. Scales the runner count based on the depth of the job queue meaning a more 1:1 scaling of runners to queued jobs (caveat, see drawback #4)
|
||||||
|
3. Like all scaling metrics, you can manage workflow allocation to the RunnerDeployment through the use of [GitHub labels](#runner-labels).
|
||||||
|
|
||||||
|
**Drawbacks of this metric**
|
||||||
|
1. A list of repositories must be included within the scaling metric. Maintaining a list of repositories may not be viable in larger environments or self-serve environments.
|
||||||
|
2. May not scale quick enough for some users needs. This metric is pull based and so the queue depth is polled as configured by the sync period, as a result scaling performance is bound by this sync period meaning there is a lag to scaling activity.
|
||||||
|
3. Relatively large amounts of API requests required to maintain this metric, you may run in API rate limit issues depending on the size of your environment and how aggressive your sync period configuration is.
|
||||||
|
4. The GitHub API doesn't provide a way to filter workflow jobs to just those targeting self-hosted runners. If your environment's workflows target both self-hosted and GitHub hosted runners then the queue depth this metric scales against isn't a true 1:1 mapping of queue depth to required runner count. As a result of this, this metric may scale too aggressively for your actual self-hosted runner count needs.
|
||||||
|
|
||||||
|
Example `RunnerDeployment` backed by a `HorizontalRunnerAutoscaler`:
|
||||||
|
|
||||||
|
**_Important!!! We no longer include the attribute `replicas` in our `RunnerDeployment` if we are configuring autoscaling!_**
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
|
kind: RunnerDeployment
|
||||||
|
metadata:
|
||||||
|
name: example-runner-deployment
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
repository: example/myrepo
|
||||||
---
|
---
|
||||||
apiVersion: actions.summerwind.dev/v1alpha1
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
@@ -405,29 +461,19 @@ spec:
|
|||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: example-runner-deployment
|
name: example-runner-deployment
|
||||||
minReplicas: 1
|
minReplicas: 1
|
||||||
maxReplicas: 3
|
maxReplicas: 5
|
||||||
metrics:
|
metrics:
|
||||||
- type: TotalNumberOfQueuedAndInProgressWorkflowRuns
|
- type: TotalNumberOfQueuedAndInProgressWorkflowRuns
|
||||||
repositoryNames:
|
repositoryNames:
|
||||||
- actions-runner-controller/actions-runner-controller
|
- example/myrepo
|
||||||
```
|
|
||||||
|
|
||||||
Additionally, the `HorizontalRunnerAutoscaler` also has an anti-flapping option that prevents periodic loop of scaling up and down.
|
|
||||||
By default, it doesn't scale down until the grace period of 10 minutes passes after a scale up. The grace period can be configured however by adding the setting `scaleDownDelaySecondsAfterScaleOut` in the `HorizontalRunnerAutoscaler` `spec`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
spec:
|
|
||||||
scaleDownDelaySecondsAfterScaleOut: 60
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**PercentageRunnersBusy**
|
**PercentageRunnersBusy**
|
||||||
|
|
||||||
The `HorizontalRunnerAutoscaler` will poll GitHub based on the configuration sync period for the number of busy runners which live in the RunnerDeployment's namespace and scale based on the settings
|
The `HorizontalRunnerAutoscaler` will poll GitHub for the number of runners in the `busy` state which live in the RunnerDeployment's namespace, it will then scale depending on how you have configured the scale factors.
|
||||||
|
|
||||||
**Kustomize Config :** The period can be customised in the `config/default/manager_auth_proxy_patch.yaml` patch<br />
|
|
||||||
|
|
||||||
**Benefits of this metric**
|
**Benefits of this metric**
|
||||||
1. Supports named repositories server side the same as the `TotalNumberOfQueuedAndInProgressWorkflowRuns` metric [#313](https://github.com/actions-runner-controller/actions-runner-controller/pull/313)
|
1. Supports named repositories server-side the same as the `TotalNumberOfQueuedAndInProgressWorkflowRuns` metric [#313](https://github.com/actions-runner-controller/actions-runner-controller/pull/313)
|
||||||
2. Supports GitHub organization wide scaling without maintaining an explicit list of repositories, this is especially useful for those that are working at a larger scale. [#223](https://github.com/actions-runner-controller/actions-runner-controller/pull/223)
|
2. Supports GitHub organization wide scaling without maintaining an explicit list of repositories, this is especially useful for those that are working at a larger scale. [#223](https://github.com/actions-runner-controller/actions-runner-controller/pull/223)
|
||||||
3. Like all scaling metrics, you can manage workflow allocation to the RunnerDeployment through the use of [GitHub labels](#runner-labels)
|
3. Like all scaling metrics, you can manage workflow allocation to the RunnerDeployment through the use of [GitHub labels](#runner-labels)
|
||||||
4. Supports scaling desired runner count on both a percentage increase / decrease basis as well as on a fixed increase / decrease count basis [#223](https://github.com/actions-runner-controller/actions-runner-controller/pull/223) [#315](https://github.com/actions-runner-controller/actions-runner-controller/pull/315)
|
4. Supports scaling desired runner count on both a percentage increase / decrease basis as well as on a fixed increase / decrease count basis [#223](https://github.com/actions-runner-controller/actions-runner-controller/pull/223) [#315](https://github.com/actions-runner-controller/actions-runner-controller/pull/315)
|
||||||
@@ -436,11 +482,9 @@ The `HorizontalRunnerAutoscaler` will poll GitHub based on the configuration syn
|
|||||||
1. May not scale quick enough for some users needs. This metric is pull based and so the number of busy runners are polled as configured by the sync period, as a result scaling performance is bound by this sync period meaning there is a lag to scaling activity.
|
1. May not scale quick enough for some users needs. This metric is pull based and so the number of busy runners are polled as configured by the sync period, as a result scaling performance is bound by this sync period meaning there is a lag to scaling activity.
|
||||||
2. We are scaling up and down based on indicative information rather than a count of the actual number of queued jobs and so the desired runner count is likely to under provision new runners or overprovision them relative to actual job queue depth, this may or may not be a problem for you.
|
2. We are scaling up and down based on indicative information rather than a count of the actual number of queued jobs and so the desired runner count is likely to under provision new runners or overprovision them relative to actual job queue depth, this may or may not be a problem for you.
|
||||||
|
|
||||||
|
|
||||||
Examples of each scaling type implemented with a `RunnerDeployment` backed by a `HorizontalRunnerAutoscaler`:
|
Examples of each scaling type implemented with a `RunnerDeployment` backed by a `HorizontalRunnerAutoscaler`:
|
||||||
|
|
||||||
|
**_Important!!! We no longer include the attribute `replicas` in our `RunnerDeployment` if we are configuring autoscaling!_**
|
||||||
_Important!!! We no longer include the attribute `replicas` in our `RunnerDeployment` if we are configuring autoscaling!_
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
---
|
---
|
||||||
@@ -452,7 +496,7 @@ spec:
|
|||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: example-runner-deployment
|
name: example-runner-deployment
|
||||||
minReplicas: 1
|
minReplicas: 1
|
||||||
maxReplicas: 3
|
maxReplicas: 5
|
||||||
metrics:
|
metrics:
|
||||||
- type: PercentageRunnersBusy
|
- type: PercentageRunnersBusy
|
||||||
scaleUpThreshold: '0.75' # The percentage of busy runners at which the number of desired runners are re-evaluated to scale up
|
scaleUpThreshold: '0.75' # The percentage of busy runners at which the number of desired runners are re-evaluated to scale up
|
||||||
@@ -471,7 +515,7 @@ spec:
|
|||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: example-runner-deployment
|
name: example-runner-deployment
|
||||||
minReplicas: 1
|
minReplicas: 1
|
||||||
maxReplicas: 3
|
maxReplicas: 5
|
||||||
metrics:
|
metrics:
|
||||||
- type: PercentageRunnersBusy
|
- type: PercentageRunnersBusy
|
||||||
scaleUpThreshold: '0.75' # The percentage of busy runners at which the number of desired runners are re-evaluated to scale up
|
scaleUpThreshold: '0.75' # The percentage of busy runners at which the number of desired runners are re-evaluated to scale up
|
||||||
@@ -480,35 +524,23 @@ spec:
|
|||||||
scaleDownAdjustment: 1 # The scale down runner count subtracted from the desired count
|
scaleDownAdjustment: 1 # The scale down runner count subtracted from the desired count
|
||||||
```
|
```
|
||||||
|
|
||||||
Like the previous metric, the scale down factor respects the anti-flapping configuration is applied to the `HorizontalRunnerAutoscaler` as mentioned previously:
|
#### Webhook Driven Scaling
|
||||||
|
|
||||||
```yaml
|
> To configure pull driven scaling see the [Pull Driven Scaling](#pull-driven-scaling) section
|
||||||
spec:
|
|
||||||
scaleDownDelaySecondsAfterScaleOut: 60
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Faster Autoscaling with GitHub Webhook
|
Webhooks are processed by a seperate webhook server. The webhook server receives GitHub Webhook events and scales
|
||||||
|
|
||||||
__**IMPORTANT : Due to missing webhook events, webhook based scaling is not available for enterprise level RunnerDeployments. This was explored in issue [#470](https://github.com/actions-runner-controller/actions-runner-controller/issues/470).**__
|
|
||||||
|
|
||||||
> This feature is an ADVANCED feature which may require more work to set up.
|
|
||||||
> Please get prepared to put some time and effort to learn and leverage this feature!
|
|
||||||
|
|
||||||
`actions-runner-controller` has an optional Webhook server that receives GitHub Webhook events and scale
|
|
||||||
[`RunnerDeployments`](#runnerdeployments) by updating corresponding [`HorizontalRunnerAutoscalers`](#autoscaling).
|
[`RunnerDeployments`](#runnerdeployments) by updating corresponding [`HorizontalRunnerAutoscalers`](#autoscaling).
|
||||||
|
|
||||||
Today, the Webhook server can be configured to respond GitHub `check_run`, `pull_request`, and `push` events
|
Today, the Webhook server can be configured to respond GitHub `check_run`, `workflow_job`, `pull_request` and `push` events
|
||||||
by scaling up the matching `HorizontalRunnerAutoscaler` by N replica(s), where `N` is configurable within
|
by scaling up the matching `HorizontalRunnerAutoscaler` by N replica(s), where `N` is configurable within `HorizontalRunnerAutoscaler`'s `spec:`.
|
||||||
`HorizontalRunnerAutoscaler's` `Spec`.
|
|
||||||
|
|
||||||
More concretely, you can configure the targeted GitHub event types and the `N` in
|
More concretely, you can configure the targeted GitHub event types and the `N` in `scaleUpTriggers`:
|
||||||
`scaleUpTriggers`:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
spec:
|
spec:
|
||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
scaleUpTriggers:
|
scaleUpTriggers:
|
||||||
- githubEvent:
|
- githubEvent:
|
||||||
checkRun:
|
checkRun:
|
||||||
@@ -518,21 +550,20 @@ spec:
|
|||||||
duration: "5m"
|
duration: "5m"
|
||||||
```
|
```
|
||||||
|
|
||||||
With the above example, the webhook server scales `myrunners` by `1` replica for 5 minutes on each `check_run` event
|
With the above example, the webhook server scales `example-runners` by `1` replica for 5 minutes on each `check_run` event with the type of `created` and the status of `queued` received.
|
||||||
with the type of `created` and the status of `queued` received.
|
|
||||||
|
|
||||||
The primary benefit of autoscaling on Webhook compared to the standard autoscaling is that this one allows you to
|
Of note is the `HRA.spec.scaleUpTriggers[].duration` attribute. This attribute is used to calculate if the replica number added via the trigger is expired or not. On each reconcilation loop, the controller sums up all the non-expiring replica numbers from previous scale up triggers. It then compares the summed desired replica number against the current replica number. If the summed desired replica number > the current number then it means the replica count needs to scale up.
|
||||||
immediately add "resource slack" for future GitHub Actions job runs.
|
|
||||||
|
|
||||||
In contrast, the standard autoscaling requires you to wait next sync period to add
|
As mentioned previously, the `scaleDownDelaySecondsAfterScaleOut` property has the final say still. If the latest scale-up time + the anti-flapping duration is later than the current time, it doesn’t immediately scale up and instead retries the calculation again later to see if it needs to scale yet.
|
||||||
insufficient runners. You can definitely shorten the sync period to make the standard autoscaling more responsive.
|
|
||||||
But doing so eventually results in the controller not being functional due to it being rated limited by the GitHub API.
|
---
|
||||||
|
|
||||||
|
The primary benefit of autoscaling on Webhook compared to the pull driven scaling is that it is far quicker as it allows you to immediately add runners resource rather than waiting for the next sync period.
|
||||||
|
|
||||||
> You can learn the implementation details in [#282](https://github.com/actions-runner-controller/actions-runner-controller/pull/282)
|
> You can learn the implementation details in [#282](https://github.com/actions-runner-controller/actions-runner-controller/pull/282)
|
||||||
|
|
||||||
To enable this feature, you firstly need to install the webhook server.
|
To enable this feature, you firstly need to install the webhook server, currently, only our Helm chart has the ability install it:
|
||||||
|
_[see the values documentation for all configuration options](https://github.com/actions-runner-controller/actions-runner-controller/blob/master/charts/actions-runner-controller/README.md)_
|
||||||
Currently, only our Helm chart has the ability install it.
|
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ helm --upgrade install actions-runner-controller/actions-runner-controller \
|
$ helm --upgrade install actions-runner-controller/actions-runner-controller \
|
||||||
@@ -548,10 +579,42 @@ Once you were able to confirm that the Webhook server is ready and running from
|
|||||||
GitHub sending PING events to the Webhook server - create or update your `HorizontalRunnerAutoscaler` resources
|
GitHub sending PING events to the Webhook server - create or update your `HorizontalRunnerAutoscaler` resources
|
||||||
by learning the following configuration examples.
|
by learning the following configuration examples.
|
||||||
|
|
||||||
- [Example 1: Scale up on each `check_run` event](#example-1-scale-up-on-each-check_run-event)
|
- [Example 1: Scale on each `workflow_job` event](#example-1-scale-on-each-workflow_job-event)
|
||||||
- [Example 2: Scale on each `pull_request` event against `develop` or `main` branches](#example-2-scale-on-each-pull_request-event-against-develop-or-main-branches)
|
- [Example 2: Scale up on each `check_run` event](#example-2-scale-up-on-each-check_run-event)
|
||||||
|
- [Example 3: Scale on each `pull_request` event against a given set of branches](#example-3-scale-on-each-pull_request-event-against-a-given-set-of-branches)
|
||||||
|
- [Example 4: Scale on each `push` event](#example-4-scale-on-each-push-event)
|
||||||
|
|
||||||
##### Example 1: Scale up on each `check_run` event
|
##### Example 1: Scale on each `workflow_job` event
|
||||||
|
|
||||||
|
> This feature requires controller version => [v0.20.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.20.0)
|
||||||
|
|
||||||
|
The most flexible webhook GitHub offers is the `workflow_job` webhook, it includes the `runs-on` information in the payload allowing scaling based on runner labels.
|
||||||
|
|
||||||
|
This webhook should cover most people's needs, please experiment with this webhook first before considering the others.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
kind: RunnerDeployment
|
||||||
|
metadata:
|
||||||
|
name: example-runners
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
spec:
|
||||||
|
repository: example/myrepo
|
||||||
|
---
|
||||||
|
kind: HorizontalRunnerAutoscaler
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
name: example-runners
|
||||||
|
scaleUpTriggers:
|
||||||
|
- githubEvent: {}
|
||||||
|
duration: "30m"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can configure your GitHub webhook settings to only include `Workflows Job` events, so that it sends us three kinds of `workflow_job` events per a job run.
|
||||||
|
|
||||||
|
Each kind has a `status` of `queued`, `in_progress` and `completed`. With the above configuration, `actions-runner-controller` adds one runner for a `workflow_job` event whose `status` is `queued`. Similarly, it removes one runner for a `workflow_job` event whose `status` is `completed`. The cavaet to this to remember is that this the scale down is within the bounds of your `scaleDownDelaySecondsAfterScaleOut` configuration, if this time hasn't past the scale down will be defered.
|
||||||
|
|
||||||
|
##### Example 2: Scale up on each `check_run` event
|
||||||
|
|
||||||
> Note: This should work almost like https://github.com/philips-labs/terraform-aws-github-runner
|
> Note: This should work almost like https://github.com/philips-labs/terraform-aws-github-runner
|
||||||
|
|
||||||
@@ -560,14 +623,16 @@ To scale up replicas of the runners for `example/myrepo` by 1 for 5 minutes on e
|
|||||||
```yaml
|
```yaml
|
||||||
kind: RunnerDeployment
|
kind: RunnerDeployment
|
||||||
metadata:
|
metadata:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
spec:
|
spec:
|
||||||
repository: example/myrepo
|
template:
|
||||||
|
spec:
|
||||||
|
repository: example/myrepo
|
||||||
---
|
---
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
spec:
|
spec:
|
||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
scaleUpTriggers:
|
scaleUpTriggers:
|
||||||
- githubEvent:
|
- githubEvent:
|
||||||
checkRun:
|
checkRun:
|
||||||
@@ -582,38 +647,44 @@ To scale up replicas of the runners for `myorg` organization by 1 for 5 minutes
|
|||||||
```yaml
|
```yaml
|
||||||
kind: RunnerDeployment
|
kind: RunnerDeployment
|
||||||
metadata:
|
metadata:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
spec:
|
spec:
|
||||||
organization: myorg
|
template:
|
||||||
|
spec:
|
||||||
|
organization: myorg
|
||||||
---
|
---
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
spec:
|
spec:
|
||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
scaleUpTriggers:
|
scaleUpTriggers:
|
||||||
- githubEvent:
|
- githubEvent:
|
||||||
checkRun:
|
checkRun:
|
||||||
types: ["created"]
|
types: ["created"]
|
||||||
status: "queued"
|
status: "queued"
|
||||||
# allow only certain repositories within your organization to trigger autoscaling
|
# Optionally restrict autoscaling to being triggered by events from specific repositories within your organization still
|
||||||
# repositories: ["myrepo", "myanotherrepo"]
|
# repositories: ["myrepo", "myanotherrepo"]
|
||||||
amount: 1
|
amount: 1
|
||||||
duration: "5m"
|
duration: "5m"
|
||||||
```
|
```
|
||||||
|
|
||||||
###### Example 2: Scale on each `pull_request` event against `develop` or `main` branches
|
##### Example 3: Scale on each `pull_request` event against a given set of branches
|
||||||
|
|
||||||
|
To scale up replicas of the runners for `example/myrepo` by 1 for 5 minutes on each `pull_request` against the `main` or `develop` branch you write manifests like the below:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
kind: RunnerDeployment
|
kind: RunnerDeployment
|
||||||
metadata:
|
metadata:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
spec:
|
spec:
|
||||||
repository: example/myrepo
|
template:
|
||||||
|
spec:
|
||||||
|
repository: example/myrepo
|
||||||
---
|
---
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
spec:
|
spec:
|
||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
scaleUpTriggers:
|
scaleUpTriggers:
|
||||||
- githubEvent:
|
- githubEvent:
|
||||||
pullRequest:
|
pullRequest:
|
||||||
@@ -625,90 +696,56 @@ spec:
|
|||||||
|
|
||||||
See ["activity types"](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request) for the list of valid values for `scaleUpTriggers[].githubEvent.pullRequest.types`.
|
See ["activity types"](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request) for the list of valid values for `scaleUpTriggers[].githubEvent.pullRequest.types`.
|
||||||
|
|
||||||
###### Example 3: Scale on each `workflow_job` event
|
###### Example 4: Scale on each push event
|
||||||
|
|
||||||
> This feature depends on an unreleased GitHub feature
|
To scale up replicas of the runners for `example/myrepo` by 1 for 5 minutes on each `push` write manifests like the below:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
kind: RunnerDeployment
|
kind: RunnerDeployment
|
||||||
metadata:
|
metadata:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
spec:
|
spec:
|
||||||
repository: example/myrepo
|
repository: example/myrepo
|
||||||
---
|
---
|
||||||
kind: HorizontalRunnerAutoscaler
|
kind: HorizontalRunnerAutoscaler
|
||||||
spec:
|
spec:
|
||||||
scaleTargetRef:
|
scaleTargetRef:
|
||||||
name: myrunners
|
name: example-runners
|
||||||
scaleUpTriggers:
|
scaleUpTriggers:
|
||||||
- githubEvent: {}
|
- githubEvent:
|
||||||
duration: "30m"
|
push:
|
||||||
|
amount: 1
|
||||||
|
duration: "5m"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can configure your GitHub webhook settings to only include `Workflows Job` events, so that it sends us three kinds of `workflow_job` events per a job run.
|
|
||||||
|
|
||||||
Each kind has a `status` of `queued`, `in_progress` and `completed`.
|
|
||||||
With the above configuration, `actions-runner-controller` adds one runner for a `workflow_job` event whose `status` is `queued`. Similarly, it removes one runner for a `workflow_job` event whose `status` is `completed`.
|
|
||||||
|
|
||||||
Beware that a scale-down after a scale-up is deferred until `scaleDownDelaySecondsAfterScaleOut` elapses. Let's say you had configured `scaleDownDelaySecondsAfterScaleOut` of 60 seconds, 2 consequtive workflow jobs will result in immediately adding 2 runners. The 2 runners are removed only after 60 seconds. This basically gives you 60 seconds of a "grace period" that makes it possible for self-hosted runners to immediately run additional workflow jobs enqueued in that 60 seconds.
|
|
||||||
|
|
||||||
You must not include `spec.metrics` like `PercentageRunnersBusy` when using this feature, as it is unnecessary. That is, if you've configured the webhook for `workflow_job`, it should be enough for all the scale-out need.
|
|
||||||
|
|
||||||
#### Autoscaling to/from 0
|
#### Autoscaling to/from 0
|
||||||
|
|
||||||
> This feature is available since actions-runner-controller v0.19.0
|
> This feature requires controller version => [v0.19.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.19.0)
|
||||||
|
|
||||||
Previously, we've discussed about [how to scale a RunnerDeployment to/from 0](#note-on-scaling-tofrom-0)
|
_Note: The controller creates a "registration-only" runner per RunnerReplicaSet when it is being scaled to zero and retains it until there are one or more runners available. This is a deprecated feature for GitHub Cloud as "registration-only" runners are no longer needed due to GitHub changing their runner [routing logic](https://docs.github.com/en/enterprise-cloud@latest/actions/hosting-your-own-runners/using-self-hosted-runners-in-a-workflow#routing-precedence-for-self-hosted-runners) to no longer fail a workflow run if it targets a runner label that there are no registered runners for._
|
||||||
|
|
||||||
To automate the process of scaling to/from 0, you can use `HorizontalRunnerAutoscaler` with a caveat.
|
The regular `RunnerDeployment` `replicas:` attribute as well as the `HorizontalRunnerAutoscaler` `minReplicas:` attribute supports being set to 0.
|
||||||
|
|
||||||
That is, you need to choose one of the following configuration for metrics and triggers:
|
The main use case for scaling from 0 is with the `HorizontalRunnerAutoscaler` kind. To scale from 0 whilst still being able to provision runners as jobs are queued we must use the `HorizontalRunnerAutoscaler` with only certain scaling configurations, only the below configurations support scaling from 0 whilst also being able to provision runners as jobs are queued:
|
||||||
|
|
||||||
- `TotalNumberOfQueuedAndInProgressWorkflowRuns`
|
- `TotalNumberOfQueuedAndInProgressWorkflowRuns`
|
||||||
- `PercentageRunnersBusy` + `TotalNumberOfQueuedAndInProgressWorkflowRuns`
|
- `PercentageRunnersBusy` + `TotalNumberOfQueuedAndInProgressWorkflowRuns`
|
||||||
- `PercentageRunnersBusy` + Webhook-based autoscaling
|
- `PercentageRunnersBusy` + Webhook-based autoscaling
|
||||||
|
- Webhook-based autoscaling only
|
||||||
|
|
||||||
This is due to that `PercentageRunnersBusy`, by its definition, needs one or more GitHub runners that can become `busy`, which cannot happen at all when you have 0 active runners.
|
`PercentageRunnersBusy` can't be used alone as, by its definition, it needs one or more GitHub runners to become `busy` to be able to scale. If there isn't a runner to pick up a job and enter a `busy` state then the controller will never know to provision a runner to begin with as this metric has no knowledge of the job queue and is relying using the number of busy runners as a means for calculating the desired replica count.
|
||||||
|
|
||||||
If and only if HorizontalRunnerAutoscaler is configured to have a secondary metric of `TotalNumberOfQueuedAndInProgressWorkflowRuns` and the controller sees the primary metric of `PercentageRunnersBusy` returned 0 desired replicas, it uses the secondary metric for calculating the desired replicas once again.
|
If a HorizontalRunnerAutoscaler is configured with a secondary metric of `TotalNumberOfQueuedAndInProgressWorkflowRuns` then be aware that the controller will check the primary metric of `PercentageRunnersBusy` first and will only use the secondary metric to calculate the desired replica count if the primary metric returns 0 desired replicas.
|
||||||
|
|
||||||
A correctly configured `TotalNumberOfQueuedAndInProgressWorkflowRuns` can return non-zero desired replicas even when there are no runners other than [registration-only runners](#note-on-scaling-tofrom-0), hence the `PercentageRunnersBusy` + `TotalNumberOfQueuedAndInProgressWorkflowRuns` configuration makes scaling from zero possible.
|
|
||||||
|
|
||||||
Similarly, Webhook-based autoscaling works regardless of there are active runners, hence `PercentageRunnersBusy` + Webhook-based autoscaling configuration makes scaling from zero, too.
|
|
||||||
|
|
||||||
#### Scheduled Overrides
|
#### Scheduled Overrides
|
||||||
|
|
||||||
> This feature is available since actions-runner-controller v0.19.0
|
> This feature requires controller version => [v0.19.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.19.0)
|
||||||
|
|
||||||
`Scheduled Overrides` allows you to configure HorizontalRunnerAutoscaler so that its Spec gets updated only during a certain period of time.
|
`Scheduled Overrides` allows you to configure `HorizontalRunnerAutoscaler` so that its `spec:` gets updated only during a certain period of time. This feature is usually used for following scenarios:
|
||||||
|
|
||||||
usually, this feature is used for following scenarios:
|
- You want to reduce your infrastructure costs by scaling your Kubernetes nodes down outside a given period
|
||||||
|
- You want to scale for scheduled spikes in workloads
|
||||||
|
|
||||||
- You want to pay for your infrastructure cost running runners only in business hours
|
The most basic usage of this feature is to set a non-repeating override:
|
||||||
- You want to prepare for scheduled spikes in workloads
|
|
||||||
|
|
||||||
For the first scenario, you might consider configuration like the below:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
apiVersion: actions.summerwind.dev/v1alpha1
|
|
||||||
kind: HorizontalRunnerAutoscaler
|
|
||||||
metadata:
|
|
||||||
name: example-runner-deployment-autoscaler
|
|
||||||
spec:
|
|
||||||
scaleTargetRef:
|
|
||||||
name: example-runner-deployment
|
|
||||||
scheduledOverrides:
|
|
||||||
# Override minReplicas to 0 only between 0am sat to 0am mon
|
|
||||||
- startTime: "2021-05-01T00:00:00+09:00"
|
|
||||||
endTime: "2021-05-03T00:00:00+09:00"
|
|
||||||
recurrenceRule:
|
|
||||||
frequency: Weekly
|
|
||||||
untilTime: "2022-05-01T00:00:00+09:00"
|
|
||||||
minReplicas: 0
|
|
||||||
minReplicas: 1
|
|
||||||
```
|
|
||||||
|
|
||||||
For the second scenario, you might consider something like the below:
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: actions.summerwind.dev/v1alpha1
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
@@ -726,10 +763,31 @@ spec:
|
|||||||
minReplicas: 1
|
minReplicas: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
The most basic usage of this feature is actually the second scenario mentioned above.
|
|
||||||
A scheduled override without `recurrenceRule` is considered a one-off override, that is active between `startTime` and `endTime`. In the second scenario, it overrides `minReplicas` to `100` only between `2021-06-01T00:00:00+09:00` and `2021-06-03T00:00:00+09:00`.
|
A scheduled override without `recurrenceRule` is considered a one-off override, that is active between `startTime` and `endTime`. In the second scenario, it overrides `minReplicas` to `100` only between `2021-06-01T00:00:00+09:00` and `2021-06-03T00:00:00+09:00`.
|
||||||
|
|
||||||
A scheduled override with `recurrenceRule` is considered a recurring override. A recurring override is initially active between `startTime` and `endTime`, and then it repeatedly get activated after a certain period of time denoted by `frequency`.
|
A more advanced configuration is to include a `recurrenceRule` in the override:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: actions.summerwind.dev/v1alpha1
|
||||||
|
kind: HorizontalRunnerAutoscaler
|
||||||
|
metadata:
|
||||||
|
name: example-runner-deployment-autoscaler
|
||||||
|
spec:
|
||||||
|
scaleTargetRef:
|
||||||
|
name: example-runner-deployment
|
||||||
|
scheduledOverrides:
|
||||||
|
# Override minReplicas to 0 only between 0am sat to 0am mon
|
||||||
|
- startTime: "2021-05-01T00:00:00+09:00"
|
||||||
|
endTime: "2021-05-03T00:00:00+09:00"
|
||||||
|
recurrenceRule:
|
||||||
|
frequency: Weekly
|
||||||
|
# Optional sunset datetime attribute
|
||||||
|
# untilTime: "2022-05-01T00:00:00+09:00"
|
||||||
|
minReplicas: 0
|
||||||
|
minReplicas: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
A recurring override is initially active between `startTime` and `endTime`, and then it repeatedly get activated after a certain period of time denoted by `frequency`.
|
||||||
|
|
||||||
`frequecy` can take one of the following values:
|
`frequecy` can take one of the following values:
|
||||||
|
|
||||||
@@ -740,7 +798,7 @@ A scheduled override with `recurrenceRule` is considered a recurring override. A
|
|||||||
|
|
||||||
By default, a scheduled override repeats forever. If you want it to repeat until a specific point in time, define `untilTime`. The controller create the last recurrence of the override until the recurrence's `startTime` is equal or earlier than `untilTime`.
|
By default, a scheduled override repeats forever. If you want it to repeat until a specific point in time, define `untilTime`. The controller create the last recurrence of the override until the recurrence's `startTime` is equal or earlier than `untilTime`.
|
||||||
|
|
||||||
Do note that you have enough slack for `untilTime`, so that a delayed or offline `actions-runner-controller` is much less likely to miss the last recurrence. For example, you might want to set `untilTime` to `M` minutes after the last recurrence's `startTime`, so that `actions-runner-controller` being offline up to `M` minutes doesn't miss the last recurrence.
|
Do ensure that you have enough slack for `untilTime` so that a delayed or offline `actions-runner-controller` is much less likely to miss the last recurrence. For example, you might want to set `untilTime` to `M` minutes after the last recurrence's `startTime`, so that `actions-runner-controller` being offline up to `M` minutes doesn't miss the last recurrence.
|
||||||
|
|
||||||
**Combining Multiple Scheduled Overrides**:
|
**Combining Multiple Scheduled Overrides**:
|
||||||
|
|
||||||
@@ -748,6 +806,8 @@ In case you have a more complex scenarios, try writing two or more entries under
|
|||||||
|
|
||||||
The earlier entry is prioritized higher than later entries. So you usually define one-time overrides in the top of your list, then yearly, monthly, weekly, and lastly daily overrides.
|
The earlier entry is prioritized higher than later entries. So you usually define one-time overrides in the top of your list, then yearly, monthly, weekly, and lastly daily overrides.
|
||||||
|
|
||||||
|
A common use case for this may be to have 1 override to scale to 0 during the week outside of core business hours and another override to scale to 0 during all hours of the weekend.
|
||||||
|
|
||||||
### Runner with DinD
|
### Runner with DinD
|
||||||
|
|
||||||
When using default runner, runner pod starts up 2 containers: runner and DinD (Docker-in-Docker). This might create issues if there's `LimitRange` set to namespace.
|
When using default runner, runner pod starts up 2 containers: runner and DinD (Docker-in-Docker). This might create issues if there's `LimitRange` set to namespace.
|
||||||
@@ -804,9 +864,17 @@ spec:
|
|||||||
key: node-role.kubernetes.io/test
|
key: node-role.kubernetes.io/test
|
||||||
operator: Exists
|
operator: Exists
|
||||||
|
|
||||||
|
topologySpreadConstraints:
|
||||||
|
- maxSkew: 1
|
||||||
|
topologyKey: kubernetes.io/hostname
|
||||||
|
whenUnsatisfiable: ScheduleAnyway
|
||||||
|
labelSelector:
|
||||||
|
matchLabels:
|
||||||
|
runner-deployment-name: actions-runner
|
||||||
|
|
||||||
repository: mumoshu/actions-runner-controller-ci
|
repository: mumoshu/actions-runner-controller-ci
|
||||||
# The default "summerwind/actions-runner" images are available at DockerHub:
|
# The default "summerwind/actions-runner" images are available at DockerHub:
|
||||||
# https://hub.docker.com/r/summerwind/actions-runner
|
# https://hub.docker.com/r/summerwind/actions-runner
|
||||||
# You can also build your own and specify it like the below:
|
# You can also build your own and specify it like the below:
|
||||||
image: custom-image/actions-runner:latest
|
image: custom-image/actions-runner:latest
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
@@ -965,7 +1033,7 @@ spec:
|
|||||||
|
|
||||||
### Using IRSA (IAM Roles for Service Accounts) in EKS
|
### Using IRSA (IAM Roles for Service Accounts) in EKS
|
||||||
|
|
||||||
`actions-runner-controller` v0.15.0 or later has support for IRSA in EKS.
|
> This feature requires controller version => [v0.15.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.15.0)
|
||||||
|
|
||||||
As similar as for regular pods and deployments, you firstly need an existing service account with the IAM role associated.
|
As similar as for regular pods and deployments, you firstly need an existing service account with the IAM role associated.
|
||||||
Create one using e.g. `eksctl`. You can refer to [the EKS documentation](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) for more details.
|
Create one using e.g. `eksctl`. You can refer to [the EKS documentation](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) for more details.
|
||||||
@@ -993,7 +1061,7 @@ spec:
|
|||||||
|
|
||||||
Istio 1.7.0 or greater has `holdApplicationUntilProxyStarts` added in https://github.com/istio/istio/pull/24737, which enables you to delay the `runner` container startup until the injected `istio-proxy` container finish starting. Try using it if you need to use Istio. Otherwise the runner is unlikely to work, because it fails to call any GitHub API to register itself due to `istio-proxy` being not up and running yet.
|
Istio 1.7.0 or greater has `holdApplicationUntilProxyStarts` added in https://github.com/istio/istio/pull/24737, which enables you to delay the `runner` container startup until the injected `istio-proxy` container finish starting. Try using it if you need to use Istio. Otherwise the runner is unlikely to work, because it fails to call any GitHub API to register itself due to `istio-proxy` being not up and running yet.
|
||||||
|
|
||||||
Note that there's no official Istio integration in actions-runner-controller. It should work, but it isn't covered by our acceptance test(contribution is welcomed). In addition to that, none of the actions-runner-controller maintainers use Istio daily. If you need more information, or have any issues using it, refer to the following links:
|
Note that there's no official Istio integration in actions-runner-controller. It should work, but it isn't covered by our acceptance test (a contribution to resolve this is welcomed). In addition to that, none of the actions-runner-controller maintainers use Istio daily. If you need more information, or have any issues using it, refer to the following links:
|
||||||
|
|
||||||
- https://github.com/actions-runner-controller/actions-runner-controller/issues/591
|
- https://github.com/actions-runner-controller/actions-runner-controller/issues/591
|
||||||
- https://github.com/actions-runner-controller/actions-runner-controller/pull/592
|
- https://github.com/actions-runner-controller/actions-runner-controller/pull/592
|
||||||
@@ -1001,10 +1069,7 @@ Note that there's no official Istio integration in actions-runner-controller. It
|
|||||||
|
|
||||||
### Stateful Runners
|
### Stateful Runners
|
||||||
|
|
||||||
> This is a documentation about a unreleased version of actions-runner-controller.
|
> This feature requires controller version => [v0.20.0](https://github.com/actions-runner-controller/actions-runner-controller/releases/tag/v0.20.0)
|
||||||
>
|
|
||||||
> It would be great if you could try building the latest controller image following https://github.com/actions-runner-controller/actions-runner-controller#contributing if you are eager to test it early and help
|
|
||||||
> developers by reporting any bugs :smile:
|
|
||||||
|
|
||||||
`actions-runner-controller` supports `RunnerSet` API that let you deploy stateful runners. A stateful runner is designed to be able to store some data persists across GitHub Actions workflow and job runs. You might find it useful, for example, to speed up your docker builds by persisting the docker layer cache.
|
`actions-runner-controller` supports `RunnerSet` API that let you deploy stateful runners. A stateful runner is designed to be able to store some data persists across GitHub Actions workflow and job runs. You might find it useful, for example, to speed up your docker builds by persisting the docker layer cache.
|
||||||
|
|
||||||
@@ -1093,10 +1158,9 @@ We envision that `RunnerSet` will eventually replace `RunnerDeployment`, as `Run
|
|||||||
|
|
||||||
**Limitations**
|
**Limitations**
|
||||||
|
|
||||||
A known down-side of `RunnerSet` compared to `RunnerDeployment` is that it is uanble to create [a registration-only pod on scaling-down to zero](https://github.com/actions-runner-controller/actions-runner-controller#note-on-scaling-tofrom-0). To workaround that, you need to create a `RunnerDeployment` with `spec.repliacs` set to `0` with `spec.repository`, `spec.organization`, or `spec.enterprise`, and `spec.labels` and `spec.groups` as same values as your `RunnerSet`, so that you can keep the registration-only runner regardless of the number of `RunnerSet`-managed runners.
|
* For autoscaling the `RunnerSet` kind only supports pull driven scaling or the `workflow_job` event for webhook driven scaling.
|
||||||
|
* For autoscaling the `RunnerSet` kind doesn't support the [registration-only runner](#autoscaling-tofrom-0)
|
||||||
A known down-side of relying on `StatefulSet` is that it misses a support for `maxUnavailable`.
|
* A known down-side of relying on `StatefulSet` is that it misses a support for `maxUnavailable`. A `StatefulSet` basically works like `maxUnavailable: 1` in `Deployment`, which means that it can take down only one pod concurrently while doing a rolling-update of pods. Kubernetes 1.22 doesn't support customizing it yet so probably it takes more releases to arrive. See https://github.com/kubernetes/kubernetes/issues/68397 for more information.
|
||||||
A `StatefulSet` basically works like `maxUnavailable: 1` in `Deployment`, which means that it can take down only one pod concurrently while doing a rolling-update of pods. Kubernetes 1.22 doesn't support customizing it yet so probably it takes more releases to arrive. See https://github.com/kubernetes/kubernetes/issues/68397 for more information.
|
|
||||||
|
|
||||||
### Ephemeral Runners
|
### Ephemeral Runners
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ type HorizontalRunnerAutoscalerSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
MinReplicas *int `json:"minReplicas,omitempty"`
|
MinReplicas *int `json:"minReplicas,omitempty"`
|
||||||
|
|
||||||
// MinReplicas is the maximum number of replicas the deployment is allowed to scale
|
// MaxReplicas is the maximum number of replicas the deployment is allowed to scale
|
||||||
// +optional
|
// +optional
|
||||||
MaxReplicas *int `json:"maxReplicas,omitempty"`
|
MaxReplicas *int `json:"maxReplicas,omitempty"`
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,9 @@ type RunnerPodSpec struct {
|
|||||||
// +optional
|
// +optional
|
||||||
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`
|
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`
|
||||||
|
|
||||||
|
// +optional
|
||||||
|
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraint,omitempty"`
|
||||||
|
|
||||||
// RuntimeClassName is the container runtime configuration that containers should run under.
|
// RuntimeClassName is the container runtime configuration that containers should run under.
|
||||||
// More info: https://kubernetes.io/docs/concepts/containers/runtime-class
|
// More info: https://kubernetes.io/docs/concepts/containers/runtime-class
|
||||||
// +optional
|
// +optional
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -706,6 +707,13 @@ func (in *RunnerPodSpec) DeepCopyInto(out *RunnerPodSpec) {
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if in.TopologySpreadConstraints != nil {
|
||||||
|
in, out := &in.TopologySpreadConstraints, &out.TopologySpreadConstraints
|
||||||
|
*out = make([]v1.TopologySpreadConstraint, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
if in.RuntimeClassName != nil {
|
if in.RuntimeClassName != nil {
|
||||||
in, out := &in.RuntimeClassName, &out.RuntimeClassName
|
in, out := &in.RuntimeClassName, &out.RuntimeClassName
|
||||||
*out = new(string)
|
*out = new(string)
|
||||||
|
|||||||
@@ -2,3 +2,4 @@
|
|||||||
lint-conf: charts/.ci/lint-config.yaml
|
lint-conf: charts/.ci/lint-config.yaml
|
||||||
chart-repos:
|
chart-repos:
|
||||||
- jetstack=https://charts.jetstack.io
|
- jetstack=https://charts.jetstack.io
|
||||||
|
check-version-increment: false # Disable checking that the chart version has been bumped
|
||||||
|
|||||||
@@ -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.15.0
|
||||||
|
|
||||||
# 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.3
|
||||||
|
|
||||||
home: https://github.com/actions-runner-controller/actions-runner-controller
|
home: https://github.com/actions-runner-controller/actions-runner-controller
|
||||||
|
|
||||||
|
|||||||
@@ -4,36 +4,40 @@ 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 | |
|
||||||
| `authSecret.create` | Deploy the controller auth secret | false |
|
| `authSecret.create` | Deploy the controller auth secret | false |
|
||||||
| `authSecret.name` | Set the name of the auth secret | controller-manager |
|
| `authSecret.name` | Set the name of the auth secret | controller-manager |
|
||||||
|
| `authSecret.annotations` | Set annotations for the auth Secret | |
|
||||||
| `authSecret.github_app_id` | The ID of your GitHub App. **This can't be set at the same time as `authSecret.github_token`** | |
|
| `authSecret.github_app_id` | The ID of your GitHub App. **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_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 |
|
||||||
| `image.dindSidecarRepositoryAndTag` | The "repository/image" of the dind sidecar container | docker:dind |
|
| `image.dindSidecarRepositoryAndTag` | The "repository/image" of the dind sidecar container | docker:dind |
|
||||||
| `image.pullPolicy` | The pull policy of the controller image | IfNotPresent |
|
| `image.pullPolicy` | The pull policy of the controller image | IfNotPresent |
|
||||||
| `metrics.serviceMonitor` | Deploy serviceMonitor kind for for use with prometheus-operator CRDs | false |
|
| `metrics.serviceMonitor` | Deploy serviceMonitor kind for for use with prometheus-operator CRDs | false |
|
||||||
|
| `metrics.serviceAnnotations` | Set annotations for the provisioned metrics service resource | |
|
||||||
| `metrics.port` | Set port of metrics service | 8443 |
|
| `metrics.port` | Set port of metrics service | 8443 |
|
||||||
| `metrics.proxy.enabled` | Deploy kube-rbac-proxy container in controller pod | true |
|
| `metrics.proxy.enabled` | Deploy kube-rbac-proxy container in controller pod | true |
|
||||||
| `metrics.proxy.image.repository` | The "repository/image" of the kube-proxy container | quay.io/brancz/kube-rbac-proxy |
|
| `metrics.proxy.image.repository` | The "repository/image" of the kube-proxy container | quay.io/brancz/kube-rbac-proxy |
|
||||||
| `metrics.proxy.image.tag` | The tag of the kube-proxy image to use when pulling the container | v0.10.0 |
|
| `metrics.proxy.image.tag` | The tag of the kube-proxy image to use when pulling the container | v0.10.0 |
|
||||||
| `metrics.serviceMonitorLabels` | Set labels to apply to ServiceMonitor resources | |
|
| `metrics.serviceMonitorLabels` | Set labels to apply to ServiceMonitor resources | |
|
||||||
| `imagePullSecrets` | Specifies the secret to be used when pulling the controller pod containers | |
|
| `imagePullSecrets` | Specifies the secret to be used when pulling the controller pod containers | |
|
||||||
| `fullNameOverride` | Override the full resource names | |
|
| `fullNameOverride` | Override the full resource names | |
|
||||||
| `nameOverride` | Override the resource name prefix | |
|
| `nameOverride` | Override the resource name prefix | |
|
||||||
@@ -44,16 +48,20 @@ _Default values are the defaults set in the charts values.yaml, some properties
|
|||||||
| `serviceAccount.name` | Set the name of the service account | |
|
| `serviceAccount.name` | Set the name of the service account | |
|
||||||
| `securityContext` | Set the security context for each container in the controller pod | |
|
| `securityContext` | Set the security context for each container in the controller pod | |
|
||||||
| `podSecurityContext` | Set the security context to controller pod | |
|
| `podSecurityContext` | Set the security context to controller pod | |
|
||||||
|
| `service.annotations` | Set annotations for the provisioned webhook service resource | |
|
||||||
| `service.port` | Set controller service type | |
|
| `service.port` | Set controller service type | |
|
||||||
| `service.type` | Set controller service ports | |
|
| `service.type` | Set controller service ports | |
|
||||||
| `topologySpreadConstraints` | Set the controller pod topologySpreadConstraints | |
|
| `topologySpreadConstraints` | Set the controller pod topologySpreadConstraints | |
|
||||||
| `nodeSelector` | Set the controller pod nodeSelector | |
|
| `nodeSelector` | Set the controller pod nodeSelector | |
|
||||||
| `resources` | Set the controller pod resources | |
|
| `resources` | Set the controller pod resources | |
|
||||||
| `affinity` | Set the controller pod affinity rules | |
|
| `affinity` | Set the controller pod affinity rules |
|
||||||
|
| `podDisruptionBudget.enabled` | Enables a PDB to ensure HA of controller pods | false |
|
||||||
|
| `podDisruptionBudget.minAvailable` | Minimum number of pods that must be available after eviction | |
|
||||||
|
| `podDisruptionBudget.maxUnavailable` | Maximum number of pods that can be unavailable after eviction. Kubernetes 1.7+ required. | |
|
||||||
| `tolerations` | Set the controller pod tolerations | |
|
| `tolerations` | Set the controller pod tolerations | |
|
||||||
| `env` | Set environment variables for the controller container | |
|
| `env` | Set environment variables for the controller container | |
|
||||||
| `priorityClassName` | Set the controller pod priorityClassName | |
|
| `priorityClassName` | Set the controller pod priorityClassName | |
|
||||||
| `scope.watchNamespace` | Tells the controller which namespace to watch if `scope.singleNamespace` is true | |
|
| `scope.watchNamespace` | Tells the controller and the github webhook server which namespace to watch if `scope.singleNamespace` is true | `Release.Namespace` (the default namespace of the helm chart). |
|
||||||
| `scope.singleNamespace` | Limit the controller to watch a single namespace | false |
|
| `scope.singleNamespace` | Limit the controller to watch a single namespace | false |
|
||||||
| `githubWebhookServer.logLevel` | Set the log level of the githubWebhookServer container | |
|
| `githubWebhookServer.logLevel` | Set the log level of the githubWebhookServer container | |
|
||||||
| `githubWebhookServer.replicaCount` | Set the number of webhook server pods | 1 |
|
| `githubWebhookServer.replicaCount` | Set the number of webhook server pods | 1 |
|
||||||
@@ -84,3 +92,6 @@ _Default values are the defaults set in the charts values.yaml, some properties
|
|||||||
| `githubWebhookServer.ingress.annotations` | Set annotations for the ingress kind | |
|
| `githubWebhookServer.ingress.annotations` | Set annotations for the ingress kind | |
|
||||||
| `githubWebhookServer.ingress.hosts` | Set hosts configuration for ingress | `[{"host": "chart-example.local", "paths": []}]` |
|
| `githubWebhookServer.ingress.hosts` | Set hosts configuration for ingress | `[{"host": "chart-example.local", "paths": []}]` |
|
||||||
| `githubWebhookServer.ingress.tls` | Set tls configuration for ingress | |
|
| `githubWebhookServer.ingress.tls` | Set tls configuration for ingress | |
|
||||||
|
| `githubWebhookServer.podDisruptionBudget.enabled` | Enables a PDB to ensure HA of githubwebhook pods | false |
|
||||||
|
| `githubWebhookServer.podDisruptionBudget.minAvailable` | Minimum number of pods that must be available after eviction | |
|
||||||
|
| `githubWebhookServer.podDisruptionBudget.maxUnavailable` | Maximum number of pods that can be unavailable after eviction. Kubernetes 1.7+ required. | |
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
---
|
|
||||||
apiVersion: apiextensions.k8s.io/v1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
@@ -14,291 +12,228 @@ spec:
|
|||||||
listKind: HorizontalRunnerAutoscalerList
|
listKind: HorizontalRunnerAutoscalerList
|
||||||
plural: horizontalrunnerautoscalers
|
plural: horizontalrunnerautoscalers
|
||||||
shortNames:
|
shortNames:
|
||||||
- hra
|
- hra
|
||||||
singular: horizontalrunnerautoscaler
|
singular: horizontalrunnerautoscaler
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
versions:
|
versions:
|
||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
- jsonPath: .spec.minReplicas
|
- jsonPath: .spec.minReplicas
|
||||||
name: Min
|
name: Min
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .spec.maxReplicas
|
- jsonPath: .spec.maxReplicas
|
||||||
name: Max
|
name: Max
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .status.desiredReplicas
|
- jsonPath: .status.desiredReplicas
|
||||||
name: Desired
|
name: Desired
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .status.scheduledOverridesSummary
|
- jsonPath: .status.scheduledOverridesSummary
|
||||||
name: Schedule
|
name: Schedule
|
||||||
type: string
|
type: string
|
||||||
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 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'
|
||||||
description: 'APIVersion defines the versioned schema of this representation
|
type: string
|
||||||
of an object. Servers should convert recognized schemas to the latest
|
kind:
|
||||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
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'
|
||||||
type: string
|
type: string
|
||||||
kind:
|
metadata:
|
||||||
description: 'Kind is a string value representing the REST resource this
|
type: object
|
||||||
object represents. Servers may infer this from the endpoint the client
|
spec:
|
||||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
description: HorizontalRunnerAutoscalerSpec defines the desired state of HorizontalRunnerAutoscaler
|
||||||
type: string
|
properties:
|
||||||
metadata:
|
capacityReservations:
|
||||||
type: object
|
items:
|
||||||
spec:
|
description: CapacityReservation specifies the number of replicas temporarily added to the scale target until ExpirationTime.
|
||||||
description: HorizontalRunnerAutoscalerSpec defines the desired state
|
properties:
|
||||||
of HorizontalRunnerAutoscaler
|
expirationTime:
|
||||||
properties:
|
format: date-time
|
||||||
capacityReservations:
|
type: string
|
||||||
items:
|
name:
|
||||||
description: CapacityReservation specifies the number of replicas
|
type: string
|
||||||
temporarily added to the scale target until ExpirationTime.
|
replicas:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
maxReplicas:
|
||||||
|
description: MaxReplicas is the maximum number of replicas the deployment is allowed to scale
|
||||||
|
type: integer
|
||||||
|
metrics:
|
||||||
|
description: Metrics is the collection of various metric targets to calculate desired number of runners
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
repositoryNames:
|
||||||
|
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`.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
scaleDownAdjustment:
|
||||||
|
description: ScaleDownAdjustment is the number of runners removed on scale-down. You can only specify either ScaleDownFactor or ScaleDownAdjustment.
|
||||||
|
type: integer
|
||||||
|
scaleDownFactor:
|
||||||
|
description: ScaleDownFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be removed.
|
||||||
|
type: string
|
||||||
|
scaleDownThreshold:
|
||||||
|
description: ScaleDownThreshold is the percentage of busy runners less than which will trigger the hpa to scale the runners down.
|
||||||
|
type: string
|
||||||
|
scaleUpAdjustment:
|
||||||
|
description: ScaleUpAdjustment is the number of runners added on scale-up. You can only specify either ScaleUpFactor or ScaleUpAdjustment.
|
||||||
|
type: integer
|
||||||
|
scaleUpFactor:
|
||||||
|
description: ScaleUpFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be added.
|
||||||
|
type: string
|
||||||
|
scaleUpThreshold:
|
||||||
|
description: ScaleUpThreshold is the percentage of busy runners greater than which will trigger the hpa to scale runners up.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: Type is the type of metric to be used for autoscaling. The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
minReplicas:
|
||||||
|
description: MinReplicas is the minimum number of replicas the deployment is allowed to scale
|
||||||
|
type: integer
|
||||||
|
scaleDownDelaySecondsAfterScaleOut:
|
||||||
|
description: ScaleDownDelaySecondsAfterScaleUp is the approximate delay for a scale down followed by a scale up Used to prevent flapping (down->up->down->... loop)
|
||||||
|
type: integer
|
||||||
|
scaleTargetRef:
|
||||||
|
description: ScaleTargetRef sis the reference to scaled resource like RunnerDeployment
|
||||||
properties:
|
properties:
|
||||||
expirationTime:
|
kind:
|
||||||
format: date-time
|
description: Kind is the type of resource being referenced
|
||||||
|
enum:
|
||||||
|
- RunnerDeployment
|
||||||
|
- RunnerSet
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
|
description: Name is the name of resource being referenced
|
||||||
type: string
|
type: string
|
||||||
replicas:
|
|
||||||
type: integer
|
|
||||||
type: object
|
type: object
|
||||||
type: array
|
scaleUpTriggers:
|
||||||
maxReplicas:
|
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."
|
||||||
description: MinReplicas is the maximum number of replicas the deployment
|
items:
|
||||||
is allowed to scale
|
properties:
|
||||||
type: integer
|
amount:
|
||||||
metrics:
|
type: integer
|
||||||
description: Metrics is the collection of various metric targets to
|
duration:
|
||||||
calculate desired number of runners
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
repositoryNames:
|
|
||||||
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`.
|
|
||||||
items:
|
|
||||||
type: string
|
type: string
|
||||||
type: array
|
githubEvent:
|
||||||
scaleDownAdjustment:
|
properties:
|
||||||
description: ScaleDownAdjustment is the number of runners removed
|
checkRun:
|
||||||
on scale-down. You can only specify either ScaleDownFactor
|
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
|
||||||
or ScaleDownAdjustment.
|
properties:
|
||||||
type: integer
|
names:
|
||||||
scaleDownFactor:
|
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.
|
||||||
description: ScaleDownFactor is the multiplicative factor applied
|
items:
|
||||||
to the current number of runners used to determine how many
|
type: string
|
||||||
pods should be removed.
|
type: array
|
||||||
type: string
|
repositories:
|
||||||
scaleDownThreshold:
|
description: Repositories is a list of GitHub repositories. Any check_run event whose repository matches one of repositories in the list can trigger autoscaling.
|
||||||
description: ScaleDownThreshold is the percentage of busy runners
|
items:
|
||||||
less than which will trigger the hpa to scale the runners
|
type: string
|
||||||
down.
|
type: array
|
||||||
type: string
|
status:
|
||||||
scaleUpAdjustment:
|
|
||||||
description: ScaleUpAdjustment is the number of runners added
|
|
||||||
on scale-up. You can only specify either ScaleUpFactor or
|
|
||||||
ScaleUpAdjustment.
|
|
||||||
type: integer
|
|
||||||
scaleUpFactor:
|
|
||||||
description: ScaleUpFactor is the multiplicative factor applied
|
|
||||||
to the current number of runners used to determine how many
|
|
||||||
pods should be added.
|
|
||||||
type: string
|
|
||||||
scaleUpThreshold:
|
|
||||||
description: ScaleUpThreshold is the percentage of busy runners
|
|
||||||
greater than which will trigger the hpa to scale runners up.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type is the type of metric to be used for autoscaling.
|
|
||||||
The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
minReplicas:
|
|
||||||
description: MinReplicas is the minimum number of replicas the deployment
|
|
||||||
is allowed to scale
|
|
||||||
type: integer
|
|
||||||
scaleDownDelaySecondsAfterScaleOut:
|
|
||||||
description: ScaleDownDelaySecondsAfterScaleUp is the approximate
|
|
||||||
delay for a scale down followed by a scale up Used to prevent flapping
|
|
||||||
(down->up->down->... loop)
|
|
||||||
type: integer
|
|
||||||
scaleTargetRef:
|
|
||||||
description: ScaleTargetRef sis the reference to scaled resource like
|
|
||||||
RunnerDeployment
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
description: Kind is the type of resource being referenced
|
|
||||||
enum:
|
|
||||||
- RunnerDeployment
|
|
||||||
- RunnerSet
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
description: Name is the name of resource being referenced
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
scaleUpTriggers:
|
|
||||||
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."
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
amount:
|
|
||||||
type: integer
|
|
||||||
duration:
|
|
||||||
type: string
|
|
||||||
githubEvent:
|
|
||||||
properties:
|
|
||||||
checkRun:
|
|
||||||
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
|
|
||||||
properties:
|
|
||||||
names:
|
|
||||||
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.
|
|
||||||
items:
|
|
||||||
type: string
|
type: string
|
||||||
type: array
|
types:
|
||||||
repositories:
|
items:
|
||||||
description: Repositories is a list of GitHub repositories.
|
type: string
|
||||||
Any check_run event whose repository matches one of
|
type: array
|
||||||
repositories in the list can trigger autoscaling.
|
type: object
|
||||||
items:
|
pullRequest:
|
||||||
type: string
|
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request
|
||||||
type: array
|
properties:
|
||||||
status:
|
branches:
|
||||||
type: string
|
items:
|
||||||
types:
|
type: string
|
||||||
items:
|
type: array
|
||||||
type: string
|
types:
|
||||||
type: array
|
items:
|
||||||
type: object
|
type: string
|
||||||
pullRequest:
|
type: array
|
||||||
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request
|
type: object
|
||||||
properties:
|
push:
|
||||||
branches:
|
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
|
||||||
items:
|
type: object
|
||||||
type: string
|
type: object
|
||||||
type: array
|
type: object
|
||||||
types:
|
type: array
|
||||||
items:
|
scheduledOverrides:
|
||||||
type: string
|
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.
|
||||||
type: array
|
items:
|
||||||
type: object
|
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.
|
||||||
push:
|
properties:
|
||||||
description: PushSpec is the condition for triggering scale-up
|
endTime:
|
||||||
on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
|
description: EndTime is the time at which the first override ends.
|
||||||
type: object
|
format: date-time
|
||||||
type: object
|
type: string
|
||||||
type: object
|
minReplicas:
|
||||||
type: array
|
description: MinReplicas is the number of runners while overriding. If omitted, it doesn't override minReplicas.
|
||||||
scheduledOverrides:
|
minimum: 0
|
||||||
description: ScheduledOverrides is the list of ScheduledOverride.
|
nullable: true
|
||||||
It can be used to override a few fields of HorizontalRunnerAutoscalerSpec
|
type: integer
|
||||||
on schedule. The earlier a scheduled override is, the higher it
|
recurrenceRule:
|
||||||
is prioritized.
|
properties:
|
||||||
items:
|
frequency:
|
||||||
description: ScheduledOverride can be used to override a few fields
|
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 HorizontalRunnerAutoscalerSpec on schedule. A schedule can
|
enum:
|
||||||
optionally be recurring, so that the correspoding override happens
|
- Daily
|
||||||
every day, week, month, or year.
|
- Weekly
|
||||||
properties:
|
- Monthly
|
||||||
endTime:
|
- Yearly
|
||||||
description: EndTime is the time at which the first override
|
type: string
|
||||||
ends.
|
untilTime:
|
||||||
format: date-time
|
description: UntilTime is the time of the final recurrence. If empty, the schedule recurs forever.
|
||||||
type: string
|
format: date-time
|
||||||
minReplicas:
|
type: string
|
||||||
description: MinReplicas is the number of runners while overriding.
|
type: object
|
||||||
If omitted, it doesn't override minReplicas.
|
startTime:
|
||||||
minimum: 0
|
description: StartTime is the time at which the first override starts.
|
||||||
nullable: true
|
format: date-time
|
||||||
type: integer
|
type: string
|
||||||
recurrenceRule:
|
required:
|
||||||
properties:
|
- endTime
|
||||||
frequency:
|
- startTime
|
||||||
description: Frequency is the name of a predefined interval
|
type: object
|
||||||
of each recurrence. The valid values are "Daily", "Weekly",
|
type: array
|
||||||
"Monthly", and "Yearly". If empty, the corresponding override
|
type: object
|
||||||
happens only once.
|
status:
|
||||||
enum:
|
properties:
|
||||||
- Daily
|
cacheEntries:
|
||||||
- Weekly
|
items:
|
||||||
- Monthly
|
properties:
|
||||||
- Yearly
|
expirationTime:
|
||||||
type: string
|
format: date-time
|
||||||
untilTime:
|
type: string
|
||||||
description: UntilTime is the time of the final recurrence.
|
key:
|
||||||
If empty, the schedule recurs forever.
|
type: string
|
||||||
format: date-time
|
value:
|
||||||
type: string
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
startTime:
|
type: array
|
||||||
description: StartTime is the time at which the first override
|
desiredReplicas:
|
||||||
starts.
|
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.
|
||||||
format: date-time
|
type: integer
|
||||||
type: string
|
lastSuccessfulScaleOutTime:
|
||||||
required:
|
format: date-time
|
||||||
- endTime
|
nullable: true
|
||||||
- startTime
|
type: string
|
||||||
type: object
|
observedGeneration:
|
||||||
type: array
|
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.
|
||||||
type: object
|
format: int64
|
||||||
status:
|
type: integer
|
||||||
properties:
|
scheduledOverridesSummary:
|
||||||
cacheEntries:
|
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.
|
||||||
items:
|
type: string
|
||||||
properties:
|
type: object
|
||||||
expirationTime:
|
type: object
|
||||||
format: date-time
|
served: true
|
||||||
type: string
|
storage: true
|
||||||
key:
|
subresources:
|
||||||
type: string
|
status: {}
|
||||||
value:
|
preserveUnknownFields: false
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
desiredReplicas:
|
|
||||||
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.
|
|
||||||
type: integer
|
|
||||||
lastSuccessfulScaleOutTime:
|
|
||||||
format: date-time
|
|
||||||
nullable: true
|
|
||||||
type: string
|
|
||||||
observedGeneration:
|
|
||||||
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.
|
|
||||||
format: int64
|
|
||||||
type: integer
|
|
||||||
scheduledOverridesSummary:
|
|
||||||
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.
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
served: true
|
|
||||||
storage: true
|
|
||||||
subresources:
|
|
||||||
status: {}
|
|
||||||
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
@@ -22,7 +22,7 @@ Due to the above you can't just do a `helm upgrade` to release the latest versio
|
|||||||
|
|
||||||
```shell
|
```shell
|
||||||
# REMEMBER TO UPDATE THE CHART_VERSION TO RELEVANT CHART VERISON!!!!
|
# REMEMBER TO UPDATE THE CHART_VERSION TO RELEVANT CHART VERISON!!!!
|
||||||
CHART_VERSION=0.11.0
|
CHART_VERSION=0.14.0
|
||||||
|
|
||||||
curl -L https://github.com/actions-runner-controller/actions-runner-controller/releases/download/actions-runner-controller-${CHART_VERSION}/actions-runner-controller-${CHART_VERSION}.tgz | tar zxv --strip 1 actions-runner-controller/crds
|
curl -L https://github.com/actions-runner-controller/actions-runner-controller/releases/download/actions-runner-controller-${CHART_VERSION}/actions-runner-controller-${CHART_VERSION}.tgz | tar zxv --strip 1 actions-runner-controller/crds
|
||||||
|
|
||||||
@@ -32,9 +32,10 @@ kubectl apply -f crds/
|
|||||||
2. Upgrade the Helm release
|
2. Upgrade the Helm release
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
helm upgrade --install \
|
# helm upgrade [RELEASE] [CHART] [flags]
|
||||||
--namespace actions-runner-system \
|
helm upgrade actions-runner-controller \
|
||||||
--version ${CHART_VERSION} \
|
|
||||||
actions-runner-controller/actions-runner-controller \
|
actions-runner-controller/actions-runner-controller \
|
||||||
actions-runner-controller
|
--install \
|
||||||
|
--namespace actions-runner-system \
|
||||||
|
--version ${CHART_VERSION}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -58,3 +58,7 @@ Create the name of the service account to use
|
|||||||
{{- define "actions-runner-controller-github-webhook-server.serviceMonitorName" -}}
|
{{- define "actions-runner-controller-github-webhook-server.serviceMonitorName" -}}
|
||||||
{{- include "actions-runner-controller-github-webhook-server.fullname" . | trunc 47 }}-service-monitor
|
{{- include "actions-runner-controller-github-webhook-server.fullname" . | trunc 47 }}-service-monitor
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "actions-runner-controller-github-webhook-server.pdbName" -}}
|
||||||
|
{{- include "actions-runner-controller-github-webhook-server.fullname" . | trunc 59 }}-pdb
|
||||||
|
{{- end }}
|
||||||
@@ -107,3 +107,7 @@ Create the name of the service account to use
|
|||||||
{{- define "actions-runner-controller.servingCertName" -}}
|
{{- define "actions-runner-controller.servingCertName" -}}
|
||||||
{{- include "actions-runner-controller.fullname" . }}-serving-cert
|
{{- include "actions-runner-controller.fullname" . }}-serving-cert
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
{{- define "actions-runner-controller.pdbName" -}}
|
||||||
|
{{- include "actions-runner-controller.fullname" . | trunc 59 }}-pdb
|
||||||
|
{{- end }}
|
||||||
@@ -21,4 +21,4 @@ spec:
|
|||||||
issuerRef:
|
issuerRef:
|
||||||
kind: Issuer
|
kind: Issuer
|
||||||
name: {{ include "actions-runner-controller.selfsignedIssuerName" . }}
|
name: {{ include "actions-runner-controller.selfsignedIssuerName" . }}
|
||||||
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
|
secretName: {{ include "actions-runner-controller.servingCertName" . }}
|
||||||
|
|||||||
@@ -7,4 +7,8 @@ data:
|
|||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: controller-manager
|
name: controller-manager
|
||||||
|
{{- if .Values.authSecret.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{ toYaml .Values.authSecret.annotations | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -5,6 +5,10 @@ metadata:
|
|||||||
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
name: {{ include "actions-runner-controller.metricsServiceName" . }}
|
name: {{ include "actions-runner-controller.metricsServiceName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- with .Values.metrics.serviceAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
ports:
|
ports:
|
||||||
- name: metrics-port
|
- name: metrics-port
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{{- if .Values.podDisruptionBudget.enabled }}
|
||||||
|
apiVersion: policy/v1beta1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
|
name: {{ include "actions-runner-controller.pdbName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.podDisruptionBudget.minAvailable }}
|
||||||
|
minAvailable: {{ .Values.podDisruptionBudget.minAvailable }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.podDisruptionBudget.maxUnavailable }}
|
||||||
|
maxUnavailable: {{ .Values.podDisruptionBudget.maxUnavailable }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "actions-runner-controller.selectorLabels" . | nindent 6 }}
|
||||||
|
{{- end -}}
|
||||||
@@ -37,7 +37,12 @@ spec:
|
|||||||
{{- $metricsHost := .Values.metrics.proxy.enabled | ternary "127.0.0.1" "0.0.0.0" }}
|
{{- $metricsHost := .Values.metrics.proxy.enabled | ternary "127.0.0.1" "0.0.0.0" }}
|
||||||
{{- $metricsPort := .Values.metrics.proxy.enabled | ternary "8080" .Values.metrics.port }}
|
{{- $metricsPort := .Values.metrics.proxy.enabled | ternary "8080" .Values.metrics.port }}
|
||||||
- "--metrics-addr={{ $metricsHost }}:{{ $metricsPort }}"
|
- "--metrics-addr={{ $metricsHost }}:{{ $metricsPort }}"
|
||||||
|
{{- if .Values.enableLeaderElection }}
|
||||||
- "--enable-leader-election"
|
- "--enable-leader-election"
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.leaderElectionId }}
|
||||||
|
- "--leader-election-id={{ .Values.leaderElectionId }}"
|
||||||
|
{{- end }}
|
||||||
- "--sync-period={{ .Values.syncPeriod }}"
|
- "--sync-period={{ .Values.syncPeriod }}"
|
||||||
- "--docker-image={{ .Values.image.dindSidecarRepositoryAndTag }}"
|
- "--docker-image={{ .Values.image.dindSidecarRepositoryAndTag }}"
|
||||||
- "--runner-image={{ .Values.image.actionsRunnerRepositoryAndTag }}"
|
- "--runner-image={{ .Values.image.actionsRunnerRepositoryAndTag }}"
|
||||||
@@ -134,7 +139,7 @@ spec:
|
|||||||
- name: cert
|
- name: cert
|
||||||
secret:
|
secret:
|
||||||
defaultMode: 420
|
defaultMode: 420
|
||||||
secretName: webhook-server-cert
|
secretName: {{ include "actions-runner-controller.servingCertName" . }}
|
||||||
- name: tmp
|
- name: tmp
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
{{- with .Values.nodeSelector }}
|
{{- with .Values.nodeSelector }}
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ spec:
|
|||||||
{{- if .Values.githubWebhookServer.logLevel }}
|
{{- if .Values.githubWebhookServer.logLevel }}
|
||||||
- "--log-level={{ .Values.githubWebhookServer.logLevel }}"
|
- "--log-level={{ .Values.githubWebhookServer.logLevel }}"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- if .Values.scope.singleNamespace }}
|
||||||
|
- "--watch-namespace={{ default .Release.Namespace .Values.scope.watchNamespace }}"
|
||||||
|
{{- end }}
|
||||||
command:
|
command:
|
||||||
- "/github-webhook-server"
|
- "/github-webhook-server"
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{{- if .Values.githubWebhookServer.podDisruptionBudget.enabled }}
|
||||||
|
apiVersion: policy/v1beta1
|
||||||
|
kind: PodDisruptionBudget
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
|
name: {{ include "actions-runner-controller-github-webhook-server.pdbName" . }}
|
||||||
|
namespace: {{ .Release.Namespace }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.githubWebhookServer.podDisruptionBudget.minAvailable }}
|
||||||
|
minAvailable: {{ .Values.githubWebhookServer.podDisruptionBudget.minAvailable }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.githubWebhookServer.podDisruptionBudget.maxUnavailable }}
|
||||||
|
maxUnavailable: {{ .Values.githubWebhookServer.podDisruptionBudget.maxUnavailable }}
|
||||||
|
{{- end }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "actions-runner-controller-github-webhook-server.selectorLabels" . | nindent 6 }}
|
||||||
|
{{- end -}}
|
||||||
@@ -4,14 +4,20 @@ kind: Secret
|
|||||||
metadata:
|
metadata:
|
||||||
name: {{ include "actions-runner-controller.secretName" . }}
|
name: {{ include "actions-runner-controller.secretName" . }}
|
||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
|
{{- if .Values.authSecret.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{ toYaml .Values.authSecret.annotations | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
type: Opaque
|
type: Opaque
|
||||||
data:
|
data:
|
||||||
{{- if .Values.authSecret.github_app_id }}
|
{{- if .Values.authSecret.github_app_id }}
|
||||||
|
# Keep this as a string as strings integrate better with things like AWS Parameter Store, see PR #882 for an example
|
||||||
github_app_id: {{ .Values.authSecret.github_app_id | toString | b64enc }}
|
github_app_id: {{ .Values.authSecret.github_app_id | toString | b64enc }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.authSecret.github_app_installation_id }}
|
{{- if .Values.authSecret.github_app_installation_id }}
|
||||||
|
# Keep this as a string as strings integrate better with things like AWS Parameter Store, see PR #882 for an example
|
||||||
github_app_installation_id: {{ .Values.authSecret.github_app_installation_id | toString | b64enc }}
|
github_app_installation_id: {{ .Values.authSecret.github_app_installation_id | toString | b64enc }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.authSecret.github_app_private_key }}
|
{{- if .Values.authSecret.github_app_private_key }}
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ metadata:
|
|||||||
namespace: {{ .Release.Namespace }}
|
namespace: {{ .Release.Namespace }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
{{- include "actions-runner-controller.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.service.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.service.type }}
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -8,6 +8,11 @@ replicaCount: 1
|
|||||||
|
|
||||||
syncPeriod: 10m
|
syncPeriod: 10m
|
||||||
|
|
||||||
|
enableLeaderElection: true
|
||||||
|
# Specifies the controller id for leader election.
|
||||||
|
# Must be unique if more than one controller installed onto the same namespace.
|
||||||
|
#leaderElectionId: "actions-runner-controller"
|
||||||
|
|
||||||
# The controller tries its best not to repeat the duplicate GitHub API call
|
# The controller tries its best not to repeat the duplicate GitHub API call
|
||||||
# within this duration.
|
# within this duration.
|
||||||
# Defaults to syncPeriod - 10s.
|
# Defaults to syncPeriod - 10s.
|
||||||
@@ -21,7 +26,9 @@ syncPeriod: 10m
|
|||||||
authSecret:
|
authSecret:
|
||||||
create: false
|
create: false
|
||||||
name: "controller-manager"
|
name: "controller-manager"
|
||||||
|
annotations: {}
|
||||||
### GitHub Apps Configuration
|
### GitHub Apps Configuration
|
||||||
|
## NOTE: IDs MUST be strings, use quotes
|
||||||
#github_app_id: ""
|
#github_app_id: ""
|
||||||
#github_app_installation_id: ""
|
#github_app_installation_id: ""
|
||||||
#github_app_private_key: |
|
#github_app_private_key: |
|
||||||
@@ -65,11 +72,15 @@ securityContext:
|
|||||||
# runAsNonRoot: true
|
# runAsNonRoot: true
|
||||||
# runAsUser: 1000
|
# runAsUser: 1000
|
||||||
|
|
||||||
|
# Webhook service resource
|
||||||
service:
|
service:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
port: 443
|
port: 443
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
# Metrics service resource
|
||||||
metrics:
|
metrics:
|
||||||
|
serviceAnnotations: {}
|
||||||
serviceMonitor: false
|
serviceMonitor: false
|
||||||
serviceMonitorLabels: {}
|
serviceMonitorLabels: {}
|
||||||
port: 8443
|
port: 8443
|
||||||
@@ -98,6 +109,12 @@ tolerations: []
|
|||||||
|
|
||||||
affinity: {}
|
affinity: {}
|
||||||
|
|
||||||
|
# Only one of minAvailable or maxUnavailable can be set
|
||||||
|
podDisruptionBudget:
|
||||||
|
enabled: false
|
||||||
|
# minAvailable: 1
|
||||||
|
# maxUnavailable: 3
|
||||||
|
|
||||||
# Leverage a PriorityClass to ensure your pods survive resource shortages
|
# Leverage a PriorityClass to ensure your pods survive resource shortages
|
||||||
# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
|
# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
|
||||||
# PriorityClass: system-cluster-critical
|
# PriorityClass: system-cluster-critical
|
||||||
@@ -168,3 +185,9 @@ githubWebhookServer:
|
|||||||
# - secretName: chart-example-tls
|
# - secretName: chart-example-tls
|
||||||
# hosts:
|
# hosts:
|
||||||
# - chart-example.local
|
# - chart-example.local
|
||||||
|
|
||||||
|
# Only one of minAvailable or maxUnavailable can be set
|
||||||
|
podDisruptionBudget:
|
||||||
|
enabled: false
|
||||||
|
# minAvailable: 1
|
||||||
|
# maxUnavailable: 3
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
---
|
|
||||||
apiVersion: apiextensions.k8s.io/v1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
@@ -14,291 +12,228 @@ spec:
|
|||||||
listKind: HorizontalRunnerAutoscalerList
|
listKind: HorizontalRunnerAutoscalerList
|
||||||
plural: horizontalrunnerautoscalers
|
plural: horizontalrunnerautoscalers
|
||||||
shortNames:
|
shortNames:
|
||||||
- hra
|
- hra
|
||||||
singular: horizontalrunnerautoscaler
|
singular: horizontalrunnerautoscaler
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
versions:
|
versions:
|
||||||
- additionalPrinterColumns:
|
- additionalPrinterColumns:
|
||||||
- jsonPath: .spec.minReplicas
|
- jsonPath: .spec.minReplicas
|
||||||
name: Min
|
name: Min
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .spec.maxReplicas
|
- jsonPath: .spec.maxReplicas
|
||||||
name: Max
|
name: Max
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .status.desiredReplicas
|
- jsonPath: .status.desiredReplicas
|
||||||
name: Desired
|
name: Desired
|
||||||
type: number
|
type: number
|
||||||
- jsonPath: .status.scheduledOverridesSummary
|
- jsonPath: .status.scheduledOverridesSummary
|
||||||
name: Schedule
|
name: Schedule
|
||||||
type: string
|
type: string
|
||||||
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 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'
|
||||||
description: 'APIVersion defines the versioned schema of this representation
|
type: string
|
||||||
of an object. Servers should convert recognized schemas to the latest
|
kind:
|
||||||
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
|
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'
|
||||||
type: string
|
type: string
|
||||||
kind:
|
metadata:
|
||||||
description: 'Kind is a string value representing the REST resource this
|
type: object
|
||||||
object represents. Servers may infer this from the endpoint the client
|
spec:
|
||||||
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
|
description: HorizontalRunnerAutoscalerSpec defines the desired state of HorizontalRunnerAutoscaler
|
||||||
type: string
|
properties:
|
||||||
metadata:
|
capacityReservations:
|
||||||
type: object
|
items:
|
||||||
spec:
|
description: CapacityReservation specifies the number of replicas temporarily added to the scale target until ExpirationTime.
|
||||||
description: HorizontalRunnerAutoscalerSpec defines the desired state
|
properties:
|
||||||
of HorizontalRunnerAutoscaler
|
expirationTime:
|
||||||
properties:
|
format: date-time
|
||||||
capacityReservations:
|
type: string
|
||||||
items:
|
name:
|
||||||
description: CapacityReservation specifies the number of replicas
|
type: string
|
||||||
temporarily added to the scale target until ExpirationTime.
|
replicas:
|
||||||
|
type: integer
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
maxReplicas:
|
||||||
|
description: MaxReplicas is the maximum number of replicas the deployment is allowed to scale
|
||||||
|
type: integer
|
||||||
|
metrics:
|
||||||
|
description: Metrics is the collection of various metric targets to calculate desired number of runners
|
||||||
|
items:
|
||||||
|
properties:
|
||||||
|
repositoryNames:
|
||||||
|
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`.
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
type: array
|
||||||
|
scaleDownAdjustment:
|
||||||
|
description: ScaleDownAdjustment is the number of runners removed on scale-down. You can only specify either ScaleDownFactor or ScaleDownAdjustment.
|
||||||
|
type: integer
|
||||||
|
scaleDownFactor:
|
||||||
|
description: ScaleDownFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be removed.
|
||||||
|
type: string
|
||||||
|
scaleDownThreshold:
|
||||||
|
description: ScaleDownThreshold is the percentage of busy runners less than which will trigger the hpa to scale the runners down.
|
||||||
|
type: string
|
||||||
|
scaleUpAdjustment:
|
||||||
|
description: ScaleUpAdjustment is the number of runners added on scale-up. You can only specify either ScaleUpFactor or ScaleUpAdjustment.
|
||||||
|
type: integer
|
||||||
|
scaleUpFactor:
|
||||||
|
description: ScaleUpFactor is the multiplicative factor applied to the current number of runners used to determine how many pods should be added.
|
||||||
|
type: string
|
||||||
|
scaleUpThreshold:
|
||||||
|
description: ScaleUpThreshold is the percentage of busy runners greater than which will trigger the hpa to scale runners up.
|
||||||
|
type: string
|
||||||
|
type:
|
||||||
|
description: Type is the type of metric to be used for autoscaling. The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
type: array
|
||||||
|
minReplicas:
|
||||||
|
description: MinReplicas is the minimum number of replicas the deployment is allowed to scale
|
||||||
|
type: integer
|
||||||
|
scaleDownDelaySecondsAfterScaleOut:
|
||||||
|
description: ScaleDownDelaySecondsAfterScaleUp is the approximate delay for a scale down followed by a scale up Used to prevent flapping (down->up->down->... loop)
|
||||||
|
type: integer
|
||||||
|
scaleTargetRef:
|
||||||
|
description: ScaleTargetRef sis the reference to scaled resource like RunnerDeployment
|
||||||
properties:
|
properties:
|
||||||
expirationTime:
|
kind:
|
||||||
format: date-time
|
description: Kind is the type of resource being referenced
|
||||||
|
enum:
|
||||||
|
- RunnerDeployment
|
||||||
|
- RunnerSet
|
||||||
type: string
|
type: string
|
||||||
name:
|
name:
|
||||||
|
description: Name is the name of resource being referenced
|
||||||
type: string
|
type: string
|
||||||
replicas:
|
|
||||||
type: integer
|
|
||||||
type: object
|
type: object
|
||||||
type: array
|
scaleUpTriggers:
|
||||||
maxReplicas:
|
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."
|
||||||
description: MinReplicas is the maximum number of replicas the deployment
|
items:
|
||||||
is allowed to scale
|
properties:
|
||||||
type: integer
|
amount:
|
||||||
metrics:
|
type: integer
|
||||||
description: Metrics is the collection of various metric targets to
|
duration:
|
||||||
calculate desired number of runners
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
repositoryNames:
|
|
||||||
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`.
|
|
||||||
items:
|
|
||||||
type: string
|
type: string
|
||||||
type: array
|
githubEvent:
|
||||||
scaleDownAdjustment:
|
properties:
|
||||||
description: ScaleDownAdjustment is the number of runners removed
|
checkRun:
|
||||||
on scale-down. You can only specify either ScaleDownFactor
|
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
|
||||||
or ScaleDownAdjustment.
|
properties:
|
||||||
type: integer
|
names:
|
||||||
scaleDownFactor:
|
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.
|
||||||
description: ScaleDownFactor is the multiplicative factor applied
|
items:
|
||||||
to the current number of runners used to determine how many
|
type: string
|
||||||
pods should be removed.
|
type: array
|
||||||
type: string
|
repositories:
|
||||||
scaleDownThreshold:
|
description: Repositories is a list of GitHub repositories. Any check_run event whose repository matches one of repositories in the list can trigger autoscaling.
|
||||||
description: ScaleDownThreshold is the percentage of busy runners
|
items:
|
||||||
less than which will trigger the hpa to scale the runners
|
type: string
|
||||||
down.
|
type: array
|
||||||
type: string
|
status:
|
||||||
scaleUpAdjustment:
|
|
||||||
description: ScaleUpAdjustment is the number of runners added
|
|
||||||
on scale-up. You can only specify either ScaleUpFactor or
|
|
||||||
ScaleUpAdjustment.
|
|
||||||
type: integer
|
|
||||||
scaleUpFactor:
|
|
||||||
description: ScaleUpFactor is the multiplicative factor applied
|
|
||||||
to the current number of runners used to determine how many
|
|
||||||
pods should be added.
|
|
||||||
type: string
|
|
||||||
scaleUpThreshold:
|
|
||||||
description: ScaleUpThreshold is the percentage of busy runners
|
|
||||||
greater than which will trigger the hpa to scale runners up.
|
|
||||||
type: string
|
|
||||||
type:
|
|
||||||
description: Type is the type of metric to be used for autoscaling.
|
|
||||||
The only supported Type is TotalNumberOfQueuedAndInProgressWorkflowRuns
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
minReplicas:
|
|
||||||
description: MinReplicas is the minimum number of replicas the deployment
|
|
||||||
is allowed to scale
|
|
||||||
type: integer
|
|
||||||
scaleDownDelaySecondsAfterScaleOut:
|
|
||||||
description: ScaleDownDelaySecondsAfterScaleUp is the approximate
|
|
||||||
delay for a scale down followed by a scale up Used to prevent flapping
|
|
||||||
(down->up->down->... loop)
|
|
||||||
type: integer
|
|
||||||
scaleTargetRef:
|
|
||||||
description: ScaleTargetRef sis the reference to scaled resource like
|
|
||||||
RunnerDeployment
|
|
||||||
properties:
|
|
||||||
kind:
|
|
||||||
description: Kind is the type of resource being referenced
|
|
||||||
enum:
|
|
||||||
- RunnerDeployment
|
|
||||||
- RunnerSet
|
|
||||||
type: string
|
|
||||||
name:
|
|
||||||
description: Name is the name of resource being referenced
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
scaleUpTriggers:
|
|
||||||
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."
|
|
||||||
items:
|
|
||||||
properties:
|
|
||||||
amount:
|
|
||||||
type: integer
|
|
||||||
duration:
|
|
||||||
type: string
|
|
||||||
githubEvent:
|
|
||||||
properties:
|
|
||||||
checkRun:
|
|
||||||
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#check_run
|
|
||||||
properties:
|
|
||||||
names:
|
|
||||||
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.
|
|
||||||
items:
|
|
||||||
type: string
|
type: string
|
||||||
type: array
|
types:
|
||||||
repositories:
|
items:
|
||||||
description: Repositories is a list of GitHub repositories.
|
type: string
|
||||||
Any check_run event whose repository matches one of
|
type: array
|
||||||
repositories in the list can trigger autoscaling.
|
type: object
|
||||||
items:
|
pullRequest:
|
||||||
type: string
|
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request
|
||||||
type: array
|
properties:
|
||||||
status:
|
branches:
|
||||||
type: string
|
items:
|
||||||
types:
|
type: string
|
||||||
items:
|
type: array
|
||||||
type: string
|
types:
|
||||||
type: array
|
items:
|
||||||
type: object
|
type: string
|
||||||
pullRequest:
|
type: array
|
||||||
description: https://docs.github.com/en/actions/reference/events-that-trigger-workflows#pull_request
|
type: object
|
||||||
properties:
|
push:
|
||||||
branches:
|
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
|
||||||
items:
|
type: object
|
||||||
type: string
|
type: object
|
||||||
type: array
|
type: object
|
||||||
types:
|
type: array
|
||||||
items:
|
scheduledOverrides:
|
||||||
type: string
|
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.
|
||||||
type: array
|
items:
|
||||||
type: object
|
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.
|
||||||
push:
|
properties:
|
||||||
description: PushSpec is the condition for triggering scale-up
|
endTime:
|
||||||
on push event Also see https://docs.github.com/en/actions/reference/events-that-trigger-workflows#push
|
description: EndTime is the time at which the first override ends.
|
||||||
type: object
|
format: date-time
|
||||||
type: object
|
type: string
|
||||||
type: object
|
minReplicas:
|
||||||
type: array
|
description: MinReplicas is the number of runners while overriding. If omitted, it doesn't override minReplicas.
|
||||||
scheduledOverrides:
|
minimum: 0
|
||||||
description: ScheduledOverrides is the list of ScheduledOverride.
|
nullable: true
|
||||||
It can be used to override a few fields of HorizontalRunnerAutoscalerSpec
|
type: integer
|
||||||
on schedule. The earlier a scheduled override is, the higher it
|
recurrenceRule:
|
||||||
is prioritized.
|
properties:
|
||||||
items:
|
frequency:
|
||||||
description: ScheduledOverride can be used to override a few fields
|
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 HorizontalRunnerAutoscalerSpec on schedule. A schedule can
|
enum:
|
||||||
optionally be recurring, so that the correspoding override happens
|
- Daily
|
||||||
every day, week, month, or year.
|
- Weekly
|
||||||
properties:
|
- Monthly
|
||||||
endTime:
|
- Yearly
|
||||||
description: EndTime is the time at which the first override
|
type: string
|
||||||
ends.
|
untilTime:
|
||||||
format: date-time
|
description: UntilTime is the time of the final recurrence. If empty, the schedule recurs forever.
|
||||||
type: string
|
format: date-time
|
||||||
minReplicas:
|
type: string
|
||||||
description: MinReplicas is the number of runners while overriding.
|
type: object
|
||||||
If omitted, it doesn't override minReplicas.
|
startTime:
|
||||||
minimum: 0
|
description: StartTime is the time at which the first override starts.
|
||||||
nullable: true
|
format: date-time
|
||||||
type: integer
|
type: string
|
||||||
recurrenceRule:
|
required:
|
||||||
properties:
|
- endTime
|
||||||
frequency:
|
- startTime
|
||||||
description: Frequency is the name of a predefined interval
|
type: object
|
||||||
of each recurrence. The valid values are "Daily", "Weekly",
|
type: array
|
||||||
"Monthly", and "Yearly". If empty, the corresponding override
|
type: object
|
||||||
happens only once.
|
status:
|
||||||
enum:
|
properties:
|
||||||
- Daily
|
cacheEntries:
|
||||||
- Weekly
|
items:
|
||||||
- Monthly
|
properties:
|
||||||
- Yearly
|
expirationTime:
|
||||||
type: string
|
format: date-time
|
||||||
untilTime:
|
type: string
|
||||||
description: UntilTime is the time of the final recurrence.
|
key:
|
||||||
If empty, the schedule recurs forever.
|
type: string
|
||||||
format: date-time
|
value:
|
||||||
type: string
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
startTime:
|
type: array
|
||||||
description: StartTime is the time at which the first override
|
desiredReplicas:
|
||||||
starts.
|
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.
|
||||||
format: date-time
|
type: integer
|
||||||
type: string
|
lastSuccessfulScaleOutTime:
|
||||||
required:
|
format: date-time
|
||||||
- endTime
|
nullable: true
|
||||||
- startTime
|
type: string
|
||||||
type: object
|
observedGeneration:
|
||||||
type: array
|
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.
|
||||||
type: object
|
format: int64
|
||||||
status:
|
type: integer
|
||||||
properties:
|
scheduledOverridesSummary:
|
||||||
cacheEntries:
|
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.
|
||||||
items:
|
type: string
|
||||||
properties:
|
type: object
|
||||||
expirationTime:
|
type: object
|
||||||
format: date-time
|
served: true
|
||||||
type: string
|
storage: true
|
||||||
key:
|
subresources:
|
||||||
type: string
|
status: {}
|
||||||
value:
|
preserveUnknownFields: false
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
type: array
|
|
||||||
desiredReplicas:
|
|
||||||
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.
|
|
||||||
type: integer
|
|
||||||
lastSuccessfulScaleOutTime:
|
|
||||||
format: date-time
|
|
||||||
nullable: true
|
|
||||||
type: string
|
|
||||||
observedGeneration:
|
|
||||||
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.
|
|
||||||
format: int64
|
|
||||||
type: integer
|
|
||||||
scheduledOverridesSummary:
|
|
||||||
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.
|
|
||||||
type: string
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
served: true
|
|
||||||
storage: true
|
|
||||||
subresources:
|
|
||||||
status: {}
|
|
||||||
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
@@ -6,6 +6,7 @@ resources:
|
|||||||
- bases/actions.summerwind.dev_runnerreplicasets.yaml
|
- bases/actions.summerwind.dev_runnerreplicasets.yaml
|
||||||
- bases/actions.summerwind.dev_runnerdeployments.yaml
|
- bases/actions.summerwind.dev_runnerdeployments.yaml
|
||||||
- bases/actions.summerwind.dev_horizontalrunnerautoscalers.yaml
|
- bases/actions.summerwind.dev_horizontalrunnerautoscalers.yaml
|
||||||
|
- bases/actions.summerwind.dev_runnersets.yaml
|
||||||
# +kubebuilder:scaffold:crdkustomizeresource
|
# +kubebuilder:scaffold:crdkustomizeresource
|
||||||
|
|
||||||
patchesStrategicMerge:
|
patchesStrategicMerge:
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ func (r *HorizontalRunnerAutoscalerReconciler) suggestDesiredReplicas(st scaleTa
|
|||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
} else if numMetrics > 2 {
|
} else if numMetrics > 2 {
|
||||||
return nil, fmt.Errorf("Too many autoscaling metrics configured: It must be 0 to 2, but got %d", numMetrics)
|
return nil, fmt.Errorf("too many autoscaling metrics configured: It must be 0 to 2, but got %d", numMetrics)
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryMetric := metrics[0]
|
primaryMetric := metrics[0]
|
||||||
@@ -93,7 +93,7 @@ func (r *HorizontalRunnerAutoscalerReconciler) suggestDesiredReplicas(st scaleTa
|
|||||||
case v1alpha1.AutoscalingMetricTypePercentageRunnersBusy:
|
case v1alpha1.AutoscalingMetricTypePercentageRunnersBusy:
|
||||||
suggested, err = r.suggestReplicasByPercentageRunnersBusy(st, hra, primaryMetric)
|
suggested, err = r.suggestReplicasByPercentageRunnersBusy(st, hra, primaryMetric)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("validting autoscaling metrics: unsupported metric type %q", primaryMetric)
|
return nil, fmt.Errorf("validating autoscaling metrics: unsupported metric type %q", primaryMetric)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package controllers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -40,6 +41,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
scaleTargetKey = "scaleTarget"
|
scaleTargetKey = "scaleTarget"
|
||||||
|
|
||||||
|
keyPrefixEnterprise = "enterprises/"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HorizontalRunnerAutoscalerGitHubWebhook autoscales a HorizontalRunnerAutoscaler and the RunnerDeployment on each
|
// HorizontalRunnerAutoscalerGitHubWebhook autoscales a HorizontalRunnerAutoscaler and the RunnerDeployment on each
|
||||||
@@ -98,6 +101,7 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
|
|
||||||
// respond ok to GET / e.g. for health check
|
// respond ok to GET / e.g. for health check
|
||||||
if r.Method == http.MethodGet {
|
if r.Method == http.MethodGet {
|
||||||
|
ok = true
|
||||||
fmt.Fprintln(w, "webhook server is running")
|
fmt.Fprintln(w, "webhook server is running")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -141,6 +145,20 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
"delivery", r.Header.Get("X-GitHub-Delivery"),
|
"delivery", r.Header.Get("X-GitHub-Delivery"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var enterpriseEvent struct {
|
||||||
|
Enterprise struct {
|
||||||
|
Slug string `json:"slug,omitempty"`
|
||||||
|
} `json:"enterprise,omitempty"`
|
||||||
|
}
|
||||||
|
if err := json.Unmarshal(payload, &enterpriseEvent); err != nil {
|
||||||
|
var s string
|
||||||
|
if payload != nil {
|
||||||
|
s = string(payload)
|
||||||
|
}
|
||||||
|
autoscaler.Log.Error(err, "could not parse webhook payload for extracting enterprise slug", "webhookType", webhookType, "payload", s)
|
||||||
|
}
|
||||||
|
enterpriseSlug := enterpriseEvent.Enterprise.Slug
|
||||||
|
|
||||||
switch e := event.(type) {
|
switch e := event.(type) {
|
||||||
case *gogithub.PushEvent:
|
case *gogithub.PushEvent:
|
||||||
target, err = autoscaler.getScaleUpTarget(
|
target, err = autoscaler.getScaleUpTarget(
|
||||||
@@ -149,6 +167,9 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
e.Repo.GetName(),
|
e.Repo.GetName(),
|
||||||
e.Repo.Owner.GetLogin(),
|
e.Repo.Owner.GetLogin(),
|
||||||
e.Repo.Owner.GetType(),
|
e.Repo.Owner.GetType(),
|
||||||
|
// Most go-github Event types don't seem to contain Enteprirse(.Slug) fields
|
||||||
|
// we need, so we parse it by ourselves.
|
||||||
|
enterpriseSlug,
|
||||||
autoscaler.MatchPushEvent(e),
|
autoscaler.MatchPushEvent(e),
|
||||||
)
|
)
|
||||||
case *gogithub.PullRequestEvent:
|
case *gogithub.PullRequestEvent:
|
||||||
@@ -158,6 +179,9 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
e.Repo.GetName(),
|
e.Repo.GetName(),
|
||||||
e.Repo.Owner.GetLogin(),
|
e.Repo.Owner.GetLogin(),
|
||||||
e.Repo.Owner.GetType(),
|
e.Repo.Owner.GetType(),
|
||||||
|
// Most go-github Event types don't seem to contain Enteprirse(.Slug) fields
|
||||||
|
// we need, so we parse it by ourselves.
|
||||||
|
enterpriseSlug,
|
||||||
autoscaler.MatchPullRequestEvent(e),
|
autoscaler.MatchPullRequestEvent(e),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -174,6 +198,9 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
e.Repo.GetName(),
|
e.Repo.GetName(),
|
||||||
e.Repo.Owner.GetLogin(),
|
e.Repo.Owner.GetLogin(),
|
||||||
e.Repo.Owner.GetType(),
|
e.Repo.Owner.GetType(),
|
||||||
|
// Most go-github Event types don't seem to contain Enteprirse(.Slug) fields
|
||||||
|
// we need, so we parse it by ourselves.
|
||||||
|
enterpriseSlug,
|
||||||
autoscaler.MatchCheckRunEvent(e),
|
autoscaler.MatchCheckRunEvent(e),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -191,13 +218,14 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
"repository.name", e.Repo.GetName(),
|
"repository.name", e.Repo.GetName(),
|
||||||
"repository.owner.login", e.Repo.Owner.GetLogin(),
|
"repository.owner.login", e.Repo.Owner.GetLogin(),
|
||||||
"repository.owner.type", e.Repo.Owner.GetType(),
|
"repository.owner.type", e.Repo.Owner.GetType(),
|
||||||
|
"enterprise.slug", enterpriseSlug,
|
||||||
"action", e.GetAction(),
|
"action", e.GetAction(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := e.WorkflowJob.Labels
|
labels := e.WorkflowJob.Labels
|
||||||
|
|
||||||
switch e.GetAction() {
|
switch action := e.GetAction(); action {
|
||||||
case "queued", "completed":
|
case "queued", "completed":
|
||||||
target, err = autoscaler.getJobScaleUpTargetForRepoOrOrg(
|
target, err = autoscaler.getJobScaleUpTargetForRepoOrOrg(
|
||||||
context.TODO(),
|
context.TODO(),
|
||||||
@@ -205,6 +233,7 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
e.Repo.GetName(),
|
e.Repo.GetName(),
|
||||||
e.Repo.Owner.GetLogin(),
|
e.Repo.Owner.GetLogin(),
|
||||||
e.Repo.Owner.GetType(),
|
e.Repo.Owner.GetType(),
|
||||||
|
enterpriseSlug,
|
||||||
labels,
|
labels,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -220,7 +249,13 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) Handle(w http.Respons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
ok = true
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
|
log.V(2).Info("Received and ignored a workflow_job event as it triggers neither scale-up nor scale-down", "action", action)
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
case *gogithub.PingEvent:
|
case *gogithub.PingEvent:
|
||||||
ok = true
|
ok = true
|
||||||
@@ -391,7 +426,7 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getScaleTarget(ctx co
|
|||||||
"Found too many scale targets: "+
|
"Found too many scale targets: "+
|
||||||
"It must be exactly one to avoid ambiguity. "+
|
"It must be exactly one to avoid ambiguity. "+
|
||||||
"Either set Namespace for the webhook-based autoscaler to let it only find HRAs in the namespace, "+
|
"Either set Namespace for the webhook-based autoscaler to let it only find HRAs in the namespace, "+
|
||||||
"or update Repository or Organization fields in your RunnerDeployment resources to fix the ambiguity.",
|
"or update Repository, Organization, or Enterprise fields in your RunnerDeployment resources to fix the ambiguity.",
|
||||||
"scaleTargets", strings.Join(scaleTargetIDs, ","))
|
"scaleTargets", strings.Join(scaleTargetIDs, ","))
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -400,7 +435,7 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getScaleTarget(ctx co
|
|||||||
return &targets[0], nil
|
return &targets[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getScaleUpTarget(ctx context.Context, log logr.Logger, repo, owner, ownerType string, f func(v1alpha1.ScaleUpTrigger) bool) (*ScaleTarget, error) {
|
func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getScaleUpTarget(ctx context.Context, log logr.Logger, repo, owner, ownerType, enterprise string, f func(v1alpha1.ScaleUpTrigger) bool) (*ScaleTarget, error) {
|
||||||
repositoryRunnerKey := owner + "/" + repo
|
repositoryRunnerKey := owner + "/" + repo
|
||||||
|
|
||||||
if target, err := autoscaler.getScaleTarget(ctx, repositoryRunnerKey, f); err != nil {
|
if target, err := autoscaler.getScaleTarget(ctx, repositoryRunnerKey, f); err != nil {
|
||||||
@@ -423,17 +458,37 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getScaleUpTarget(ctx
|
|||||||
} else if target != nil {
|
} else if target != nil {
|
||||||
log.Info("scale up target is organizational runners", "organization", owner)
|
log.Info("scale up target is organizational runners", "organization", owner)
|
||||||
return target, nil
|
return target, nil
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if enterprise == "" {
|
||||||
log.V(1).Info("no repository runner or organizational runner found",
|
log.V(1).Info("no repository runner or organizational runner found",
|
||||||
"repository", repositoryRunnerKey,
|
"repository", repositoryRunnerKey,
|
||||||
"organization", owner,
|
"organization", owner,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if target, err := autoscaler.getScaleTarget(ctx, enterpriseKey(enterprise), f); err != nil {
|
||||||
|
log.Error(err, "finding enterprise runner", "enterprise", enterprise)
|
||||||
|
return nil, err
|
||||||
|
} else if target != nil {
|
||||||
|
log.Info("scale up target is enterprise runners", "enterprise", enterprise)
|
||||||
|
return target, nil
|
||||||
|
} else {
|
||||||
|
log.V(1).Info("no repository/organizational/enterprise runner found",
|
||||||
|
"repository", repositoryRunnerKey,
|
||||||
|
"organization", owner,
|
||||||
|
"enterprises", enterprise,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getJobScaleUpTargetForRepoOrOrg(ctx context.Context, log logr.Logger, repo, owner, ownerType string, labels []string) (*ScaleTarget, error) {
|
func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getJobScaleUpTargetForRepoOrOrg(
|
||||||
|
ctx context.Context, log logr.Logger, repo, owner, ownerType, enterprise string, labels []string,
|
||||||
|
) (*ScaleTarget, error) {
|
||||||
repositoryRunnerKey := owner + "/" + repo
|
repositoryRunnerKey := owner + "/" + repo
|
||||||
|
|
||||||
if target, err := autoscaler.getJobScaleTarget(ctx, repositoryRunnerKey, labels); err != nil {
|
if target, err := autoscaler.getJobScaleTarget(ctx, repositoryRunnerKey, labels); err != nil {
|
||||||
@@ -456,11 +511,28 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) getJobScaleUpTargetFo
|
|||||||
} else if target != nil {
|
} else if target != nil {
|
||||||
log.Info("job scale up target is organizational runners", "organization", owner)
|
log.Info("job scale up target is organizational runners", "organization", owner)
|
||||||
return target, nil
|
return target, nil
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if enterprise == "" {
|
||||||
log.V(1).Info("no repository runner or organizational runner found",
|
log.V(1).Info("no repository runner or organizational runner found",
|
||||||
"repository", repositoryRunnerKey,
|
"repository", repositoryRunnerKey,
|
||||||
"organization", owner,
|
"organization", owner,
|
||||||
)
|
)
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if target, err := autoscaler.getJobScaleTarget(ctx, enterpriseKey(enterprise), labels); err != nil {
|
||||||
|
log.Error(err, "finding enterprise runner", "enterprise", enterprise)
|
||||||
|
return nil, err
|
||||||
|
} else if target != nil {
|
||||||
|
log.Info("scale up target is enterprise runners", "enterprise", enterprise)
|
||||||
|
return target, nil
|
||||||
|
} else {
|
||||||
|
log.V(1).Info("no repository/organizational/enterprise runner found",
|
||||||
|
"repository", repositoryRunnerKey,
|
||||||
|
"organization", owner,
|
||||||
|
"enterprises", enterprise,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@@ -542,7 +614,7 @@ HRA:
|
|||||||
// Ensure that the RunnerDeployment-managed runners have all the labels requested by the workflow_job.
|
// Ensure that the RunnerDeployment-managed runners have all the labels requested by the workflow_job.
|
||||||
for _, l := range labels {
|
for _, l := range labels {
|
||||||
var matched bool
|
var matched bool
|
||||||
for _, l2 := range rd.Spec.Template.Labels {
|
for _, l2 := range rd.Spec.Template.Spec.Labels {
|
||||||
if l == l2 {
|
if l == l2 {
|
||||||
matched = true
|
matched = true
|
||||||
break
|
break
|
||||||
@@ -649,7 +721,13 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) SetupWithManager(mgr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{rd.Spec.Template.Spec.Repository, rd.Spec.Template.Spec.Organization}
|
keys := []string{rd.Spec.Template.Spec.Repository, rd.Spec.Template.Spec.Organization}
|
||||||
|
|
||||||
|
if enterprise := rd.Spec.Template.Spec.Enterprise; enterprise != "" {
|
||||||
|
keys = append(keys, enterpriseKey(enterprise))
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
case "RunnerSet":
|
case "RunnerSet":
|
||||||
var rs v1alpha1.RunnerSet
|
var rs v1alpha1.RunnerSet
|
||||||
|
|
||||||
@@ -657,7 +735,13 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) SetupWithManager(mgr
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return []string{rs.Spec.Repository, rs.Spec.Organization}
|
keys := []string{rs.Spec.Repository, rs.Spec.Organization}
|
||||||
|
|
||||||
|
if enterprise := rs.Spec.Enterprise; enterprise != "" {
|
||||||
|
keys = append(keys, enterpriseKey(enterprise))
|
||||||
|
}
|
||||||
|
|
||||||
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -670,3 +754,7 @@ func (autoscaler *HorizontalRunnerAutoscalerGitHubWebhook) SetupWithManager(mgr
|
|||||||
Named(name).
|
Named(name).
|
||||||
Complete(autoscaler)
|
Complete(autoscaler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func enterpriseKey(name string) string {
|
||||||
|
return keyPrefixEnterprise + name
|
||||||
|
}
|
||||||
|
|||||||
@@ -114,6 +114,145 @@ func TestWebhookPing(t *testing.T) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestWebhookWorkflowJob(t *testing.T) {
|
||||||
|
setupTest := func() github.WorkflowJobEvent {
|
||||||
|
f, err := os.Open("testdata/org_webhook_workflow_job_payload.json")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("could not open the fixture: %s", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
var e github.WorkflowJobEvent
|
||||||
|
if err := json.NewDecoder(f).Decode(&e); err != nil {
|
||||||
|
t.Fatalf("invalid json: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
t.Run("Successful", func(t *testing.T) {
|
||||||
|
e := setupTest()
|
||||||
|
hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{
|
||||||
|
ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rd := &actionsv1alpha1.RunnerDeployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.RunnerDeploymentSpec{
|
||||||
|
Template: actionsv1alpha1.RunnerTemplate{
|
||||||
|
Spec: actionsv1alpha1.RunnerSpec{
|
||||||
|
RunnerConfig: actionsv1alpha1.RunnerConfig{
|
||||||
|
Organization: "MYORG",
|
||||||
|
Labels: []string{"label1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
initObjs := []runtime.Object{hra, rd}
|
||||||
|
|
||||||
|
testServerWithInitObjs(t,
|
||||||
|
"workflow_job",
|
||||||
|
&e,
|
||||||
|
200,
|
||||||
|
"scaled test-name by 1",
|
||||||
|
initObjs,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
t.Run("WrongLabels", func(t *testing.T) {
|
||||||
|
e := setupTest()
|
||||||
|
hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{
|
||||||
|
ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rd := &actionsv1alpha1.RunnerDeployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.RunnerDeploymentSpec{
|
||||||
|
Template: actionsv1alpha1.RunnerTemplate{
|
||||||
|
Spec: actionsv1alpha1.RunnerSpec{
|
||||||
|
RunnerConfig: actionsv1alpha1.RunnerConfig{
|
||||||
|
Organization: "MYORG",
|
||||||
|
Labels: []string{"bad-label"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
initObjs := []runtime.Object{hra, rd}
|
||||||
|
|
||||||
|
testServerWithInitObjs(t,
|
||||||
|
"workflow_job",
|
||||||
|
&e,
|
||||||
|
200,
|
||||||
|
"no horizontalrunnerautoscaler to scale for this github event",
|
||||||
|
initObjs,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
// This test verifies that the old way of matching labels doesn't work anymore
|
||||||
|
t.Run("OldLabels", func(t *testing.T) {
|
||||||
|
e := setupTest()
|
||||||
|
hra := &actionsv1alpha1.HorizontalRunnerAutoscaler{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.HorizontalRunnerAutoscalerSpec{
|
||||||
|
ScaleTargetRef: actionsv1alpha1.ScaleTargetRef{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rd := &actionsv1alpha1.RunnerDeployment{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-name",
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.RunnerDeploymentSpec{
|
||||||
|
Template: actionsv1alpha1.RunnerTemplate{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: map[string]string{
|
||||||
|
"label1": "label1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: actionsv1alpha1.RunnerSpec{
|
||||||
|
RunnerConfig: actionsv1alpha1.RunnerConfig{
|
||||||
|
Organization: "MYORG",
|
||||||
|
Labels: []string{"bad-label"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
initObjs := []runtime.Object{hra, rd}
|
||||||
|
|
||||||
|
testServerWithInitObjs(t,
|
||||||
|
"workflow_job",
|
||||||
|
&e,
|
||||||
|
200,
|
||||||
|
"no horizontalrunnerautoscaler to scale for this github event",
|
||||||
|
initObjs,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetRequest(t *testing.T) {
|
func TestGetRequest(t *testing.T) {
|
||||||
hra := HorizontalRunnerAutoscalerGitHubWebhook{}
|
hra := HorizontalRunnerAutoscalerGitHubWebhook{}
|
||||||
request, _ := http.NewRequest(http.MethodGet, "/", nil)
|
request, _ := http.NewRequest(http.MethodGet, "/", nil)
|
||||||
@@ -177,13 +316,11 @@ func installTestLogger(webhook *HorizontalRunnerAutoscalerGitHubWebhook) *bytes.
|
|||||||
return logs
|
return logs
|
||||||
}
|
}
|
||||||
|
|
||||||
func testServer(t *testing.T, eventType string, event interface{}, wantCode int, wantBody string) {
|
func testServerWithInitObjs(t *testing.T, eventType string, event interface{}, wantCode int, wantBody string, initObjs []runtime.Object) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
hraWebhook := &HorizontalRunnerAutoscalerGitHubWebhook{}
|
hraWebhook := &HorizontalRunnerAutoscalerGitHubWebhook{}
|
||||||
|
|
||||||
var initObjs []runtime.Object
|
|
||||||
|
|
||||||
client := fake.NewFakeClientWithScheme(sc, initObjs...)
|
client := fake.NewFakeClientWithScheme(sc, initObjs...)
|
||||||
|
|
||||||
logs := installTestLogger(hraWebhook)
|
logs := installTestLogger(hraWebhook)
|
||||||
@@ -227,6 +364,11 @@ func testServer(t *testing.T, eventType string, event interface{}, wantCode int,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testServer(t *testing.T, eventType string, event interface{}, wantCode int, wantBody string) {
|
||||||
|
var initObjs []runtime.Object
|
||||||
|
testServerWithInitObjs(t, eventType, event, wantCode, wantBody, initObjs)
|
||||||
|
}
|
||||||
|
|
||||||
func sendWebhook(server *httptest.Server, eventType string, event interface{}) (*http.Response, error) {
|
func sendWebhook(server *httptest.Server, eventType string, event interface{}) (*http.Response, error) {
|
||||||
jsonBuf := &bytes.Buffer{}
|
jsonBuf := &bytes.Buffer{}
|
||||||
enc := json.NewEncoder(jsonBuf)
|
enc := json.NewEncoder(jsonBuf)
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ func (r *RunnerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("Successfully deleted egistration-only runner pod to free node and cluster resource")
|
log.Info("Successfully deleted registration-only runner pod to free node and cluster resource")
|
||||||
|
|
||||||
// Return here to not recreate the deleted pod, because recreating it is the waste of cluster and node resource,
|
// Return here to not recreate the deleted pod, because recreating it is the waste of cluster and node resource,
|
||||||
// and also defeats the original purpose of scale-from/to-zero we're trying to implement by using the registration-only runner.
|
// and also defeats the original purpose of scale-from/to-zero we're trying to implement by using the registration-only runner.
|
||||||
@@ -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,
|
||||||
@@ -680,6 +680,10 @@ func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
|
|||||||
pod.Spec.Tolerations = runnerSpec.Tolerations
|
pod.Spec.Tolerations = runnerSpec.Tolerations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(runnerSpec.TopologySpreadConstraints) != 0 {
|
||||||
|
pod.Spec.TopologySpreadConstraints = runnerSpec.TopologySpreadConstraints
|
||||||
|
}
|
||||||
|
|
||||||
if len(runnerSpec.EphemeralContainers) != 0 {
|
if len(runnerSpec.EphemeralContainers) != 0 {
|
||||||
pod.Spec.EphemeralContainers = runnerSpec.EphemeralContainers
|
pod.Spec.EphemeralContainers = runnerSpec.EphemeralContainers
|
||||||
}
|
}
|
||||||
@@ -738,11 +742,6 @@ func newRunnerPod(template corev1.Pod, runnerSpec v1alpha1.RunnerConfig, default
|
|||||||
dockerdInRunnerPrivileged bool = dockerdInRunner
|
dockerdInRunnerPrivileged bool = dockerdInRunner
|
||||||
)
|
)
|
||||||
|
|
||||||
runnerImage := runnerSpec.Image
|
|
||||||
if runnerImage == "" {
|
|
||||||
runnerImage = defaultRunnerImage
|
|
||||||
}
|
|
||||||
|
|
||||||
workDir := runnerSpec.WorkDir
|
workDir := runnerSpec.WorkDir
|
||||||
if workDir == "" {
|
if workDir == "" {
|
||||||
workDir = "/runner/_work"
|
workDir = "/runner/_work"
|
||||||
@@ -843,7 +842,13 @@ func newRunnerPod(template corev1.Pod, runnerSpec v1alpha1.RunnerConfig, default
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runnerContainer.Image = runnerImage
|
if runnerSpec.Image != "" {
|
||||||
|
runnerContainer.Image = runnerSpec.Image
|
||||||
|
}
|
||||||
|
if runnerContainer.Image == "" {
|
||||||
|
runnerContainer.Image = defaultRunnerImage
|
||||||
|
}
|
||||||
|
|
||||||
if runnerContainer.ImagePullPolicy == "" {
|
if runnerContainer.ImagePullPolicy == "" {
|
||||||
runnerContainer.ImagePullPolicy = corev1.PullAlways
|
runnerContainer.ImagePullPolicy = corev1.PullAlways
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ type RunnerPodReconciler struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// This names requires at leaset one slash to work.
|
// This names requires at least one slash to work.
|
||||||
// See https://github.com/google/knative-gcp/issues/378
|
// See https://github.com/google/knative-gcp/issues/378
|
||||||
runnerPodFinalizerName = "actions.summerwind.dev/runner-pod"
|
runnerPodFinalizerName = "actions.summerwind.dev/runner-pod"
|
||||||
|
|
||||||
|
|||||||
151
controllers/testdata/org_webhook_workflow_job_payload.json
vendored
Normal file
151
controllers/testdata/org_webhook_workflow_job_payload.json
vendored
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
{
|
||||||
|
"action": "queued",
|
||||||
|
"workflow_job": {
|
||||||
|
"id": 1234567890,
|
||||||
|
"run_id": 1234567890,
|
||||||
|
"run_url": "https://api.github.com/repos/MYORG/MYREPO/actions/runs/1234567890",
|
||||||
|
"node_id": "CR_kwDOGCados7e1x2g",
|
||||||
|
"head_sha": "1234567890123456789012345678901234567890",
|
||||||
|
"url": "https://api.github.com/repos/MYORG/MYREPO/actions/jobs/1234567890",
|
||||||
|
"html_url": "https://github.com/MYORG/MYREPO/runs/1234567890",
|
||||||
|
"status": "queued",
|
||||||
|
"conclusion": null,
|
||||||
|
"started_at": "2021-09-28T23:45:29Z",
|
||||||
|
"completed_at": null,
|
||||||
|
"name": "build",
|
||||||
|
"steps": [],
|
||||||
|
"check_run_url": "https://api.github.com/repos/MYORG/MYREPO/check-runs/1234567890",
|
||||||
|
"labels": [
|
||||||
|
"label1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"id": 1234567890,
|
||||||
|
"node_id": "ABCDEFGHIJKLMNOPQRSTUVWXYZ=",
|
||||||
|
"name": "MYREPO",
|
||||||
|
"full_name": "MYORG/MYREPO",
|
||||||
|
"private": true,
|
||||||
|
"owner": {
|
||||||
|
"login": "MYORG",
|
||||||
|
"id": 1234567890,
|
||||||
|
"node_id": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1234567890?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/MYORG",
|
||||||
|
"html_url": "https://github.com/MYORG",
|
||||||
|
"followers_url": "https://api.github.com/users/MYORG/followers",
|
||||||
|
"following_url": "https://api.github.com/users/MYORG/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/MYORG/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/MYORG/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/MYORG/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/MYORG/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/MYORG/repos",
|
||||||
|
"events_url": "https://api.github.com/users/MYORG/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/MYORG/received_events",
|
||||||
|
"type": "Organization",
|
||||||
|
"site_admin": false
|
||||||
|
},
|
||||||
|
"html_url": "https://github.com/MYORG/MYREPO",
|
||||||
|
"description": "MYREPO",
|
||||||
|
"fork": false,
|
||||||
|
"url": "https://api.github.com/repos/MYORG/MYREPO",
|
||||||
|
"forks_url": "https://api.github.com/repos/MYORG/MYREPO/forks",
|
||||||
|
"keys_url": "https://api.github.com/repos/MYORG/MYREPO/keys{/key_id}",
|
||||||
|
"collaborators_url": "https://api.github.com/repos/MYORG/MYREPO/collaborators{/collaborator}",
|
||||||
|
"teams_url": "https://api.github.com/repos/MYORG/MYREPO/teams",
|
||||||
|
"hooks_url": "https://api.github.com/repos/MYORG/MYREPO/hooks",
|
||||||
|
"issue_events_url": "https://api.github.com/repos/MYORG/MYREPO/issues/events{/number}",
|
||||||
|
"events_url": "https://api.github.com/repos/MYORG/MYREPO/events",
|
||||||
|
"assignees_url": "https://api.github.com/repos/MYORG/MYREPO/assignees{/user}",
|
||||||
|
"branches_url": "https://api.github.com/repos/MYORG/MYREPO/branches{/branch}",
|
||||||
|
"tags_url": "https://api.github.com/repos/MYORG/MYREPO/tags",
|
||||||
|
"blobs_url": "https://api.github.com/repos/MYORG/MYREPO/git/blobs{/sha}",
|
||||||
|
"git_tags_url": "https://api.github.com/repos/MYORG/MYREPO/git/tags{/sha}",
|
||||||
|
"git_refs_url": "https://api.github.com/repos/MYORG/MYREPO/git/refs{/sha}",
|
||||||
|
"trees_url": "https://api.github.com/repos/MYORG/MYREPO/git/trees{/sha}",
|
||||||
|
"statuses_url": "https://api.github.com/repos/MYORG/MYREPO/statuses/{sha}",
|
||||||
|
"languages_url": "https://api.github.com/repos/MYORG/MYREPO/languages",
|
||||||
|
"stargazers_url": "https://api.github.com/repos/MYORG/MYREPO/stargazers",
|
||||||
|
"contributors_url": "https://api.github.com/repos/MYORG/MYREPO/contributors",
|
||||||
|
"subscribers_url": "https://api.github.com/repos/MYORG/MYREPO/subscribers",
|
||||||
|
"subscription_url": "https://api.github.com/repos/MYORG/MYREPO/subscription",
|
||||||
|
"commits_url": "https://api.github.com/repos/MYORG/MYREPO/commits{/sha}",
|
||||||
|
"git_commits_url": "https://api.github.com/repos/MYORG/MYREPO/git/commits{/sha}",
|
||||||
|
"comments_url": "https://api.github.com/repos/MYORG/MYREPO/comments{/number}",
|
||||||
|
"issue_comment_url": "https://api.github.com/repos/MYORG/MYREPO/issues/comments{/number}",
|
||||||
|
"contents_url": "https://api.github.com/repos/MYORG/MYREPO/contents/{+path}",
|
||||||
|
"compare_url": "https://api.github.com/repos/MYORG/MYREPO/compare/{base}...{head}",
|
||||||
|
"merges_url": "https://api.github.com/repos/MYORG/MYREPO/merges",
|
||||||
|
"archive_url": "https://api.github.com/repos/MYORG/MYREPO/{archive_format}{/ref}",
|
||||||
|
"downloads_url": "https://api.github.com/repos/MYORG/MYREPO/downloads",
|
||||||
|
"issues_url": "https://api.github.com/repos/MYORG/MYREPO/issues{/number}",
|
||||||
|
"pulls_url": "https://api.github.com/repos/MYORG/MYREPO/pulls{/number}",
|
||||||
|
"milestones_url": "https://api.github.com/repos/MYORG/MYREPO/milestones{/number}",
|
||||||
|
"notifications_url": "https://api.github.com/repos/MYORG/MYREPO/notifications{?since,all,participating}",
|
||||||
|
"labels_url": "https://api.github.com/repos/MYORG/MYREPO/labels{/name}",
|
||||||
|
"releases_url": "https://api.github.com/repos/MYORG/MYREPO/releases{/id}",
|
||||||
|
"deployments_url": "https://api.github.com/repos/MYORG/MYREPO/deployments",
|
||||||
|
"created_at": "2021-09-10T18:55:38Z",
|
||||||
|
"updated_at": "2021-09-10T18:55:41Z",
|
||||||
|
"pushed_at": "2021-09-28T23:25:26Z",
|
||||||
|
"git_url": "git://github.com/MYORG/MYREPO.git",
|
||||||
|
"ssh_url": "git@github.com:MYORG/MYREPO.git",
|
||||||
|
"clone_url": "https://github.com/MYORG/MYREPO.git",
|
||||||
|
"svn_url": "https://github.com/MYORG/MYREPO",
|
||||||
|
"homepage": null,
|
||||||
|
"size": 121,
|
||||||
|
"stargazers_count": 0,
|
||||||
|
"watchers_count": 0,
|
||||||
|
"language": null,
|
||||||
|
"has_issues": true,
|
||||||
|
"has_projects": true,
|
||||||
|
"has_downloads": true,
|
||||||
|
"has_wiki": true,
|
||||||
|
"has_pages": false,
|
||||||
|
"forks_count": 0,
|
||||||
|
"mirror_url": null,
|
||||||
|
"archived": false,
|
||||||
|
"disabled": false,
|
||||||
|
"open_issues_count": 1,
|
||||||
|
"license": null,
|
||||||
|
"allow_forking": false,
|
||||||
|
"forks": 0,
|
||||||
|
"open_issues": 1,
|
||||||
|
"watchers": 0,
|
||||||
|
"default_branch": "master"
|
||||||
|
},
|
||||||
|
"organization": {
|
||||||
|
"login": "MYORG",
|
||||||
|
"id": 1234567890,
|
||||||
|
"node_id": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
"url": "https://api.github.com/orgs/MYORG",
|
||||||
|
"repos_url": "https://api.github.com/orgs/MYORG/repos",
|
||||||
|
"events_url": "https://api.github.com/orgs/MYORG/events",
|
||||||
|
"hooks_url": "https://api.github.com/orgs/MYORG/hooks",
|
||||||
|
"issues_url": "https://api.github.com/orgs/MYORG/issues",
|
||||||
|
"members_url": "https://api.github.com/orgs/MYORG/members{/member}",
|
||||||
|
"public_members_url": "https://api.github.com/orgs/MYORG/public_members{/member}",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1234567890?v=4",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
|
"sender": {
|
||||||
|
"login": "MYNAME",
|
||||||
|
"id": 1234567890,
|
||||||
|
"node_id": "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1234567890?v=4",
|
||||||
|
"gravatar_id": "",
|
||||||
|
"url": "https://api.github.com/users/MYNAME",
|
||||||
|
"html_url": "https://github.com/MYNAME",
|
||||||
|
"followers_url": "https://api.github.com/users/MYNAME/followers",
|
||||||
|
"following_url": "https://api.github.com/users/MYNAME/following{/other_user}",
|
||||||
|
"gists_url": "https://api.github.com/users/MYNAME/gists{/gist_id}",
|
||||||
|
"starred_url": "https://api.github.com/users/MYNAME/starred{/owner}{/repo}",
|
||||||
|
"subscriptions_url": "https://api.github.com/users/MYNAME/subscriptions",
|
||||||
|
"organizations_url": "https://api.github.com/users/MYNAME/orgs",
|
||||||
|
"repos_url": "https://api.github.com/users/MYNAME/repos",
|
||||||
|
"events_url": "https://api.github.com/users/MYNAME/events{/privacy}",
|
||||||
|
"received_events_url": "https://api.github.com/users/MYNAME/received_events",
|
||||||
|
"type": "User",
|
||||||
|
"site_admin": false
|
||||||
|
}
|
||||||
|
}
|
||||||
4
go.mod
4
go.mod
@@ -14,8 +14,8 @@ require (
|
|||||||
github.com/onsi/gomega v1.13.0
|
github.com/onsi/gomega v1.13.0
|
||||||
github.com/prometheus/client_golang v1.11.0
|
github.com/prometheus/client_golang v1.11.0
|
||||||
github.com/teambition/rrule-go v1.6.2
|
github.com/teambition/rrule-go v1.6.2
|
||||||
go.uber.org/zap v1.17.0
|
go.uber.org/zap v1.19.0
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||||
k8s.io/api v0.21.1
|
k8s.io/api v0.21.1
|
||||||
k8s.io/apimachinery v0.21.1
|
k8s.io/apimachinery v0.21.1
|
||||||
|
|||||||
78
go.sum
78
go.sum
@@ -10,18 +10,29 @@ cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO
|
|||||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0=
|
cloud.google.com/go v0.54.0 h1:3ithwDMr7/3vpAMXiH+ZQnYbuIsh+OPhUPMFC9enmn0=
|
||||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
|
||||||
|
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
|
||||||
|
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
|
||||||
|
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||||
|
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||||
|
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||||
@@ -47,6 +58,7 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
|
|||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||||
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@@ -65,6 +77,7 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR
|
|||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
@@ -91,7 +104,9 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn
|
|||||||
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
|
||||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||||
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
@@ -144,11 +159,14 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
@@ -166,7 +184,9 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
|||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
@@ -182,11 +202,14 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
|
|||||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
|
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
@@ -399,7 +422,9 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1
|
|||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
@@ -409,6 +434,7 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
|||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||||
@@ -421,6 +447,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
|
|||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
|
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
|
||||||
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
|
||||||
|
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
||||||
|
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
@@ -481,6 +509,7 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@@ -491,8 +520,14 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
|
||||||
@@ -503,12 +538,16 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
|
|||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -544,8 +583,14 @@ golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -609,9 +654,19 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK
|
|||||||
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
|
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
||||||
@@ -632,12 +687,19 @@ google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsb
|
|||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
|
||||||
|
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
|
||||||
|
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
@@ -657,17 +719,32 @@ google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvx
|
|||||||
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
|
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
|
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
|
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@@ -719,6 +796,7 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c=
|
k8s.io/api v0.21.1 h1:94bbZ5NTjdINJEdzOkpS4vdPhkb1VFpTYC9zh43f75c=
|
||||||
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
|
k8s.io/api v0.21.1/go.mod h1:FstGROTmsSHBarKc8bylzXih8BLNYTiS3TZcsoEDg2s=
|
||||||
k8s.io/apiextensions-apiserver v0.21.1 h1:AA+cnsb6w7SZ1vD32Z+zdgfXdXY8X9uGX5bN6EoPEIo=
|
k8s.io/apiextensions-apiserver v0.21.1 h1:AA+cnsb6w7SZ1vD32Z+zdgfXdXY8X9uGX5bN6EoPEIo=
|
||||||
|
|||||||
7
main.go
7
main.go
@@ -65,6 +65,7 @@ func main() {
|
|||||||
|
|
||||||
metricsAddr string
|
metricsAddr string
|
||||||
enableLeaderElection bool
|
enableLeaderElection bool
|
||||||
|
leaderElectionId string
|
||||||
syncPeriod time.Duration
|
syncPeriod time.Duration
|
||||||
|
|
||||||
gitHubAPICacheDuration time.Duration
|
gitHubAPICacheDuration time.Duration
|
||||||
@@ -81,12 +82,14 @@ func main() {
|
|||||||
var c github.Config
|
var c github.Config
|
||||||
err = envconfig.Process("github", &c)
|
err = envconfig.Process("github", &c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(os.Stderr, "Error: Environment variable read failed.")
|
fmt.Fprintf(os.Stderr, "Error: processing environment variables: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
flag.StringVar(&metricsAddr, "metrics-addr", ":8080", "The address the metric endpoint binds to.")
|
||||||
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
|
flag.BoolVar(&enableLeaderElection, "enable-leader-election", false,
|
||||||
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
|
"Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.")
|
||||||
|
flag.StringVar(&leaderElectionId, "leader-election-id", "actions-runner-controller", "Controller id for leader election.")
|
||||||
flag.StringVar(&runnerImage, "runner-image", defaultRunnerImage, "The image name of self-hosted runner container.")
|
flag.StringVar(&runnerImage, "runner-image", defaultRunnerImage, "The image name of self-hosted runner container.")
|
||||||
flag.StringVar(&dockerImage, "docker-image", defaultDockerImage, "The image name of docker sidecar container.")
|
flag.StringVar(&dockerImage, "docker-image", defaultDockerImage, "The image name of docker sidecar container.")
|
||||||
flag.StringVar(&dockerRegistryMirror, "docker-registry-mirror", "", "The default Docker Registry Mirror used by runners.")
|
flag.StringVar(&dockerRegistryMirror, "docker-registry-mirror", "", "The default Docker Registry Mirror used by runners.")
|
||||||
@@ -129,7 +132,7 @@ func main() {
|
|||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
MetricsBindAddress: metricsAddr,
|
MetricsBindAddress: metricsAddr,
|
||||||
LeaderElection: enableLeaderElection,
|
LeaderElection: enableLeaderElection,
|
||||||
LeaderElectionID: "actions-runner-controller",
|
LeaderElectionID: leaderElectionId,
|
||||||
Port: 9443,
|
Port: 9443,
|
||||||
SyncPeriod: &syncPeriod,
|
SyncPeriod: &syncPeriod,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
|
|||||||
136
pkg/githubwebhookdeliveryforwarder/cmd/main.go
Normal file
136
pkg/githubwebhookdeliveryforwarder/cmd/main.go
Normal 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
|
||||||
|
}
|
||||||
202
pkg/githubwebhookdeliveryforwarder/githubwebhookdelivery.go
Normal file
202
pkg/githubwebhookdeliveryforwarder/githubwebhookdelivery.go
Normal 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/v37/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.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
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().Time)
|
||||||
|
})
|
||||||
|
|
||||||
|
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...)
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
NAME ?= summerwind/actions-runner
|
NAME ?= summerwind/actions-runner
|
||||||
DIND_RUNNER_NAME ?= ${NAME}-dind
|
DIND_RUNNER_NAME ?= ${NAME}-dind
|
||||||
TAG ?= latest
|
TAG ?= latest
|
||||||
|
TARGET_PLATFORM ?= $(shell arch)
|
||||||
|
|
||||||
RUNNER_VERSION ?= 2.280.3
|
RUNNER_VERSION ?= 2.280.3
|
||||||
DOCKER_VERSION ?= 20.10.8
|
DOCKER_VERSION ?= 20.10.8
|
||||||
@@ -23,8 +24,8 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
docker-build-ubuntu:
|
docker-build-ubuntu:
|
||||||
docker build --build-arg TARGETPLATFORM=$(shell arch) --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:${TAG} .
|
docker build --build-arg TARGETPLATFORM=${TARGET_PLATFORM} --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${NAME}:${TAG} .
|
||||||
docker build --build-arg TARGETPLATFORM=$(shell arch) --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${DIND_RUNNER_NAME}:${TAG} -f Dockerfile.dindrunner .
|
docker build --build-arg TARGETPLATFORM=${TARGET_PLATFORM} --build-arg RUNNER_VERSION=${RUNNER_VERSION} --build-arg DOCKER_VERSION=${DOCKER_VERSION} -t ${DIND_RUNNER_NAME}:${TAG} -f Dockerfile.dindrunner .
|
||||||
|
|
||||||
docker-push-ubuntu:
|
docker-push-ubuntu:
|
||||||
docker push ${NAME}:${TAG}
|
docker push ${NAME}:${TAG}
|
||||||
|
|||||||
@@ -1,23 +1,43 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
RUNNER_HOME=${RUNNER_HOME:-/runner}
|
||||||
|
|
||||||
|
LIGHTGREEN="\e[0;32m"
|
||||||
|
LIGHTRED="\e[0;31m"
|
||||||
|
WHITE="\e[0;97m"
|
||||||
|
RESET="\e[0m"
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "${WHITE}${@}${RESET}\n" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "${LIGHTGREEN}${@}${RESET}\n" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "${LIGHTRED}${@}${RESET}\n" 1>&2
|
||||||
|
}
|
||||||
|
|
||||||
if [ ! -z "${STARTUP_DELAY_IN_SECONDS}" ]; then
|
if [ ! -z "${STARTUP_DELAY_IN_SECONDS}" ]; then
|
||||||
echo "Delaying startup by ${STARTUP_DELAY_IN_SECONDS} seconds" 1>&2
|
log "Delaying startup by ${STARTUP_DELAY_IN_SECONDS} seconds"
|
||||||
sleep ${STARTUP_DELAY_IN_SECONDS}
|
sleep ${STARTUP_DELAY_IN_SECONDS}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ -z "${GITHUB_URL}" ]; then
|
if [ -z "${GITHUB_URL}" ]; then
|
||||||
echo "Working with public GitHub" 1>&2
|
log "Working with public GitHub"
|
||||||
GITHUB_URL="https://github.com/"
|
GITHUB_URL="https://github.com/"
|
||||||
else
|
else
|
||||||
length=${#GITHUB_URL}
|
length=${#GITHUB_URL}
|
||||||
last_char=${GITHUB_URL:length-1:1}
|
last_char=${GITHUB_URL:length-1:1}
|
||||||
|
|
||||||
[[ $last_char != "/" ]] && GITHUB_URL="$GITHUB_URL/"; :
|
[[ $last_char != "/" ]] && GITHUB_URL="$GITHUB_URL/"; :
|
||||||
echo "Github endpoint URL ${GITHUB_URL}"
|
log "Github endpoint URL ${GITHUB_URL}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${RUNNER_NAME}" ]; then
|
if [ -z "${RUNNER_NAME}" ]; then
|
||||||
echo "RUNNER_NAME must be set" 1>&2
|
error "RUNNER_NAME must be set"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -30,12 +50,12 @@ elif [ -n "${RUNNER_REPO}" ]; then
|
|||||||
elif [ -n "${RUNNER_ENTERPRISE}" ]; then
|
elif [ -n "${RUNNER_ENTERPRISE}" ]; then
|
||||||
ATTACH="enterprises/${RUNNER_ENTERPRISE}"
|
ATTACH="enterprises/${RUNNER_ENTERPRISE}"
|
||||||
else
|
else
|
||||||
echo "At least one of RUNNER_ORG or RUNNER_REPO or RUNNER_ENTERPRISE must be set" 1>&2
|
error "At least one of RUNNER_ORG or RUNNER_REPO or RUNNER_ENTERPRISE must be set"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "${RUNNER_TOKEN}" ]; then
|
if [ -z "${RUNNER_TOKEN}" ]; then
|
||||||
echo "RUNNER_TOKEN must be set" 1>&2
|
error "RUNNER_TOKEN must be set"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -44,15 +64,19 @@ if [ -z "${RUNNER_REPO}" ] && [ -n "${RUNNER_GROUP}" ];then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Hack due to https://github.com/actions-runner-controller/actions-runner-controller/issues/252#issuecomment-758338483
|
# Hack due to https://github.com/actions-runner-controller/actions-runner-controller/issues/252#issuecomment-758338483
|
||||||
if [ ! -d /runner ]; then
|
if [ ! -d "${RUNNER_HOME}" ]; then
|
||||||
echo "/runner should be an emptyDir mount. Please fix the pod spec." 1>&2
|
error "${RUNNER_HOME} should be an emptyDir mount. Please fix the pod spec."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
sudo chown -R runner:docker /runner
|
# if this is not a testing environment
|
||||||
cp -r /runnertmp/* /runner/
|
if [ -z "${UNITTEST:-}" ]; then
|
||||||
|
sudo chown -R runner:docker ${RUNNER_HOME}
|
||||||
|
mv /runnertmp/* ${RUNNER_HOME}/
|
||||||
|
fi
|
||||||
|
|
||||||
cd /runner
|
cd ${RUNNER_HOME}
|
||||||
|
# past that point, it's all relative pathes from /runner
|
||||||
|
|
||||||
config_args=()
|
config_args=()
|
||||||
if [ "${RUNNER_FEATURE_FLAG_EPHEMERAL:-}" == "true" -a "${RUNNER_EPHEMERAL}" != "false" ]; then
|
if [ "${RUNNER_FEATURE_FLAG_EPHEMERAL:-}" == "true" -a "${RUNNER_EPHEMERAL}" != "false" ]; then
|
||||||
@@ -60,54 +84,71 @@ if [ "${RUNNER_FEATURE_FLAG_EPHEMERAL:-}" == "true" -a "${RUNNER_EPHEMERAL}" !=
|
|||||||
echo "Passing --ephemeral to config.sh to enable the ephemeral runner."
|
echo "Passing --ephemeral to config.sh to enable the ephemeral runner."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
./config.sh --unattended --replace \
|
retries_left=10
|
||||||
--name "${RUNNER_NAME}" \
|
while [[ ${retries_left} -gt 0 ]]; do
|
||||||
--url "${GITHUB_URL}${ATTACH}" \
|
log "Configuring the runner."
|
||||||
--token "${RUNNER_TOKEN}" \
|
./config.sh --unattended --replace \
|
||||||
--runnergroup "${RUNNER_GROUPS}" \
|
--name "${RUNNER_NAME}" \
|
||||||
--labels "${RUNNER_LABELS}" \
|
--url "${GITHUB_URL}${ATTACH}" \
|
||||||
--work "${RUNNER_WORKDIR}" "${config_args[@]}"
|
--token "${RUNNER_TOKEN}" \
|
||||||
|
--runnergroup "${RUNNER_GROUPS}" \
|
||||||
|
--labels "${RUNNER_LABELS}" \
|
||||||
|
--work "${RUNNER_WORKDIR}" "${config_args[@]}"
|
||||||
|
|
||||||
if [ -f /runner/.runner ]; then
|
if [ -f .runner ]; then
|
||||||
echo Runner has successfully been configured with the following data.
|
success "Runner successfully configured."
|
||||||
cat /runner/.runner
|
break
|
||||||
# Note: the `.runner` file's content should be something like the below:
|
fi
|
||||||
#
|
|
||||||
# $ cat /runner/.runner
|
error "Configuration failed. Retrying"
|
||||||
# {
|
retries_left=$((retries_left - 1))
|
||||||
# "agentId": 117, #=> corresponds to the ID of the runner
|
sleep 1
|
||||||
# "agentName": "THE_RUNNER_POD_NAME",
|
done
|
||||||
# "poolId": 1,
|
|
||||||
# "poolName": "Default",
|
if [ ! -f .runner ]; then
|
||||||
# "serverUrl": "https://pipelines.actions.githubusercontent.com/SOME_RANDOM_ID",
|
# we couldn't configure and register the runner; no point continuing
|
||||||
# "gitHubUrl": "https://github.com/USER/REPO",
|
error "Configuration failed!"
|
||||||
# "workFolder": "/some/work/dir" #=> corresponds to Runner.Spec.WorkDir
|
exit 2
|
||||||
# }
|
|
||||||
#
|
|
||||||
# Especially `agentId` is important, as other than listing all the runners in the repo,
|
|
||||||
# this is the only change we could get the exact runnner ID which can be useful for further
|
|
||||||
# GitHub API call like the below. Note that 171 is the agentId seen above.
|
|
||||||
# curl \
|
|
||||||
# -H "Accept: application/vnd.github.v3+json" \
|
|
||||||
# -H "Authorization: bearer ${GITHUB_TOKEN}"
|
|
||||||
# https://api.github.com/repos/USER/REPO/actions/runners/171
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
cat .runner
|
||||||
|
# Note: the `.runner` file's content should be something like the below:
|
||||||
|
#
|
||||||
|
# $ cat /runner/.runner
|
||||||
|
# {
|
||||||
|
# "agentId": 117, #=> corresponds to the ID of the runner
|
||||||
|
# "agentName": "THE_RUNNER_POD_NAME",
|
||||||
|
# "poolId": 1,
|
||||||
|
# "poolName": "Default",
|
||||||
|
# "serverUrl": "https://pipelines.actions.githubusercontent.com/SOME_RANDOM_ID",
|
||||||
|
# "gitHubUrl": "https://github.com/USER/REPO",
|
||||||
|
# "workFolder": "/some/work/dir" #=> corresponds to Runner.Spec.WorkDir
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# Especially `agentId` is important, as other than listing all the runners in the repo,
|
||||||
|
# this is the only change we could get the exact runnner ID which can be useful for further
|
||||||
|
# GitHub API call like the below. Note that 171 is the agentId seen above.
|
||||||
|
# curl \
|
||||||
|
# -H "Accept: application/vnd.github.v3+json" \
|
||||||
|
# -H "Authorization: bearer ${GITHUB_TOKEN}"
|
||||||
|
# https://api.github.com/repos/USER/REPO/actions/runners/171
|
||||||
|
|
||||||
if [ -n "${RUNNER_REGISTRATION_ONLY}" ]; then
|
if [ -n "${RUNNER_REGISTRATION_ONLY}" ]; then
|
||||||
echo
|
success "This runner is configured to be registration-only. Exiting without starting the runner service..."
|
||||||
echo "This runner is configured to be registration-only. Exiting without starting the runner service..."
|
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir ./externals
|
if [ -z "${UNITTEST:-}" ]; then
|
||||||
# Hack due to the DinD volumes
|
mkdir ./externals
|
||||||
mv ./externalstmp/* ./externals/
|
# Hack due to the DinD volumes
|
||||||
|
mv ./externalstmp/* ./externals/
|
||||||
|
|
||||||
for f in runsvc.sh RunnerService.js; do
|
for f in runsvc.sh RunnerService.js; do
|
||||||
diff {bin,patched}/${f} || :
|
diff {bin,patched}/${f} || :
|
||||||
sudo mv bin/${f}{,.bak}
|
sudo mv bin/${f}{,.bak}
|
||||||
sudo mv {patched,bin}/${f}
|
sudo mv {patched,bin}/${f}
|
||||||
done
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
args=()
|
args=()
|
||||||
if [ "${RUNNER_FEATURE_FLAG_EPHEMERAL:-}" != "true" -a "${RUNNER_EPHEMERAL}" != "false" ]; then
|
if [ "${RUNNER_FEATURE_FLAG_EPHEMERAL:-}" != "true" -a "${RUNNER_EPHEMERAL}" != "false" ]; then
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ var (
|
|||||||
// This tests ues testing.Logf extensively for debugging purpose.
|
// This tests ues testing.Logf extensively for debugging purpose.
|
||||||
// But messages logged via Logf shows up only when the test failed by default.
|
// But messages logged via Logf shows up only when the test failed by default.
|
||||||
// To always enable logging, do not forget to pass `-test.v` to `go test`.
|
// To always enable logging, do not forget to pass `-test.v` to `go test`.
|
||||||
// If you're using VS Code, open `Workspace Settings` and search for `go test flags`, edit the `settings.json` and put the below:
|
// If you're using VS Code, open `Workspace Settings` and search for `go test flags`, edit the `.vscode/settings.json` and put the below:
|
||||||
// "go.testFlags": ["-v"]
|
// "go.testFlags": ["-v"]
|
||||||
//
|
//
|
||||||
// This function requires a few environment variables to be set to provide some test data.
|
// This function requires a few environment variables to be set to provide some test data.
|
||||||
@@ -298,7 +298,7 @@ func installActionsWorkflow(t *testing.T, testID, runnerLabel, testResultCMNameP
|
|||||||
Name: wfName,
|
Name: wfName,
|
||||||
On: testing.On{
|
On: testing.On{
|
||||||
Push: &testing.Push{
|
Push: &testing.Push{
|
||||||
Branches: []string{"main"},
|
Branches: []string{"master"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Jobs: map[string]testing.Job{},
|
Jobs: map[string]testing.Job{},
|
||||||
@@ -403,5 +403,5 @@ func verifyActionsWorkflowRun(t *testing.T, env *testing.Env, testJobs []job) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return results, err
|
return results, err
|
||||||
}, 60*time.Second, 10*time.Second).Should(gomega.Equal(expected))
|
}, 3*60*time.Second, 10*time.Second).Should(gomega.Equal(expected))
|
||||||
}
|
}
|
||||||
|
|||||||
37
test/entrypoint/entrypoint_unittest.sh
Executable file
37
test/entrypoint/entrypoint_unittest.sh
Executable file
@@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source logging.sh
|
||||||
|
|
||||||
|
for unittest in ./should*; do
|
||||||
|
log "**********************************"
|
||||||
|
log " UNIT TEST: ${unittest}"
|
||||||
|
log "**********************************"
|
||||||
|
log ""
|
||||||
|
|
||||||
|
cd ${unittest}
|
||||||
|
./test.sh
|
||||||
|
ret_code=$?
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
log ""
|
||||||
|
log ""
|
||||||
|
if [ "${ret_code}" = "0" ]; then
|
||||||
|
success "Completed: unit test ${unittest}"
|
||||||
|
else
|
||||||
|
error "Completed: unit test ${unittest} with errors"
|
||||||
|
failed="true"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -n "${failed:-}" ]; then
|
||||||
|
error ""
|
||||||
|
error "*************************************"
|
||||||
|
error "All unit tests completed, with errors"
|
||||||
|
error "*************************************"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
success ""
|
||||||
|
success "***************************************"
|
||||||
|
success "All unit tests completed with no errors"
|
||||||
|
success "***************************************"
|
||||||
|
fi
|
||||||
18
test/entrypoint/logging.sh
Executable file
18
test/entrypoint/logging.sh
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
29
test/entrypoint/should_retry_configuring/config.sh
Executable file
29
test/entrypoint/should_retry_configuring/config.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "$*" > runner_config
|
||||||
|
success "I'm pretending the configuration is not successful"
|
||||||
|
# increasing a counter to measure how many times we restarted
|
||||||
|
count=`cat counter 2>/dev/null|| echo "0"`
|
||||||
|
count=$((count + 1))
|
||||||
|
echo ${count} > counter
|
||||||
|
|
||||||
31
test/entrypoint/should_retry_configuring/runsvc.sh
Executable file
31
test/entrypoint/should_retry_configuring/runsvc.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
success ""
|
||||||
|
success "Running the service..."
|
||||||
|
# SHOULD NOT HAPPEN
|
||||||
|
# creating a file to show this script has run
|
||||||
|
touch runsvc_ran
|
||||||
|
success "...successful"
|
||||||
|
success ""
|
||||||
|
|
||||||
|
|
||||||
74
test/entrypoint/should_retry_configuring/test.sh
Executable file
74
test/entrypoint/should_retry_configuring/test.sh
Executable file
@@ -0,0 +1,74 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# UNITTEST: retry config
|
||||||
|
# Will simulate a configuration failure and expects:
|
||||||
|
# - the configuration step to be run 10 times
|
||||||
|
# - the entrypoint script to exit with error code 2
|
||||||
|
# - the runsvc.sh script to never run.
|
||||||
|
|
||||||
|
source ../logging.sh
|
||||||
|
|
||||||
|
entrypoint_log() {
|
||||||
|
while read I; do
|
||||||
|
printf "\tentrypoint.sh: $I\n"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Setting up the test"
|
||||||
|
export UNITTEST=true
|
||||||
|
export RUNNER_HOME=localhome
|
||||||
|
export RUNNER_NAME="example_runner_name"
|
||||||
|
export RUNNER_REPO="myorg/myrepo"
|
||||||
|
export RUNNER_TOKEN="xxxxxxxxxxxxx"
|
||||||
|
|
||||||
|
mkdir -p ${RUNNER_HOME}/bin
|
||||||
|
# add up the config.sh and runsvc.sh
|
||||||
|
ln -s ../config.sh ${RUNNER_HOME}/config.sh
|
||||||
|
ln -s ../../runsvc.sh ${RUNNER_HOME}/bin/runsvc.sh
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf ${RUNNER_HOME}
|
||||||
|
unset UNITTEST
|
||||||
|
unset RUNNERHOME
|
||||||
|
unset RUNNER_NAME
|
||||||
|
unset RUNNER_REPO
|
||||||
|
unset RUNNER_TOKEN
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT SIGTERM SIGQUIT EXIT
|
||||||
|
|
||||||
|
log "Running the entrypoint"
|
||||||
|
log ""
|
||||||
|
|
||||||
|
../../../runner/entrypoint.sh 2> >(entrypoint_log)
|
||||||
|
|
||||||
|
if [ "$?" != "2" ]; then
|
||||||
|
error "========================================="
|
||||||
|
error "Configuration should have thrown an error"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
success "Entrypoint didn't complete successfully"
|
||||||
|
success ""
|
||||||
|
|
||||||
|
log "Checking the counter, should have 10 iterations"
|
||||||
|
count=`cat ${RUNNER_HOME}/counter || "notfound"`
|
||||||
|
if [ "${count}" != "10" ]; then
|
||||||
|
error "============================================="
|
||||||
|
error "The retry loop should have done 10 iterations"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
success "Retry loop went up to 10"
|
||||||
|
success
|
||||||
|
|
||||||
|
log "Checking that runsvc never ran"
|
||||||
|
if [ -f ${RUNNER_HOME}/runsvc_ran ]; then
|
||||||
|
error "================================================================="
|
||||||
|
error "runsvc was invoked, entrypoint.sh should have failed before that."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "runsvc.sh never ran"
|
||||||
|
success
|
||||||
|
success "==========================="
|
||||||
|
success "Test completed successfully"
|
||||||
|
exit 0
|
||||||
29
test/entrypoint/should_switch_to_ephemeral_upstream_feature/config.sh
Executable file
29
test/entrypoint/should_switch_to_ephemeral_upstream_feature/config.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success "I'm configured normally"
|
||||||
|
touch .runner
|
||||||
|
echo "$*" > runner_config
|
||||||
|
success "created a dummy config file"
|
||||||
|
success
|
||||||
|
# adding a counter to see how many times we've gone through a configuration step
|
||||||
|
count=`cat counter 2>/dev/null|| echo "0"`
|
||||||
|
count=$((count + 1))
|
||||||
|
echo ${count} > counter
|
||||||
|
|
||||||
31
test/entrypoint/should_switch_to_ephemeral_upstream_feature/runsvc.sh
Executable file
31
test/entrypoint/should_switch_to_ephemeral_upstream_feature/runsvc.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
success ""
|
||||||
|
success "Running the service..."
|
||||||
|
# test if --once is present as a parameter
|
||||||
|
echo "$*" | grep -q 'once' && error "Should not include --once in the parameters"
|
||||||
|
success "...successful"
|
||||||
|
touch runsvc_ran
|
||||||
|
success ""
|
||||||
|
|
||||||
|
|
||||||
81
test/entrypoint/should_switch_to_ephemeral_upstream_feature/test.sh
Executable file
81
test/entrypoint/should_switch_to_ephemeral_upstream_feature/test.sh
Executable file
@@ -0,0 +1,81 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# UNITTEST: should work as non ephemeral
|
||||||
|
# Will simulate a scenario where ephemeral=false. expects:
|
||||||
|
# - the configuration step to be run exactly once
|
||||||
|
# - the entrypoint script to exit with no error
|
||||||
|
# - the runsvc.sh script to run without the --once flag
|
||||||
|
|
||||||
|
source ../logging.sh
|
||||||
|
|
||||||
|
entrypoint_log() {
|
||||||
|
while read I; do
|
||||||
|
printf "\tentrypoint.sh: $I\n"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Setting up the test"
|
||||||
|
export UNITTEST=true
|
||||||
|
export RUNNER_HOME=localhome
|
||||||
|
export RUNNER_NAME="example_runner_name"
|
||||||
|
export RUNNER_REPO="myorg/myrepo"
|
||||||
|
export RUNNER_TOKEN="xxxxxxxxxxxxx"
|
||||||
|
export RUNNER_EPHEMERAL=true
|
||||||
|
export RUNNER_FEATURE_FLAG_EPHEMERAL=true
|
||||||
|
|
||||||
|
mkdir -p ${RUNNER_HOME}/bin
|
||||||
|
# add up the config.sh and runsvc.sh
|
||||||
|
ln -s ../config.sh ${RUNNER_HOME}/config.sh
|
||||||
|
ln -s ../../runsvc.sh ${RUNNER_HOME}/bin/runsvc.sh
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf ${RUNNER_HOME}
|
||||||
|
unset UNITTEST
|
||||||
|
unset RUNNERHOME
|
||||||
|
unset RUNNER_NAME
|
||||||
|
unset RUNNER_REPO
|
||||||
|
unset RUNNER_TOKEN
|
||||||
|
unset RUNNER_EPHEMERAL
|
||||||
|
unset RUNNER_FEATURE_FLAG_EPHEMERAL
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT SIGTERM SIGQUIT EXIT
|
||||||
|
|
||||||
|
log "Running the entrypoint"
|
||||||
|
log ""
|
||||||
|
|
||||||
|
../../../runner/entrypoint.sh 2> >(entrypoint_log)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
error "==========================================="
|
||||||
|
error "Entrypoint script did not exit successfully"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Testing if we went through the configuration step only once"
|
||||||
|
count=`cat ${RUNNER_HOME}/counter || echo "not_found"`
|
||||||
|
if [ ${count} != "1" ]; then
|
||||||
|
error "==============================================="
|
||||||
|
error "The configuration step was not run exactly once"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Testing if the configuration included the --ephemeral flag"
|
||||||
|
if ! grep -q -- '--ephemeral' ${RUNNER_HOME}/runner_config; then
|
||||||
|
error "==============================================="
|
||||||
|
error "The configuration did not include the --ephemeral flag"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "The configuration ran ${count} time(s)"
|
||||||
|
|
||||||
|
log "Testing if runsvc ran"
|
||||||
|
if [ ! -f "${RUNNER_HOME}/runsvc_ran" ]; then
|
||||||
|
error "=============================="
|
||||||
|
error "The runner service has not run"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
success "The service ran"
|
||||||
|
success ""
|
||||||
|
success "==========================="
|
||||||
|
success "Test completed successfully"
|
||||||
29
test/entrypoint/should_work_non_ephemeral/config.sh
Executable file
29
test/entrypoint/should_work_non_ephemeral/config.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success "I'm configured normally"
|
||||||
|
touch .runner
|
||||||
|
echo "$*" > runner_config
|
||||||
|
success "created a dummy config file"
|
||||||
|
success
|
||||||
|
# adding a counter to see how many times we've gone through a configuration step
|
||||||
|
count=`cat counter 2>/dev/null|| echo "0"`
|
||||||
|
count=$((count + 1))
|
||||||
|
echo ${count} > counter
|
||||||
|
|
||||||
31
test/entrypoint/should_work_non_ephemeral/runsvc.sh
Executable file
31
test/entrypoint/should_work_non_ephemeral/runsvc.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
success ""
|
||||||
|
success "Running the service..."
|
||||||
|
# test if --once is present as a parameter
|
||||||
|
echo "$*" | grep -q 'once' && error "Should not include --once in the parameters"
|
||||||
|
success "...successful"
|
||||||
|
touch runsvc_ran
|
||||||
|
success ""
|
||||||
|
|
||||||
|
|
||||||
72
test/entrypoint/should_work_non_ephemeral/test.sh
Executable file
72
test/entrypoint/should_work_non_ephemeral/test.sh
Executable file
@@ -0,0 +1,72 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# UNITTEST: should work as non ephemeral
|
||||||
|
# Will simulate a scenario where ephemeral=false. expects:
|
||||||
|
# - the configuration step to be run exactly once
|
||||||
|
# - the entrypoint script to exit with no error
|
||||||
|
# - the runsvc.sh script to run without the --once flag
|
||||||
|
|
||||||
|
source ../logging.sh
|
||||||
|
|
||||||
|
entrypoint_log() {
|
||||||
|
while read I; do
|
||||||
|
printf "\tentrypoint.sh: $I\n"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Setting up the test"
|
||||||
|
export UNITTEST=true
|
||||||
|
export RUNNER_HOME=localhome
|
||||||
|
export RUNNER_NAME="example_runner_name"
|
||||||
|
export RUNNER_REPO="myorg/myrepo"
|
||||||
|
export RUNNER_TOKEN="xxxxxxxxxxxxx"
|
||||||
|
export RUNNER_EPHEMERAL=false
|
||||||
|
|
||||||
|
mkdir -p ${RUNNER_HOME}/bin
|
||||||
|
# add up the config.sh and runsvc.sh
|
||||||
|
ln -s ../config.sh ${RUNNER_HOME}/config.sh
|
||||||
|
ln -s ../../runsvc.sh ${RUNNER_HOME}/bin/runsvc.sh
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf ${RUNNER_HOME}
|
||||||
|
unset UNITTEST
|
||||||
|
unset RUNNERHOME
|
||||||
|
unset RUNNER_NAME
|
||||||
|
unset RUNNER_REPO
|
||||||
|
unset RUNNER_TOKEN
|
||||||
|
unset RUNNER_EPHEMERAL
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT SIGTERM SIGQUIT EXIT
|
||||||
|
|
||||||
|
log "Running the entrypoint"
|
||||||
|
log ""
|
||||||
|
|
||||||
|
../../../runner/entrypoint.sh 2> >(entrypoint_log)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
error "==========================================="
|
||||||
|
error "Entrypoint script did not exit successfully"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Testing if we went through the configuration step only once"
|
||||||
|
count=`cat ${RUNNER_HOME}/counter || echo "not_found"`
|
||||||
|
if [ ${count} != "1" ]; then
|
||||||
|
error "==============================================="
|
||||||
|
error "The configuration step was not run exactly once"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "The configuration ran ${count} time(s)"
|
||||||
|
|
||||||
|
log "Testing if runsvc ran"
|
||||||
|
if [ ! -f "${RUNNER_HOME}/runsvc_ran" ]; then
|
||||||
|
error "=============================="
|
||||||
|
error "The runner service has not run"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
success "The service ran"
|
||||||
|
success ""
|
||||||
|
success "==========================="
|
||||||
|
success "Test completed successfully"
|
||||||
29
test/entrypoint/should_work_normally/config.sh
Executable file
29
test/entrypoint/should_work_normally/config.sh
Executable file
@@ -0,0 +1,29 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success "I'm configured normally"
|
||||||
|
touch .runner
|
||||||
|
echo "$*" > runner_config
|
||||||
|
success "created a dummy config file"
|
||||||
|
success
|
||||||
|
# Adding a counter to see how many times we've gone through the configuration step
|
||||||
|
count=`cat counter 2>/dev/null|| echo "0"`
|
||||||
|
count=$((count + 1))
|
||||||
|
echo ${count} > counter
|
||||||
|
|
||||||
31
test/entrypoint/should_work_normally/runsvc.sh
Executable file
31
test/entrypoint/should_work_normally/runsvc.sh
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
export LIGHTGREEN='\e[0;32m'
|
||||||
|
export LIGHTRED='\e[0;31m'
|
||||||
|
export WHITE='\e[0;97m'
|
||||||
|
export RESET='\e[0m'
|
||||||
|
|
||||||
|
log(){
|
||||||
|
printf "\t${WHITE}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
success(){
|
||||||
|
printf "\t${LIGHTGREEN}$@${RESET}\n" 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
error(){
|
||||||
|
printf "\t${LIGHTRED}$@${RESET}\n" 2>&1
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
success ""
|
||||||
|
success "Running the service..."
|
||||||
|
# test if --once is present as a parameter
|
||||||
|
echo "$*" | grep -q 'once' || error "Should include --once in the parameters"j
|
||||||
|
success "...successful"
|
||||||
|
touch runsvc_ran
|
||||||
|
success ""
|
||||||
|
|
||||||
|
|
||||||
77
test/entrypoint/should_work_normally/test.sh
Executable file
77
test/entrypoint/should_work_normally/test.sh
Executable file
@@ -0,0 +1,77 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# UNITTEST: should work normally
|
||||||
|
# Will simulate a normal execution scenario. expects:
|
||||||
|
# - the configuration step to be run exactly once
|
||||||
|
# - the entrypoint script to exit with no error
|
||||||
|
# - the runsvc.sh script to run with the --once flag activated.
|
||||||
|
|
||||||
|
source ../logging.sh
|
||||||
|
|
||||||
|
entrypoint_log() {
|
||||||
|
while read I; do
|
||||||
|
printf "\tentrypoint.sh: $I\n"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Setting up the test"
|
||||||
|
export UNITTEST=true
|
||||||
|
export RUNNER_HOME=localhome
|
||||||
|
export RUNNER_NAME="example_runner_name"
|
||||||
|
export RUNNER_REPO="myorg/myrepo"
|
||||||
|
export RUNNER_TOKEN="xxxxxxxxxxxxx"
|
||||||
|
|
||||||
|
mkdir -p ${RUNNER_HOME}/bin
|
||||||
|
# add up the config.sh and runsvc.sh
|
||||||
|
ln -s ../config.sh ${RUNNER_HOME}/config.sh
|
||||||
|
ln -s ../../runsvc.sh ${RUNNER_HOME}/bin/runsvc.sh
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
rm -rf ${RUNNER_HOME}
|
||||||
|
unset UNITTEST
|
||||||
|
unset RUNNERHOME
|
||||||
|
unset RUNNER_NAME
|
||||||
|
unset RUNNER_REPO
|
||||||
|
unset RUNNER_TOKEN
|
||||||
|
}
|
||||||
|
|
||||||
|
trap cleanup SIGINT SIGTERM SIGQUIT EXIT
|
||||||
|
|
||||||
|
log "Running the entrypoint"
|
||||||
|
log ""
|
||||||
|
|
||||||
|
../../../runner/entrypoint.sh 2> >(entrypoint_log)
|
||||||
|
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
error "=========================="
|
||||||
|
error "Test completed with errors"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Testing if the configuration step was run only once"
|
||||||
|
count=`cat ${RUNNER_HOME}/counter || echo "not_found"`
|
||||||
|
if [ ${count} != "1" ]; then
|
||||||
|
error "==============================================="
|
||||||
|
error "The configuration step was not run exactly once"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
success "The configuration ran ${count} time(s)"
|
||||||
|
|
||||||
|
log "Testing if the configuration included the --ephemeral flag"
|
||||||
|
if grep -q -- '--ephemeral' ${RUNNER_HOME}/runner_config; then
|
||||||
|
error "==============================================="
|
||||||
|
error "The configuration should not include the --ephemeral flag"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Testing if runsvc ran"
|
||||||
|
if [ ! -f "${RUNNER_HOME}/runsvc_ran" ]; then
|
||||||
|
error "=============================="
|
||||||
|
error "The runner service has not run"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
success "The service ran"
|
||||||
|
success ""
|
||||||
|
success "==========================="
|
||||||
|
success "Test completed successfully"
|
||||||
@@ -89,7 +89,7 @@ func (g *GitRepo) gitCommitCmd(ctx context.Context, dir, msg string) *exec.Cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *GitRepo) gitPushCmd(ctx context.Context, dir string) *exec.Cmd {
|
func (g *GitRepo) gitPushCmd(ctx context.Context, dir string) *exec.Cmd {
|
||||||
cmd := exec.CommandContext(ctx, "git", "push", "origin", "main")
|
cmd := exec.CommandContext(ctx, "git", "push", "origin", "master")
|
||||||
cmd.Dir = dir
|
cmd.Dir = dir
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user