mirror of
https://github.com/actions/actions-runner-controller.git
synced 2025-12-10 11:41:27 +00:00
Compare commits
11 Commits
v0.16.1
...
actions-ru
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2146c62c9e | ||
|
|
28e80a2d28 | ||
|
|
831db9ee2a | ||
|
|
4d69e0806e | ||
|
|
d37cd69e9b | ||
|
|
a2690aa5cb | ||
|
|
da020df0fd | ||
|
|
6c64ae6a01 | ||
|
|
42c7d0489d | ||
|
|
b3bef6404c | ||
|
|
1127c447c4 |
7
.github/workflows/build-runner.yml
vendored
7
.github/workflows/build-runner.yml
vendored
@@ -27,10 +27,14 @@ jobs:
|
||||
- name: actions-runner-dind
|
||||
dockerfile: dindrunner.Dockerfile
|
||||
env:
|
||||
RUNNER_VERSION: 2.275.1
|
||||
RUNNER_VERSION: 2.276.1
|
||||
DOCKER_VERSION: 19.03.12
|
||||
DOCKERHUB_USERNAME: ${{ github.repository_owner }}
|
||||
steps:
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo ::set-output name=sha_short::${GITHUB_SHA::7}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -61,4 +65,5 @@ jobs:
|
||||
DOCKER_VERSION=${{ env.DOCKER_VERSION }}
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_USERNAME }}/${{ matrix.name }}:v${{ env.RUNNER_VERSION }}
|
||||
${{ env.DOCKERHUB_USERNAME }}/${{ matrix.name }}:v${{ env.RUNNER_VERSION }}-${{ steps.vars.outputs.sha_short }}
|
||||
${{ env.DOCKERHUB_USERNAME }}/${{ matrix.name }}:latest
|
||||
|
||||
75
.github/workflows/on-push-lint-charts.yml
vendored
Normal file
75
.github/workflows/on-push-lint-charts.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
name: Lint and Test Charts
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'charts/**'
|
||||
- '.github/**'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
KUBE_SCORE_VERSION: 1.10.0
|
||||
HELM_VERSION: v3.4.1
|
||||
|
||||
jobs:
|
||||
lint-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v1
|
||||
with:
|
||||
version: ${{ env.HELM_VERSION }}
|
||||
|
||||
- name: Set up kube-score
|
||||
run: |
|
||||
wget https://github.com/zegl/kube-score/releases/download/v${{ env.KUBE_SCORE_VERSION }}/kube-score_${{ env.KUBE_SCORE_VERSION }}_linux_amd64 -O kube-score
|
||||
chmod 755 kube-score
|
||||
|
||||
- name: Kube-score generated manifests
|
||||
run: helm template --values charts/.ci/values-kube-score.yaml charts/* | ./kube-score score -
|
||||
--ignore-test pod-networkpolicy
|
||||
--ignore-test deployment-has-poddisruptionbudget
|
||||
--ignore-test deployment-has-host-podantiaffinity
|
||||
--ignore-test container-security-context
|
||||
--ignore-test pod-probes
|
||||
--ignore-test container-image-tag
|
||||
--enable-optional-test container-security-context-privileged
|
||||
--enable-optional-test container-security-context-readonlyrootfilesystem
|
||||
|
||||
# python is a requirement for the chart-testing action below (supports yamllint among other tests)
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: helm/chart-testing-action@v2.0.1
|
||||
|
||||
- name: Run chart-testing (list-changed)
|
||||
id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --config charts/.ci/ct-config.yaml)
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
|
||||
- name: Run chart-testing (lint)
|
||||
run: ct lint --config charts/.ci/ct-config.yaml
|
||||
|
||||
- name: Create kind cluster
|
||||
uses: helm/kind-action@v1.0.0
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
|
||||
# We need cert-manager already installed in the cluster because we assume the CRDs exist
|
||||
- name: Install cert-manager
|
||||
run: |
|
||||
helm repo add jetstack https://charts.jetstack.io --force-update
|
||||
helm install cert-manager jetstack/cert-manager --set installCRDs=true --wait
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
|
||||
- name: Run chart-testing (install)
|
||||
run: ct install --config charts/.ci/ct-config.yaml
|
||||
101
.github/workflows/on-push-master-publish-chart.yml
vendored
Normal file
101
.github/workflows/on-push-master-publish-chart.yml
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
name: Publish helm chart
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main # assume that the branch name may change in future
|
||||
paths:
|
||||
- 'charts/**'
|
||||
- '.github/**'
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
KUBE_SCORE_VERSION: 1.10.0
|
||||
HELM_VERSION: v3.4.1
|
||||
|
||||
jobs:
|
||||
lint-chart:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v1
|
||||
with:
|
||||
version: ${{ env.HELM_VERSION }}
|
||||
|
||||
- name: Set up kube-score
|
||||
run: |
|
||||
wget https://github.com/zegl/kube-score/releases/download/v${{ env.KUBE_SCORE_VERSION }}/kube-score_${{ env.KUBE_SCORE_VERSION }}_linux_amd64 -O kube-score
|
||||
chmod 755 kube-score
|
||||
|
||||
- name: Kube-score generated manifests
|
||||
run: helm template --values charts/.ci/values-kube-score.yaml charts/* | ./kube-score score -
|
||||
--ignore-test pod-networkpolicy
|
||||
--ignore-test deployment-has-poddisruptionbudget
|
||||
--ignore-test deployment-has-host-podantiaffinity
|
||||
--ignore-test container-security-context
|
||||
--ignore-test pod-probes
|
||||
--ignore-test container-image-tag
|
||||
--enable-optional-test container-security-context-privileged
|
||||
--enable-optional-test container-security-context-readonlyrootfilesystem
|
||||
|
||||
# python is a requirement for the chart-testing action below (supports yamllint among other tests)
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.7
|
||||
|
||||
- name: Set up chart-testing
|
||||
uses: helm/chart-testing-action@v2.0.1
|
||||
|
||||
- name: Run chart-testing (list-changed)
|
||||
id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --config charts/.ci/ct-config.yaml)
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "::set-output name=changed::true"
|
||||
fi
|
||||
|
||||
- name: Run chart-testing (lint)
|
||||
run: ct lint --config charts/.ci/ct-config.yaml
|
||||
|
||||
- name: Create kind cluster
|
||||
uses: helm/kind-action@v1.0.0
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
|
||||
# We need cert-manager already installed in the cluster because we assume the CRDs exist
|
||||
- name: Install cert-manager
|
||||
run: |
|
||||
helm repo add jetstack https://charts.jetstack.io --force-update
|
||||
helm install cert-manager jetstack/cert-manager --set installCRDs=true --wait
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
|
||||
- name: Run chart-testing (install)
|
||||
run: ct install --config charts/.ci/ct-config.yaml
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
|
||||
publish-chart:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
needs: lint-chart
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Configure Git
|
||||
run: |
|
||||
git config user.name "$GITHUB_ACTOR"
|
||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Run chart-releaser
|
||||
uses: helm/chart-releaser-action@v1.1.0
|
||||
env:
|
||||
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
8
.github/workflows/release.yml
vendored
8
.github/workflows/release.yml
vendored
@@ -9,6 +9,10 @@ jobs:
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ github.repository_owner }}
|
||||
steps:
|
||||
- name: Set outputs
|
||||
id: vars
|
||||
run: echo ::set-output name=sha_short::${GITHUB_SHA::7}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -52,5 +56,7 @@ jobs:
|
||||
file: Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ env.DOCKERHUB_USERNAME }}/actions-runner-controller:${{ env.VERSION }}
|
||||
tags: |
|
||||
${{ env.DOCKERHUB_USERNAME }}/actions-runner-controller:${{ env.VERSION }}
|
||||
${{ env.DOCKERHUB_USERNAME }}/actions-runner-controller:${{ env.VERSION }}-${{ steps.vars.outputs.sha_short }}
|
||||
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -26,3 +26,6 @@ bin
|
||||
|
||||
.envrc
|
||||
*.pem
|
||||
|
||||
# OS
|
||||
.DS_STORE
|
||||
58
README.md
58
README.md
@@ -14,21 +14,71 @@ actions-runner-controller uses [cert-manager](https://cert-manager.io/docs/insta
|
||||
|
||||
- [Installing cert-manager on Kubernetes](https://cert-manager.io/docs/installation/kubernetes/)
|
||||
|
||||
Install the custom resource and actions-runner-controller itself. This will create actions-runner-system namespace in your Kubernetes and deploy the required resources.
|
||||
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.
|
||||
|
||||
`kubectl`:
|
||||
|
||||
```
|
||||
kubectl apply -f https://github.com/summerwind/actions-runner-controller/releases/latest/download/actions-runner-controller.yaml
|
||||
# REPLACE "v0.16.1" with the latest release
|
||||
kubectl apply -f https://github.com/summerwind/actions-runner-controller/releases/download/v0.16.1/actions-runner-controller.yaml
|
||||
```
|
||||
|
||||
`helm`:
|
||||
|
||||
```
|
||||
helm repo add actions-runner-controller https://summerwind.github.io/actions-runner-controller
|
||||
helm upgrade --install -n actions-runner-system actions-runner-controller/actions-runner-controller
|
||||
```
|
||||
|
||||
### Github Enterprise support
|
||||
|
||||
If you use either Github Enterprise Cloud or Server (and have recent enought version supporting Actions), you can use **actions-runner-controller** with those, too. Authentication works same way as with public Github (repo and organization level).
|
||||
If you use either Github Enterprise Cloud or Server, you can use **actions-runner-controller** with those, too.
|
||||
Authentication works same way as with public Github (repo and organization level).
|
||||
The minimum version of Github Enterprise Server is 3.0.0 (or rc1/rc2).
|
||||
In most cases maintainers do not have environment where to test changes and are reliant on the community for testing.
|
||||
|
||||
|
||||
```shell
|
||||
kubectl set env deploy controller-manager -c manager GITHUB_ENTERPRISE_URL=<GHEC/S URL> --namespace actions-runner-system
|
||||
```
|
||||
|
||||
[Enterprise level](https://docs.github.com/en/enterprise-server@2.22/actions/hosting-your-own-runners/adding-self-hosted-runners#adding-a-self-hosted-runner-to-an-enterprise) runners are not working yet as there's no API definition for those.
|
||||
#### Enterprise runners usage
|
||||
|
||||
In order to use enterprise runners you must have Admin access to Github Enterprise and you should do Personal Access Token (PAT)
|
||||
with `enterprise:admin` access. Enterprise runners are not possible to run with Github APP or any other permission.
|
||||
|
||||
When you use enterprise runners those will get access to Github Organisations. However, access to the repositories is **NOT**
|
||||
allowed by default. Each Github Organisation must allow Enterprise runner groups to be used in repositories.
|
||||
This is needed only one time and is permanent after that.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
apiVersion: actions.summerwind.dev/v1alpha1
|
||||
kind: RunnerDeployment
|
||||
metadata:
|
||||
name: ghe-runner-deployment
|
||||
spec:
|
||||
replicas: 2
|
||||
template:
|
||||
spec:
|
||||
enterprise: your-enterprise-name
|
||||
dockerdWithinRunnerContainer: true
|
||||
resources:
|
||||
limits:
|
||||
cpu: "4000m"
|
||||
memory: "2Gi"
|
||||
requests:
|
||||
cpu: "200m"
|
||||
memory: "200Mi"
|
||||
volumeMounts:
|
||||
- mountPath: /runner
|
||||
name: runner
|
||||
volumes:
|
||||
- name: runner
|
||||
emptyDir: {}
|
||||
|
||||
```
|
||||
|
||||
## Setting up authentication with GitHub API
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@ import (
|
||||
|
||||
// RunnerSpec defines the desired state of Runner
|
||||
type RunnerSpec struct {
|
||||
// +optional
|
||||
// +kubebuilder:validation:Pattern=`^[^/]+$`
|
||||
Enterprise string `json:"enterprise,omitempty"`
|
||||
|
||||
// +optional
|
||||
// +kubebuilder:validation:Pattern=`^[^/]+$`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
@@ -92,12 +96,22 @@ type RunnerSpec struct {
|
||||
|
||||
// ValidateRepository validates repository field.
|
||||
func (rs *RunnerSpec) ValidateRepository() error {
|
||||
// Organization and repository are both exclusive.
|
||||
if len(rs.Organization) == 0 && len(rs.Repository) == 0 {
|
||||
return errors.New("Spec needs organization or repository")
|
||||
// Enterprise, Organization and repository are both exclusive.
|
||||
foundCount := 0
|
||||
if len(rs.Organization) > 0 {
|
||||
foundCount += 1
|
||||
}
|
||||
if len(rs.Organization) > 0 && len(rs.Repository) > 0 {
|
||||
return errors.New("Spec cannot have both organization and repository")
|
||||
if len(rs.Repository) > 0 {
|
||||
foundCount += 1
|
||||
}
|
||||
if len(rs.Enterprise) > 0 {
|
||||
foundCount += 1
|
||||
}
|
||||
if foundCount == 0 {
|
||||
return errors.New("Spec needs enterprise, organization or repository")
|
||||
}
|
||||
if foundCount > 1 {
|
||||
return errors.New("Spec cannot have many fields defined enterprise, organization and repository")
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -113,6 +127,7 @@ type RunnerStatus struct {
|
||||
|
||||
// RunnerStatusRegistration contains runner registration status
|
||||
type RunnerStatusRegistration struct {
|
||||
Enterprise string `json:"enterprise,omitempty"`
|
||||
Organization string `json:"organization,omitempty"`
|
||||
Repository string `json:"repository,omitempty"`
|
||||
Labels []string `json:"labels,omitempty"`
|
||||
@@ -122,6 +137,7 @@ type RunnerStatusRegistration struct {
|
||||
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.enterprise",name=Enterprise,type=string
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.organization",name=Organization,type=string
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.repository",name=Repository,type=string
|
||||
// +kubebuilder:printcolumn:JSONPath=".spec.labels",name=Labels,type=string
|
||||
|
||||
4
charts/.ci/ct-config.yaml
Normal file
4
charts/.ci/ct-config.yaml
Normal file
@@ -0,0 +1,4 @@
|
||||
# This file defines the config for "ct" (chart tester) used by the helm linting GitHub workflow
|
||||
lint-conf: charts/.ci/lint-config.yaml
|
||||
chart-repos:
|
||||
- jetstack=https://charts.jetstack.io
|
||||
6
charts/.ci/lint-config.yaml
Normal file
6
charts/.ci/lint-config.yaml
Normal file
@@ -0,0 +1,6 @@
|
||||
rules:
|
||||
# One blank line is OK
|
||||
empty-lines:
|
||||
max-start: 1
|
||||
max-end: 1
|
||||
max: 1
|
||||
3
charts/.ci/scripts/local-ct-lint.sh
Executable file
3
charts/.ci/scripts/local-ct-lint.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
docker run --rm -it -w /repo -v $(pwd):/repo quay.io/helmpack/chart-testing ct lint --all --config charts/.ci/ct-config.yaml
|
||||
15
charts/.ci/scripts/local-kube-score.sh
Executable file
15
charts/.ci/scripts/local-kube-score.sh
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
|
||||
for chart in `ls charts`;
|
||||
do
|
||||
helm template --values charts/$chart/ci/ci-values.yaml charts/$chart | kube-score score - \
|
||||
--ignore-test pod-networkpolicy \
|
||||
--ignore-test deployment-has-poddisruptionbudget \
|
||||
--ignore-test deployment-has-host-podantiaffinity \
|
||||
--ignore-test pod-probes \
|
||||
--ignore-test container-image-tag \
|
||||
--enable-optional-test container-security-context-privileged \
|
||||
--enable-optional-test container-security-context-readonlyrootfilesystem \
|
||||
--ignore-test container-security-context
|
||||
done
|
||||
@@ -15,9 +15,22 @@ type: application
|
||||
# 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.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 0.1.0
|
||||
version: 0.3.1
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
appVersion: 0.11.2
|
||||
appVersion: 0.17.0
|
||||
|
||||
home: https://github.com/summerwind/actions-runner-controller
|
||||
|
||||
sources:
|
||||
- https://github.com/summerwind/actions-runner-controller
|
||||
|
||||
maintainers:
|
||||
- name: summerwind
|
||||
email: contact@summerwind.jp
|
||||
url: https://github.com/summerwind
|
||||
- name: funkypenguin
|
||||
email: davidy@funkypenguin.co.nz
|
||||
url: https://www.funkypenguin.co.nz
|
||||
|
||||
27
charts/actions-runner-controller/ci/ci-values.yaml
Normal file
27
charts/actions-runner-controller/ci/ci-values.yaml
Normal file
@@ -0,0 +1,27 @@
|
||||
# This file sets some opinionated values for kube-score to use
|
||||
# when parsing the chart
|
||||
image:
|
||||
pullPolicy: Always
|
||||
|
||||
podSecurityContext:
|
||||
fsGroup: 2000
|
||||
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 2000
|
||||
|
||||
resources:
|
||||
limits:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
requests:
|
||||
cpu: 100m
|
||||
memory: 128Mi
|
||||
|
||||
# Set the following to true to create a dummy secret, allowing the manager pod to start
|
||||
# This is only useful in CI
|
||||
createDummySecret: true
|
||||
@@ -426,6 +426,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
|
||||
@@ -426,6 +426,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
|
||||
@@ -7,6 +7,9 @@ metadata:
|
||||
name: runners.actions.summerwind.dev
|
||||
spec:
|
||||
additionalPrinterColumns:
|
||||
- JSONPath: .spec.enterprise
|
||||
name: Enterprise
|
||||
type: string
|
||||
- JSONPath: .spec.organization
|
||||
name: Organization
|
||||
type: string
|
||||
@@ -419,6 +422,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
@@ -1541,6 +1547,8 @@ spec:
|
||||
registration:
|
||||
description: RunnerStatusRegistration contains runner registration status
|
||||
properties:
|
||||
enterprise:
|
||||
type: string
|
||||
expiresAt:
|
||||
format: date-time
|
||||
type: string
|
||||
|
||||
@@ -89,7 +89,7 @@ Create the name of the service account to use
|
||||
{{- end }}
|
||||
|
||||
{{- define "actions-runner-controller.authProxyServiceName" -}}
|
||||
{{- include "actions-runner-controller.fullname" . }}-controller-manager-metrics-service
|
||||
{{- include "actions-runner-controller.fullname" . }}-metrics-service
|
||||
{{- end }}
|
||||
|
||||
{{- define "actions-runner-controller.selfsignedIssuerName" -}}
|
||||
|
||||
10
charts/actions-runner-controller/templates/ci-secret.yaml
Normal file
10
charts/actions-runner-controller/templates/ci-secret.yaml
Normal file
@@ -0,0 +1,10 @@
|
||||
# This template only exists to facilitate CI testing of the chart, since
|
||||
# a secret is expected to be found in the namespace by the controller manager
|
||||
{{ if .Values.createDummySecret -}}
|
||||
apiVersion: v1
|
||||
data:
|
||||
github_token: dGVzdA==
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: controller-manager
|
||||
{{- end }}
|
||||
@@ -57,6 +57,10 @@ spec:
|
||||
optional: true
|
||||
- name: GITHUB_APP_PRIVATE_KEY
|
||||
value: /etc/actions-runner-controller/github_app_private_key
|
||||
{{- range $key, $val := .Values.env }}
|
||||
- name: {{ $key }}
|
||||
value: {{ $val | quote }}
|
||||
{{- end }}
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (cat "v" .Chart.AppVersion | replace " " "") }}"
|
||||
name: manager
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
@@ -66,10 +70,14 @@ spec:
|
||||
protocol: TCP
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
volumeMounts:
|
||||
- mountPath: "/etc/actions-runner-controller"
|
||||
name: controller-manager
|
||||
readOnly: true
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /tmp/k8s-webhook-server/serving-certs
|
||||
name: cert
|
||||
readOnly: true
|
||||
@@ -78,11 +86,16 @@ spec:
|
||||
- "--upstream=http://127.0.0.1:8080/"
|
||||
- "--logtostderr=true"
|
||||
- "--v=10"
|
||||
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.1
|
||||
image: "{{ .Values.kube_rbac_proxy.image.repository }}:{{ .Values.kube_rbac_proxy.image.tag }}"
|
||||
name: kube-rbac-proxy
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
ports:
|
||||
- containerPort: 8443
|
||||
name: https
|
||||
resources:
|
||||
{{- toYaml .Values.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
||||
terminationGracePeriodSeconds: 10
|
||||
volumes:
|
||||
- name: controller-manager
|
||||
@@ -92,6 +105,8 @@ spec:
|
||||
secret:
|
||||
defaultMode: 420
|
||||
secretName: webhook-server-cert
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
|
||||
@@ -26,6 +26,11 @@ image:
|
||||
dindSidecarRepositoryAndTag: "docker:dind"
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
kube_rbac_proxy:
|
||||
image:
|
||||
repository: gcr.io/kubebuilder/kube-rbac-proxy
|
||||
tag: v0.4.1
|
||||
|
||||
imagePullSecrets: []
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
@@ -98,3 +103,8 @@ affinity: {}
|
||||
# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
|
||||
# PriorityClass: system-cluster-critical
|
||||
priorityClassName: ""
|
||||
|
||||
env: {}
|
||||
# http_proxy: "proxy.com:8080"
|
||||
# https_proxy: "proxy.com:8080"
|
||||
# no_proxy: ""
|
||||
@@ -426,6 +426,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
|
||||
@@ -426,6 +426,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
|
||||
@@ -7,6 +7,9 @@ metadata:
|
||||
name: runners.actions.summerwind.dev
|
||||
spec:
|
||||
additionalPrinterColumns:
|
||||
- JSONPath: .spec.enterprise
|
||||
name: Enterprise
|
||||
type: string
|
||||
- JSONPath: .spec.organization
|
||||
name: Organization
|
||||
type: string
|
||||
@@ -419,6 +422,9 @@ spec:
|
||||
type: object
|
||||
dockerdWithinRunnerContainer:
|
||||
type: boolean
|
||||
enterprise:
|
||||
pattern: ^[^/]+$
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
description: EnvVar represents an environment variable present in a Container.
|
||||
@@ -1541,6 +1547,8 @@ spec:
|
||||
registration:
|
||||
description: RunnerStatusRegistration contains runner registration status
|
||||
properties:
|
||||
enterprise:
|
||||
type: string
|
||||
expiresAt:
|
||||
format: date-time
|
||||
type: string
|
||||
|
||||
@@ -204,7 +204,7 @@ func (r *HorizontalRunnerAutoscalerReconciler) calculateReplicasByPercentageRunn
|
||||
}
|
||||
|
||||
// ListRunners will return all runners managed by GitHub - not restricted to ns
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, orgName, "")
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, "", orgName, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||
|
||||
if removed {
|
||||
if len(runner.Status.Registration.Token) > 0 {
|
||||
ok, err := r.unregisterRunner(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
ok, err := r.unregisterRunner(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to unregister runner")
|
||||
return ctrl.Result{}, err
|
||||
@@ -194,7 +194,7 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
runnerBusy, err := r.isRunnerBusy(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
runnerBusy, err := r.isRunnerBusy(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to check if runner is busy")
|
||||
return ctrl.Result{}, nil
|
||||
@@ -227,8 +227,8 @@ func (r *RunnerReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, org, repo)
|
||||
func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, enterprise, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -242,8 +242,8 @@ func (r *RunnerReconciler) isRunnerBusy(ctx context.Context, org, repo, name str
|
||||
return false, fmt.Errorf("runner not found")
|
||||
}
|
||||
|
||||
func (r *RunnerReconciler) unregisterRunner(ctx context.Context, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, org, repo)
|
||||
func (r *RunnerReconciler) unregisterRunner(ctx context.Context, enterprise, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
@@ -263,7 +263,7 @@ func (r *RunnerReconciler) unregisterRunner(ctx context.Context, org, repo, name
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if err := r.GitHubClient.RemoveRunner(ctx, org, repo, id); err != nil {
|
||||
if err := r.GitHubClient.RemoveRunner(ctx, enterprise, org, repo, id); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ func (r *RunnerReconciler) updateRegistrationToken(ctx context.Context, runner v
|
||||
|
||||
log := r.Log.WithValues("runner", runner.Name)
|
||||
|
||||
rt, err := r.GitHubClient.GetRegistrationToken(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
rt, err := r.GitHubClient.GetRegistrationToken(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
if err != nil {
|
||||
r.Recorder.Event(&runner, corev1.EventTypeWarning, "FailedUpdateRegistrationToken", "Updating registration token failed")
|
||||
log.Error(err, "Failed to get new registration token")
|
||||
@@ -339,6 +339,10 @@ func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
|
||||
Name: "RUNNER_REPO",
|
||||
Value: runner.Spec.Repository,
|
||||
},
|
||||
{
|
||||
Name: "RUNNER_ENTERPRISE",
|
||||
Value: runner.Spec.Enterprise,
|
||||
},
|
||||
{
|
||||
Name: "RUNNER_LABELS",
|
||||
Value: strings.Join(runner.Spec.Labels, ","),
|
||||
@@ -504,6 +508,7 @@ func (r *RunnerReconciler) newPod(runner v1alpha1.Runner) (corev1.Pod, error) {
|
||||
SecurityContext: &corev1.SecurityContext{
|
||||
Privileged: &privileged,
|
||||
},
|
||||
Resources: runner.Spec.DockerdContainerResources,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (r *RunnerReplicaSetReconciler) Reconcile(req ctrl.Request) (ctrl.Result, e
|
||||
// get runners that are currently not busy
|
||||
var notBusy []v1alpha1.Runner
|
||||
for _, runner := range myRunners {
|
||||
busy, err := r.isRunnerBusy(ctx, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
busy, err := r.isRunnerBusy(ctx, runner.Spec.Enterprise, runner.Spec.Organization, runner.Spec.Repository, runner.Name)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to check if runner is busy")
|
||||
return ctrl.Result{}, err
|
||||
@@ -187,8 +187,8 @@ func (r *RunnerReplicaSetReconciler) SetupWithManager(mgr ctrl.Manager) error {
|
||||
Complete(r)
|
||||
}
|
||||
|
||||
func (r *RunnerReplicaSetReconciler) isRunnerBusy(ctx context.Context, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, org, repo)
|
||||
func (r *RunnerReplicaSetReconciler) isRunnerBusy(ctx context.Context, enterprise, org, repo, name string) (bool, error) {
|
||||
runners, err := r.GitHubClient.ListRunners(ctx, enterprise, org, repo)
|
||||
r.Log.Info("runners", "github", runners)
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
||||
@@ -78,7 +78,7 @@ func (c *Config) NewClient() (*Client, error) {
|
||||
}
|
||||
|
||||
// GetRegistrationToken returns a registration token tied with the name of repository and runner.
|
||||
func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name string) (*github.RegistrationToken, error) {
|
||||
func (c *Client) GetRegistrationToken(ctx context.Context, enterprise, org, repo, name string) (*github.RegistrationToken, error) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
@@ -89,13 +89,13 @@ func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name strin
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
owner, repo, err := getOwnerAndRepo(org, repo)
|
||||
enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo)
|
||||
|
||||
if err != nil {
|
||||
return rt, err
|
||||
}
|
||||
|
||||
rt, res, err := c.createRegistrationToken(ctx, owner, repo)
|
||||
rt, res, err := c.createRegistrationToken(ctx, enterprise, owner, repo)
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create registration token: %v", err)
|
||||
@@ -114,14 +114,14 @@ func (c *Client) GetRegistrationToken(ctx context.Context, org, repo, name strin
|
||||
}
|
||||
|
||||
// RemoveRunner removes a runner with specified runner ID from repository.
|
||||
func (c *Client) RemoveRunner(ctx context.Context, org, repo string, runnerID int64) error {
|
||||
owner, repo, err := getOwnerAndRepo(org, repo)
|
||||
func (c *Client) RemoveRunner(ctx context.Context, enterprise, org, repo string, runnerID int64) error {
|
||||
enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := c.removeRunner(ctx, owner, repo, runnerID)
|
||||
res, err := c.removeRunner(ctx, enterprise, owner, repo, runnerID)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to remove runner: %v", err)
|
||||
@@ -135,8 +135,8 @@ func (c *Client) RemoveRunner(ctx context.Context, org, repo string, runnerID in
|
||||
}
|
||||
|
||||
// ListRunners returns a list of runners of specified owner/repository name.
|
||||
func (c *Client) ListRunners(ctx context.Context, org, repo string) ([]*github.Runner, error) {
|
||||
owner, repo, err := getOwnerAndRepo(org, repo)
|
||||
func (c *Client) ListRunners(ctx context.Context, enterprise, org, repo string) ([]*github.Runner, error) {
|
||||
enterprise, owner, repo, err := getEnterpriseOrganisationAndRepo(enterprise, org, repo)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -146,7 +146,7 @@ func (c *Client) ListRunners(ctx context.Context, org, repo string) ([]*github.R
|
||||
|
||||
opts := github.ListOptions{PerPage: 10}
|
||||
for {
|
||||
list, res, err := c.listRunners(ctx, owner, repo, &opts)
|
||||
list, res, err := c.listRunners(ctx, enterprise, owner, repo, &opts)
|
||||
|
||||
if err != nil {
|
||||
return runners, fmt.Errorf("failed to list runners: %v", err)
|
||||
@@ -174,42 +174,52 @@ func (c *Client) cleanup() {
|
||||
}
|
||||
}
|
||||
|
||||
// wrappers for github functions (switch between organization/repository mode)
|
||||
// wrappers for github functions (switch between enterprise/organization/repository mode)
|
||||
// so the calling functions don't need to switch and their code is a bit cleaner
|
||||
|
||||
func (c *Client) createRegistrationToken(ctx context.Context, owner, repo string) (*github.RegistrationToken, *github.Response, error) {
|
||||
func (c *Client) createRegistrationToken(ctx context.Context, enterprise, org, repo string) (*github.RegistrationToken, *github.Response, error) {
|
||||
if len(repo) > 0 {
|
||||
return c.Client.Actions.CreateRegistrationToken(ctx, owner, repo)
|
||||
}
|
||||
|
||||
return c.Client.Actions.CreateOrganizationRegistrationToken(ctx, owner)
|
||||
}
|
||||
|
||||
func (c *Client) removeRunner(ctx context.Context, owner, repo string, runnerID int64) (*github.Response, error) {
|
||||
if len(repo) > 0 {
|
||||
return c.Client.Actions.RemoveRunner(ctx, owner, repo, runnerID)
|
||||
}
|
||||
|
||||
return c.Client.Actions.RemoveOrganizationRunner(ctx, owner, runnerID)
|
||||
}
|
||||
|
||||
func (c *Client) listRunners(ctx context.Context, owner, repo string, opts *github.ListOptions) (*github.Runners, *github.Response, error) {
|
||||
if len(repo) > 0 {
|
||||
return c.Client.Actions.ListRunners(ctx, owner, repo, opts)
|
||||
}
|
||||
|
||||
return c.Client.Actions.ListOrganizationRunners(ctx, owner, opts)
|
||||
}
|
||||
|
||||
// Validates owner and repo arguments. Both are optional, but at least one should be specified
|
||||
func getOwnerAndRepo(org, repo string) (string, string, error) {
|
||||
if len(repo) > 0 {
|
||||
return splitOwnerAndRepo(repo)
|
||||
return c.Client.Actions.CreateRegistrationToken(ctx, org, repo)
|
||||
}
|
||||
if len(org) > 0 {
|
||||
return org, "", nil
|
||||
return c.Client.Actions.CreateOrganizationRegistrationToken(ctx, org)
|
||||
}
|
||||
return "", "", fmt.Errorf("organization and repository are both empty")
|
||||
return c.Client.Enterprise.CreateRegistrationToken(ctx, enterprise)
|
||||
}
|
||||
|
||||
func (c *Client) removeRunner(ctx context.Context, enterprise, org, repo string, runnerID int64) (*github.Response, error) {
|
||||
if len(repo) > 0 {
|
||||
return c.Client.Actions.RemoveRunner(ctx, org, repo, runnerID)
|
||||
}
|
||||
if len(org) > 0 {
|
||||
return c.Client.Actions.RemoveOrganizationRunner(ctx, org, runnerID)
|
||||
}
|
||||
return c.Client.Enterprise.RemoveRunner(ctx, enterprise, runnerID)
|
||||
}
|
||||
|
||||
func (c *Client) listRunners(ctx context.Context, enterprise, org, repo string, opts *github.ListOptions) (*github.Runners, *github.Response, error) {
|
||||
if len(repo) > 0 {
|
||||
return c.Client.Actions.ListRunners(ctx, org, repo, opts)
|
||||
}
|
||||
if len(org) > 0 {
|
||||
return c.Client.Actions.ListOrganizationRunners(ctx, org, opts)
|
||||
}
|
||||
return c.Client.Enterprise.ListRunners(ctx, enterprise, opts)
|
||||
}
|
||||
|
||||
// Validates enterprise, organisation and repo arguments. Both are optional, but at least one should be specified
|
||||
func getEnterpriseOrganisationAndRepo(enterprise, org, repo string) (string, string, string, error) {
|
||||
if len(repo) > 0 {
|
||||
owner, repository, err := splitOwnerAndRepo(repo)
|
||||
return "", owner, repository, err
|
||||
}
|
||||
if len(org) > 0 {
|
||||
return "", org, "", nil
|
||||
}
|
||||
if len(enterprise) > 0 {
|
||||
return enterprise, "", "", nil
|
||||
}
|
||||
return "", "", "", fmt.Errorf("enterprise, organization and repository are all empty")
|
||||
}
|
||||
|
||||
func getRegistrationKey(org, repo string) string {
|
||||
|
||||
@@ -39,22 +39,26 @@ func TestMain(m *testing.M) {
|
||||
|
||||
func TestGetRegistrationToken(t *testing.T) {
|
||||
tests := []struct {
|
||||
org string
|
||||
repo string
|
||||
token string
|
||||
err bool
|
||||
enterprise string
|
||||
org string
|
||||
repo string
|
||||
token string
|
||||
err bool
|
||||
}{
|
||||
{org: "", repo: "test/valid", token: fake.RegistrationToken, err: false},
|
||||
{org: "", repo: "test/invalid", token: "", err: true},
|
||||
{org: "", repo: "test/error", token: "", err: true},
|
||||
{org: "test", repo: "", token: fake.RegistrationToken, err: false},
|
||||
{org: "invalid", repo: "", token: "", err: true},
|
||||
{org: "error", repo: "", token: "", err: true},
|
||||
{enterprise: "", org: "", repo: "test/valid", token: fake.RegistrationToken, err: false},
|
||||
{enterprise: "", org: "", repo: "test/invalid", token: "", err: true},
|
||||
{enterprise: "", org: "", repo: "test/error", token: "", err: true},
|
||||
{enterprise: "", org: "test", repo: "", token: fake.RegistrationToken, err: false},
|
||||
{enterprise: "", org: "invalid", repo: "", token: "", err: true},
|
||||
{enterprise: "", org: "error", repo: "", token: "", err: true},
|
||||
{enterprise: "test", org: "", repo: "", token: fake.RegistrationToken, err: false},
|
||||
{enterprise: "invalid", org: "", repo: "", token: "", err: true},
|
||||
{enterprise: "error", org: "", repo: "", token: "", err: true},
|
||||
}
|
||||
|
||||
client := newTestClient()
|
||||
for i, tt := range tests {
|
||||
rt, err := client.GetRegistrationToken(context.Background(), tt.org, tt.repo, "test")
|
||||
rt, err := client.GetRegistrationToken(context.Background(), tt.enterprise, tt.org, tt.repo, "test")
|
||||
if !tt.err && err != nil {
|
||||
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||
}
|
||||
@@ -66,22 +70,26 @@ func TestGetRegistrationToken(t *testing.T) {
|
||||
|
||||
func TestListRunners(t *testing.T) {
|
||||
tests := []struct {
|
||||
org string
|
||||
repo string
|
||||
length int
|
||||
err bool
|
||||
enterprise string
|
||||
org string
|
||||
repo string
|
||||
length int
|
||||
err bool
|
||||
}{
|
||||
{org: "", repo: "test/valid", length: 2, err: false},
|
||||
{org: "", repo: "test/invalid", length: 0, err: true},
|
||||
{org: "", repo: "test/error", length: 0, err: true},
|
||||
{org: "test", repo: "", length: 2, err: false},
|
||||
{org: "invalid", repo: "", length: 0, err: true},
|
||||
{org: "error", repo: "", length: 0, err: true},
|
||||
{enterprise: "", org: "", repo: "test/valid", length: 2, err: false},
|
||||
{enterprise: "", org: "", repo: "test/invalid", length: 0, err: true},
|
||||
{enterprise: "", org: "", repo: "test/error", length: 0, err: true},
|
||||
{enterprise: "", org: "test", repo: "", length: 2, err: false},
|
||||
{enterprise: "", org: "invalid", repo: "", length: 0, err: true},
|
||||
{enterprise: "", org: "error", repo: "", length: 0, err: true},
|
||||
{enterprise: "test", org: "", repo: "", length: 2, err: false},
|
||||
{enterprise: "invalid", org: "", repo: "", length: 0, err: true},
|
||||
{enterprise: "error", org: "", repo: "", length: 0, err: true},
|
||||
}
|
||||
|
||||
client := newTestClient()
|
||||
for i, tt := range tests {
|
||||
runners, err := client.ListRunners(context.Background(), tt.org, tt.repo)
|
||||
runners, err := client.ListRunners(context.Background(), tt.enterprise, tt.org, tt.repo)
|
||||
if !tt.err && err != nil {
|
||||
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||
}
|
||||
@@ -93,21 +101,25 @@ func TestListRunners(t *testing.T) {
|
||||
|
||||
func TestRemoveRunner(t *testing.T) {
|
||||
tests := []struct {
|
||||
org string
|
||||
repo string
|
||||
err bool
|
||||
enterprise string
|
||||
org string
|
||||
repo string
|
||||
err bool
|
||||
}{
|
||||
{org: "", repo: "test/valid", err: false},
|
||||
{org: "", repo: "test/invalid", err: true},
|
||||
{org: "", repo: "test/error", err: true},
|
||||
{org: "test", repo: "", err: false},
|
||||
{org: "invalid", repo: "", err: true},
|
||||
{org: "error", repo: "", err: true},
|
||||
{enterprise: "", org: "", repo: "test/valid", err: false},
|
||||
{enterprise: "", org: "", repo: "test/invalid", err: true},
|
||||
{enterprise: "", org: "", repo: "test/error", err: true},
|
||||
{enterprise: "", org: "test", repo: "", err: false},
|
||||
{enterprise: "", org: "invalid", repo: "", err: true},
|
||||
{enterprise: "", org: "error", repo: "", err: true},
|
||||
{enterprise: "test", org: "", repo: "", err: false},
|
||||
{enterprise: "invalid", org: "", repo: "", err: true},
|
||||
{enterprise: "error", org: "", repo: "", err: true},
|
||||
}
|
||||
|
||||
client := newTestClient()
|
||||
for i, tt := range tests {
|
||||
err := client.RemoveRunner(context.Background(), tt.org, tt.repo, int64(1))
|
||||
err := client.RemoveRunner(context.Background(), tt.enterprise, tt.org, tt.repo, int64(1))
|
||||
if !tt.err && err != nil {
|
||||
t.Errorf("[%d] unexpected error: %v", i, err)
|
||||
}
|
||||
|
||||
5
go.mod
5
go.mod
@@ -6,10 +6,7 @@ require (
|
||||
github.com/bradleyfalzon/ghinstallation v1.1.1
|
||||
github.com/davecgh/go-spew v1.1.1
|
||||
github.com/go-logr/logr v0.1.0
|
||||
github.com/google/go-github v17.0.0+incompatible // indirect
|
||||
github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04
|
||||
github.com/google/go-github/v33 v33.0.0
|
||||
github.com/google/go-querystring v1.0.0
|
||||
github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/onsi/ginkgo v1.8.0
|
||||
|
||||
8
go.sum
8
go.sum
@@ -116,14 +116,10 @@ github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-github/v29 v29.0.2 h1:opYN6Wc7DOz7Ku3Oh4l7prmkOMwEcQxpFtxdU8N8Pts=
|
||||
github.com/google/go-github/v29 v29.0.2/go.mod h1:CHKiKKPHJ0REzfwc14QMklvtHwCveD0PxlMjLlzAM5E=
|
||||
github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04 h1:wEYk2h/GwOhImcVjiTIceP88WxVbXw2F+ARYUQMEsfg=
|
||||
github.com/google/go-github/v32 v32.1.1-0.20200822031813-d57a3a84ba04/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||
github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM=
|
||||
github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
|
||||
github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a h1:Z9Nzq8ntvvXCLnFGOkzzcD8HDOzOo+obuwE5oK85vNQ=
|
||||
github.com/google/go-github/v33 v33.0.1-0.20210204004227-319dcffb518a/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
|
||||
@@ -16,14 +16,16 @@ if [ -z "${RUNNER_NAME}" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -n "${RUNNER_ORG}" ] && [ -n "${RUNNER_REPO}" ]; then
|
||||
if [ -n "${RUNNER_ORG}" ] && [ -n "${RUNNER_REPO}" ] && [ -n "${RUNNER_ENTERPRISE}" ]; then
|
||||
ATTACH="${RUNNER_ORG}/${RUNNER_REPO}"
|
||||
elif [ -n "${RUNNER_ORG}" ]; then
|
||||
ATTACH="${RUNNER_ORG}"
|
||||
elif [ -n "${RUNNER_REPO}" ]; then
|
||||
ATTACH="${RUNNER_REPO}"
|
||||
elif [ -n "${RUNNER_ENTERPRISE}" ]; then
|
||||
ATTACH="enterprises/${RUNNER_ENTERPRISE}"
|
||||
else
|
||||
echo "At least one of RUNNER_ORG or RUNNER_REPO must be set" 1>&2
|
||||
echo "At least one of RUNNER_ORG or RUNNER_REPO or RUNNER_ENTERPRISE must be set" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user