this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

POC: Homebrew CI on Tangled knot

+270
+20
k8s/ci/ci-hook.sh
··· 1 + #!/bin/sh 2 + # Post-receive CI hook — notifies push-webhook service on every push. 3 + # Installed by the ci-hook-installer sidecar. 4 + 5 + WEBHOOK_URL="http://push-webhook.ci.svc.cluster.local:3000/cgi-bin/webhook" 6 + REPO_PATH="${GIT_DIR#/home/git/repositories/}" 7 + 8 + while read -r oldrev newrev refname; do 9 + author=$(git log -1 --format='%an' "$newrev" 2>/dev/null || echo '') 10 + message=$(git log -1 --format='%s' "$newrev" 2>/dev/null || echo '') 11 + 12 + wget -q -O /dev/null --post-data \ 13 + "repo=${REPO_PATH} 14 + ref=${refname} 15 + before=${oldrev} 16 + after=${newrev} 17 + author=${author} 18 + message=${message}" \ 19 + "$WEBHOOK_URL" 2>/dev/null || true 20 + done
+68
k8s/ci/deployment.yaml
··· 1 + apiVersion: apps/v1 2 + kind: Deployment 3 + metadata: 4 + name: push-webhook 5 + namespace: ci 6 + spec: 7 + replicas: 1 8 + selector: 9 + matchLabels: 10 + app: push-webhook 11 + template: 12 + metadata: 13 + labels: 14 + app: push-webhook 15 + spec: 16 + containers: 17 + - name: webhook 18 + image: busybox:1 19 + command: ["httpd", "-f", "-p", "3000", "-h", "/app"] 20 + ports: 21 + - name: http 22 + containerPort: 3000 23 + env: 24 + - name: WATCH_REPOS 25 + value: "infrastructure" 26 + - name: WATCH_BRANCH 27 + value: "main" 28 + volumeMounts: 29 + - name: cgi-bin 30 + mountPath: /app/cgi-bin 31 + - name: secrets 32 + mountPath: /secrets 33 + readOnly: true 34 + livenessProbe: 35 + httpGet: 36 + path: /cgi-bin/health 37 + port: 3000 38 + initialDelaySeconds: 3 39 + periodSeconds: 30 40 + readinessProbe: 41 + httpGet: 42 + path: /cgi-bin/health 43 + port: 3000 44 + initialDelaySeconds: 2 45 + periodSeconds: 10 46 + securityContext: 47 + runAsNonRoot: true 48 + runAsUser: 1000 49 + readOnlyRootFilesystem: true 50 + allowPrivilegeEscalation: false 51 + capabilities: 52 + drop: 53 + - ALL 54 + resources: 55 + requests: 56 + cpu: 10m 57 + memory: 16Mi 58 + limits: 59 + cpu: 100m 60 + memory: 32Mi 61 + volumes: 62 + - name: cgi-bin 63 + configMap: 64 + name: webhook-script 65 + defaultMode: 0755 66 + - name: secrets 67 + secret: 68 + secretName: telegram-credentials
+2
k8s/ci/health.sh
··· 1 + #!/bin/sh 2 + printf 'Content-Type: text/plain\r\n\r\nok'
+22
k8s/ci/kustomization.yaml
··· 1 + apiVersion: kustomize.config.k8s.io/v1beta1 2 + kind: Kustomization 3 + 4 + generatorOptions: 5 + disableNameSuffixHash: true 6 + 7 + resources: 8 + - namespace.yaml 9 + - deployment.yaml 10 + - service.yaml 11 + - network-policy.yaml 12 + 13 + configMapGenerator: 14 + - name: webhook-script 15 + namespace: ci 16 + files: 17 + - webhook=webhook.sh 18 + - health=health.sh 19 + - name: ci-hooks 20 + namespace: knot 21 + files: 22 + - ci-hook.sh
+4
k8s/ci/namespace.yaml
··· 1 + apiVersion: v1 2 + kind: Namespace 3 + metadata: 4 + name: ci
+18
k8s/ci/network-policy.yaml
··· 1 + apiVersion: networking.k8s.io/v1 2 + kind: NetworkPolicy 3 + metadata: 4 + name: push-webhook-ingress 5 + namespace: ci 6 + spec: 7 + podSelector: 8 + matchLabels: 9 + app: push-webhook 10 + policyTypes: 11 + - Ingress 12 + ingress: 13 + - from: 14 + - namespaceSelector: 15 + matchLabels: 16 + kubernetes.io/metadata.name: knot 17 + ports: 18 + - port: 3000
+12
k8s/ci/service.yaml
··· 1 + apiVersion: v1 2 + kind: Service 3 + metadata: 4 + name: push-webhook 5 + namespace: ci 6 + spec: 7 + selector: 8 + app: push-webhook 9 + ports: 10 + - name: http 11 + port: 3000 12 + targetPort: 3000
+74
k8s/ci/webhook.sh
··· 1 + #!/bin/sh 2 + # CGI handler — receives push notifications from ci-hook.sh 3 + 4 + body=$(head -c "${CONTENT_LENGTH:-0}") 5 + printf '%s\n' "$body" >&2 6 + 7 + field() { printf '%s\n' "$body" | sed -n "s/^$1=//p" | head -1; } 8 + 9 + repo=$(field repo) 10 + ref=$(field ref) 11 + after=$(field after) 12 + author=$(field author) 13 + message=$(field message) 14 + 15 + case "$ref" in 16 + refs/tags/*) ref_type=tag; ref_name="${ref#refs/tags/}" ;; 17 + refs/heads/*) ref_type=branch; ref_name="${ref#refs/heads/}" ;; 18 + *) ref_type=ref; ref_name="$ref" ;; 19 + esac 20 + 21 + repo_name="${repo##*/}" 22 + 23 + printf '%s %s=%s by %s\n' "$repo" "$ref_type" "$ref_name" "${author:-unknown}" >&2 24 + 25 + # Filtering 26 + watched_repo=false 27 + if [ -z "$WATCH_REPOS" ]; then 28 + watched_repo=true 29 + else 30 + for r in $(printf '%s' "$WATCH_REPOS" | tr ',' ' '); do 31 + [ "$r" = "$repo" ] || [ "$r" = "$repo_name" ] && watched_repo=true 32 + done 33 + fi 34 + 35 + watched_ref=false 36 + [ "$ref_type" = "tag" ] || [ "$ref_name" = "${WATCH_BRANCH:-main}" ] && watched_ref=true 37 + 38 + printf 'Content-Type: text/plain\r\n\r\n' 39 + 40 + if [ "$watched_repo" = false ] || [ "$watched_ref" = false ]; then 41 + echo "ok (not watched)" 42 + exit 0 43 + fi 44 + 45 + # Build notification 46 + [ "$ref_type" = "tag" ] \ 47 + && ref_label="Tag: \`$ref_name\`" \ 48 + || ref_label="Branch: \`$ref_name\`" 49 + 50 + short_sha=$(printf '%.7s' "$after") 51 + [ -n "$message" ] \ 52 + && commit_line="\`$short_sha\` $message" \ 53 + || commit_line="\`$short_sha\`" 54 + 55 + text="*Push to $repo_name* 56 + $ref_label" 57 + [ -n "$author" ] && text="$text 58 + By: $author" 59 + text="$text 60 + 61 + $commit_line" 62 + 63 + # JSON-escape and collapse newlines 64 + json_text=$(printf '%s' "$text" | sed 's/\\/\\\\/g; s/"/\\"/g' | awk 'NR>1{printf "\\n"}{printf "%s",$0}') 65 + 66 + BOT_TOKEN=$(tr -d '[:space:]' < /secrets/bot-token) 67 + CHAT_ID=$(tr -d '[:space:]' < /secrets/chat-id) 68 + 69 + wget -q -O /dev/null \ 70 + --header='Content-Type: application/json' \ 71 + --post-data="{\"chat_id\":\"$CHAT_ID\",\"text\":\"$json_text\",\"parse_mode\":\"Markdown\"}" \ 72 + "https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" 2>&1 | cat >&2 73 + 74 + echo "ok (notified)"
+43
k8s/knot/deployment.yaml
··· 77 77 limits: 78 78 cpu: 500m 79 79 memory: 512Mi 80 + - name: ci-hook-installer 81 + image: busybox:1 82 + command: ["sh", "-c"] 83 + args: 84 + - | 85 + REPO_ROOT=/repos 86 + HOOK_SRC=/ci-hooks/ci-hook.sh 87 + 88 + while true; do 89 + for hookdir in "$REPO_ROOT"/*/*/hooks; do 90 + [ -d "$hookdir/post-receive.d" ] || continue 91 + dest="$hookdir/post-receive.d/50-ci-notify" 92 + if [ ! -f "$dest" ] || ! cmp -s "$HOOK_SRC" "$dest"; then 93 + cp "$HOOK_SRC" "$dest" && chmod +x "$dest" && echo "installed: $dest" 94 + fi 95 + done 96 + sleep 30 97 + done 98 + volumeMounts: 99 + - name: data 100 + mountPath: /repos 101 + subPath: repositories 102 + - name: ci-hooks 103 + mountPath: /ci-hooks 104 + readOnly: true 105 + securityContext: 106 + runAsUser: 1000 107 + runAsGroup: 1000 108 + readOnlyRootFilesystem: true 109 + allowPrivilegeEscalation: false 110 + capabilities: 111 + drop: 112 + - ALL 113 + resources: 114 + requests: 115 + cpu: 10m 116 + memory: 16Mi 117 + limits: 118 + cpu: 50m 119 + memory: 32Mi 80 120 volumes: 81 121 - name: data 82 122 persistentVolumeClaim: ··· 84 124 - name: sshd-hardening 85 125 configMap: 86 126 name: sshd-hardening 127 + - name: ci-hooks 128 + configMap: 129 + name: ci-hooks
+7
k8s/kustomization.yaml
··· 9 9 - knot 10 10 - registry 11 11 - alerting 12 + - ci 12 13 - opake 13 14 14 15 generatorOptions: ··· 84 85 - metaurl=juicefs/metaurl.secret 85 86 - access-key=shared/s3-access-key.secret 86 87 - secret-key=shared/s3-secret-key.secret 88 + - name: telegram-credentials 89 + namespace: ci 90 + type: Opaque 91 + files: 92 + - bot-token=alerting/telegram-bot-token.secret 93 + - chat-id=alerting/telegram-chat-id.secret