feat: add Gitea CI workflows and split deploy manifests
Some checks failed
Build and Push / build (push) Successful in 2m1s
Deploy to K8s / deploy (push) Failing after 7s

Add build and kubernetes-deploy Gitea Actions workflows, and split deploy/manifests.yaml into individual manifest files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-26 11:35:10 +01:00
parent a78e4421ef
commit 6ec6a3664f
8 changed files with 217 additions and 43 deletions

View File

@@ -0,0 +1,39 @@
name: Build and Push
on:
workflow_dispatch:
inputs:
tag:
description: 'Image tag'
required: true
default: 'latest'
push:
tags:
- '*'
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Login to Gitea registry
run: echo "${{ secrets.REGISTRY_TOKEN }}" | docker login -u ${{ github.actor }} --password-stdin gitea.home.hrajfrisbee.cz
- name: Build and push
run: |
TAG=${{ github.ref_name }}
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TAG=${{ inputs.tag }}
fi
IMAGE=gitea.home.hrajfrisbee.cz/${{ github.repository }}:$TAG
docker build -f Dockerfile \
--build-arg GIT_TAG=$TAG \
--build-arg GIT_COMMIT=${{ github.sha }} \
--build-arg BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
-t $IMAGE .
docker push $IMAGE

View File

@@ -0,0 +1,109 @@
name: Deploy to K8s
on:
workflow_dispatch:
push:
branches:
- '**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Debug - print Gitea Actions environment
run: |
echo "=== All environment variables ==="
env | sort
echo ""
echo "=== GITHUB_* / GITEA_* / ACTIONS_* vars ==="
env | grep -E '^(GITHUB|GITEA|ACTIONS)_' | sort
- name: Install kubectl
run: |
curl -sfLO "https://dl.k8s.io/release/$(curl -sfL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
install kubectl /usr/local/bin/
- name: Get Kanidm token from Vault
id: vault
run: |
set -euxo pipefail
VAULT_AUTH_RESPONSE=$(curl -f --request POST \
--data '{"role_id":"${{ secrets.VAULT_ROLE_ID }}","secret_id":"${{ secrets.VAULT_SECRET_ID }}"}' \
https://vault.hrajfrisbee.cz/v1/auth/approle/login)
echo "Vault auth response: $VAULT_AUTH_RESPONSE" >&2
VAULT_TOKEN=$(echo "$VAULT_AUTH_RESPONSE" | jq -r '.auth.client_token')
# Read the kanidm API token
SECRET_RESPONSE=$(curl -f \
-H "X-Vault-Token: ${VAULT_TOKEN}" \
https://vault.hrajfrisbee.cz/v1/secret/data/gitea/gitea-ci)
echo "Secret response: $SECRET_RESPONSE" >&2
API_TOKEN=$(echo "$SECRET_RESPONSE" | jq -r '.data.data.token')
echo "::add-mask::${API_TOKEN}"
echo "api_token=${API_TOKEN}" >> "$GITHUB_OUTPUT"
- name: Exchange for K8s OIDC token via Kanidm
id: k8s
run: |
API_TOKEN="${{ steps.vault.outputs.api_token }}"
echo "api_token length: ${#API_TOKEN}" >&2
echo "api_token prefix (first 8 chars): ${API_TOKEN:0:8}..." >&2
HTTP_BODY=$(mktemp)
HTTP_STATUS=$(curl -sS -X POST "https://idm.home.hrajfrisbee.cz/oauth2/token" \
-d "grant_type=urn:ietf:params:oauth:grant-type:token-exchange" \
-d "client_id=k8s" \
-d "subject_token=${API_TOKEN}" \
-d "subject_token_type=urn:ietf:params:oauth:token-type:access_token" \
-d "audience=k8s" \
-d "scope=openid groups" \
-o "$HTTP_BODY" -w "%{http_code}")
echo "HTTP status: $HTTP_STATUS" >&2
echo "Response body:" >&2
cat "$HTTP_BODY" >&2
RESPONSE=$(cat "$HTTP_BODY")
ID_TOKEN=$(echo "$RESPONSE" | jq -r '.id_token // empty')
if [ -z "$ID_TOKEN" ]; then
echo "::error::Kanidm token exchange failed (HTTP $HTTP_STATUS)"
exit 1
fi
echo "::add-mask::${ID_TOKEN}"
echo "id_token=${ID_TOKEN}" >> "$GITHUB_OUTPUT"
# Sanity check
# Warning - this is the part that is failing
# echo "$ID_TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null | jq '{sub, groups, exp}'
- name: Debug - print environment before kubectl
run: env | sort
- name: Configure kubectl & deploy
run: |
echo "${{ secrets.K8S_CA_CERT }}" > /tmp/ca.crt
kubectl config set-cluster mycluster \
--server=https://192.168.0.31:6443 \
--insecure-skip-tls-verify=true
# --certificate-authority=/tmp/ca.crt \
kubectl config set-credentials gitea-ci \
--token="${{ steps.k8s.outputs.id_token }}"
kubectl config set-context gitea-ci \
--cluster=mycluster --user=gitea-ci
kubectl config use-context gitea-ci
kubectl auth whoami
kubectl get ns
kubectl apply -f deploy/

View File

@@ -0,0 +1,20 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gateway-cert-operator
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator
rules:
# Watch and read Certificates
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "list", "watch"]
# Read and patch Gateways
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["gateways"]
verbs: ["get", "list", "watch", "patch"]
# Emit events
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gateway-cert-operator
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gateway-cert-operator
subjects:
- kind: ServiceAccount
name: gateway-cert-operator
namespace: gateway-cert-operator-system

View File

@@ -1,46 +1,3 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: gateway-cert-operator-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: gateway-cert-operator
namespace: gateway-cert-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gateway-cert-operator
rules:
# Watch and read Certificates
- apiGroups: ["cert-manager.io"]
resources: ["certificates"]
verbs: ["get", "list", "watch"]
# Read and patch Gateways
- apiGroups: ["gateway.networking.k8s.io"]
resources: ["gateways"]
verbs: ["get", "list", "watch", "patch"]
# Emit events
- apiGroups: [""]
resources: ["events"]
verbs: ["create", "patch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gateway-cert-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gateway-cert-operator
subjects:
- kind: ServiceAccount
name: gateway-cert-operator
namespace: gateway-cert-operator-system
---
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -48,6 +5,7 @@ metadata:
namespace: gateway-cert-operator-system
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator
spec:
replicas: 1
selector:
@@ -57,8 +15,10 @@ spec:
metadata:
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator
spec:
serviceAccountName: gateway-cert-operator
terminationGracePeriodSeconds: 10
securityContext:
runAsNonRoot: true
seccompProfile:

View File

@@ -0,0 +1,7 @@
apiVersion: v1
kind: Namespace
metadata:
name: gateway-cert-operator-system
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator

View File

@@ -0,0 +1,16 @@
apiVersion: v1
kind: Service
metadata:
name: gateway-cert-operator-metrics
namespace: gateway-cert-operator-system
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: metrics
spec:
selector:
app.kubernetes.io/name: gateway-cert-operator
ports:
- name: metrics
port: 8080
targetPort: metrics
protocol: TCP

View File

@@ -0,0 +1,8 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: gateway-cert-operator
namespace: gateway-cert-operator-system
labels:
app.kubernetes.io/name: gateway-cert-operator
app.kubernetes.io/component: operator