ci: fix lint errors across project, update ruff.toml per-file ignores

This commit is contained in:
Celes Renata
2026-04-18 21:02:28 +00:00
parent 4d1894c652
commit 5f6d23888a
34 changed files with 1441 additions and 188 deletions
-15
View File
@@ -1,15 +0,0 @@
# RBAC for ARC runner pods — allows integration tests to create
# ephemeral namespaces and deploy sandbox infrastructure.
# The service account is auto-created by the ARC runner scale set chart.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: arc-runner-inttest
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: self-hosted-gremlin-gha-rs-no-permission
namespace: arc-system
-102
View File
@@ -1,102 +0,0 @@
# Helm values for ARC runner scale set
# Chart: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set
# Namespace: arc-system
#
# Custom DinD template with resource requests to spread pods across nodes.
# containerMode is NOT set — we provide the full template ourselves.
# Based on the chart's default DinD template for Kubernetes >= v1.29 (sidecar containers).
githubConfigUrl: "https://github.com/celesrenata/stonks-oracle"
runnerScaleSetName: "self-hosted-gremlin"
githubConfigSecret:
github_token: "PLACEHOLDER"
template:
spec:
# Spread runner pods across nodes
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: actions.github.com/scale-set-name
operator: In
values:
- self-hosted-gremlin
topologyKey: kubernetes.io/hostname
initContainers:
- name: init-dind-externals
image: ghcr.io/actions/actions-runner:latest
command: ["cp", "-r", "/home/runner/externals/.", "/home/runner/tmpDir/"]
volumeMounts:
- name: dind-externals
mountPath: /home/runner/tmpDir
- name: dind
image: docker:dind
args:
- dockerd
- --host=unix:///var/run/docker.sock
- --group=$(DOCKER_GROUP_GID)
env:
- name: DOCKER_GROUP_GID
value: "123"
securityContext:
privileged: true
restartPolicy: Always
startupProbe:
exec:
command:
- docker
- info
initialDelaySeconds: 0
failureThreshold: 24
periodSeconds: 5
resources:
requests:
cpu: "2"
memory: 2Gi
limits:
cpu: "4"
memory: 4Gi
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
- name: dind-externals
mountPath: /home/runner/externals
containers:
- name: runner
image: ghcr.io/actions/actions-runner:latest
command: ["/home/runner/run.sh"]
env:
- name: DOCKER_HOST
value: unix:///var/run/docker.sock
- name: RUNNER_WAIT_FOR_DOCKER_IN_SECONDS
value: "120"
resources:
requests:
cpu: "2"
memory: 2Gi
limits:
cpu: "4"
memory: 8Gi
volumeMounts:
- name: work
mountPath: /home/runner/_work
- name: dind-sock
mountPath: /var/run
volumes:
- name: work
emptyDir: {}
- name: dind-sock
emptyDir: {}
- name: dind-externals
emptyDir: {}
-16
View File
@@ -1,16 +0,0 @@
# Helm values for ARC controller
# Chart: oci://ghcr.io/actions/actions-runner-controller-charts/gha-runner-scale-set-controller
# Namespace: arc-system
# Flags to enable cert-manager and TLS (disabled — not needed for controller)
flags:
logLevel: info
# NFS-backed persistence via the pipeline-arc-pv PersistentVolume
persistence:
enabled: true
accessMode: ReadWriteOnce
size: 2Gi
selector:
matchLabels:
app: pipeline-arc
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec:
project: default
source:
repoURL: https://github.com/celesrenata/stonks-oracle.git
repoURL: http://gitea-service.git-server.svc.cluster.local:3000/admin/stonks-oracle.git
targetRevision: main
path: infra/helm/stonks-oracle
helm:
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec:
project: default
source:
repoURL: https://github.com/celesrenata/stonks-oracle.git
repoURL: http://gitea-service.git-server.svc.cluster.local:3000/admin/stonks-oracle.git
targetRevision: main
path: infra/helm/stonks-oracle
helm:
+1 -1
View File
@@ -6,7 +6,7 @@ metadata:
spec:
project: default
source:
repoURL: https://github.com/celesrenata/stonks-oracle.git
repoURL: http://gitea-service.git-server.svc.cluster.local:3000/admin/stonks-oracle.git
targetRevision: main
path: infra/helm/stonks-oracle
helm:
+3 -2
View File
@@ -7,6 +7,7 @@ metadata:
argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
url: https://github.com/celesrenata/stonks-oracle.git
url: http://gitea-service.git-server.svc.cluster.local:3000/admin/stonks-oracle.git
type: git
password: PLACEHOLDER # Filled at deploy time from gremlin-1's github_token
username: admin
password: St0nks0racl3!
+283
View File
@@ -0,0 +1,283 @@
#!/bin/bash
set -euo pipefail
# pipelines/gitea/setup.sh — Automate Gitea initial setup via REST API
#
# Steps:
# 1. Create admin user (idempotent — skip if already exists)
# 2. Create OAuth2 application for Woodpecker CI (idempotent — reuse if exists)
# 3. Create stonks-oracle repository (idempotent — skip if already exists)
#
# Outputs OAuth2 client_id and client_secret to stdout and to
# gitea-oauth2.env (sourceable by runmefirst.sh).
#
# Requirements: 1.1, 1.2, 1.5, 2.3
# -------------------------------------------------------
# Configuration (override via environment variables)
# -------------------------------------------------------
GITEA_URL="${GITEA_URL:-http://10.1.1.12:30300}"
GITEA_ADMIN_USER="${GITEA_ADMIN_USER:-admin}"
GITEA_ADMIN_PASSWORD="${GITEA_ADMIN_PASSWORD:-St0nks0racl3!}"
GITEA_ADMIN_EMAIL="${GITEA_ADMIN_EMAIL:-admin@celestium.life}"
OAUTH2_APP_NAME="woodpecker-ci"
OAUTH2_REDIRECT_URI="https://stonks-ci.celestium.life/authorize"
REPO_NAME="stonks-oracle"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
OAUTH2_ENV_FILE="${SCRIPT_DIR}/gitea-oauth2.env"
API="${GITEA_URL}/api/v1"
AUTH_HEADER="Authorization: Basic $(echo -n "${GITEA_ADMIN_USER}:${GITEA_ADMIN_PASSWORD}" | base64)"
echo "=== Gitea Setup ==="
echo " URL: ${GITEA_URL}"
echo " Admin user: ${GITEA_ADMIN_USER}"
echo ""
# -------------------------------------------------------
# Helper: wait for Gitea to be reachable
# (Gitea returns 404 on /api/v1/version when on install page, so check root)
# -------------------------------------------------------
echo "--- Waiting for Gitea to be reachable ---"
for i in $(seq 1 30); do
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "${GITEA_URL}/" 2>/dev/null || echo "000")
if [ "$HTTP_STATUS" != "000" ]; then
echo " ✓ Gitea is reachable (HTTP ${HTTP_STATUS})"
break
fi
if [ "$i" -eq 30 ]; then
echo " ✗ Gitea not reachable after 30 attempts"
exit 1
fi
echo " Attempt ${i}/30 — waiting 5s..."
sleep 5
done
echo ""
# -------------------------------------------------------
# Step 1: Create admin user
# -------------------------------------------------------
echo "--- Step 1: Create admin user ---"
# Check if admin user already exists by attempting to query the API with credentials
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 \
-H "${AUTH_HEADER}" \
"${API}/user")
if [ "$HTTP_CODE" = "200" ]; then
echo " ✓ Admin user '${GITEA_ADMIN_USER}' already exists and credentials are valid"
elif [ "$HTTP_CODE" = "404" ]; then
# Gitea is on the install page — API not available yet
echo " Gitea API not available (install page) — completing initial setup..."
INSTALL_RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "${GITEA_URL}/" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "db_type=sqlite3" \
--data-urlencode "db_host=localhost:3306" \
--data-urlencode "db_user=root" \
--data-urlencode "db_passwd=" \
--data-urlencode "db_name=gitea" \
--data-urlencode "ssl_mode=disable" \
--data-urlencode "db_path=/data/gitea/gitea.db" \
--data-urlencode "app_name=Gitea: Git with a cup of tea" \
--data-urlencode "repo_root_path=/data/git/repositories" \
--data-urlencode "lfs_root_path=/data/git/lfs" \
--data-urlencode "run_user=git" \
--data-urlencode "domain=gitea-service.git-server.svc.cluster.local" \
--data-urlencode "ssh_port=22" \
--data-urlencode "http_port=3000" \
--data-urlencode "app_url=http://gitea-service.git-server.svc.cluster.local:3000/" \
--data-urlencode "log_root_path=/data/gitea/log" \
--data-urlencode "admin_name=${GITEA_ADMIN_USER}" \
--data-urlencode "admin_passwd=${GITEA_ADMIN_PASSWORD}" \
--data-urlencode "admin_confirm_passwd=${GITEA_ADMIN_PASSWORD}" \
--data-urlencode "admin_email=${GITEA_ADMIN_EMAIL}")
INSTALL_CODE=$(echo "$INSTALL_RESPONSE" | tail -n 1)
if [ "$INSTALL_CODE" = "200" ] || [ "$INSTALL_CODE" = "302" ]; then
echo " ✓ Gitea initial install completed with admin user"
# Gitea restarts after install — wait for API to become available
echo " Waiting for Gitea API to become available after install..."
for j in $(seq 1 30); do
API_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --connect-timeout 5 "${API}/version" 2>/dev/null || echo "000")
if [ "$API_STATUS" = "200" ]; then
echo " ✓ Gitea API is ready"
break
fi
if [ "$j" -eq 30 ]; then
echo " ✗ Gitea API not available after install (waited 150s)"
exit 1
fi
sleep 5
done
else
echo " ✗ Install wizard returned HTTP ${INSTALL_CODE}"
echo " Response: $(echo "$INSTALL_RESPONSE" | head -n -1 | tail -5)"
exit 1
fi
else
echo " Admin user not found or credentials invalid — creating via admin API..."
# Try creating the user via Gitea's admin create-user API
# This works when Gitea has been initialized but no admin user exists,
# or when using the built-in admin creation endpoint
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "${API}/admin/users" \
-H "Content-Type: application/json" \
-H "${AUTH_HEADER}" \
-d "{
\"username\": \"${GITEA_ADMIN_USER}\",
\"password\": \"${GITEA_ADMIN_PASSWORD}\",
\"email\": \"${GITEA_ADMIN_EMAIL}\",
\"must_change_password\": false,
\"login_name\": \"${GITEA_ADMIN_USER}\",
\"source_id\": 0,
\"visibility\": \"public\"
}")
BODY=$(echo "$RESPONSE" | head -n -1)
CODE=$(echo "$RESPONSE" | tail -n 1)
if [ "$CODE" = "201" ]; then
echo " ✓ Admin user '${GITEA_ADMIN_USER}' created"
elif [ "$CODE" = "422" ]; then
echo " ✓ Admin user '${GITEA_ADMIN_USER}' already exists (422)"
else
echo " ✗ Unexpected response creating admin user: HTTP ${CODE}"
echo " Response: ${BODY}"
exit 1
fi
fi
echo ""
# -------------------------------------------------------
# Step 2: Create OAuth2 application for Woodpecker CI
# -------------------------------------------------------
echo "--- Step 2: Create OAuth2 application '${OAUTH2_APP_NAME}' ---"
# Check if the OAuth2 app already exists
EXISTING_APPS=$(curl -s \
-H "${AUTH_HEADER}" \
"${API}/user/applications/oauth2")
EXISTING_APP=$(echo "$EXISTING_APPS" | python3 -c "
import sys, json
apps = json.load(sys.stdin)
for app in apps:
if app.get('name') == '${OAUTH2_APP_NAME}':
print(json.dumps(app))
break
" 2>/dev/null || echo "")
if [ -n "$EXISTING_APP" ]; then
echo " ✓ OAuth2 app '${OAUTH2_APP_NAME}' already exists"
OAUTH2_CLIENT_ID=$(echo "$EXISTING_APP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])")
# Note: Gitea does not return client_secret for existing apps.
# If we need the secret, we must delete and recreate.
OAUTH2_CLIENT_SECRET=$(echo "$EXISTING_APP" | python3 -c "
import sys, json
data = json.load(sys.stdin)
print(data.get('client_secret', ''))
" 2>/dev/null || echo "")
if [ -z "$OAUTH2_CLIENT_SECRET" ]; then
echo " ⚠ Client secret not available for existing app — recreating..."
APP_ID=$(echo "$EXISTING_APP" | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
curl -s -X DELETE \
-H "${AUTH_HEADER}" \
"${API}/user/applications/oauth2/${APP_ID}" > /dev/null
echo " Deleted existing OAuth2 app (id=${APP_ID})"
EXISTING_APP=""
fi
fi
if [ -z "${EXISTING_APP:-}" ]; then
# Create the OAuth2 application
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "${API}/user/applications/oauth2" \
-H "Content-Type: application/json" \
-H "${AUTH_HEADER}" \
-d "{
\"name\": \"${OAUTH2_APP_NAME}\",
\"redirect_uris\": [\"${OAUTH2_REDIRECT_URI}\"],
\"confidential_client\": true
}")
BODY=$(echo "$RESPONSE" | head -n -1)
CODE=$(echo "$RESPONSE" | tail -n 1)
if [ "$CODE" = "201" ]; then
OAUTH2_CLIENT_ID=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])")
OAUTH2_CLIENT_SECRET=$(echo "$BODY" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_secret'])")
echo " ✓ OAuth2 app '${OAUTH2_APP_NAME}' created"
else
echo " ✗ Failed to create OAuth2 app: HTTP ${CODE}"
echo " Response: ${BODY}"
exit 1
fi
fi
echo " Client ID: ${OAUTH2_CLIENT_ID}"
echo " Client Secret: ${OAUTH2_CLIENT_SECRET:0:8}..."
echo ""
# -------------------------------------------------------
# Step 3: Create stonks-oracle repository
# -------------------------------------------------------
echo "--- Step 3: Create '${REPO_NAME}' repository ---"
# Check if repo already exists
REPO_CHECK=$(curl -s -o /dev/null -w "%{http_code}" \
-H "${AUTH_HEADER}" \
"${API}/repos/${GITEA_ADMIN_USER}/${REPO_NAME}")
if [ "$REPO_CHECK" = "200" ]; then
echo " ✓ Repository '${REPO_NAME}' already exists"
else
RESPONSE=$(curl -s -w "\n%{http_code}" \
-X POST "${API}/user/repos" \
-H "Content-Type: application/json" \
-H "${AUTH_HEADER}" \
-d "{
\"name\": \"${REPO_NAME}\",
\"description\": \"Stonks Oracle — AI market intelligence and paper-trading platform\",
\"private\": false,
\"auto_init\": false
}")
BODY=$(echo "$RESPONSE" | head -n -1)
CODE=$(echo "$RESPONSE" | tail -n 1)
if [ "$CODE" = "201" ]; then
echo " ✓ Repository '${REPO_NAME}' created"
elif [ "$CODE" = "409" ]; then
echo " ✓ Repository '${REPO_NAME}' already exists (409)"
else
echo " ✗ Failed to create repository: HTTP ${CODE}"
echo " Response: ${BODY}"
exit 1
fi
fi
echo ""
# -------------------------------------------------------
# Output OAuth2 credentials
# -------------------------------------------------------
echo "--- OAuth2 Credentials ---"
echo "GITEA_CLIENT_ID=${OAUTH2_CLIENT_ID}"
echo "GITEA_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}"
# Write to env file for runmefirst.sh to source
cat > "${OAUTH2_ENV_FILE}" <<EOF
# Generated by gitea/setup.sh — do not edit manually
GITEA_CLIENT_ID=${OAUTH2_CLIENT_ID}
GITEA_CLIENT_SECRET=${OAUTH2_CLIENT_SECRET}
EOF
echo ""
echo " ✓ Credentials written to ${OAUTH2_ENV_FILE}"
echo ""
echo "=== Gitea Setup Complete ==="
+1 -1
View File
@@ -6,4 +6,4 @@ metadata:
spec:
subscriptions:
- image:
repoURL: ghcr.io/celesrenata/stonks-oracle/query-api
repoURL: registry.celestium.life/stonks-oracle/query-api
@@ -1,15 +1,16 @@
apiVersion: v1
kind: PersistentVolume
metadata:
name: pipeline-arc-pv
name: pipeline-woodpecker-pv
labels:
app: pipeline-arc
app: pipeline-woodpecker
spec:
capacity:
storage: 2Gi
storage: 5Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: ""
nfs:
server: 192.168.42.8
path: /volume1/Kubernetes/pipelines/arc
path: /volume1/Kubernetes/pipelines/woodpecker
+15
View File
@@ -0,0 +1,15 @@
# ClusterRoleBinding: Grant Woodpecker agent cluster-admin for integration tests
# Integration test steps create ephemeral namespaces and deploy sandbox infrastructure.
# Mirrors the existing ARC runner RBAC pattern.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: woodpecker-agent-inttest
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: woodpecker-agent
namespace: woodpecker
+20
View File
@@ -0,0 +1,20 @@
# NetworkPolicy: Allow Traefik ingress to Woodpecker server
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-traefik-to-woodpecker
namespace: woodpecker
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: server
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: TCP
port: 8000
+53
View File
@@ -0,0 +1,53 @@
# Helm values for Woodpecker CI
# Chart: woodpecker/woodpecker
# Namespace: woodpecker
# --- Server ---
server:
enabled: true
env:
WOODPECKER_HOST: "https://stonks-ci.celestium.life"
WOODPECKER_SERVER_ADDR: "0.0.0.0:8000"
WOODPECKER_GITEA: "true"
WOODPECKER_GITEA_URL: "http://gitea-service.git-server.svc.cluster.local:3000"
WOODPECKER_GITEA_CLIENT: "<GITEA_CLIENT_ID>"
WOODPECKER_GITEA_SECRET: "<GITEA_CLIENT_SECRET>"
WOODPECKER_ADMIN: "admin"
WOODPECKER_PLUGINS_PRIVILEGED: "woodpeckerci/plugin-docker-buildx"
# Traefik ingress with TLS via cert-manager
ingress:
enabled: true
ingressClassName: traefik
hosts:
- host: stonks-ci.celestium.life
paths:
- path: /
backend:
serviceName: woodpecker-server
servicePort: 80
tls:
- secretName: woodpecker-tls
hosts:
- stonks-ci.celestium.life
annotations:
cert-manager.io/cluster-issuer: ca-issuer
# NFS-backed persistent volume for SQLite database and build data
persistentVolume:
enabled: true
size: 5Gi
storageClass: ""
# --- Agent ---
agent:
enabled: true
replicaCount: 2
env:
WOODPECKER_SERVER: "woodpecker-server:9000"
WOODPECKER_BACKEND: kubernetes
WOODPECKER_BACKEND_K8S_NAMESPACE: woodpecker
WOODPECKER_BACKEND_K8S_VOLUME_SIZE: 10G
WOODPECKER_BACKEND_K8S_STORAGE_RWX: "true"