add helm chart and workflow to publish

This commit is contained in:
2026-01-13 21:17:14 +08:00
parent 6298940adb
commit 6a2a0f7683
9 changed files with 588 additions and 5 deletions

View File

@@ -1,8 +1,9 @@
name: Build and Push Docker Image name: Build and Push
on: on:
push: push:
branches: ["main", "master"] branches: ["main", "master"]
tags: ["v*"]
pull_request: pull_request:
branches: ["main", "master"] branches: ["main", "master"]
workflow_dispatch: workflow_dispatch:
@@ -12,7 +13,7 @@ env:
IMAGE_NAME: ${{ github.repository }} IMAGE_NAME: ${{ github.repository }}
jobs: jobs:
build: build-image:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: read contents: read
@@ -22,6 +23,9 @@ jobs:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@@ -38,14 +42,63 @@ jobs:
with: with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: | tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=ref,event=branch type=ref,event=branch
type=sha type=sha,prefix=sha-
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: .
platforms: linux/amd64 platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }} push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
publish-chart:
needs: build-image
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Helm
uses: azure/setup-helm@v4
- name: Login to GHCR
run: echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ${{ env.REGISTRY }} --username ${{ github.actor }} --password-stdin
- name: Get Version
id: get_version
run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV
- name: Update Chart Version and Image Tag
run: |
CHART_PATH="charts/gitea-runner-operator"
# Update version (stripping v)
sed -i "s/^version:.*/version: ${{ env.VERSION }}/" $CHART_PATH/Chart.yaml
# Update appVersion (keeping v, matches docker tag)
sed -i "s/^appVersion:.*/appVersion: \"v${{ env.VERSION }}\"/" $CHART_PATH/Chart.yaml
# Update image tag in values.yaml to match the release
# Replaces 'tag: "latest"' with 'tag: "v1.2.3"'
sed -i 's/tag: "latest"/tag: "v${{ env.VERSION }}"/' $CHART_PATH/values.yaml
- name: Package Helm Chart
run: |
helm package charts/gitea-runner-operator
- name: Push Helm Chart
run: |
# Push to oci://ghcr.io/<owner>/charts
# The chart will be accessible as oci://ghcr.io/<owner>/charts/gitea-runner-operator
OWNER=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
helm push gitea-runner-operator-${{ env.VERSION }}.tgz oci://${{ env.REGISTRY }}/${OWNER}/charts

View File

@@ -16,7 +16,14 @@ A Kubernetes Operator to manage ephemeral Gitea Act runners. This operator autom
## Installation (Helm Chart) ## Installation (Helm Chart)
### Incoming You can install the operator using the provided Helm chart.
```bash
# Install the chart
helm upgrade --install gitea-runner-operator ./charts/gitea-runner-operator \
--namespace gitea-runner-operator-system \
--create-namespace
```
## Installation (Manual) ## Installation (Manual)

View File

@@ -0,0 +1,17 @@
apiVersion: v2
name: gitea-runner-operator
description: A Helm chart for managing Gitea Runner Operator
type: application
version: 0.1.0
appVersion: "0.0.1"
keywords:
- gitea
- runner
- operator
- ci
- cd
home: https://github.com/bapung/gitea-runner-operator
sources:
- https://github.com/bapung/gitea-runner-operator
maintainers:
- name: bapung

View File

@@ -0,0 +1,37 @@
Gitea Runner Operator has been installed!
1. Check if the controller is running:
kubectl get pods -n {{ .Release.Namespace }} -l control-plane=controller-manager
2. Create a Secret with your Gitea credentials:
kubectl create secret generic gitea-runner-secret \
--namespace {{ .Release.Namespace }} \
--from-literal=registrationToken=<YOUR_TOKEN> \
--from-literal=authToken=<YOUR_API_TOKEN>
3. Create a RunnerGroup instance to spawn runners:
apiVersion: gitea.bpg.pw/v1alpha1
kind: RunnerGroup
metadata:
name: example-runner
namespace: {{ .Release.Namespace }}
spec:
scope: repo
org: your-org
repo: your-repo
giteaURL: https://gitea.example.com
maxActiveRunners: 2
labels: ["ubuntu-latest"]
registrationToken:
secretRef:
name: gitea-runner-secret
key: registrationToken
authToken:
secretRef:
name: gitea-runner-secret
key: authToken
For more details, please visit: https://github.com/bapung/gitea-runner-operator

View File

@@ -0,0 +1,63 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "gitea-runner-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "gitea-runner-operator.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "gitea-runner-operator.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "gitea-runner-operator.labels" -}}
helm.sh/chart: {{ include "gitea-runner-operator.chart" . }}
{{ include "gitea-runner-operator.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "gitea-runner-operator.selectorLabels" -}}
app.kubernetes.io/name: {{ include "gitea-runner-operator.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
control-plane: controller-manager
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "gitea-runner-operator.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "gitea-runner-operator.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,67 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
spec:
replicas: 1
selector:
matchLabels:
{{- include "gitea-runner-operator.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "gitea-runner-operator.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "gitea-runner-operator.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: manager
command:
- /manager
args:
- --leader-elect={{ .Values.manager.leaderElect }}
- --health-probe-bind-address={{ .Values.manager.healthProbeBindAddress }}
- --metrics-bind-address={{ .Values.manager.metricsBindAddress }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
livenessProbe:
httpGet:
path: /healthz
port: {{ .Values.manager.healthProbeBindAddress | trimPrefix ":" }}
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: {{ .Values.manager.healthProbeBindAddress | trimPrefix ":" }}
initialDelaySeconds: 5
periodSeconds: 10
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
terminationGracePeriodSeconds: 10

View File

@@ -0,0 +1,262 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "gitea-runner-operator.serviceAccountName" . }}
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- if .Values.rbac.create -}}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-leader-election-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-manager-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- batch
resources:
- jobs
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups/finalizers
verbs:
- update
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups/status
verbs:
- get
- patch
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-metrics-reader
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-metrics-auth-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-leader-election-rolebinding
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "gitea-runner-operator.fullname" . }}-leader-election-role
subjects:
- kind: ServiceAccount
name: {{ include "gitea-runner-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-manager-rolebinding
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "gitea-runner-operator.fullname" . }}-manager-role
subjects:
- kind: ServiceAccount
name: {{ include "gitea-runner-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-metrics-auth-rolebinding
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "gitea-runner-operator.fullname" . }}-metrics-auth-role
subjects:
- kind: ServiceAccount
name: {{ include "gitea-runner-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-runnergroup-admin-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups
verbs:
- '*'
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-runnergroup-editor-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups/status
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-runnergroup-viewer-role
labels:
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
rules:
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups
verbs:
- get
- list
- watch
- apiGroups:
- gitea.bpg.pw
resources:
- runnergroups/status
verbs:
- get
{{- end }}

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "gitea-runner-operator.fullname" . }}-metrics-service
labels:
control-plane: controller-manager
{{- include "gitea-runner-operator.labels" . | nindent 4 }}
spec:
ports:
- name: https
port: 8443
protocol: TCP
targetPort: {{ .Values.manager.metricsBindAddress | trimPrefix ":" }}
selector:
{{- include "gitea-runner-operator.selectorLabels" . | nindent 4 }}

View File

@@ -0,0 +1,62 @@
# Default values for gitea-runner-operator.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
repository: ghcr.io/bapung/gitea-runner-operator
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "latest"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: true
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: "gitea-runner-operator-controller-manager"
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
nodeSelector: {}
tolerations: []
affinity: {}
# Manager configuration
manager:
metricsBindAddress: ":8443"
healthProbeBindAddress: ":8081"
leaderElect: true
# RBAC configuration
rbac:
create: true