From 6ec6a3664fb4154cc037fcd7a4297ea24b66d77e Mon Sep 17 00:00:00 2001 From: Jan Novak Date: Thu, 26 Mar 2026 11:35:10 +0100 Subject: [PATCH] feat: add Gitea CI workflows and split deploy manifests Add build and kubernetes-deploy Gitea Actions workflows, and split deploy/manifests.yaml into individual manifest files. Co-Authored-By: Claude Sonnet 4.6 --- .gitea/workflows/build.yaml | 39 +++++++ .gitea/workflows/kubernetes-deploy.yaml | 109 ++++++++++++++++++ deploy/clusterrole_gateway-cert-operator.yaml | 20 ++++ ...sterrolebinding_gateway-cert-operator.yaml | 15 +++ ... => deployment_gateway-cert-operator.yaml} | 46 +------- ...amespace_gateway-cert-operator-system.yaml | 7 ++ ...service_gateway-cert-operator-metrics.yaml | 16 +++ .../serviceaccount_gateway-cert-operator.yaml | 8 ++ 8 files changed, 217 insertions(+), 43 deletions(-) create mode 100644 .gitea/workflows/build.yaml create mode 100644 .gitea/workflows/kubernetes-deploy.yaml create mode 100644 deploy/clusterrole_gateway-cert-operator.yaml create mode 100644 deploy/clusterrolebinding_gateway-cert-operator.yaml rename deploy/{manifests.yaml => deployment_gateway-cert-operator.yaml} (61%) create mode 100644 deploy/namespace_gateway-cert-operator-system.yaml create mode 100644 deploy/service_gateway-cert-operator-metrics.yaml create mode 100644 deploy/serviceaccount_gateway-cert-operator.yaml diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..4fe6d67 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -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 diff --git a/.gitea/workflows/kubernetes-deploy.yaml b/.gitea/workflows/kubernetes-deploy.yaml new file mode 100644 index 0000000..0e7f777 --- /dev/null +++ b/.gitea/workflows/kubernetes-deploy.yaml @@ -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/ diff --git a/deploy/clusterrole_gateway-cert-operator.yaml b/deploy/clusterrole_gateway-cert-operator.yaml new file mode 100644 index 0000000..33680b7 --- /dev/null +++ b/deploy/clusterrole_gateway-cert-operator.yaml @@ -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"] diff --git a/deploy/clusterrolebinding_gateway-cert-operator.yaml b/deploy/clusterrolebinding_gateway-cert-operator.yaml new file mode 100644 index 0000000..20d552a --- /dev/null +++ b/deploy/clusterrolebinding_gateway-cert-operator.yaml @@ -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 diff --git a/deploy/manifests.yaml b/deploy/deployment_gateway-cert-operator.yaml similarity index 61% rename from deploy/manifests.yaml rename to deploy/deployment_gateway-cert-operator.yaml index a9f06c7..9f353cf 100644 --- a/deploy/manifests.yaml +++ b/deploy/deployment_gateway-cert-operator.yaml @@ -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: diff --git a/deploy/namespace_gateway-cert-operator-system.yaml b/deploy/namespace_gateway-cert-operator-system.yaml new file mode 100644 index 0000000..b07190d --- /dev/null +++ b/deploy/namespace_gateway-cert-operator-system.yaml @@ -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 diff --git a/deploy/service_gateway-cert-operator-metrics.yaml b/deploy/service_gateway-cert-operator-metrics.yaml new file mode 100644 index 0000000..f00d80e --- /dev/null +++ b/deploy/service_gateway-cert-operator-metrics.yaml @@ -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 diff --git a/deploy/serviceaccount_gateway-cert-operator.yaml b/deploy/serviceaccount_gateway-cert-operator.yaml new file mode 100644 index 0000000..8fd09a1 --- /dev/null +++ b/deploy/serviceaccount_gateway-cert-operator.yaml @@ -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