Compare commits

..

14 Commits

Author SHA1 Message Date
Yusuke Kuoka
42abad5def chart: Bump version to 0.23.0 (#2449) 2023-03-30 10:10:18 +09:00
Milas Bowman
514b7da742 Install Docker Compose v2 as a Docker CLI plugin (#2326)
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-29 10:40:10 +09:00
Francesco Renzi
c8e3bb5ec3 Remove containerMode from values (#2442) 2023-03-28 10:16:38 +01:00
Milas Bowman
878c9b8b49 runner: Use Docker socket via shared emptyDir instead of TCP/mTLS (#2324)
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-28 11:29:16 +09:00
Jonathan Wiemers
4536707af6 chart: Allow webhook server env to be set individually (#2377)
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-28 11:18:07 +09:00
Waldek Herka
13802c5a6d chart: Restricting the RBAC rules on secrets (#2265)
Co-authored-by: Waldek Herka <wherka-ama@users.noreply.github.com>
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-28 08:43:33 +09:00
cskinfill
362fa5d52e crd: Add enterprise, organization, repository, and runner labels to runnerdeployments print columns (#2310)
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-28 08:43:01 +09:00
Zane Hala
65184f1ed8 chart: Allow customization of admission webhook timeout (#2398)
Co-authored-by: Yusuke Kuoka <ykuoka@gmail.com>
2023-03-28 08:42:20 +09:00
Bassem Dghaidi
c23e31123c Housekeeping: move adrs/ to docs/ and update status (#2443)
Co-authored-by: Francesco Renzi <rentziass@github.com>
2023-03-27 10:38:27 -04:00
Nikola Jokic
56e1c62ac2 Add labels to autoscaling runner set subresources to allow easier inspection (#2391)
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
2023-03-27 11:19:34 +02:00
Bassem Dghaidi
64cedff2b4 Delete e2e-test-dispatch-workflow.yaml (#2441) 2023-03-24 07:11:57 -04:00
Bassem Dghaidi
37f93b794e Enhance quickstart troubleshooting guidelines (#2435) 2023-03-23 11:40:58 -04:00
Francesco Renzi
dc833e57a0 Add new workflows (#2423) 2023-03-23 14:39:37 +00:00
Tingluo Huang
5228aded87 Update e2e workflow (#2430) 2023-03-21 14:11:47 -04:00
53 changed files with 1191 additions and 716 deletions

View File

@@ -0,0 +1,160 @@
name: 'Execute and Assert ARC E2E Test Action'
description: 'Queue E2E test workflow and assert workflow run result to be succeed'
inputs:
auth-token:
description: 'GitHub access token to queue workflow run'
required: true
repo-owner:
description: "The repository owner name that has the test workflow file, ex: actions"
required: true
repo-name:
description: "The repository name that has the test workflow file, ex: test"
required: true
workflow-file:
description: 'The file name of the workflow yaml, ex: test.yml'
required: true
arc-name:
description: 'The name of the configured gha-runner-scale-set'
required: true
arc-namespace:
description: 'The namespace of the configured gha-runner-scale-set'
required: true
arc-controller-namespace:
description: 'The namespace of the configured gha-runner-scale-set-controller'
required: true
runs:
using: "composite"
steps:
- name: Queue test workflow
shell: bash
id: queue_workflow
run: |
queue_time=`date +%FT%TZ`
echo "queue_time=$queue_time" >> $GITHUB_OUTPUT
curl -X POST https://api.github.com/repos/${{inputs.repo-owner}}/${{inputs.repo-name}}/actions/workflows/${{inputs.workflow-file}}/dispatches \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${{inputs.auth-token}}" \
-d '{"ref": "main", "inputs": { "arc_name": "${{inputs.arc-name}}" } }'
- name: Fetch workflow run & job ids
uses: actions/github-script@v6
id: query_workflow
with:
script: |
// Try to find the workflow run triggered by the previous step using the workflow_dispatch event.
// - Find recently create workflow runs in the test repository
// - For each workflow run, list its workflow job and see if the job's labels contain `inputs.arc-name`
// - Since the inputs.arc-name should be unique per e2e workflow run, once we find the job with the label, we find the workflow that we just triggered.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const owner = '${{inputs.repo-owner}}'
const repo = '${{inputs.repo-name}}'
const workflow_id = '${{inputs.workflow-file}}'
let workflow_run_id = 0
let workflow_job_id = 0
let workflow_run_html_url = ""
let count = 0
while (count++<12) {
await sleep(10 * 1000);
let listRunResponse = await github.rest.actions.listWorkflowRuns({
owner: owner,
repo: repo,
workflow_id: workflow_id,
created: '>${{steps.queue_workflow.outputs.queue_time}}'
})
if (listRunResponse.data.total_count > 0) {
console.log(`Found some new workflow runs for ${workflow_id}`)
for (let i = 0; i<listRunResponse.data.total_count; i++) {
let workflowRun = listRunResponse.data.workflow_runs[i]
console.log(`Check if workflow run ${workflowRun.id} is triggered by us.`)
let listJobResponse = await github.rest.actions.listJobsForWorkflowRun({
owner: owner,
repo: repo,
run_id: workflowRun.id
})
console.log(`Workflow run ${workflowRun.id} has ${listJobResponse.data.total_count} jobs.`)
if (listJobResponse.data.total_count > 0) {
for (let j = 0; j<listJobResponse.data.total_count; j++) {
let workflowJob = listJobResponse.data.jobs[j]
console.log(`Check if workflow job ${workflowJob.id} is triggered by us.`)
console.log(JSON.stringify(workflowJob.labels));
if (workflowJob.labels.includes('${{inputs.arc-name}}')) {
console.log(`Workflow job ${workflowJob.id} (Run id: ${workflowJob.run_id}) is triggered by us.`)
workflow_run_id = workflowJob.run_id
workflow_job_id = workflowJob.id
workflow_run_html_url = workflowRun.html_url
break
}
}
}
if (workflow_job_id > 0) {
break;
}
}
}
if (workflow_job_id > 0) {
break;
}
}
if (workflow_job_id == 0) {
core.setFailed(`Can't find workflow run and workflow job triggered to 'runs-on ${{inputs.arc-name}}'`)
} else {
core.setOutput('workflow_run', workflow_run_id);
core.setOutput('workflow_job', workflow_job_id);
core.setOutput('workflow_run_url', workflow_run_html_url);
}
- name: Generate summary about the triggered workflow run
shell: bash
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Triggered workflow run** |
|:--------------------------:|
| ${{steps.query_workflow.outputs.workflow_run_url}} |
EOF
- name: Wait for workflow to finish successfully
uses: actions/github-script@v6
with:
script: |
// Wait 5 minutes and make sure the workflow run we triggered completed with result 'success'
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
const owner = '${{inputs.repo-owner}}'
const repo = '${{inputs.repo-name}}'
const workflow_run_id = ${{steps.query_workflow.outputs.workflow_run}}
const workflow_job_id = ${{steps.query_workflow.outputs.workflow_job}}
let count = 0
while (count++<10) {
await sleep(30 * 1000);
let getRunResponse = await github.rest.actions.getWorkflowRun({
owner: owner,
repo: repo,
run_id: workflow_run_id
})
console.log(`${getRunResponse.data.html_url}: ${getRunResponse.data.status} (${getRunResponse.data.conclusion})`);
if (getRunResponse.data.status == 'completed') {
if ( getRunResponse.data.conclusion == 'success') {
console.log(`Workflow run finished properly.`)
return
} else {
core.setFailed(`The triggered workflow run finish with result ${getRunResponse.data.conclusion}`)
return
}
}
}
core.setFailed(`The triggered workflow run didn't finish properly using ${{inputs.arc-name}}`)
- name: Gather logs and cleanup
shell: bash
if: always()
run: |
helm uninstall ${{ inputs.arc-name }} --namespace ${{inputs.arc-namespace}} --debug
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n ${{inputs.arc-name}} -l app.kubernetes.io/instance=${{ inputs.arc-name }}
kubectl logs deployment/arc-gha-runner-scale-set-controller -n ${{inputs.arc-controller-namespace}}

View File

@@ -2,21 +2,21 @@ name: 'Setup ARC E2E Test Action'
description: 'Build controller image, create kind cluster, load the image, and exchange ARC configure token.' description: 'Build controller image, create kind cluster, load the image, and exchange ARC configure token.'
inputs: inputs:
github-app-id: app-id:
description: 'GitHub App Id for exchange access token' description: 'GitHub App Id for exchange access token'
required: true required: true
github-app-pk: app-pk:
description: "GitHub App private key for exchange access token" description: "GitHub App private key for exchange access token"
required: true required: true
github-app-org: image-name:
description: 'The organization the GitHub App has installed on'
required: true
docker-image-name:
description: "Local docker image name for building" description: "Local docker image name for building"
required: true required: true
docker-image-tag: image-tag:
description: "Tag of ARC Docker image for building" description: "Tag of ARC Docker image for building"
required: true required: true
target-org:
description: "The test organization for ARC e2e test"
required: true
outputs: outputs:
token: token:
@@ -42,23 +42,22 @@ runs:
platforms: linux/amd64 platforms: linux/amd64
load: true load: true
build-args: | build-args: |
DOCKER_IMAGE_NAME=${{inputs.docker-image-name}} DOCKER_IMAGE_NAME=${{inputs.image-name}}
VERSION=${{inputs.docker-image-tag}} VERSION=${{inputs.image-tag}}
tags: | tags: |
${{inputs.docker-image-name}}:${{inputs.docker-image-tag}} ${{inputs.image-name}}:${{inputs.image-tag}}
cache-from: type=gha no-cache: true
cache-to: type=gha,mode=max
- name: Create minikube cluster and load image - name: Create minikube cluster and load image
shell: bash shell: bash
run: | run: |
minikube start minikube start
minikube image load ${{inputs.docker-image-name}}:${{inputs.docker-image-tag}} minikube image load ${{inputs.image-name}}:${{inputs.image-tag}}
- name: Get configure token - name: Get configure token
id: config-token id: config-token
uses: peter-murray/workflow-application-token-action@8e1ba3bf1619726336414f1014e37f17fbadf1db uses: peter-murray/workflow-application-token-action@8e1ba3bf1619726336414f1014e37f17fbadf1db
with: with:
application_id: ${{ inputs.github-app-id }} application_id: ${{ inputs.app-id }}
application_private_key: ${{ inputs.github-app-pk }} application_private_key: ${{ inputs.app-pk }}
organization: ${{ inputs.github-app-org }} organization: ${{ inputs.target-org}}

View File

@@ -1,16 +0,0 @@
name: ARC Reusable Workflow
on:
workflow_dispatch:
inputs:
date_time:
description: 'Datetime for runner name uniqueness, format: %Y-%m-%d-%H-%M-%S-%3N, example: 2023-02-14-13-00-16-791'
required: true
jobs:
arc-runner-job:
strategy:
fail-fast: false
matrix:
job: [1, 2, 3]
runs-on: arc-runner-${{ inputs.date_time }}
steps:
- run: echo "Hello World!" >> $GITHUB_STEP_SUMMARY

View File

@@ -8,52 +8,35 @@ on:
branches: branches:
- master - master
workflow_dispatch: workflow_dispatch:
inputs:
target_org: permissions:
description: The org of the test repository. contents: read
required: true
default: actions-runner-controller
target_repo:
description: The repository to install the ARC.
required: true
default: arc_e2e_test_dummy
env: env:
TARGET_ORG: actions-runner-controller TARGET_ORG: actions-runner-controller
TARGET_REPO: arc_e2e_test_dummy TARGET_REPO: arc_e2e_test_dummy
IMAGE_NAME: "arc-test-image" IMAGE_NAME: "arc-test-image"
IMAGE_VERSION: "dev" IMAGE_VERSION: "dev"
jobs: jobs:
default-setup: default-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: "arc-test-workflow.yaml" WORKFLOW_FILE: "arc-test-workflow.yaml"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
@@ -85,88 +68,61 @@ jobs:
- name: Install gha-runner-scale-set - name: Install gha-runner-scale-set
id: install_arc id: install_arc
run: | run: |
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1)) ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
./charts/gha-runner-scale-set \ ./charts/gha-runner-scale-set \
--debug --debug
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{env.WORKFLOW_FILE}}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF
single-namespace-setup: single-namespace-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: "arc-test-workflow.yaml" WORKFLOW_FILE: "arc-test-workflow.yaml"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
@@ -200,88 +156,61 @@ jobs:
- name: Install gha-runner-scale-set - name: Install gha-runner-scale-set
id: install_arc id: install_arc
run: | run: |
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1)) ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
./charts/gha-runner-scale-set \ ./charts/gha-runner-scale-set \
--debug --debug
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{env.WORKFLOW_FILE}}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF
dind-mode-setup: dind-mode-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: arc-test-dind-workflow.yaml WORKFLOW_FILE: arc-test-dind-workflow.yaml
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
@@ -313,11 +242,11 @@ jobs:
- name: Install gha-runner-scale-set - name: Install gha-runner-scale-set
id: install_arc id: install_arc
run: | run: |
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1)) ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
--set containerMode.type="dind" \ --set containerMode.type="dind" \
./charts/gha-runner-scale-set \ ./charts/gha-runner-scale-set \
@@ -325,81 +254,59 @@ jobs:
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{env.WORKFLOW_FILE}}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF
kubernetes-mode-setup: kubernetes-mode-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: "arc-test-kubernetes-workflow.yaml" WORKFLOW_FILE: "arc-test-kubernetes-workflow.yaml"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
run: | run: |
echo "Install openebs/dynamic-localpv-provisioner"
helm repo add openebs https://openebs.github.io/charts
helm repo update
helm install openebs openebs/openebs -n openebs --create-namespace
helm install arc \ helm install arc \
--namespace "arc-systems" \ --namespace "arc-systems" \
--create-namespace \ --create-namespace \
@@ -423,20 +330,16 @@ jobs:
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l app.kubernetes.io/name=gha-runner-scale-set-controller
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems kubectl describe deployment arc-gha-runner-scale-set-controller -n arc-systems
kubectl wait --timeout=30s --for=condition=ready pod -n openebs -l name=openebs-localpv-provisioner
- name: Install gha-runner-scale-set - name: Install gha-runner-scale-set
id: install_arc id: install_arc
run: | run: |
echo "Install openebs/dynamic-localpv-provisioner" ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm repo add openebs https://openebs.github.io/charts
helm repo update
helm install openebs openebs/openebs -n openebs --create-namespace
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
--set containerMode.type="kubernetes" \ --set containerMode.type="kubernetes" \
--set containerMode.kubernetesModeWorkVolumeClaim.accessModes={"ReadWriteOnce"} \ --set containerMode.kubernetesModeWorkVolumeClaim.accessModes={"ReadWriteOnce"} \
@@ -447,77 +350,50 @@ jobs:
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{env.WORKFLOW_FILE}}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF
auth-proxy-setup: auth-proxy-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: "arc-test-workflow.yaml" WORKFLOW_FILE: "arc-test-workflow.yaml"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
@@ -558,11 +434,11 @@ jobs:
--namespace=arc-runners \ --namespace=arc-runners \
--from-literal=username=github \ --from-literal=username=github \
--from-literal=password='actions' --from-literal=password='actions'
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1)) ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
--set proxy.https.url="http://host.minikube.internal:3128" \ --set proxy.https.url="http://host.minikube.internal:3128" \
--set proxy.https.credentialSecretRef="proxy-auth" \ --set proxy.https.credentialSecretRef="proxy-auth" \
@@ -572,77 +448,50 @@ jobs:
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{env.WORKFLOW_FILE}}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF
anonymous-proxy-setup: anonymous-proxy-setup:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.id == github.repository_id
env: env:
WORKFLOW_FILE: "arc-test-workflow.yaml" WORKFLOW_FILE: "arc-test-workflow.yaml"
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
- name: Resolve inputs ref: ${{github.head_ref}}
id: resolved_inputs
run: |
TARGET_ORG="${{env.TARGET_ORG}}"
TARGET_REPO="${{env.TARGET_REPO}}"
if [ ! -z "${{inputs.target_org}}" ]; then
TARGET_ORG="${{inputs.target_org}}"
fi
if [ ! -z "${{inputs.target_repo}}" ]; then
TARGET_REPO="${{inputs.target_repo}}"
fi
echo "TARGET_ORG=$TARGET_ORG" >> $GITHUB_OUTPUT
echo "TARGET_REPO=$TARGET_REPO" >> $GITHUB_OUTPUT
- uses: ./.github/actions/setup-arc-e2e - uses: ./.github/actions/setup-arc-e2e
id: setup id: setup
with: with:
github-app-id: ${{secrets.ACTIONS_ACCESS_APP_ID}} app-id: ${{secrets.E2E_TESTS_ACCESS_APP_ID}}
github-app-pk: ${{secrets.ACTIONS_ACCESS_PK}} app-pk: ${{secrets.E2E_TESTS_ACCESS_PK}}
github-app-org: ${{steps.resolved_inputs.outputs.TARGET_ORG}} image-name: ${{env.IMAGE_NAME}}
docker-image-name: ${{env.IMAGE_NAME}} image-tag: ${{env.IMAGE_VERSION}}
docker-image-tag: ${{env.IMAGE_VERSION}} target-org: ${{env.TARGET_ORG}}
- name: Install gha-runner-scale-set-controller - name: Install gha-runner-scale-set-controller
id: install_arc_controller id: install_arc_controller
@@ -678,11 +527,11 @@ jobs:
--name squid \ --name squid \
--publish 3128:3128 \ --publish 3128:3128 \
ubuntu/squid:latest ubuntu/squid:latest
ARC_NAME=arc-runner-${{github.job}}-$(date +'%M-%S')-$(($RANDOM % 100 + 1)) ARC_NAME=${{github.job}}-$(date +'%M%S')$((($RANDOM + 100) % 100 + 1))
helm install "$ARC_NAME" \ helm install "$ARC_NAME" \
--namespace "arc-runners" \ --namespace "arc-runners" \
--create-namespace \ --create-namespace \
--set githubConfigUrl="https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}" \ --set githubConfigUrl="https://github.com/${{ env.TARGET_ORG }}/${{env.TARGET_REPO}}" \
--set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \ --set githubConfigSecret.github_token="${{ steps.setup.outputs.token }}" \
--set proxy.https.url="http://host.minikube.internal:3128" \ --set proxy.https.url="http://host.minikube.internal:3128" \
--set "proxy.noProxy[0]=10.96.0.1:443" \ --set "proxy.noProxy[0]=10.96.0.1:443" \
@@ -691,44 +540,28 @@ jobs:
echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT echo "ARC_NAME=$ARC_NAME" >> $GITHUB_OUTPUT
count=0 count=0
while true; do while true; do
POD_NAME=$(kubectl get pods -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME -o name) POD_NAME=$(kubectl get pods -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME -o name)
if [ -n "$POD_NAME" ]; then if [ -n "$POD_NAME" ]; then
echo "Pod found: $POD_NAME" echo "Pod found: $POD_NAME"
break break
fi fi
if [ "$count" -ge 10 ]; then if [ "$count" -ge 10 ]; then
echo "Timeout waiting for listener pod with label auto-scaling-runner-set-name=$ARC_NAME" echo "Timeout waiting for listener pod with label actions.github.com/scale-set-name=$ARC_NAME"
exit 1 exit 1
fi fi
sleep 1 sleep 1
done done
kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l auto-scaling-runner-set-name=$ARC_NAME kubectl wait --timeout=30s --for=condition=ready pod -n arc-systems -l actions.github.com/scale-set-name=$ARC_NAME
kubectl get pod -n arc-systems kubectl get pod -n arc-systems
- name: Test ARC scales pods up and down - name: Test ARC E2E
id: test uses: ./.github/actions/execute-assert-arc-e2e
run: | timeout-minutes: 10
export GITHUB_TOKEN="${{ steps.setup.outputs.token }}" with:
export ARC_NAME="${{ steps.install_arc.outputs.ARC_NAME }}" auth-token: ${{ steps.setup.outputs.token }}
export WORKFLOW_FILE="${{ env.WORKFLOW_FILE }}" repo-owner: ${{ env.TARGET_ORG }}
go test ./test_e2e_arc -v repo-name: ${{env.TARGET_REPO}}
workflow-file: ${{env.WORKFLOW_FILE}}
- name: Uninstall gha-runner-scale-set arc-name: ${{steps.install_arc.outputs.ARC_NAME}}
if: always() && steps.install_arc.outcome == 'success' arc-namespace: "arc-runners"
run: | arc-controller-namespace: "arc-systems"
helm uninstall ${{ steps.install_arc.outputs.ARC_NAME }} --namespace arc-runners
kubectl wait --timeout=10s --for=delete AutoScalingRunnerSet -n demo -l app.kubernetes.io/instance=${{ steps.install_arc.outputs.ARC_NAME }}
- name: Dump gha-runner-scale-set-controller logs
if: always() && steps.install_arc_controller.outcome == 'success'
run: |
kubectl logs deployment/arc-gha-runner-scale-set-controller -n arc-systems
- name: Job summary
if: always() && steps.install_arc.outcome == 'success'
run: |
cat <<-EOF > $GITHUB_STEP_SUMMARY
| **Outcome** | ${{ steps.test.outcome }} |
|----------------|--------------------------------------------- |
| **References** | [Test workflow runs](https://github.com/${{ steps.resolved_inputs.outputs.TARGET_ORG }}/${{steps.resolved_inputs.outputs.TARGET_REPO}}/actions/workflows/${{ env.WORKFLOW_FILE }}) |
EOF

80
.github/workflows/go.yaml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: Go
on:
push:
branches:
- master
paths:
- '.github/workflows/go.yaml'
- '**.go'
- 'go.mod'
- 'go.sum'
pull_request:
paths:
- '.github/workflows/go.yaml'
- '**.go'
- 'go.mod'
- 'go.sum'
permissions:
contents: read
jobs:
fmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
cache: false
- name: fmt
run: go fmt ./...
- name: Check diff
run: git diff --exit-code
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
cache: false
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
only-new-issues: true
version: v1.51.1
generate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
cache: false
- name: Generate
run: make generate
- name: Check diff
run: git diff --exit-code
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
- run: make manifests
- name: Check diff
run: git diff --exit-code
- name: Install kubebuilder
run: |
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_linux_amd64.tar.gz
tar zxvf kubebuilder_2.3.2_linux_amd64.tar.gz
sudo mv kubebuilder_2.3.2_linux_amd64 /usr/local/kubebuilder
- name: Run go tests
run: |
go test -short `go list ./... | grep -v ./test_e2e_arc`

View File

@@ -1,23 +0,0 @@
name: golangci-lint
on:
push:
branches:
- master
pull_request:
permissions:
contents: read
pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.19
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
with:
only-new-issues: true
version: v1.51.1

View File

@@ -1,60 +0,0 @@
name: Validate ARC
on:
pull_request:
branches:
- master
paths-ignore:
- '**.md'
- '.github/ISSUE_TEMPLATE/**'
- '.github/workflows/publish-canary.yaml'
- '.github/workflows/validate-chart.yaml'
- '.github/workflows/publish-chart.yaml'
- '.github/workflows/runners.yaml'
- '.github/workflows/publish-arc.yaml'
- '.github/workflows/validate-entrypoint.yaml'
- '.github/renovate.*'
- 'runner/**'
- '.gitignore'
- 'PROJECT'
- 'LICENSE'
- 'Makefile'
permissions:
contents: read
jobs:
test-controller:
name: Test ARC
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set-up Go
uses: actions/setup-go@v3
with:
go-version: '1.19'
check-latest: false
- uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Install kubebuilder
run: |
curl -L -O https://github.com/kubernetes-sigs/kubebuilder/releases/download/v2.3.2/kubebuilder_2.3.2_linux_amd64.tar.gz
tar zxvf kubebuilder_2.3.2_linux_amd64.tar.gz
sudo mv kubebuilder_2.3.2_linux_amd64 /usr/local/kubebuilder
- name: Run tests
run: |
make test
- name: Verify manifests are up-to-date
run: |
make manifests
git diff --exit-code

View File

@@ -61,6 +61,9 @@ if [ "${tool}" == "helm" ]; then
flags+=( --set githubWebhookServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET}) flags+=( --set githubWebhookServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
flags+=( --set actionsMetricsServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET}) flags+=( --set actionsMetricsServer.imagePullSecrets[0].name=${IMAGE_PULL_SECRET})
fi fi
if [ "${WATCH_NAMESPACE}" != "" ]; then
flags+=( --set watchNamespace=${WATCH_NAMESPACE} --set singleNamespace=true)
fi
if [ "${CHART_VERSION}" != "" ]; then if [ "${CHART_VERSION}" != "" ]; then
flags+=( --version ${CHART_VERSION}) flags+=( --version ${CHART_VERSION})
fi fi
@@ -69,6 +72,9 @@ if [ "${tool}" == "helm" ]; then
flags+=( --set githubWebhookServer.logFormat=${LOG_FORMAT}) flags+=( --set githubWebhookServer.logFormat=${LOG_FORMAT})
flags+=( --set actionsMetricsServer.logFormat=${LOG_FORMAT}) flags+=( --set actionsMetricsServer.logFormat=${LOG_FORMAT})
fi fi
if [ "${ADMISSION_WEBHOOKS_TIMEOUT}" != "" ]; then
flags+=( --set admissionWebHooks.timeoutSeconds=${ADMISSION_WEBHOOKS_TIMEOUT})
fi
if [ -n "${CREATE_SECRETS_USING_HELM}" ]; then if [ -n "${CREATE_SECRETS_USING_HELM}" ]; then
if [ -z "${WEBHOOK_GITHUB_TOKEN}" ]; then if [ -z "${WEBHOOK_GITHUB_TOKEN}" ]; then
echo 'Failed deploying secret "actions-metrics-server" using helm. Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2 echo 'Failed deploying secret "actions-metrics-server" using helm. Set WEBHOOK_GITHUB_TOKEN to deploy.' 1>&2
@@ -77,6 +83,10 @@ if [ "${tool}" == "helm" ]; then
flags+=( --set actionsMetricsServer.secret.create=true) flags+=( --set actionsMetricsServer.secret.create=true)
flags+=( --set actionsMetricsServer.secret.github_token=${WEBHOOK_GITHUB_TOKEN}) flags+=( --set actionsMetricsServer.secret.github_token=${WEBHOOK_GITHUB_TOKEN})
fi fi
if [ -n "${GITHUB_WEBHOOK_SERVER_ENV_NAME}" ] && [ -n "${GITHUB_WEBHOOK_SERVER_ENV_VALUE}" ]; then
flags+=( --set githubWebhookServer.env[0].name=${GITHUB_WEBHOOK_SERVER_ENV_NAME})
flags+=( --set githubWebhookServer.env[0].value=${GITHUB_WEBHOOK_SERVER_ENV_VALUE})
fi
set -vx set -vx

View File

@@ -77,6 +77,11 @@ type RunnerDeploymentStatus struct {
// +kubebuilder:object:root=true // +kubebuilder:object:root=true
// +kubebuilder:resource:shortName=rdeploy // +kubebuilder:resource:shortName=rdeploy
// +kubebuilder:subresource:status // +kubebuilder:subresource:status
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.enterprise",name=Enterprise,type=string
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.organization",name=Organization,type=string
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.repository",name=Repository,type=string
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.group",name=Group,type=string
// +kubebuilder:printcolumn:JSONPath=".spec.template.spec.labels",name=Labels,type=string
// +kubebuilder:printcolumn:JSONPath=".spec.replicas",name=Desired,type=number // +kubebuilder:printcolumn:JSONPath=".spec.replicas",name=Desired,type=number
// +kubebuilder:printcolumn:JSONPath=".status.replicas",name=Current,type=number // +kubebuilder:printcolumn:JSONPath=".status.replicas",name=Current,type=number
// +kubebuilder:printcolumn:JSONPath=".status.updatedReplicas",name=Up-To-Date,type=number // +kubebuilder:printcolumn:JSONPath=".status.updatedReplicas",name=Up-To-Date,type=number

View File

@@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes # This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version. # to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/) # Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.22.0 version: 0.23.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.27.0 appVersion: 0.27.1
home: https://github.com/actions/actions-runner-controller home: https://github.com/actions/actions-runner-controller

View File

@@ -17,6 +17,21 @@ spec:
scope: Namespaced scope: Namespaced
versions: versions:
- additionalPrinterColumns: - additionalPrinterColumns:
- jsonPath: .spec.template.spec.enterprise
name: Enterprise
type: string
- jsonPath: .spec.template.spec.organization
name: Organization
type: string
- jsonPath: .spec.template.spec.repository
name: Repository
type: string
- jsonPath: .spec.template.spec.group
name: Group
type: string
- jsonPath: .spec.template.spec.labels
name: Labels
type: string
- jsonPath: .spec.replicas - jsonPath: .spec.replicas
name: Desired name: Desired
type: number type: number

View File

@@ -117,10 +117,14 @@ spec:
name: {{ include "actions-runner-controller.secretName" . }} name: {{ include "actions-runner-controller.secretName" . }}
optional: true optional: true
{{- end }} {{- end }}
{{- if kindIs "slice" .Values.githubWebhookServer.env }}
{{- toYaml .Values.githubWebhookServer.env | nindent 8 }}
{{- else }}
{{- range $key, $val := .Values.githubWebhookServer.env }} {{- range $key, $val := .Values.githubWebhookServer.env }}
- name: {{ $key }} - name: {{ $key }}
value: {{ $val | quote }} value: {{ $val | quote }}
{{- end }} {{- end }}
{{- end }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (cat "v" .Chart.AppVersion | replace " " "") }}" image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default (cat "v" .Chart.AppVersion | replace " " "") }}"
name: github-webhook-server name: github-webhook-server
imagePullPolicy: {{ .Values.image.pullPolicy }} imagePullPolicy: {{ .Values.image.pullPolicy }}

View File

@@ -250,14 +250,6 @@ rules:
- patch - patch
- update - update
- watch - watch
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
{{- if .Values.runner.statusUpdateHook.enabled }} {{- if .Values.runner.statusUpdateHook.enabled }}
- apiGroups: - apiGroups:
- "" - ""
@@ -311,11 +303,4 @@ rules:
- list - list
- create - create
- delete - delete
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
{{- end }} {{- end }}

View File

@@ -0,0 +1,21 @@
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.scope.singleNamespace }}
kind: RoleBinding
{{- else }}
kind: ClusterRoleBinding
{{- end }}
metadata:
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
{{- if .Values.scope.singleNamespace }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
subjects:
- kind: ServiceAccount
name: {{ include "actions-runner-controller.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}

View File

@@ -0,0 +1,24 @@
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.scope.singleNamespace }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
creationTimestamp: null
name: {{ include "actions-runner-controller.managerRoleName" . }}-secrets
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
{{- if .Values.rbac.allowGrantingKubernetesContainerModePermissions }}
{{/* These permissions are required by ARC to create RBAC resources for the runner pod to use the kubernetes container mode. */}}
{{/* See https://github.com/actions/actions-runner-controller/pull/1268/files#r917331632 */}}
- create
- delete
{{- end }}

View File

@@ -44,6 +44,7 @@ webhooks:
resources: resources:
- runners - runners
sideEffects: None sideEffects: None
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
- admissionReviewVersions: - admissionReviewVersions:
- v1beta1 - v1beta1
{{- if .Values.scope.singleNamespace }} {{- if .Values.scope.singleNamespace }}
@@ -74,6 +75,7 @@ webhooks:
resources: resources:
- runnerdeployments - runnerdeployments
sideEffects: None sideEffects: None
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
- admissionReviewVersions: - admissionReviewVersions:
- v1beta1 - v1beta1
{{- if .Values.scope.singleNamespace }} {{- if .Values.scope.singleNamespace }}
@@ -104,6 +106,7 @@ webhooks:
resources: resources:
- runnerreplicasets - runnerreplicasets
sideEffects: None sideEffects: None
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
- admissionReviewVersions: - admissionReviewVersions:
- v1beta1 - v1beta1
{{- if .Values.scope.singleNamespace }} {{- if .Values.scope.singleNamespace }}
@@ -136,6 +139,7 @@ webhooks:
objectSelector: objectSelector:
matchLabels: matchLabels:
"actions-runner-controller/inject-registration-token": "true" "actions-runner-controller/inject-registration-token": "true"
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
--- ---
apiVersion: admissionregistration.k8s.io/v1 apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration kind: ValidatingWebhookConfiguration
@@ -177,6 +181,7 @@ webhooks:
resources: resources:
- runners - runners
sideEffects: None sideEffects: None
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
- admissionReviewVersions: - admissionReviewVersions:
- v1beta1 - v1beta1
{{- if .Values.scope.singleNamespace }} {{- if .Values.scope.singleNamespace }}
@@ -207,6 +212,7 @@ webhooks:
resources: resources:
- runnerdeployments - runnerdeployments
sideEffects: None sideEffects: None
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
- admissionReviewVersions: - admissionReviewVersions:
- v1beta1 - v1beta1
{{- if .Values.scope.singleNamespace }} {{- if .Values.scope.singleNamespace }}
@@ -238,6 +244,7 @@ webhooks:
- runnerreplicasets - runnerreplicasets
sideEffects: None sideEffects: None
{{ if not (or (hasKey .Values.admissionWebHooks "caBundle") .Values.certManagerEnabled) }} {{ if not (or (hasKey .Values.admissionWebHooks "caBundle") .Values.certManagerEnabled) }}
timeoutSeconds: {{ .Values.admissionWebHooks.timeoutSeconds | default 10}}
--- ---
apiVersion: v1 apiVersion: v1
kind: Secret kind: Secret

View File

@@ -279,6 +279,19 @@ githubWebhookServer:
# queueLimit: 100 # queueLimit: 100
terminationGracePeriodSeconds: 10 terminationGracePeriodSeconds: 10
lifecycle: {} lifecycle: {}
# specify additional environment variables for the webhook server pod.
# It's possible to specify either key vale pairs e.g.:
# my_env_var: "some value"
# my_other_env_var: "other value"
# or a list of complete environment variable definitions e.g.:
# - name: GITHUB_WEBHOOK_SECRET_TOKEN
# valueFrom:
# secretKeyRef:
# key: GITHUB_WEBHOOK_SECRET_TOKEN
# name: prod-gha-controller-webhook-token
# optional: true
env: {}
actionsMetrics: actionsMetrics:
serviceAnnotations: {} serviceAnnotations: {}

View File

@@ -40,6 +40,7 @@ helm.sh/chart: {{ include "gha-runner-scale-set.chart" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }} {{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }} app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: gha-runner-scale-set
{{- end }} {{- end }}
{{/* {{/*

View File

@@ -10,6 +10,7 @@ metadata:
name: {{ .Release.Name }} name: {{ .Release.Name }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app.kubernetes.io/component: "autoscaling-runner-set"
{{- include "gha-runner-scale-set.labels" . | nindent 4 }} {{- include "gha-runner-scale-set.labels" . | nindent 4 }}
spec: spec:
githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }} githubConfigUrl: {{ required ".Values.githubConfigUrl is required" (trimSuffix "/" .Values.githubConfigUrl) }}
@@ -90,14 +91,15 @@ spec:
{{ $key }}: {{ $val | toYaml | nindent 8 }} {{ $key }}: {{ $val | toYaml | nindent 8 }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- if eq .Values.containerMode.type "kubernetes" }} {{- $containerMode := .Values.containerMode }}
{{- if eq $containerMode.type "kubernetes" }}
serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }} serviceAccountName: {{ default (include "gha-runner-scale-set.kubeModeServiceAccountName" .) .Values.template.spec.serviceAccountName }}
{{- else }} {{- else }}
serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }} serviceAccountName: {{ default (include "gha-runner-scale-set.noPermissionServiceAccountName" .) .Values.template.spec.serviceAccountName }}
{{- end }} {{- end }}
{{- if or .Values.template.spec.initContainers (eq .Values.containerMode.type "dind") }} {{- if or .Values.template.spec.initContainers (eq $containerMode.type "dind") }}
initContainers: initContainers:
{{- if eq .Values.containerMode.type "dind" }} {{- if eq $containerMode.type "dind" }}
- name: init-dind-externals - name: init-dind-externals
{{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }} {{- include "gha-runner-scale-set.dind-init-container" . | nindent 8 }}
{{- end }} {{- end }}
@@ -106,13 +108,13 @@ spec:
{{- end }} {{- end }}
{{- end }} {{- end }}
containers: containers:
{{- if eq .Values.containerMode.type "dind" }} {{- if eq $containerMode.type "dind" }}
- name: runner - name: runner
{{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }} {{- include "gha-runner-scale-set.dind-runner-container" . | nindent 8 }}
- name: dind - name: dind
{{- include "gha-runner-scale-set.dind-container" . | nindent 8 }} {{- include "gha-runner-scale-set.dind-container" . | nindent 8 }}
{{- include "gha-runner-scale-set.non-runner-non-dind-containers" . | nindent 6 }} {{- include "gha-runner-scale-set.non-runner-non-dind-containers" . | nindent 6 }}
{{- else if eq .Values.containerMode.type "kubernetes" }} {{- else if eq $containerMode.type "kubernetes" }}
- name: runner - name: runner
{{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }} {{- include "gha-runner-scale-set.kubernetes-mode-runner-container" . | nindent 8 }}
{{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }} {{- include "gha-runner-scale-set.non-runner-containers" . | nindent 6 }}
@@ -120,16 +122,16 @@ spec:
{{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }} {{- include "gha-runner-scale-set.default-mode-runner-containers" . | nindent 6 }}
{{- end }} {{- end }}
{{- $tlsConfig := (default (dict) .Values.githubServerTLS) }} {{- $tlsConfig := (default (dict) .Values.githubServerTLS) }}
{{- if or .Values.template.spec.volumes (eq .Values.containerMode.type "dind") (eq .Values.containerMode.type "kubernetes") $tlsConfig.runnerMountPath }} {{- if or .Values.template.spec.volumes (eq $containerMode.type "dind") (eq $containerMode.type "kubernetes") $tlsConfig.runnerMountPath }}
volumes: volumes:
{{- if $tlsConfig.runnerMountPath }} {{- if $tlsConfig.runnerMountPath }}
{{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }} {{- include "gha-runner-scale-set.tls-volume" $tlsConfig | nindent 6 }}
{{- end }} {{- end }}
{{- if eq .Values.containerMode.type "dind" }} {{- if eq $containerMode.type "dind" }}
{{- include "gha-runner-scale-set.dind-volume" . | nindent 6 }} {{- include "gha-runner-scale-set.dind-volume" . | nindent 6 }}
{{- include "gha-runner-scale-set.dind-work-volume" . | nindent 6 }} {{- include "gha-runner-scale-set.dind-work-volume" . | nindent 6 }}
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }} {{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
{{- else if eq .Values.containerMode.type "kubernetes" }} {{- else if eq $containerMode.type "kubernetes" }}
{{- include "gha-runner-scale-set.kubernetes-mode-work-volume" . | nindent 6 }} {{- include "gha-runner-scale-set.kubernetes-mode-work-volume" . | nindent 6 }}
{{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }} {{- include "gha-runner-scale-set.non-work-volumes" . | nindent 6 }}
{{- else }} {{- else }}

View File

@@ -1,4 +1,5 @@
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }} {{- $containerMode := .Values.containerMode }}
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
# default permission for runner pod service account in kubernetes mode (container hook) # default permission for runner pod service account in kubernetes mode (container hook)
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: Role kind: Role
@@ -21,4 +22,4 @@ rules:
- apiGroups: [""] - apiGroups: [""]
resources: ["secrets"] resources: ["secrets"]
verbs: ["get", "list", "create", "delete"] verbs: ["get", "list", "create", "delete"]
{{- end }} {{- end }}

View File

@@ -1,4 +1,5 @@
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }} {{- $containerMode := .Values.containerMode }}
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
apiVersion: rbac.authorization.k8s.io/v1 apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding kind: RoleBinding
metadata: metadata:
@@ -12,4 +13,4 @@ subjects:
- kind: ServiceAccount - kind: ServiceAccount
name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }} name: {{ include "gha-runner-scale-set.kubeModeServiceAccountName" . }}
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
{{- end }} {{- end }}

View File

@@ -1,4 +1,5 @@
{{- if and (eq .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }} {{- $containerMode := .Values.containerMode }}
{{- if and (eq $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
@@ -6,4 +7,4 @@ metadata:
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
{{- include "gha-runner-scale-set.labels" . | nindent 4 }} {{- include "gha-runner-scale-set.labels" . | nindent 4 }}
{{- end }} {{- end }}

View File

@@ -1,4 +1,5 @@
{{- if and (ne .Values.containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }} {{- $containerMode := .Values.containerMode }}
{{- if and (ne $containerMode.type "kubernetes") (not .Values.template.spec.serviceAccountName) }}
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
@@ -6,4 +7,4 @@ metadata:
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
{{- include "gha-runner-scale-set.labels" . | nindent 4 }} {{- include "gha-runner-scale-set.labels" . | nindent 4 }}
{{- end }} {{- end }}

View File

@@ -311,6 +311,10 @@ func TestTemplateRenderedAutoScalingRunnerSet(t *testing.T) {
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"]) assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/name"])
assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"]) assert.Equal(t, "test-runners", ars.Labels["app.kubernetes.io/instance"])
assert.Equal(t, "gha-runner-scale-set", ars.Labels["app.kubernetes.io/part-of"])
assert.Equal(t, "autoscaling-runner-set", ars.Labels["app.kubernetes.io/component"])
assert.NotEmpty(t, ars.Labels["app.kubernetes.io/version"])
assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl) assert.Equal(t, "https://github.com/actions", ars.Spec.GitHubConfigUrl)
assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret) assert.Equal(t, "test-runners-gha-runner-scale-set-github-secret", ars.Spec.GitHubConfigSecret)

View File

@@ -68,16 +68,16 @@ githubConfigSecret:
# key: ca.pem # key: ca.pem
# runnerMountPath: /usr/local/share/ca-certificates/ # runnerMountPath: /usr/local/share/ca-certificates/
containerMode: # containerMode:
type: "" ## type can be set to dind or kubernetes # type: "dind" ## type can be set to dind or kubernetes
## the following is required when containerMode.type=kubernetes # ## the following is required when containerMode.type=kubernetes
# kubernetesModeWorkVolumeClaim: # kubernetesModeWorkVolumeClaim:
# accessModes: ["ReadWriteOnce"] # accessModes: ["ReadWriteOnce"]
# # For local testing, use https://github.com/openebs/dynamic-localpv-provisioner/blob/develop/docs/quickstart.md to provide dynamic provision volume with storageClassName: openebs-hostpath # # For local testing, use https://github.com/openebs/dynamic-localpv-provisioner/blob/develop/docs/quickstart.md to provide dynamic provision volume with storageClassName: openebs-hostpath
# storageClassName: "dynamic-blob-storage" # storageClassName: "dynamic-blob-storage"
# resources: # resources:
# requests: # requests:
# storage: 1Gi # storage: 1Gi
## template is the PodSpec for each runner Pod ## template is the PodSpec for each runner Pod
template: template:
@@ -161,7 +161,7 @@ template:
image: ghcr.io/actions/actions-runner:latest image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"] command: ["/home/runner/run.sh"]
## Optional controller service account that needs to have required Role and RoleBinding ## Optional controller service account that needs to have required Role and RoleBinding
## to operate this gha-runner-scale-set installation. ## to operate this gha-runner-scale-set installation.
## The helm chart will try to find the controller deployment and its service account at installation time. ## The helm chart will try to find the controller deployment and its service account at installation time.
## In case the helm chart can't find the right service account, you can explicitly pass in the following value ## In case the helm chart can't find the right service account, you can explicitly pass in the following value
@@ -169,4 +169,4 @@ template:
## Note: if your controller is installed to only watch a single namespace, you have to pass these values explicitly. ## Note: if your controller is installed to only watch a single namespace, you have to pass these values explicitly.
# controllerServiceAccount: # controllerServiceAccount:
# namespace: arc-system # namespace: arc-system
# name: test-arc-gha-runner-scale-set-controller # name: test-arc-gha-runner-scale-set-controller

View File

@@ -17,6 +17,21 @@ spec:
scope: Namespaced scope: Namespaced
versions: versions:
- additionalPrinterColumns: - additionalPrinterColumns:
- jsonPath: .spec.template.spec.enterprise
name: Enterprise
type: string
- jsonPath: .spec.template.spec.organization
name: Organization
type: string
- jsonPath: .spec.template.spec.repository
name: Repository
type: string
- jsonPath: .spec.template.spec.group
name: Group
type: string
- jsonPath: .spec.template.spec.labels
name: Labels
type: string
- jsonPath: .spec.replicas - jsonPath: .spec.replicas
name: Desired name: Desired
type: number type: number

View File

@@ -523,8 +523,8 @@ func (r *AutoscalingListenerReconciler) createProxySecret(ctx context.Context, a
Name: proxyListenerSecretName(autoscalingListener), Name: proxyListenerSecretName(autoscalingListener),
Namespace: autoscalingListener.Namespace, Namespace: autoscalingListener.Namespace,
Labels: map[string]string{ Labels: map[string]string{
"auto-scaling-runner-set-namespace": autoscalingListener.Spec.AutoscalingRunnerSetNamespace, LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
"auto-scaling-runner-set-name": autoscalingListener.Spec.AutoscalingRunnerSetName, LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
}, },
}, },
Data: data, Data: data,

View File

@@ -45,9 +45,8 @@ const (
autoscalingRunnerSetOwnerKey = ".metadata.controller" autoscalingRunnerSetOwnerKey = ".metadata.controller"
LabelKeyRunnerSpecHash = "runner-spec-hash" LabelKeyRunnerSpecHash = "runner-spec-hash"
autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer" autoscalingRunnerSetFinalizerName = "autoscalingrunnerset.actions.github.com/finalizer"
runnerScaleSetIdKey = "runner-scale-set-id" runnerScaleSetIdAnnotationKey = "runner-scale-set-id"
runnerScaleSetNameKey = "runner-scale-set-name" runnerScaleSetNameAnnotationKey = "runner-scale-set-name"
runnerScaleSetRunnerGroupNameKey = "runner-scale-set-runner-group-name"
) )
// AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object // AutoscalingRunnerSetReconciler reconciles a AutoscalingRunnerSet object
@@ -140,7 +139,7 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
return ctrl.Result{}, nil return ctrl.Result{}, nil
} }
scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdKey] scaleSetIdRaw, ok := autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey]
if !ok { if !ok {
// Need to create a new runner scale set on Actions service // Need to create a new runner scale set on Actions service
log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.") log.Info("Runner scale set id annotation does not exist. Creating a new runner scale set.")
@@ -154,14 +153,14 @@ func (r *AutoscalingRunnerSetReconciler) Reconcile(ctx context.Context, req ctrl
} }
// Make sure the runner group of the scale set is up to date // Make sure the runner group of the scale set is up to date
currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetRunnerGroupNameKey] currentRunnerGroupName, ok := autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName]
if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) { if !ok || (len(autoscalingRunnerSet.Spec.RunnerGroup) > 0 && !strings.EqualFold(currentRunnerGroupName, autoscalingRunnerSet.Spec.RunnerGroup)) {
log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.") log.Info("AutoScalingRunnerSet runner group changed. Updating the runner scale set.")
return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log) return r.updateRunnerScaleSetRunnerGroup(ctx, autoscalingRunnerSet, log)
} }
// Make sure the runner scale set name is up to date // Make sure the runner scale set name is up to date
currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameKey] currentRunnerScaleSetName, ok := autoscalingRunnerSet.Annotations[runnerScaleSetNameAnnotationKey]
if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) { if !ok || (len(autoscalingRunnerSet.Spec.RunnerScaleSetName) > 0 && !strings.EqualFold(currentRunnerScaleSetName, autoscalingRunnerSet.Spec.RunnerScaleSetName)) {
log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.") log.Info("AutoScalingRunnerSet runner scale set name changed. Updating the runner scale set.")
return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log) return r.updateRunnerScaleSetName(ctx, autoscalingRunnerSet, log)
@@ -365,12 +364,18 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
if autoscalingRunnerSet.Annotations == nil { if autoscalingRunnerSet.Annotations == nil {
autoscalingRunnerSet.Annotations = map[string]string{} autoscalingRunnerSet.Annotations = map[string]string{}
} }
if autoscalingRunnerSet.Labels == nil {
autoscalingRunnerSet.Labels = map[string]string{}
}
logger.Info("Adding runner scale set ID, name and runner group name as an annotation") logger.Info("Adding runner scale set ID, name and runner group name as an annotation and url labels")
if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { if err = patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[runnerScaleSetNameKey] = runnerScaleSet.Name obj.Annotations[runnerScaleSetNameAnnotationKey] = runnerScaleSet.Name
obj.Annotations[runnerScaleSetIdKey] = strconv.Itoa(runnerScaleSet.Id) obj.Annotations[runnerScaleSetIdAnnotationKey] = strconv.Itoa(runnerScaleSet.Id)
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = runnerScaleSet.RunnerGroupName obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = runnerScaleSet.RunnerGroupName
if err := applyGitHubURLLabels(obj.Spec.GitHubConfigUrl, obj.Labels); err != nil { // should never happen
logger.Error(err, "Failed to apply GitHub URL labels")
}
}); err != nil { }); err != nil {
logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation") logger.Error(err, "Failed to add runner scale set ID, name and runner group name as an annotation")
return ctrl.Result{}, err return ctrl.Result{}, err
@@ -384,7 +389,7 @@ func (r *AutoscalingRunnerSetReconciler) createRunnerScaleSet(ctx context.Contex
} }
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
if err != nil { if err != nil {
logger.Error(err, "Failed to parse runner scale set ID") logger.Error(err, "Failed to parse runner scale set ID")
return ctrl.Result{}, err return ctrl.Result{}, err
@@ -415,7 +420,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
logger.Info("Updating runner scale set runner group name as an annotation") logger.Info("Updating runner scale set runner group name as an annotation")
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[runnerScaleSetRunnerGroupNameKey] = updatedRunnerScaleSet.RunnerGroupName obj.Annotations[AnnotationKeyGitHubRunnerGroupName] = updatedRunnerScaleSet.RunnerGroupName
}); err != nil { }); err != nil {
logger.Error(err, "Failed to update runner group name annotation") logger.Error(err, "Failed to update runner group name annotation")
return ctrl.Result{}, err return ctrl.Result{}, err
@@ -426,7 +431,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetRunnerGroup(ctx con
} }
func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) { func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) (ctrl.Result, error) {
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
if err != nil { if err != nil {
logger.Error(err, "Failed to parse runner scale set ID") logger.Error(err, "Failed to parse runner scale set ID")
return ctrl.Result{}, err return ctrl.Result{}, err
@@ -451,7 +456,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co
logger.Info("Updating runner scale set name as an annotation") logger.Info("Updating runner scale set name as an annotation")
if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) { if err := patch(ctx, r.Client, autoscalingRunnerSet, func(obj *v1alpha1.AutoscalingRunnerSet) {
obj.Annotations[runnerScaleSetNameKey] = updatedRunnerScaleSet.Name obj.Annotations[runnerScaleSetNameAnnotationKey] = updatedRunnerScaleSet.Name
}); err != nil { }); err != nil {
logger.Error(err, "Failed to update runner scale set name annotation") logger.Error(err, "Failed to update runner scale set name annotation")
return ctrl.Result{}, err return ctrl.Result{}, err
@@ -463,7 +468,7 @@ func (r *AutoscalingRunnerSetReconciler) updateRunnerScaleSetName(ctx context.Co
func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error { func (r *AutoscalingRunnerSetReconciler) deleteRunnerScaleSet(ctx context.Context, autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, logger logr.Logger) error {
logger.Info("Deleting the runner scale set from Actions service") logger.Info("Deleting the runner scale set from Actions service")
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
if err != nil { if err != nil {
// If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id. // If the annotation is not set correctly, or if it does not exist, we are going to get stuck in a loop trying to parse the scale set id.
// If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup // If the configuration is invalid (secret does not exist for example), we never get to the point to create runner set. But then, manual cleanup

View File

@@ -117,19 +117,39 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
return "", err return "", err
} }
if _, ok := created.Annotations[runnerScaleSetIdKey]; !ok { if _, ok := created.Annotations[runnerScaleSetIdAnnotationKey]; !ok {
return "", nil return "", nil
} }
if _, ok := created.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { if _, ok := created.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
return "", nil return "", nil
} }
return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdKey], created.Annotations[runnerScaleSetRunnerGroupNameKey]), nil return fmt.Sprintf("%s_%s", created.Annotations[runnerScaleSetIdAnnotationKey], created.Annotations[AnnotationKeyGitHubRunnerGroupName]), nil
}, },
autoscalingRunnerSetTestTimeout, autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation") autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("1_testgroup"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's annotation")
Eventually(
func() (string, error) {
err := k8sClient.Get(ctx, client.ObjectKey{Name: autoscalingRunnerSet.Name, Namespace: autoscalingRunnerSet.Namespace}, created)
if err != nil {
return "", err
}
if _, ok := created.Labels[LabelKeyGitHubOrganization]; !ok {
return "", nil
}
if _, ok := created.Labels[LabelKeyGitHubRepository]; !ok {
return "", nil
}
return fmt.Sprintf("%s/%s", created.Labels[LabelKeyGitHubOrganization], created.Labels[LabelKeyGitHubRepository]), nil
},
autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("owner/repo"), "RunnerScaleSet should be created/fetched and update the AutoScalingRunnerSet's label")
// Check if ephemeral runner set is created // Check if ephemeral runner set is created
Eventually( Eventually(
func() (int, error) { func() (int, error) {
@@ -351,18 +371,18 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
return "", err return "", err
} }
if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
return "", nil return "", nil
} }
return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil
}, },
autoscalingRunnerSetTestTimeout, autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation") autoscalingRunnerSetTestInterval).Should(BeEquivalentTo("testgroup2"), "AutoScalingRunnerSet should have the new runner group in its annotation")
// delete the annotation and it should be re-added // delete the annotation and it should be re-added
patched = autoscalingRunnerSet.DeepCopy() patched = autoscalingRunnerSet.DeepCopy()
delete(patched.Annotations, runnerScaleSetRunnerGroupNameKey) delete(patched.Annotations, AnnotationKeyGitHubRunnerGroupName)
err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet)) err = k8sClient.Patch(ctx, patched, client.MergeFrom(autoscalingRunnerSet))
Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet") Expect(err).NotTo(HaveOccurred(), "failed to patch AutoScalingRunnerSet")
@@ -374,11 +394,11 @@ var _ = Describe("Test AutoScalingRunnerSet controller", func() {
return "", err return "", err
} }
if _, ok := updated.Annotations[runnerScaleSetRunnerGroupNameKey]; !ok { if _, ok := updated.Annotations[AnnotationKeyGitHubRunnerGroupName]; !ok {
return "", nil return "", nil
} }
return updated.Annotations[runnerScaleSetRunnerGroupNameKey], nil return updated.Annotations[AnnotationKeyGitHubRunnerGroupName], nil
}, },
autoscalingRunnerSetTestTimeout, autoscalingRunnerSetTestTimeout,
autoscalingRunnerSetTestInterval, autoscalingRunnerSetTestInterval,
@@ -539,7 +559,7 @@ var _ = Describe("Test AutoScalingController updates", func() {
return "", err return "", err
} }
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok { if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok {
return val, nil return val, nil
} }
@@ -562,7 +582,7 @@ var _ = Describe("Test AutoScalingController updates", func() {
return "", err return "", err
} }
if val, ok := ars.Annotations[runnerScaleSetNameKey]; ok { if val, ok := ars.Annotations[runnerScaleSetNameAnnotationKey]; ok {
return val, nil return val, nil
} }

View File

@@ -356,10 +356,9 @@ func (r *EphemeralRunnerSetReconciler) createProxySecret(ctx context.Context, ep
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet), Name: proxyEphemeralRunnerSetSecretName(ephemeralRunnerSet),
Namespace: ephemeralRunnerSet.Namespace, Namespace: ephemeralRunnerSet.Namespace,
Labels: map[string]string{ Labels: map[string]string{
// TODO: figure out autoScalingRunnerSet name and set it as a label for this secret LabelKeyGitHubScaleSetName: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName],
// "auto-scaling-runner-set-namespace": ephemeralRunnerSet.Namespace, LabelKeyGitHubScaleSetNamespace: ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace],
// "auto-scaling-runner-set-name": ephemeralRunnerSet.Name,
}, },
}, },
Data: proxySecretData, Data: proxySecretData,

View File

@@ -8,6 +8,7 @@ import (
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1" "github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
"github.com/actions/actions-runner-controller/build" "github.com/actions/actions-runner-controller/build"
"github.com/actions/actions-runner-controller/github/actions"
"github.com/actions/actions-runner-controller/hash" "github.com/actions/actions-runner-controller/hash"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1" rbacv1 "k8s.io/api/rbac/v1"
@@ -19,12 +20,42 @@ const (
jitTokenKey = "jitToken" jitTokenKey = "jitToken"
) )
// labels applied to resources // Labels applied to resources
const ( const (
LabelKeyAutoScaleRunnerSetName = "auto-scaling-runner-set-name" // Kubernetes labels
LabelKeyAutoScaleRunnerSetNamespace = "auto-scaling-runner-set-namespace" LabelKeyKubernetesPartOf = "app.kubernetes.io/part-of"
LabelKeyKubernetesComponent = "app.kubernetes.io/component"
LabelKeyKubernetesVersion = "app.kubernetes.io/version"
// Github labels
LabelKeyGitHubScaleSetName = "actions.github.com/scale-set-name"
LabelKeyGitHubScaleSetNamespace = "actions.github.com/scale-set-namespace"
LabelKeyGitHubEnterprise = "actions.github.com/enterprise"
LabelKeyGitHubOrganization = "actions.github.com/organization"
LabelKeyGitHubRepository = "actions.github.com/repository"
) )
const AnnotationKeyGitHubRunnerGroupName = "actions.github.com/runner-group-name"
// Labels applied to listener roles
const (
labelKeyListenerName = "auto-scaling-listener-name"
labelKeyListenerNamespace = "auto-scaling-listener-namespace"
)
var commonLabelKeys = [...]string{
LabelKeyKubernetesPartOf,
LabelKeyKubernetesComponent,
LabelKeyKubernetesVersion,
LabelKeyGitHubScaleSetName,
LabelKeyGitHubScaleSetNamespace,
LabelKeyGitHubEnterprise,
LabelKeyGitHubOrganization,
LabelKeyGitHubRepository,
}
const labelValueKubernetesPartOf = "gha-runner-scale-set"
type resourceBuilder struct{} type resourceBuilder struct{}
func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod { func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.AutoscalingListener, serviceAccount *corev1.ServiceAccount, secret *corev1.Secret, envs ...corev1.EnvVar) *corev1.Pod {
@@ -129,6 +160,11 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
RestartPolicy: corev1.RestartPolicyNever, RestartPolicy: corev1.RestartPolicyNever,
} }
labels := make(map[string]string, len(autoscalingListener.Labels))
for key, val := range autoscalingListener.Labels {
labels[key] = val
}
newRunnerScaleSetListenerPod := &corev1.Pod{ newRunnerScaleSetListenerPod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "Pod", Kind: "Pod",
@@ -137,10 +173,7 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: autoscalingListener.Name, Name: autoscalingListener.Name,
Namespace: autoscalingListener.Namespace, Namespace: autoscalingListener.Namespace,
Labels: map[string]string{ Labels: labels,
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
},
}, },
Spec: podSpec, Spec: podSpec,
} }
@@ -149,14 +182,28 @@ func (b *resourceBuilder) newScaleSetListenerPod(autoscalingListener *v1alpha1.A
} }
func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) { func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet) (*v1alpha1.EphemeralRunnerSet, error) {
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
if err != nil { if err != nil {
return nil, err return nil, err
} }
runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash() runnerSpecHash := autoscalingRunnerSet.RunnerSetSpecHash()
newLabels := map[string]string{} newLabels := map[string]string{
newLabels[LabelKeyRunnerSpecHash] = runnerSpecHash LabelKeyRunnerSpecHash: runnerSpecHash,
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
LabelKeyKubernetesComponent: "runner-set",
LabelKeyKubernetesVersion: autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
LabelKeyGitHubScaleSetName: autoscalingRunnerSet.Name,
LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace,
}
if err := applyGitHubURLLabels(autoscalingRunnerSet.Spec.GitHubConfigUrl, newLabels); err != nil {
return nil, fmt.Errorf("failed to apply GitHub URL labels: %v", err)
}
newAnnotations := map[string]string{
AnnotationKeyGitHubRunnerGroupName: autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName],
}
newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{ newEphemeralRunnerSet := &v1alpha1.EphemeralRunnerSet{
TypeMeta: metav1.TypeMeta{}, TypeMeta: metav1.TypeMeta{},
@@ -164,6 +211,7 @@ func (b *resourceBuilder) newEphemeralRunnerSet(autoscalingRunnerSet *v1alpha1.A
GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-", GenerateName: autoscalingRunnerSet.ObjectMeta.Name + "-",
Namespace: autoscalingRunnerSet.ObjectMeta.Namespace, Namespace: autoscalingRunnerSet.ObjectMeta.Namespace,
Labels: newLabels, Labels: newLabels,
Annotations: newAnnotations,
}, },
Spec: v1alpha1.EphemeralRunnerSetSpec{ Spec: v1alpha1.EphemeralRunnerSetSpec{
Replicas: 0, Replicas: 0,
@@ -187,8 +235,8 @@ func (b *resourceBuilder) newScaleSetListenerServiceAccount(autoscalingListener
Name: scaleSetListenerServiceAccountName(autoscalingListener), Name: scaleSetListenerServiceAccountName(autoscalingListener),
Namespace: autoscalingListener.Namespace, Namespace: autoscalingListener.Namespace,
Labels: map[string]string{ Labels: map[string]string{
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName, LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
}, },
}, },
} }
@@ -202,11 +250,11 @@ func (b *resourceBuilder) newScaleSetListenerRole(autoscalingListener *v1alpha1.
Name: scaleSetListenerRoleName(autoscalingListener), Name: scaleSetListenerRoleName(autoscalingListener),
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
Labels: map[string]string{ Labels: map[string]string{
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName, LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
"auto-scaling-listener-namespace": autoscalingListener.Namespace, labelKeyListenerNamespace: autoscalingListener.Namespace,
"auto-scaling-listener-name": autoscalingListener.Name, labelKeyListenerName: autoscalingListener.Name,
"role-policy-rules-hash": rulesHash, "role-policy-rules-hash": rulesHash,
}, },
}, },
Rules: rules, Rules: rules,
@@ -236,12 +284,12 @@ func (b *resourceBuilder) newScaleSetListenerRoleBinding(autoscalingListener *v1
Name: scaleSetListenerRoleName(autoscalingListener), Name: scaleSetListenerRoleName(autoscalingListener),
Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, Namespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
Labels: map[string]string{ Labels: map[string]string{
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName, LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
"auto-scaling-listener-namespace": autoscalingListener.Namespace, labelKeyListenerNamespace: autoscalingListener.Namespace,
"auto-scaling-listener-name": autoscalingListener.Name, labelKeyListenerName: autoscalingListener.Name,
"role-binding-role-ref-hash": roleRefHash, "role-binding-role-ref-hash": roleRefHash,
"role-binding-subject-hash": subjectHash, "role-binding-subject-hash": subjectHash,
}, },
}, },
RoleRef: roleRef, RoleRef: roleRef,
@@ -259,9 +307,9 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v
Name: scaleSetListenerSecretMirrorName(autoscalingListener), Name: scaleSetListenerSecretMirrorName(autoscalingListener),
Namespace: autoscalingListener.Namespace, Namespace: autoscalingListener.Namespace,
Labels: map[string]string{ Labels: map[string]string{
LabelKeyAutoScaleRunnerSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace, LabelKeyGitHubScaleSetNamespace: autoscalingListener.Spec.AutoscalingRunnerSetNamespace,
LabelKeyAutoScaleRunnerSetName: autoscalingListener.Spec.AutoscalingRunnerSetName, LabelKeyGitHubScaleSetName: autoscalingListener.Spec.AutoscalingRunnerSetName,
"secret-data-hash": dataHash, "secret-data-hash": dataHash,
}, },
}, },
Data: secret.DeepCopy().Data, Data: secret.DeepCopy().Data,
@@ -271,7 +319,7 @@ func (b *resourceBuilder) newScaleSetListenerSecretMirror(autoscalingListener *v
} }
func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) { func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.AutoscalingRunnerSet, ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet, namespace, image string, imagePullSecrets []corev1.LocalObjectReference) (*v1alpha1.AutoscalingListener, error) {
runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdKey]) runnerScaleSetId, err := strconv.Atoi(autoscalingRunnerSet.Annotations[runnerScaleSetIdAnnotationKey])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -285,14 +333,25 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners effectiveMinRunners = *autoscalingRunnerSet.Spec.MinRunners
} }
githubConfig, err := actions.ParseGitHubConfigFromURL(autoscalingRunnerSet.Spec.GitHubConfigUrl)
if err != nil {
return nil, fmt.Errorf("failed to parse github config from url: %v", err)
}
autoscalingListener := &v1alpha1.AutoscalingListener{ autoscalingListener := &v1alpha1.AutoscalingListener{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: scaleSetListenerName(autoscalingRunnerSet), Name: scaleSetListenerName(autoscalingRunnerSet),
Namespace: namespace, Namespace: namespace,
Labels: map[string]string{ Labels: map[string]string{
LabelKeyAutoScaleRunnerSetNamespace: autoscalingRunnerSet.Namespace, LabelKeyGitHubScaleSetNamespace: autoscalingRunnerSet.Namespace,
LabelKeyAutoScaleRunnerSetName: autoscalingRunnerSet.Name, LabelKeyGitHubScaleSetName: autoscalingRunnerSet.Name,
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(), LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
LabelKeyKubernetesComponent: "runner-scale-set-listener",
LabelKeyKubernetesVersion: autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion],
LabelKeyGitHubEnterprise: githubConfig.Enterprise,
LabelKeyGitHubOrganization: githubConfig.Organization,
LabelKeyGitHubRepository: githubConfig.Repository,
LabelKeyRunnerSpecHash: autoscalingRunnerSet.ListenerSpecHash(),
}, },
}, },
Spec: v1alpha1.AutoscalingListenerSpec{ Spec: v1alpha1.AutoscalingListenerSpec{
@@ -315,11 +374,30 @@ func (b *resourceBuilder) newAutoScalingListener(autoscalingRunnerSet *v1alpha1.
} }
func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner { func (b *resourceBuilder) newEphemeralRunner(ephemeralRunnerSet *v1alpha1.EphemeralRunnerSet) *v1alpha1.EphemeralRunner {
labels := make(map[string]string)
for _, key := range commonLabelKeys {
switch key {
case LabelKeyKubernetesComponent:
labels[key] = "runner"
default:
v, ok := ephemeralRunnerSet.Labels[key]
if !ok {
continue
}
labels[key] = v
}
}
annotations := make(map[string]string)
for key, val := range ephemeralRunnerSet.Annotations {
annotations[key] = val
}
return &v1alpha1.EphemeralRunner{ return &v1alpha1.EphemeralRunner{
TypeMeta: metav1.TypeMeta{}, TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
GenerateName: ephemeralRunnerSet.Name + "-runner-", GenerateName: ephemeralRunnerSet.Name + "-runner-",
Namespace: ephemeralRunnerSet.Namespace, Namespace: ephemeralRunnerSet.Namespace,
Labels: labels,
Annotations: annotations,
}, },
Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec, Spec: ephemeralRunnerSet.Spec.EphemeralRunnerSpec,
} }
@@ -337,6 +415,7 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a
for k, v := range runner.Spec.PodTemplateSpec.Labels { for k, v := range runner.Spec.PodTemplateSpec.Labels {
labels[k] = v labels[k] = v
} }
labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue)
for k, v := range runner.ObjectMeta.Annotations { for k, v := range runner.ObjectMeta.Annotations {
annotations[k] = v annotations[k] = v
@@ -352,8 +431,6 @@ func (b *resourceBuilder) newEphemeralRunnerPod(ctx context.Context, runner *v1a
runner.Status.RunnerJITConfig, runner.Status.RunnerJITConfig,
) )
labels["actions-ephemeral-runner"] = string(corev1.ConditionTrue)
objectMeta := metav1.ObjectMeta{ objectMeta := metav1.ObjectMeta{
Name: runner.ObjectMeta.Name, Name: runner.ObjectMeta.Name,
Namespace: runner.ObjectMeta.Namespace, Namespace: runner.ObjectMeta.Namespace,
@@ -469,3 +546,22 @@ func rulesForListenerRole(resourceNames []string) []rbacv1.PolicyRule {
}, },
} }
} }
func applyGitHubURLLabels(url string, labels map[string]string) error {
githubConfig, err := actions.ParseGitHubConfigFromURL(url)
if err != nil {
return fmt.Errorf("failed to parse github config from url: %v", err)
}
if len(githubConfig.Enterprise) > 0 {
labels[LabelKeyGitHubEnterprise] = githubConfig.Enterprise
}
if len(githubConfig.Organization) > 0 {
labels[LabelKeyGitHubOrganization] = githubConfig.Organization
}
if len(githubConfig.Repository) > 0 {
labels[LabelKeyGitHubRepository] = githubConfig.Repository
}
return nil
}

View File

@@ -0,0 +1,93 @@
package actionsgithubcom
import (
"context"
"testing"
"github.com/actions/actions-runner-controller/apis/actions.github.com/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestLabelPropagation(t *testing.T) {
autoscalingRunnerSet := v1alpha1.AutoscalingRunnerSet{
ObjectMeta: metav1.ObjectMeta{
Name: "test-scale-set",
Namespace: "test-ns",
Labels: map[string]string{
LabelKeyKubernetesPartOf: labelValueKubernetesPartOf,
LabelKeyKubernetesVersion: "0.2.0",
},
Annotations: map[string]string{
runnerScaleSetIdAnnotationKey: "1",
AnnotationKeyGitHubRunnerGroupName: "test-group",
},
},
Spec: v1alpha1.AutoscalingRunnerSetSpec{
GitHubConfigUrl: "https://github.com/org/repo",
},
}
var b resourceBuilder
ephemeralRunnerSet, err := b.newEphemeralRunnerSet(&autoscalingRunnerSet)
require.NoError(t, err)
assert.Equal(t, labelValueKubernetesPartOf, ephemeralRunnerSet.Labels[LabelKeyKubernetesPartOf])
assert.Equal(t, "runner-set", ephemeralRunnerSet.Labels[LabelKeyKubernetesComponent])
assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], ephemeralRunnerSet.Labels[LabelKeyKubernetesVersion])
assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash])
assert.Equal(t, autoscalingRunnerSet.Name, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetName])
assert.Equal(t, autoscalingRunnerSet.Namespace, ephemeralRunnerSet.Labels[LabelKeyGitHubScaleSetNamespace])
assert.Equal(t, "", ephemeralRunnerSet.Labels[LabelKeyGitHubEnterprise])
assert.Equal(t, "org", ephemeralRunnerSet.Labels[LabelKeyGitHubOrganization])
assert.Equal(t, "repo", ephemeralRunnerSet.Labels[LabelKeyGitHubRepository])
assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName])
listener, err := b.newAutoScalingListener(&autoscalingRunnerSet, ephemeralRunnerSet, autoscalingRunnerSet.Namespace, "test:latest", nil)
require.NoError(t, err)
assert.Equal(t, labelValueKubernetesPartOf, listener.Labels[LabelKeyKubernetesPartOf])
assert.Equal(t, "runner-scale-set-listener", listener.Labels[LabelKeyKubernetesComponent])
assert.Equal(t, autoscalingRunnerSet.Labels[LabelKeyKubernetesVersion], listener.Labels[LabelKeyKubernetesVersion])
assert.NotEmpty(t, ephemeralRunnerSet.Labels[LabelKeyRunnerSpecHash])
assert.Equal(t, autoscalingRunnerSet.Name, listener.Labels[LabelKeyGitHubScaleSetName])
assert.Equal(t, autoscalingRunnerSet.Namespace, listener.Labels[LabelKeyGitHubScaleSetNamespace])
assert.Equal(t, "", listener.Labels[LabelKeyGitHubEnterprise])
assert.Equal(t, "org", listener.Labels[LabelKeyGitHubOrganization])
assert.Equal(t, "repo", listener.Labels[LabelKeyGitHubRepository])
listenerServiceAccount := &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
}
listenerSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
}
listenerPod := b.newScaleSetListenerPod(listener, listenerServiceAccount, listenerSecret)
assert.Equal(t, listenerPod.Labels, listener.Labels)
ephemeralRunner := b.newEphemeralRunner(ephemeralRunnerSet)
require.NoError(t, err)
for _, key := range commonLabelKeys {
if key == LabelKeyKubernetesComponent {
continue
}
assert.Equal(t, ephemeralRunnerSet.Labels[key], ephemeralRunner.Labels[key])
}
assert.Equal(t, "runner", ephemeralRunner.Labels[LabelKeyKubernetesComponent])
assert.Equal(t, autoscalingRunnerSet.Annotations[AnnotationKeyGitHubRunnerGroupName], ephemeralRunner.Annotations[AnnotationKeyGitHubRunnerGroupName])
runnerSecret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
},
}
pod := b.newEphemeralRunnerPod(context.TODO(), ephemeralRunner, runnerSecret)
for key := range ephemeralRunner.Labels {
assert.Equal(t, ephemeralRunner.Labels[key], pod.Labels[key])
}
}

View File

@@ -76,9 +76,12 @@ func TestNewRunnerPod(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
}, },
@@ -137,15 +140,7 @@ func TestNewRunnerPod(t *testing.T) {
}, },
{ {
Name: "DOCKER_HOST", Name: "DOCKER_HOST",
Value: "tcp://localhost:2376", Value: "unix:///run/docker/docker.sock",
},
{
Name: "DOCKER_TLS_VERIFY",
Value: "1",
},
{
Name: "DOCKER_CERT_PATH",
Value: "/certs/client",
}, },
}, },
VolumeMounts: []corev1.VolumeMount{ VolumeMounts: []corev1.VolumeMount{
@@ -158,9 +153,8 @@ func TestNewRunnerPod(t *testing.T) {
MountPath: "/runner/_work", MountPath: "/runner/_work",
}, },
{ {
Name: "certs-client", Name: "docker-sock",
MountPath: "/certs/client", MountPath: "/run/docker",
ReadOnly: true,
}, },
}, },
ImagePullPolicy: corev1.PullAlways, ImagePullPolicy: corev1.PullAlways,
@@ -169,10 +163,15 @@ func TestNewRunnerPod(t *testing.T) {
{ {
Name: "docker", Name: "docker",
Image: "default-docker-image", Image: "default-docker-image",
Args: []string{
"dockerd",
"--host=unix:///run/docker/docker.sock",
"--group=$(DOCKER_GROUP_GID)",
},
Env: []corev1.EnvVar{ Env: []corev1.EnvVar{
{ {
Name: "DOCKER_TLS_CERTDIR", Name: "DOCKER_GROUP_GID",
Value: "/certs", Value: "121",
}, },
}, },
VolumeMounts: []corev1.VolumeMount{ VolumeMounts: []corev1.VolumeMount{
@@ -181,8 +180,8 @@ func TestNewRunnerPod(t *testing.T) {
MountPath: "/runner", MountPath: "/runner",
}, },
{ {
Name: "certs-client", Name: "docker-sock",
MountPath: "/certs/client", MountPath: "/run/docker",
}, },
{ {
Name: "work", Name: "work",
@@ -485,9 +484,12 @@ func TestNewRunnerPod(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
} }
@@ -501,9 +503,8 @@ func TestNewRunnerPod(t *testing.T) {
MountPath: "/runner", MountPath: "/runner",
}, },
{ {
Name: "certs-client", Name: "docker-sock",
MountPath: "/certs/client", MountPath: "/run/docker",
ReadOnly: true,
}, },
} }
}), }),
@@ -527,9 +528,12 @@ func TestNewRunnerPod(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
} }
@@ -606,9 +610,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
}, },
@@ -667,15 +674,7 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
}, },
{ {
Name: "DOCKER_HOST", Name: "DOCKER_HOST",
Value: "tcp://localhost:2376", Value: "unix:///run/docker/docker.sock",
},
{
Name: "DOCKER_TLS_VERIFY",
Value: "1",
},
{
Name: "DOCKER_CERT_PATH",
Value: "/certs/client",
}, },
{ {
Name: "RUNNER_NAME", Name: "RUNNER_NAME",
@@ -696,9 +695,8 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
MountPath: "/runner/_work", MountPath: "/runner/_work",
}, },
{ {
Name: "certs-client", Name: "docker-sock",
MountPath: "/certs/client", MountPath: "/run/docker",
ReadOnly: true,
}, },
}, },
ImagePullPolicy: corev1.PullAlways, ImagePullPolicy: corev1.PullAlways,
@@ -707,10 +705,15 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
{ {
Name: "docker", Name: "docker",
Image: "default-docker-image", Image: "default-docker-image",
Args: []string{
"dockerd",
"--host=unix:///run/docker/docker.sock",
"--group=$(DOCKER_GROUP_GID)",
},
Env: []corev1.EnvVar{ Env: []corev1.EnvVar{
{ {
Name: "DOCKER_TLS_CERTDIR", Name: "DOCKER_GROUP_GID",
Value: "/certs", Value: "121",
}, },
}, },
VolumeMounts: []corev1.VolumeMount{ VolumeMounts: []corev1.VolumeMount{
@@ -719,8 +722,8 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
MountPath: "/runner", MountPath: "/runner",
}, },
{ {
Name: "certs-client", Name: "docker-sock",
MountPath: "/certs/client", MountPath: "/run/docker",
}, },
{ {
Name: "work", Name: "work",
@@ -1079,6 +1082,10 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
Name: "work", Name: "work",
MountPath: "/runner/_work", MountPath: "/runner/_work",
}, },
{
Name: "docker-sock",
MountPath: "/run/docker",
},
}, },
}, },
}, },
@@ -1097,9 +1104,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
workGenericEphemeralVolume, workGenericEphemeralVolume,
@@ -1110,13 +1120,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
MountPath: "/runner/_work", MountPath: "/runner/_work",
}, },
{ {
Name: "runner", Name: "docker-sock",
MountPath: "/runner", MountPath: "/run/docker",
}, },
{ {
Name: "certs-client", Name: "runner",
MountPath: "/certs/client", MountPath: "/runner",
ReadOnly: true,
}, },
} }
}), }),
@@ -1144,9 +1153,12 @@ func TestNewRunnerPodFromRunnerController(t *testing.T) {
}, },
}, },
{ {
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
workGenericEphemeralVolume, workGenericEphemeralVolume,

View File

@@ -30,6 +30,7 @@ import (
"github.com/go-logr/logr" "github.com/go-logr/logr"
kerrors "k8s.io/apimachinery/pkg/api/errors" kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
@@ -1001,6 +1002,35 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
) )
} }
// explicitly invoke `dockerd` to avoid automatic TLS / TCP binding
dockerdContainer.Args = append([]string{
"dockerd",
"--host=unix:///run/docker/docker.sock",
}, dockerdContainer.Args...)
// this must match a GID for the user in the runner image
// default matches GitHub Actions infra (and default runner images
// for actions-runner-controller) so typically should not need to be
// overridden
if ok, _ := envVarPresent("DOCKER_GROUP_GID", dockerdContainer.Env); !ok {
dockerdContainer.Env = append(dockerdContainer.Env,
corev1.EnvVar{
Name: "DOCKER_GROUP_GID",
Value: "121",
})
}
dockerdContainer.Args = append(dockerdContainer.Args, "--group=$(DOCKER_GROUP_GID)")
// ideally, we could mount the socket directly at `/var/run/docker.sock`
// to use the default, but that's not practical since it won't exist
// when the container starts, so can't use subPath on the volume mount
runnerContainer.Env = append(runnerContainer.Env,
corev1.EnvVar{
Name: "DOCKER_HOST",
Value: "unix:///run/docker/docker.sock",
},
)
if ok, _ := workVolumePresent(pod.Spec.Volumes); !ok { if ok, _ := workVolumePresent(pod.Spec.Volumes); !ok {
pod.Spec.Volumes = append(pod.Spec.Volumes, pod.Spec.Volumes = append(pod.Spec.Volumes,
corev1.Volume{ corev1.Volume{
@@ -1014,9 +1044,12 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
pod.Spec.Volumes = append(pod.Spec.Volumes, pod.Spec.Volumes = append(pod.Spec.Volumes,
corev1.Volume{ corev1.Volume{
Name: "certs-client", Name: "docker-sock",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{}, EmptyDir: &corev1.EmptyDirVolumeSource{
Medium: corev1.StorageMediumMemory,
SizeLimit: resource.NewScaledQuantity(1, resource.Mega),
},
}, },
}, },
) )
@@ -1030,28 +1063,14 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
) )
} }
runnerContainer.VolumeMounts = append(runnerContainer.VolumeMounts, if ok, _ := volumeMountPresent("docker-sock", runnerContainer.VolumeMounts); !ok {
corev1.VolumeMount{ runnerContainer.VolumeMounts = append(runnerContainer.VolumeMounts,
Name: "certs-client", corev1.VolumeMount{
MountPath: "/certs/client", Name: "docker-sock",
ReadOnly: true, MountPath: "/run/docker",
}, },
) )
}
runnerContainer.Env = append(runnerContainer.Env, []corev1.EnvVar{
{
Name: "DOCKER_HOST",
Value: "tcp://localhost:2376",
},
{
Name: "DOCKER_TLS_VERIFY",
Value: "1",
},
{
Name: "DOCKER_CERT_PATH",
Value: "/certs/client",
},
}...)
// Determine the volume mounts assigned to the docker sidecar. In case extra mounts are included in the RunnerSpec, append them to the standard // Determine the volume mounts assigned to the docker sidecar. In case extra mounts are included in the RunnerSpec, append them to the standard
// set of mounts. See https://github.com/actions/actions-runner-controller/issues/435 for context. // set of mounts. See https://github.com/actions/actions-runner-controller/issues/435 for context.
@@ -1060,14 +1079,16 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
Name: runnerVolumeName, Name: runnerVolumeName,
MountPath: runnerVolumeMountPath, MountPath: runnerVolumeMountPath,
}, },
{
Name: "certs-client",
MountPath: "/certs/client",
},
} }
mountPresent, _ := workVolumeMountPresent(dockerdContainer.VolumeMounts) if p, _ := volumeMountPresent("docker-sock", dockerdContainer.VolumeMounts); !p {
if !mountPresent { dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{
Name: "docker-sock",
MountPath: "/run/docker",
})
}
if p, _ := workVolumeMountPresent(dockerdContainer.VolumeMounts); !p {
dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{ dockerVolumeMounts = append(dockerVolumeMounts, corev1.VolumeMount{
Name: "work", Name: "work",
MountPath: workDir, MountPath: workDir,
@@ -1078,11 +1099,6 @@ func newRunnerPodWithContainerMode(containerMode string, template corev1.Pod, ru
dockerdContainer.Image = defaultDockerImage dockerdContainer.Image = defaultDockerImage
} }
dockerdContainer.Env = append(dockerdContainer.Env, corev1.EnvVar{
Name: "DOCKER_TLS_CERTDIR",
Value: "/certs",
})
if dockerdContainer.SecurityContext == nil { if dockerdContainer.SecurityContext == nil {
dockerdContainer.SecurityContext = &corev1.SecurityContext{ dockerdContainer.SecurityContext = &corev1.SecurityContext{
Privileged: &privileged, Privileged: &privileged,
@@ -1273,6 +1289,15 @@ func removeFinalizer(finalizers []string, finalizerName string) ([]string, bool)
return result, removed return result, removed
} }
func envVarPresent(name string, items []corev1.EnvVar) (bool, int) {
for index, item := range items {
if item.Name == name {
return true, index
}
}
return false, -1
}
func workVolumePresent(items []corev1.Volume) (bool, int) { func workVolumePresent(items []corev1.Volume) (bool, int) {
for index, item := range items { for index, item := range items {
if item.Name == "work" { if item.Name == "work" {
@@ -1283,12 +1308,16 @@ func workVolumePresent(items []corev1.Volume) (bool, int) {
} }
func workVolumeMountPresent(items []corev1.VolumeMount) (bool, int) { func workVolumeMountPresent(items []corev1.VolumeMount) (bool, int) {
return volumeMountPresent("work", items)
}
func volumeMountPresent(name string, items []corev1.VolumeMount) (bool, int) {
for index, item := range items { for index, item := range items {
if item.Name == "work" { if item.Name == name {
return true, index return true, index
} }
} }
return false, 0 return false, -1
} }
func applyWorkVolumeClaimTemplateToPod(pod *corev1.Pod, workVolumeClaimTemplate *v1alpha1.WorkVolumeClaimTemplate, workDir string) error { func applyWorkVolumeClaimTemplateToPod(pod *corev1.Pod, workVolumeClaimTemplate *v1alpha1.WorkVolumeClaimTemplate, workDir string) error {

View File

@@ -2,7 +2,7 @@
**Date**: 2023-02-02 **Date**: 2023-02-02
**Status**: Proposed **Status**: Done
## Context ## Context

View File

@@ -2,7 +2,7 @@
**Date**: 2023-02-10 **Date**: 2023-02-10
**Status**: Pending **Status**: Done
## Context ## Context

View File

@@ -0,0 +1,84 @@
# Improve ARC workflows for autoscaling runner sets
**Date**: 2023-03-17
**Status**: Done
## Context
In the [actions-runner-controller](https://github.com/actions/actions-runner-controller)
repository we essentially have two projects living side by side: the "legacy"
actions-runner-controller and the new one GitHub is supporting
(gha-runner-scale-set). To hasten progress we relied on existing workflows and
added some of our own (e.g.: end-to-end tests). We now got to a point where it's
sort of confusing what does what and why, not to mention the increased running
times of some those workflows and some GHA-related flaky tests getting in the
way of legacy ARC and viceversa. The three main areas we want to cover are: Go
code, Kubernetes manifests / Helm charts and E2E tests.
## Go code
At the moment we have three workflows that validate Go code:
- [golangci-lint](https://github.com/actions/actions-runner-controller/blob/34f3878/.github/workflows/golangci-lint.yaml):
this is a collection of linters that currently runs on all PRs and push to
master
- [Validate ARC](https://github.com/actions/actions-runner-controller/blob/01e9dd3/.github/workflows/validate-arc.yaml):
this is a bit of a catch-all workflow, other than Go tests this also validates
Kubernetes manifests, runs `go generate`, `go fmt` and `go vet`
- [Run CodeQL](https://github.com/actions/actions-runner-controller/blob/a095f0b66aad5fbc8aa8d7032f3299233e4c84d2/.github/workflows/run-codeql.yaml)
### Proposal
I think having one `Go` workflow that collects everything-Go would help a ton with
reliability and understandability of what's going on. This shouldn't be limited
to the GHA-supported mode as there are changes that even if made outside the GHA
code base could affect us (such as a dependency update).
This workflow should only run on changes to `*.go` files, `go.mod` and `go.sum`.
It should have these jobs, aiming to cover all existing functionality and
eliminate some duplication:
- `test`: run all Go tests in the project. We currently use the `-short` and
`-coverprofile` flags: while `-short` is used to skip [old ARC E2E
tests](https://github.com/actions/actions-runner-controller/blob/master/test/e2e/e2e_test.go#L85-L87),
`-coverprofile` is adding to the test time without really giving us any value
in return. We should also start using `actions/setup-go@v4` to take advantage
of caching (it would speed up our tests by a lot) or enable it on `v3` if we
have a strong reason not to upgrade. We should keep ignoring our E2E tests too
as those will be run elsewhere (either use `Short` there too or ignoring the
package like we currently do). As a dependency for tests this needs to run
`make manifests` first: we should fail there and then if there is a diff.
- `fmt`: we currently run `go fmt ./...` as part of `Validate ARC` but do
nothing with the results. We should fail in case of a diff. We don't need
caching for this job.
- `lint`: this corresponds to what's currently the `golanci-lint` workflow (this
also covers `go vet` which currently happens as part of `Validate ARC too`)
- `generate`: the current behaviour for this is actually quite risky, we
generate our code in `Validate ARC` workflow and use the results to run the
tests but we don't validate that up to date generate code is checked in. This
job should run `go generate` and fail on a diff.
- `vulncheck`: **EDIT: this is covered by CodeQL** the Go team is maintaining [`govulncheck`](https://go.dev/blog/vuln), a tool to recursively
analyzing all function calls in Go code and spot vulnerabilities on the call
stack.
## Kubernetes manifests / Helm charts
We have [recently separated](https://github.com/actions/actions-runner-controller/commit/bd9f32e3540663360cf47f04acad26e6010f772e)
Helm chart validation and we validate up-to-dateness of manifests as part of `Go
/ test`.
## End to end tests
These tests are giving us really good coverage and should be one of the main
actors when it comes to trusting our releases. Two improvements that could be
done here are:
- renaming the workflow to `GHA E2E`: since renaming our resources the `gha`
prefix has been used to identify things related to the mode GitHub supports
and these jobs strictly validate the GitHub mode _only_. Having a shorter name
allows for more readability of the various scenarios (e.g. `GHA E2E /
single-namespace-setup`).
- the test currently monitors and validates the number of pods spawning during
the workflow but not the outcome of the workflow. While not necessary to look
at pods specifics, we should at least guarantee that the workflow can
successfully conclude.

View File

@@ -86,4 +86,4 @@ Or for example if they're having problems specifically with runners:
This way users don't have to understand ARC moving parts but we still have a This way users don't have to understand ARC moving parts but we still have a
way to target them specifically if we need to. way to target them specifically if we need to.
[^1]: [ADR 2022-12-05](2022-12-05-adding-labels-k8s-resources.md) [^1]: Supersedes [ADR 2022-12-05](2022-12-05-adding-labels-k8s-resources.md)

View File

@@ -1,7 +1,5 @@
# Autoscaling Runner Scale Sets mode # Autoscaling Runner Scale Sets mode
**⚠️ This mode is currently only available for a limited number of organizations.**
This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure. This new autoscaling mode brings numerous enhancements (described in the following sections) that will make your experience more reliable and secure.
## How it works ## How it works
@@ -157,10 +155,12 @@ You can check the logs of the controller pod using the following command:
```bash ```bash
# Controller logs # Controller logs
$ kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-controller kubectl logs -n "${NAMESPACE}" -l app.kubernetes.io/name=gha-runner-scale-set-controller
```
```bash
# Runner set listener logs # Runner set listener logs
kubectl logs -n "${NAMESPACE}" -l auto-scaling-runner-set-namespace=arc-systems -l auto-scaling-runner-set-name=arc-runner-set kubectl logs -n "${NAMESPACE}" -l actions.github.com/scale-set-namespace=arc-systems -l actions.github.com/scale-set-name=arc-runner-set
``` ```
### Naming error: `Name must have up to characters` ### Naming error: `Name must have up to characters`
@@ -181,6 +181,42 @@ Error: INSTALLATION FAILED: execution error at (gha-runner-scale-set/templates/a
Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate. Verify that the secret you provided is correct and that the `githubConfigUrl` you provided is accurate.
### Access to the path `/home/runner/_work/_tool` is denied error
You might see this error if you're using kubernetes mode with persistent volumes. This is because the runner container is running with a non-root user and is causing a permissions mismatch with the mounted volume.
To fix this, you can either:
1. Use a volume type that supports `securityContext.fsGroup` (`hostPath` volumes don't support it, `local` volumes do as well as other types). Update the `fsGroup` of your runner pod to match the GID of the runner. You can do that by updating the `gha-runner-scale-set` helm chart values to include the following:
```yaml
spec:
securityContext:
fsGroup: 123
containers:
- name: runner
image: ghcr.io/actions/actions-runner:<VERSION> # Replace <VERSION> with the version you want to use
command: ["/home/runner/run.sh"]
```
1. If updating the `securityContext` of your runner pod is not a viable solution, you can workaround the issue by using `initContainers` to change the mounted volume's ownership, as follows:
```yaml
template:
spec:
initContainers:
- name: kube-init
image: ghcr.io/actions/actions-runner:latest
command: ["sudo", "chown", "-R", "1001:123", "/home/runner/_work"]
volumeMounts:
- name: work
mountPath: /home/runner/_work
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
```
## Changelog ## Changelog
### v0.3.0 ### v0.3.0
@@ -207,56 +243,3 @@ Verify that the secret you provided is correct and that the `githubConfigUrl` yo
1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223) 1. Fixed a bug that was preventing runner scale from being removed from the backend when they were deleted from the cluster [#2255](https://github.com/actions/actions-runner-controller/pull/2255) [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222) 1. Fixed bugs with the helm chart definitions preventing certain values from being set [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216) 1. Fixed a bug that prevented the configuration of a runner group for a runner scale set [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
#### Log
- [1c7b7f4](https://github.com/actions/actions-runner-controller/commit/1c7b7f4) Bump arc-2 chart version and prepare 0.2.0 release [#2313](https://github.com/actions/actions-runner-controller/pull/2313)
- [73e22a1](https://github.com/actions/actions-runner-controller/commit/73e22a1) Disable metrics serving in proxy tests [#2307](https://github.com/actions/actions-runner-controller/pull/2307)
- [9b44f00](https://github.com/actions/actions-runner-controller/commit/9b44f00) Documentation corrections [#2116](https://github.com/actions/actions-runner-controller/pull/2116)
- [6b4250c](https://github.com/actions/actions-runner-controller/commit/6b4250c) Add support for proxy [#2286](https://github.com/actions/actions-runner-controller/pull/2286)
- [ced8822](https://github.com/actions/actions-runner-controller/commit/ced8822) Resolves the erroneous webhook scale down due to check runs [#2119](https://github.com/actions/actions-runner-controller/pull/2119)
- [44c06c2](https://github.com/actions/actions-runner-controller/commit/44c06c2) fix: case-insensitive webhook label matching [#2302](https://github.com/actions/actions-runner-controller/pull/2302)
- [4103fe3](https://github.com/actions/actions-runner-controller/commit/4103fe3) Use DOCKER_IMAGE_NAME instead of NAME to avoid conflict. [#2303](https://github.com/actions/actions-runner-controller/pull/2303)
- [a44fe04](https://github.com/actions/actions-runner-controller/commit/a44fe04) Fix manager crashloopback for ARC deployments without scaleset-related controllers [#2293](https://github.com/actions/actions-runner-controller/pull/2293)
- [274d0c8](https://github.com/actions/actions-runner-controller/commit/274d0c8) Added ability to configure log level from chart values [#2252](https://github.com/actions/actions-runner-controller/pull/2252)
- [256e08e](https://github.com/actions/actions-runner-controller/commit/256e08e) Ask runner to wait for docker daemon from DinD. [#2292](https://github.com/actions/actions-runner-controller/pull/2292)
- [f677fd5](https://github.com/actions/actions-runner-controller/commit/f677fd5) doc: Fix chart name for helm commands in docs [#2287](https://github.com/actions/actions-runner-controller/pull/2287)
- [d962714](https://github.com/actions/actions-runner-controller/commit/d962714) Fix helm chart when containerMode.type=dind. [#2291](https://github.com/actions/actions-runner-controller/pull/2291)
- [3886f28](https://github.com/actions/actions-runner-controller/commit/3886f28) Add EKS test environment Terraform templates [#2290](https://github.com/actions/actions-runner-controller/pull/2290)
- [dab9004](https://github.com/actions/actions-runner-controller/commit/dab9004) Added workflow to be triggered via rest api dispatch in e2e test [#2283](https://github.com/actions/actions-runner-controller/pull/2283)
- [dd8ec1a](https://github.com/actions/actions-runner-controller/commit/dd8ec1a) Add testserver package [#2281](https://github.com/actions/actions-runner-controller/pull/2281)
- [8e52a6d](https://github.com/actions/actions-runner-controller/commit/8e52a6d) EphemeralRunner: On cleanup, if pod is pending, delete from service [#2255](https://github.com/actions/actions-runner-controller/pull/2255)
- [9990243](https://github.com/actions/actions-runner-controller/commit/9990243) Early return if finalizer does not exist to make it more readable [#2262](https://github.com/actions/actions-runner-controller/pull/2262)
- [0891981](https://github.com/actions/actions-runner-controller/commit/0891981) Port ADRs from internal repo [#2267](https://github.com/actions/actions-runner-controller/pull/2267)
- [facae69](https://github.com/actions/actions-runner-controller/commit/facae69) Remove un-required permissions for the manager-role of the new `AutoScalingRunnerSet` [#2260](https://github.com/actions/actions-runner-controller/pull/2260)
- [8f62e35](https://github.com/actions/actions-runner-controller/commit/8f62e35) Add options to multi client [#2257](https://github.com/actions/actions-runner-controller/pull/2257)
- [55951c2](https://github.com/actions/actions-runner-controller/commit/55951c2) Add new workflow to automate runner updates [#2247](https://github.com/actions/actions-runner-controller/pull/2247)
- [c4297d2](https://github.com/actions/actions-runner-controller/commit/c4297d2) Avoid deleting scale set if annotation is not parsable or if it does not exist [#2239](https://github.com/actions/actions-runner-controller/pull/2239)
- [0774f06](https://github.com/actions/actions-runner-controller/commit/0774f06) ADR: automate runner updates [#2244](https://github.com/actions/actions-runner-controller/pull/2244)
- [92ab11b](https://github.com/actions/actions-runner-controller/commit/92ab11b) Use UUID v5 for client identifiers [#2241](https://github.com/actions/actions-runner-controller/pull/2241)
- [7414dc6](https://github.com/actions/actions-runner-controller/commit/7414dc6) Add Identifier to actions.Client [#2237](https://github.com/actions/actions-runner-controller/pull/2237)
- [34efb9d](https://github.com/actions/actions-runner-controller/commit/34efb9d) Add documentation to update ARC with prometheus CRDs needed by actions metrics server [#2209](https://github.com/actions/actions-runner-controller/pull/2209)
- [fbad561](https://github.com/actions/actions-runner-controller/commit/fbad561) Allow provide pre-defined kubernetes secret when helm-install AutoScalingRunnerSet [#2234](https://github.com/actions/actions-runner-controller/pull/2234)
- [a5cef7e](https://github.com/actions/actions-runner-controller/commit/a5cef7e) Resolve CI break due to bad merge. [#2236](https://github.com/actions/actions-runner-controller/pull/2236)
- [1f4fe46](https://github.com/actions/actions-runner-controller/commit/1f4fe46) Delete RunnerScaleSet on service when AutoScalingRunnerSet is deleted. [#2223](https://github.com/actions/actions-runner-controller/pull/2223)
- [067686c](https://github.com/actions/actions-runner-controller/commit/067686c) Fix typos and markdown structure in troubleshooting guide [#2148](https://github.com/actions/actions-runner-controller/pull/2148)
- [df12e00](https://github.com/actions/actions-runner-controller/commit/df12e00) Remove network requests from actions.NewClient [#2219](https://github.com/actions/actions-runner-controller/pull/2219)
- [cc26593](https://github.com/actions/actions-runner-controller/commit/cc26593) Skip CT when list-changed=false. [#2228](https://github.com/actions/actions-runner-controller/pull/2228)
- [835eac7](https://github.com/actions/actions-runner-controller/commit/835eac7) Fix helm charts when pass values file. [#2222](https://github.com/actions/actions-runner-controller/pull/2222)
- [01e9dd3](https://github.com/actions/actions-runner-controller/commit/01e9dd3) Update Validate ARC workflow to go 1.19 [#2220](https://github.com/actions/actions-runner-controller/pull/2220)
- [8038181](https://github.com/actions/actions-runner-controller/commit/8038181) Allow update runner group for AutoScalingRunnerSet [#2216](https://github.com/actions/actions-runner-controller/pull/2216)
- [219ba5b](https://github.com/actions/actions-runner-controller/commit/219ba5b) chore(deps): bump sigs.k8s.io/controller-runtime from 0.13.1 to 0.14.1 [#2132](https://github.com/actions/actions-runner-controller/pull/2132)
- [b09e3a2](https://github.com/actions/actions-runner-controller/commit/b09e3a2) Return error for non-existing runner group. [#2215](https://github.com/actions/actions-runner-controller/pull/2215)
- [7ea60e4](https://github.com/actions/actions-runner-controller/commit/7ea60e4) Fix intermittent image push failures to GHCR [#2214](https://github.com/actions/actions-runner-controller/pull/2214)
- [c8918f5](https://github.com/actions/actions-runner-controller/commit/c8918f5) Fix URL for authenticating using a GitHub app [#2206](https://github.com/actions/actions-runner-controller/pull/2206)
- [d57d17f](https://github.com/actions/actions-runner-controller/commit/d57d17f) Add support for custom CA in actions.Client [#2199](https://github.com/actions/actions-runner-controller/pull/2199)
- [6e69c75](https://github.com/actions/actions-runner-controller/commit/6e69c75) chore(deps): bump github.com/hashicorp/go-retryablehttp from 0.7.1 to 0.7.2 [#2203](https://github.com/actions/actions-runner-controller/pull/2203)
- [882bfab](https://github.com/actions/actions-runner-controller/commit/882bfab) Renaming autoScaling to autoscaling in tests matching the convention [#2201](https://github.com/actions/actions-runner-controller/pull/2201)
- [3327f62](https://github.com/actions/actions-runner-controller/commit/3327f62) Refactor actions.Client with options to help extensibility [#2193](https://github.com/actions/actions-runner-controller/pull/2193)
- [282f2dd](https://github.com/actions/actions-runner-controller/commit/282f2dd) chore(deps): bump github.com/onsi/gomega from 1.20.2 to 1.25.0 [#2169](https://github.com/actions/actions-runner-controller/pull/2169)
- [d67f808](https://github.com/actions/actions-runner-controller/commit/d67f808) Include nikola-jokic in CODEOWNERS file [#2184](https://github.com/actions/actions-runner-controller/pull/2184)
- [4932412](https://github.com/actions/actions-runner-controller/commit/4932412) Fix L0 test to make it more reliable. [#2178](https://github.com/actions/actions-runner-controller/pull/2178)
- [6da1cde](https://github.com/actions/actions-runner-controller/commit/6da1cde) Update runner version to 2.301.1 [#2182](https://github.com/actions/actions-runner-controller/pull/2182)
- [f9bae70](https://github.com/actions/actions-runner-controller/commit/f9bae70) Add distinct namespace best practice note [#2181](https://github.com/actions/actions-runner-controller/pull/2181)
- [05a3908](https://github.com/actions/actions-runner-controller/commit/05a3908) Add arc-2 quickstart guide [#2180](https://github.com/actions/actions-runner-controller/pull/2180)
- [606ed1b](https://github.com/actions/actions-runner-controller/commit/606ed1b) Add Repository information to Runner Status [#2093](https://github.com/actions/actions-runner-controller/pull/2093)

2
go.mod
View File

@@ -1,6 +1,6 @@
module github.com/actions/actions-runner-controller module github.com/actions/actions-runner-controller
go 1.19 go 1.20
require ( require (
github.com/bradleyfalzon/ghinstallation/v2 v2.1.0 github.com/bradleyfalzon/ghinstallation/v2 v2.1.0

View File

@@ -139,8 +139,12 @@ RUN export SKIP_IPTABLES=1 \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& curl -fLo /home/runner/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ && mkdir -p /home/runner/.docker/cli-plugins \
&& chmod +x /home/runner/bin/docker-compose && curl -fLo /home/runner/.docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /home/runner/.docker/cli-plugins/docker-compose \
&& ln -s /home/runner/.docker/cli-plugins/docker-compose /home/runner/bin/docker-compose \
&& which docker-compose \
&& docker compose version
ENTRYPOINT ["/bin/bash", "-c"] ENTRYPOINT ["/bin/bash", "-c"]
CMD ["entrypoint-dind-rootless.sh"] CMD ["entrypoint-dind-rootless.sh"]

View File

@@ -116,9 +116,12 @@ RUN export SKIP_IPTABLES=1 \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& mkdir -p /home/runner/bin \ && mkdir -p /home/runner/.docker/cli-plugins \
&& curl -fLo /home/runner/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-Linux-${ARCH} \ && curl -fLo /home/runner/.docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /home/runner/bin/docker-compose && chmod +x /home/runner/.docker/cli-plugins/docker-compose \
&& ln -s /home/runner/.docker/cli-plugins/docker-compose /home/runner/bin/docker-compose \
&& which docker-compose \
&& docker compose version
ENTRYPOINT ["/bin/bash", "-c"] ENTRYPOINT ["/bin/bash", "-c"]
CMD ["entrypoint-dind-rootless.sh"] CMD ["entrypoint-dind-rootless.sh"]

View File

@@ -106,8 +106,12 @@ RUN set -vx; \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& curl -fLo /usr/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ && mkdir -p /usr/libexec/docker/cli-plugins \
&& chmod +x /usr/bin/docker-compose && curl -fLo /usr/libexec/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /usr/libexec/docker/cli-plugins/docker-compose \
&& ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose \
&& which docker-compose \
&& docker compose version
# We place the scripts in `/usr/bin` so that users who extend this image can # We place the scripts in `/usr/bin` so that users who extend this image can
# override them with scripts of the same name placed in `/usr/local/bin`. # override them with scripts of the same name placed in `/usr/local/bin`.

View File

@@ -82,8 +82,12 @@ RUN set -vx; \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& curl -fLo /usr/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ && mkdir -p /usr/libexec/docker/cli-plugins \
&& chmod +x /usr/bin/docker-compose && curl -fLo /usr/libexec/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /usr/libexec/docker/cli-plugins/docker-compose \
&& ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose \
&& which docker-compose \
&& docker compose version
# We place the scripts in `/usr/bin` so that users who extend this image can # We place the scripts in `/usr/bin` so that users who extend this image can
# override them with scripts of the same name placed in `/usr/local/bin`. # override them with scripts of the same name placed in `/usr/local/bin`.

View File

@@ -103,8 +103,12 @@ RUN set -vx; \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& curl -fLo /usr/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ && mkdir -p /usr/libexec/docker/cli-plugins \
&& chmod +x /usr/bin/docker-compose && curl -fLo /usr/libexec/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /usr/libexec/docker/cli-plugins/docker-compose \
&& ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose \
&& which docker-compose \
&& docker compose version
# We place the scripts in `/usr/bin` so that users who extend this image can # We place the scripts in `/usr/bin` so that users who extend this image can
# override them with scripts of the same name placed in `/usr/local/bin`. # override them with scripts of the same name placed in `/usr/local/bin`.

View File

@@ -80,8 +80,12 @@ RUN set -vx; \
RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \ RUN export ARCH=$(echo ${TARGETPLATFORM} | cut -d / -f2) \
&& if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \ && if [ "$ARCH" = "arm64" ]; then export ARCH=aarch64 ; fi \
&& if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \ && if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "i386" ]; then export ARCH=x86_64 ; fi \
&& curl -fLo /usr/bin/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \ && mkdir -p /usr/libexec/docker/cli-plugins \
&& chmod +x /usr/bin/docker-compose && curl -fLo /usr/libexec/docker/cli-plugins/docker-compose https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${ARCH} \
&& chmod +x /usr/libexec/docker/cli-plugins/docker-compose \
&& ln -s /usr/libexec/docker/cli-plugins/docker-compose /usr/bin/docker-compose \
&& which docker-compose \
&& docker compose version
# We place the scripts in `/usr/bin` so that users who extend this image can # We place the scripts in `/usr/bin` so that users who extend this image can
# override them with scripts of the same name placed in `/usr/local/bin`. # override them with scripts of the same name placed in `/usr/local/bin`.

View File

@@ -101,6 +101,7 @@ func TestE2E(t *testing.T) {
label string label string
controller, controllerVer string controller, controllerVer string
chart, chartVer string chart, chartVer string
opt []InstallARCOption
}{ }{
{ {
label: "stable", label: "stable",
@@ -117,6 +118,12 @@ func TestE2E(t *testing.T) {
controllerVer: vars.controllerImageTag, controllerVer: vars.controllerImageTag,
chart: "", chart: "",
chartVer: "", chartVer: "",
opt: []InstallARCOption{
func(ia *InstallARCConfig) {
ia.GithubWebhookServerEnvName = "FOO"
ia.GithubWebhookServerEnvValue = "foo"
},
},
}, },
} }
@@ -186,7 +193,7 @@ func TestE2E(t *testing.T) {
for i, v := range testedVersions { for i, v := range testedVersions {
t.Run("install actions-runner-controller "+v.label, func(t *testing.T) { t.Run("install actions-runner-controller "+v.label, func(t *testing.T) {
t.Logf("Using controller %s:%s and chart %s:%s", v.controller, v.controllerVer, v.chart, v.chartVer) t.Logf("Using controller %s:%s and chart %s:%s", v.controller, v.controllerVer, v.chart, v.chartVer)
env.installActionsRunnerController(t, v.controller, v.controllerVer, testID, v.chart, v.chartVer) env.installActionsRunnerController(t, v.controller, v.controllerVer, testID, v.chart, v.chartVer, v.opt...)
}) })
if t.Failed() { if t.Failed() {
@@ -300,7 +307,7 @@ func TestE2E(t *testing.T) {
for i, v := range testedVersions { for i, v := range testedVersions {
t.Run("install actions-runner-controller "+v.label, func(t *testing.T) { t.Run("install actions-runner-controller "+v.label, func(t *testing.T) {
t.Logf("Using controller %s:%s and chart %s:%s", v.controller, v.controllerVer, v.chart, v.chartVer) t.Logf("Using controller %s:%s and chart %s:%s", v.controller, v.controllerVer, v.chart, v.chartVer)
env.installActionsRunnerController(t, v.controller, v.controllerVer, testID, v.chart, v.chartVer) env.installActionsRunnerController(t, v.controller, v.controllerVer, testID, v.chart, v.chartVer, v.opt...)
}) })
if t.Failed() { if t.Failed() {
@@ -413,8 +420,10 @@ type env struct {
runnerNamespace string runnerNamespace string
logFormat string logFormat string
remoteKubeconfig string remoteKubeconfig string
admissionWebhooksTimeout string
imagePullSecretName string imagePullSecretName string
imagePullPolicy string imagePullPolicy string
watchNamespace string
vars vars vars vars
VerifyTimeout time.Duration VerifyTimeout time.Duration
@@ -547,6 +556,7 @@ func initTestEnv(t *testing.T, k8sMinorVer string, vars vars) *env {
e.runnerNamespace = testing.Getenv(t, "TEST_RUNNER_NAMESPACE", "default") e.runnerNamespace = testing.Getenv(t, "TEST_RUNNER_NAMESPACE", "default")
e.logFormat = testing.Getenv(t, "ARC_E2E_LOG_FORMAT", "") e.logFormat = testing.Getenv(t, "ARC_E2E_LOG_FORMAT", "")
e.remoteKubeconfig = testing.Getenv(t, "ARC_E2E_REMOTE_KUBECONFIG", "") e.remoteKubeconfig = testing.Getenv(t, "ARC_E2E_REMOTE_KUBECONFIG", "")
e.admissionWebhooksTimeout = testing.Getenv(t, "ARC_E2E_ADMISSION_WEBHOOKS_TIMEOUT", "")
e.imagePullSecretName = testing.Getenv(t, "ARC_E2E_IMAGE_PULL_SECRET_NAME", "") e.imagePullSecretName = testing.Getenv(t, "ARC_E2E_IMAGE_PULL_SECRET_NAME", "")
e.vars = vars e.vars = vars
@@ -556,6 +566,8 @@ func initTestEnv(t *testing.T, k8sMinorVer string, vars vars) *env {
e.imagePullPolicy = "IfNotPresent" e.imagePullPolicy = "IfNotPresent"
} }
e.watchNamespace = testing.Getenv(t, "TEST_WATCH_NAMESPACE", "")
if e.remoteKubeconfig == "" { if e.remoteKubeconfig == "" {
e.Kind = testing.StartKind(t, k8sMinorVer, testing.Preload(images...)) e.Kind = testing.StartKind(t, k8sMinorVer, testing.Preload(images...))
e.Env.Kubeconfig = e.Kind.Kubeconfig() e.Env.Kubeconfig = e.Kind.Kubeconfig()
@@ -706,9 +718,20 @@ func (e *env) installCertManager(t *testing.T) {
e.KubectlWaitUntilDeployAvailable(t, "cert-manager", waitCfg.WithTimeout(60*time.Second)) e.KubectlWaitUntilDeployAvailable(t, "cert-manager", waitCfg.WithTimeout(60*time.Second))
} }
func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, chart, chartVer string) { type InstallARCConfig struct {
GithubWebhookServerEnvName, GithubWebhookServerEnvValue string
}
type InstallARCOption func(*InstallARCConfig)
func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, chart, chartVer string, opts ...InstallARCOption) {
t.Helper() t.Helper()
var c InstallARCConfig
for _, opt := range opts {
opt(&c)
}
e.createControllerNamespaceAndServiceAccount(t) e.createControllerNamespaceAndServiceAccount(t)
scriptEnv := []string{ scriptEnv := []string{
@@ -724,8 +747,10 @@ func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, ch
"TEST_ID=" + testID, "TEST_ID=" + testID,
"NAME=" + repo, "NAME=" + repo,
"VERSION=" + tag, "VERSION=" + tag,
"ADMISSION_WEBHOOKS_TIMEOUT=" + e.admissionWebhooksTimeout,
"IMAGE_PULL_SECRET=" + e.imagePullSecretName, "IMAGE_PULL_SECRET=" + e.imagePullSecretName,
"IMAGE_PULL_POLICY=" + e.imagePullPolicy, "IMAGE_PULL_POLICY=" + e.imagePullPolicy,
"WATCH_NAMESPACE=" + e.watchNamespace,
} }
if e.useApp { if e.useApp {
@@ -748,6 +773,11 @@ func (e *env) installActionsRunnerController(t *testing.T, repo, tag, testID, ch
) )
} }
varEnv = append(varEnv,
"GITHUB_WEBHOOK_SERVER_ENV_NAME="+c.GithubWebhookServerEnvName,
"GITHUB_WEBHOOK_SERVER_ENV_VALUE="+c.GithubWebhookServerEnvValue,
)
scriptEnv = append(scriptEnv, varEnv...) scriptEnv = append(scriptEnv, varEnv...)
scriptEnv = append(scriptEnv, e.vars.commonScriptEnv...) scriptEnv = append(scriptEnv, e.vars.commonScriptEnv...)
@@ -1051,6 +1081,17 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
}, },
}, },
) )
// Ensure both the alias and the full command work after
// https://github.com/actions/actions-runner-controller/pull/2326
steps = append(steps,
testing.Step{
Run: "docker-compose version",
},
testing.Step{
Run: "docker compose version",
},
)
} }
steps = append(steps, steps = append(steps,
@@ -1066,7 +1107,6 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
if !kubernetesContainerMode { if !kubernetesContainerMode {
setupBuildXActionWith := &testing.With{ setupBuildXActionWith := &testing.With{
BuildkitdFlags: "--debug", BuildkitdFlags: "--debug",
Endpoint: "mycontext",
// As the consequence of setting `install: false`, it doesn't install buildx as an alias to `docker build` // As the consequence of setting `install: false`, it doesn't install buildx as an alias to `docker build`
// so we need to use `docker buildx build` in the next step // so we need to use `docker buildx build` in the next step
Install: false, Install: false,
@@ -1092,16 +1132,24 @@ func installActionsWorkflow(t *testing.T, testName, runnerLabel, testResultCMNam
setupBuildXActionWith.Driver = "docker" setupBuildXActionWith.Driver = "docker"
dockerfile = "Dockerfile.nocache" dockerfile = "Dockerfile.nocache"
} }
steps = append(steps,
testing.Step{ useCustomDockerContext := os.Getenv("ARC_E2E_USE_CUSTOM_DOCKER_CONTEXT") != ""
if useCustomDockerContext {
setupBuildXActionWith.Endpoint = "mycontext"
steps = append(steps, testing.Step{
// https://github.com/docker/buildx/issues/413#issuecomment-710660155 // https://github.com/docker/buildx/issues/413#issuecomment-710660155
// To prevent setup-buildx-action from failing with: // To prevent setup-buildx-action from failing with:
// error: could not create a builder instance with TLS data loaded from environment. Please use `docker context create <context-name>` to create a context for current environment and then create a builder instance with `docker buildx create <context-name>` // error: could not create a builder instance with TLS data loaded from environment. Please use `docker context create <context-name>` to create a context for current environment and then create a builder instance with `docker buildx create <context-name>`
Run: "docker context create mycontext", Run: "docker context create mycontext",
}, },
testing.Step{ testing.Step{
Run: "docker context use mycontext", Run: "docker context use mycontext",
}, },
)
}
steps = append(steps,
testing.Step{ testing.Step{
Name: "Set up Docker Buildx", Name: "Set up Docker Buildx",
Uses: "docker/setup-buildx-action@v1", Uses: "docker/setup-buildx-action@v1",