rebased: Add Gitea Actions act runner #666

Merged
vjm merged 27 commits from gitea-actions into main 2024-11-10 13:35:57 +00:00
5 changed files with 441 additions and 0 deletions
Showing only changes of commit d77793a52b - Show all commits

41
scripts/token.sh Normal file
View File

@ -0,0 +1,41 @@
#!/bin/sh
set -eu
check_token() {
set +e
echo "Checking for existing token..."
token="$(kubectl get secret "$SECRET_NAME" -o jsonpath="{.data['token']}" 2> /dev/null)"
[ $? -ne 0 ] && return 1
[ -z "$token" ] && return 2
return 0
}
create_token() {
echo "Waiting for new token to be generated..."
begin=$(date +%s)
end=$((begin + 300)) # 5 minutes
while true; do
[ -f /data/actions/token ] && return 0
[ "$(date +%s)" -gt $end ] && return 1
sleep 5
done
}
store_token() {
echo "Storing the token in Kubernetes secret..."
kubectl patch secret "$SECRET_NAME" -p "{\"data\":{\"token\":\"$(base64 /data/actions/token | tr -d '\n')\"}}"
}
if check_token; then
echo "Key already in place, exiting."
exit
fi
if ! create_token; then
echo "Timed out waiting for a token to appear."
exit 1
fi
store_token

View File

@ -25,6 +25,14 @@ If release name contains chart name it will be used as a full name.
{{- end -}}
{{- end -}}
{{/*
Create a default worker name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "gitea.workername" -}}
{{- printf "%s-%s" .global.Release.Name .worker | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
Create chart name and version as used by the chart label.
*/}}

View File

@ -0,0 +1,176 @@
{{- if and (and .Values.actions.job.enabled .Values.persistence.enabled) .Values.persistence.mount }}
{{- if .Values.actions.existingSecret }}
{{- fail "Can't specify both actions.job.enabled and actions.existingSecret" }}
{{- end }}
{{- $name := include "gitea.workername" (dict "global" . "worker" "actions-token-job") }}
{{- $secretName := include "gitea.workername" (dict "global" . "worker" "actions-token") }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "gitea.fullname" . }}-scripts
labels:
{{- include "gitea.labels" . | nindent 4 }}
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
data:
{{ (.Files.Glob "scripts/*.sh").AsConfig | indent 2 }}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
rules:
- apiGroups:
- ""
resources:
- secrets
resourceNames:
- {{ $secretName }}
verbs:
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ $name }}
subjects:
- kind: ServiceAccount
name: {{ $name }}
namespace: {{ .Release.Namespace }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
{{- with .Values.actions.job.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ttlSecondsAfterFinished: 0
template:
metadata:
labels:
{{- include "gitea.labels" . | nindent 8 }}
app.kubernetes.io/component: token-job
spec:
containers:
- name: actions-token-create
image: "{{ .Values.actions.job.tokenImage.repository }}:{{ .Values.actions.job.tokenImage.tag | default "latest-rootless" }}"
imagePullPolicy: {{ .Values.actions.job.tokenImage.pullPolicy }}
env:
- name: GITEA_APP_INI
value: /data/gitea/conf/app.ini
command:
- sh
- -c
- |
while ! nc -z gitea-http 3000; do
sleep 5
done
echo "Generating token..."
mkdir -p /data/actions/
gitea actions generate-runner-token | grep -E '^.{40}$' | tr -d '\n' > /data/actions/token
resources:
{{- toYaml .Values.actions.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /data
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
- name: actions-token-upload
image: "{{ .Values.actions.job.publishImage.repository }}:{{ .Values.actions.job.publishImage.tag | default "latest" }}"
imagePullPolicy: {{ .Values.actions.job.publishImage.pullPolicy }}
env:
- name: SECRET_NAME
value: {{ $secretName }}
command:
- sh
- -c
- |
printf "Checking rights to update secret... "
kubectl auth can-i update secret/${SECRET_NAME}
/scripts/token.sh
resources:
{{- toYaml .Values.actions.resources | nindent 12 }}
volumeMounts:
- mountPath: /scripts
name: scripts
readOnly: true
- mountPath: /data
name: data
readOnly: true
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
restartPolicy: Never
serviceAccount: {{ $name }}
volumes:
- name: scripts
configMap:
name: {{ include "gitea.fullname" . }}-scripts
defaultMode: 0755
- name: data
persistentVolumeClaim:
claimName: {{ .Values.persistence.claimName }}
parallelism: 1
completions: 1
backoffLimit: 1
---
apiVersion: v1
kind: Secret
metadata:
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: never
helm.sh/resource-policy: keep
argocd.argoproj.io/hook: Skip
argocd.argoproj.io/hook-delete-policy: Never
name: {{ $secretName }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
{{ $secret := (lookup "v1" "Secret" .Release.Namespace $secretName) -}}
{{ if $secret -}}
data:
signing.key: {{ (b64dec (index $secret.data "signing.key")) | b64enc }}
{{ end -}}
{{- end }}

View File

@ -0,0 +1,176 @@
{{- if and (and .Values.actions.job.enabled .Values.persistence.enabled) .Values.persistence.mount }}
{{- if .Values.actions.existingSecret }}
{{- fail "Can't specify both actions.job.enabled and actions.existingSecret" }}
{{- end }}
{{- $name := include "gitea.workername" (dict "global" . "worker" "actions-token-job") }}
{{- $secretName := include "gitea.workername" (dict "global" . "worker" "actions-token") }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "gitea.fullname" . }}-scripts
labels:
{{- include "gitea.labels" . | nindent 4 }}
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
data:
{{ (.Files.Glob "scripts/*.sh").AsConfig | indent 2 }}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
rules:
- apiGroups:
- ""
resources:
- secrets
resourceNames:
- {{ $secretName }}
verbs:
- get
- update
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ $name }}
subjects:
- kind: ServiceAccount
name: {{ $name }}
namespace: {{ .Release.Namespace }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ $name }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: hook-succeeded
{{- with .Values.actions.job.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
ttlSecondsAfterFinished: 0
template:
metadata:
labels:
{{- include "gitea.labels" . | nindent 8 }}
app.kubernetes.io/component: token-job
spec:
containers:
- name: actions-token-create
image: "{{ .Values.actions.job.tokenImage.repository }}:{{ .Values.actions.job.tokenImage.tag | default "latest-rootless" }}"
imagePullPolicy: {{ .Values.actions.job.tokenImage.pullPolicy }}
env:
- name: GITEA_APP_INI
value: /data/gitea/conf/app.ini
command:
- sh
- -c
- |
while ! nc -z gitea-http 3000; do
sleep 5
done
echo "Generating token..."
mkdir -p /data/actions/
gitea actions generate-runner-token | grep -E '^.{40}$' | tr -d '\n' > /data/actions/token
resources:
{{- toYaml .Values.actions.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /data
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
- name: actions-token-upload
image: "{{ .Values.actions.job.publishImage.repository }}:{{ .Values.actions.job.publishImage.tag | default "latest" }}"
imagePullPolicy: {{ .Values.actions.job.publishImage.pullPolicy }}
env:
- name: SECRET_NAME
value: {{ $secretName }}
command:
- sh
- -c
- |
printf "Checking rights to update secret... "
kubectl auth can-i update secret/${SECRET_NAME}
/scripts/token.sh
resources:
{{- toYaml .Values.actions.resources | nindent 12 }}
volumeMounts:
- mountPath: /scripts
name: scripts
readOnly: true
- mountPath: /data
name: data
readOnly: true
{{- if .Values.persistence.subPath }}
subPath: {{ .Values.persistence.subPath }}
{{- end }}
restartPolicy: Never
serviceAccount: {{ $name }}
volumes:
- name: scripts
configMap:
name: {{ include "gitea.fullname" . }}-scripts
defaultMode: 0755
- name: data
persistentVolumeClaim:
claimName: {{ .Values.persistence.claimName }}
parallelism: 1
completions: 1
backoffLimit: 1
---
apiVersion: v1
kind: Secret
metadata:
annotations:
# helm.sh/hook: post-install
# helm.sh/hook-delete-policy: never
helm.sh/resource-policy: keep
argocd.argoproj.io/hook: Skip
argocd.argoproj.io/hook-delete-policy: Never
name: {{ $secretName }}
labels:
{{- include "gitea.labels" . | nindent 4 }}
app.kubernetes.io/component: token-job
{{ $secret := (lookup "v1" "Secret" .Release.Namespace $secretName) -}}
{{ if $secret -}}
data:
signing.key: {{ (b64dec (index $secret.data "signing.key")) | b64enc }}
{{ end -}}
{{- end }}

View File

@ -339,6 +339,46 @@ signing:
# -----END PGP PRIVATE KEY BLOCK-----
existingSecret: ""
# Configure Gitea Actions
# - must enable persistence
# - must define deployment.env.GITEA__ACTIONS__ENABLED and GITEA__SERVER__LOCAL_ROOT_URL
## @section GiteaActions
#
## @param actions.statefulset.enabled Create an act-runner StatefulSet.
## @param actions.job.enabled Create a job that will create and save the token in a Kubernetes Secret
## @param actions.job.tokenImage.repository The image that can create a token via `gitea actions generate-runner-token`
## @param actions.job.tokenImage.tag The token image tag that can create a token
## @param actions.job.tokenImage.pullPolicy The token image pullPolicy that can create a token
## @param actions.job.publishImage.repository The image that can create the secret via kubectl
## @param actions.job.publishImage.tag The publish image tag that can create the secret
## @param actions.job.publishImage.pullPolicy The publish image pullPolicy that can create the secret
## @param actions.existingSecret Secret that contains the token
## @param actions.existingSecretKey Secret key
actions:
statefulset:
enabled: false
job:
enabled: false
annotations: {}
resources: {}
tokenImage:
repository: gitea/gitea
# tag: latest-rootless
pullPolicy: IfNotPresent
publishImage:
repository: bitnami/kubectl
# tag: latest
pullPolicy: IfNotPresent
## Specify an existing token secret
##
# existingSecret: secretName
# existingSecretKey: token
## @section Gitea
#
gitea: