Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9219cf4
init runner-org-sync service
mirkoSekulic May 12, 2026
fa4ac16
fix gitea api to be in sync with 1.26 version
mirkoSekulic May 12, 2026
c0fb114
remove replica from configmap
mirkoSekulic May 12, 2026
c45171c
install keda in studio cluster
mirkoSekulic May 12, 2026
2a7323e
use job instead of deployment for runners
mirkoSekulic May 13, 2026
3d8dbb1
manage keda secret
mirkoSekulic May 13, 2026
65d0ce9
fix the readme
mirkoSekulic May 13, 2026
0db8e57
trigger scaling
mirkoSekulic May 13, 2026
7679ab7
add a deploy workflow
mirkoSekulic May 13, 2026
f32d622
wire kustomize files corerctly
mirkoSekulic May 13, 2026
5d9656f
fix chart
mirkoSekulic May 13, 2026
68ee589
deploy sync to staging
mirkoSekulic May 13, 2026
67697e7
keda namespace fix
mirkoSekulic May 13, 2026
1d8cd4e
fix keda
mirkoSekulic May 13, 2026
0a4d99c
witch to HTTPS chart repo, OCI path was 403
mirkoSekulic May 13, 2026
4cd97d7
fix githubAPIURL
mirkoSekulic May 13, 2026
73f156d
match label host for keda
mirkoSekulic May 13, 2026
66a5e76
avoid idle runners after 30 minutes
mirkoSekulic May 13, 2026
3406029
added egress from runner-sync to otel export
mirkoSekulic May 13, 2026
163f6b6
get secret from kv refactor
mirkoSekulic May 13, 2026
6e342d0
move keda secret apply
mirkoSekulic May 13, 2026
9c7cb70
refactor telemetry
mirkoSekulic May 13, 2026
6f0285b
rop dead helpers, fail-fast on unauthorized mint
mirkoSekulic May 13, 2026
ff9e6bd
remove unused duration metrics
mirkoSekulic May 13, 2026
eb7a03a
trimspace fields and limit reader
mirkoSekulic May 13, 2026
53d1879
apply KEDA PAT secret on reconcile failure
mirkoSekulic May 18, 2026
781d11c
restore labels on unchanged k8s objects
mirkoSekulic May 18, 2026
4e32b8a
validate runner secrets before projection
mirkoSekulic May 18, 2026
0b69c8e
remove unused secret existence helper
mirkoSekulic May 18, 2026
105e918
add .lscache in gitignore
mirkoSekulic May 19, 2026
bf0cc18
use config map in chart instead of static
mirkoSekulic May 21, 2026
22cd2a4
cleanup syncroot
mirkoSekulic May 21, 2026
d56032c
support legacy secrets
mirkoSekulic May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy-gitea-runners.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ jobs:
environment: ${{ matrix.environment }}
config-chart-name: gitea-org-runner-config
artifact-name: gitea-runners
helm-set-arguments: chartVersion=0.1.0+${{ needs.determine-tag.outputs.tag }},imageTag=${{ needs.determine-tag.outputs.tag }},releaseName=gitea-runners,environment=${{ matrix.environment }}
helm-set-arguments: chartVersion=0.1.0+${{ needs.determine-tag.outputs.tag }},imageTag=${{ needs.determine-tag.outputs.tag }},releaseName=gitea-runners
trace-workflow: false
trace-team-name: 'team-studio'
secrets:
Expand Down
115 changes: 115 additions & 0 deletions .github/workflows/deploy-runner-org-sync.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
name: Deploy Runner Org Sync
on:
push:
branches: [main, feat/runners-autoscaling]
paths:
- 'src/runner-org-sync/**'
- '.github/workflows/deploy-runner-org-sync.yaml'
workflow_dispatch:
inputs:
environments:
description: 'Environments to deploy to. Multiple environments can be specified by separating them with a comma.'
required: false
default: 'dev'

permissions:
id-token: write
contents: read

jobs:
construct-environments-array:
uses: ./.github/workflows/template-studio-construct-environments.yaml
with:
# Push to the autoscaling feature branch deploys to staging only.
# Push to main and manual dispatches fall through to github.event.inputs
# (which is empty on push to main → template applies its own defaults,
# and on dispatch → the value the user typed in the form).
inputs: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/feat/runners-autoscaling') && '{"environments":"staging"}' || toJSON(github.event.inputs) }}

push-artifact:
name: Push runner-org-sync as OCI artifact
runs-on: ubuntu-latest
environment: dev
env:
REGISTRY_NAME: altinntjenestercontainerregistry
outputs:
CONFIG_REPO: ${{ steps.vars.outputs.config-repo }}
defaults:
run:
working-directory: src/runner-org-sync
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

- name: Set vars
id: vars
run: |
SHA="${GITHUB_SHA::10}"
echo "short-sha=$SHA" >> "$GITHUB_OUTPUT"
echo "image-repo=altinntjenestercontainerregistry.azurecr.io/altinn-studio/runner-org-sync:${SHA}" >> "$GITHUB_OUTPUT"
echo "config-repo=altinntjenestercontainerregistry.azurecr.io/altinn-studio/configs/runner-org-sync-repo:${SHA}" >> "$GITHUB_OUTPUT"

- name: az login
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_FC }}
tenant-id: ${{ secrets.AZURE_TENANT_ID_FC }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_FC }}

- name: az acr login
run: az acr login --name ${{ env.REGISTRY_NAME }}

- name: flux install
uses: fluxcd/flux2/action@bfa461ed2153ae5e0cca6bce08e0845268fb3088 # v2.8.2

- name: docker build
run: docker build -t ${{ steps.vars.outputs.image-repo }} -f Dockerfile .

- name: push image
run: docker push ${{ steps.vars.outputs.image-repo }}

- name: patch base with image tag
working-directory: src/runner-org-sync/infra/kustomize/base
run: |
export IMAGE="${{ steps.vars.outputs.image-repo }}"
export IMAGE_TAG="${{ steps.vars.outputs.short-sha }}"
yq -i '.metadata.annotations["altinn.studio/image"] = env(IMAGE)' cronjob.yaml
yq -i '.metadata.annotations["altinn.studio/image-tag"] = env(IMAGE_TAG)' cronjob.yaml

- name: push artifact
working-directory: src/runner-org-sync/infra/kustomize
run: |
flux push artifact oci://${{ steps.vars.outputs.config-repo }} \
--provider=azure \
--reproducible \
--path="." \
--source="$(git config --get remote.origin.url)" \
--revision="$(git branch --show-current)/$(git rev-parse HEAD)"

tag:
name: Tag artifact
needs: [push-artifact, construct-environments-array]
runs-on: ubuntu-latest
environment: ${{ matrix.environment }}
env:
REGISTRY_NAME: altinntjenestercontainerregistry
strategy:
matrix:
include: ${{ fromJSON(needs.construct-environments-array.outputs.result) }}
steps:
- name: az login
uses: azure/login@a457da9ea143d694b1b9c7c869ebb04ebe844ef5 # v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID_FC }}
tenant-id: ${{ secrets.AZURE_TENANT_ID_FC }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID_FC }}

- name: az acr login
run: az acr login --name ${{ env.REGISTRY_NAME }}

- name: flux install
uses: fluxcd/flux2/action@bfa461ed2153ae5e0cca6bce08e0845268fb3088 # v2.8.2

- name: tag artifact
run: |
flux tag artifact oci://${{ needs.push-artifact.outputs.CONFIG_REPO }} \
--tag ${{ matrix.environment }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ ipch/
*.opensdf
*.sdf
*.cachefile
*.lscache

# Visual Studio profiler
*.psess
Expand Down
51 changes: 33 additions & 18 deletions charts/gitea-org-runner-config/templates/helm-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ spec:
kind: HelmRepository
name: studio-charts
namespace: default
valuesFrom:
# runner-org-sync writes this ConfigMap in studio-runners. The
# runners.yaml key contains root Helm values with the dynamic runners list.
- kind: ConfigMap
name: runner-org-list
valuesKey: runners.yaml
values:
image:
tag: "{{ .Values.imageTag }}"
Expand All @@ -32,6 +38,32 @@ spec:
enabled: {{ .Values.dockerInDocker.enabled }}
shareWorkspace:
enabled: {{ .Values.shareWorkspace.enabled }}

# Chart-level Gitea config: the workload chart synthesises each runner
# pod's GITEA_INSTANCE_URL / RUNNER_LABELS env vars from here. The KEDA
# github-runner scaler uses apiUrl to poll org queue depth.
gitea:
instanceUrl: "{{ .Values.giteaInstanceUrl }}"
apiUrl: "{{ .Values.giteaInstanceUrl }}/api/v1"
# The runner advertises `ubuntu-latest:host` to act_runner (`:host`
# selects run-on-host mode); the KEDA scaler filters by `ubuntu-latest`
# only, matching what workflows put in `runs-on:`.
runnerLabels: "ubuntu-latest:host"
scalerLabels: "ubuntu-latest"

# KEDA wiring: name of the TriggerAuthentication ScaledJobs reference.
# The CR is materialised by runner-org-sync's deploy in the same
# namespace (src/runner-org-sync/infra/kustomize/triggerauthentication.yaml).
keda:
authenticationRef:
name: keda-gitea-auth

# Per-org concurrency caps. Default applies to every org; overrides
# keyed by org name take precedence.
maxConcurrentDefault: {{ .Values.maxConcurrentDefault | default 2 }}
maxConcurrentOverrides:
{{- toYaml (.Values.maxConcurrentOverrides | default dict) | nindent 6 }}

resources:
requests:
cpu: 500m
Expand All @@ -41,24 +73,7 @@ spec:
cpu: "2"
memory: 2Gi
ephemeral-storage: 20Gi
runners:
{{- $giteaUrl := .Values.giteaInstanceUrl }}
{{- range index .Values.runners .Values.environment }}
- name: {{ .name }}
replicas: {{ .replicas }}
environmentVariables:
- name: GITEA_INSTANCE_URL
value: "{{ $giteaUrl }}"
- name: GITEA_RUNNER_EPHEMERAL
value: "1"
- name: GITEA_RUNNER_LABELS
value: "ubuntu-latest:host"
- name: GITEA_RUNNER_REGISTRATION_TOKEN
valueFrom:
secretKeyRef:
name: {{ .registrationTokenSecretName }}
key: token
{{- end }}

tolerations:
- key: "purpose"
operator: "Equal"
Expand Down
49 changes: 8 additions & 41 deletions charts/gitea-org-runner-config/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,51 +2,18 @@ chartVersion: ""
releaseName: ""
imageTag: ""
giteaInstanceUrl: "http://altinn-repositories-public.default.svc.cluster.local"
environment: "dev"

runtimeClassName: "kata-vm-isolation"
dockerInDocker:
enabled: true
shareWorkspace:
enabled: true

# Environment-specific runner configurations
# dev/staging: only ttd
# prod: ttd, brg, dsb, ssb, ksdigi, pat, dibk, skm
runners:
dev:
- name: ttd
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-ttd-secret
staging:
- name: ttd
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-ttd-secret
prod:
- name: ttd
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-ttd-secret
- name: brg
replicas: 6
registrationTokenSecretName: altinn-gitea-runner-brg-secret
- name: dsb
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-dsb-secret
- name: ssb
replicas: 5
registrationTokenSecretName: altinn-gitea-runner-ssb-secret
- name: ksdigi
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-ksdigi-secret
- name: pat
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-pat-secret
- name: dibk
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-dibk-secret
- name: skm
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-skm-secret
- name: sfvt
replicas: 1
registrationTokenSecretName: altinn-gitea-runner-sfvt-secret
# Per-org concurrency caps applied to KEDA ScaledJobs in the workload chart.
# `maxConcurrentDefault` applies to every org; `maxConcurrentOverrides` keys
# named exceptions per org. Overrides for orgs absent from the active
# environment's runners list are harmlessly ignored.
maxConcurrentDefault: 2
maxConcurrentOverrides:
brg: 6
ssb: 5
Loading
Loading