Add scheduler backend image workflow
All checks were successful
Build scheduler-backend image / build-and-push (push) Successful in 3m36s

This commit is contained in:
Developer
2026-05-28 13:15:30 +07:00
parent 5f93d025d2
commit 433fb60f0a
5 changed files with 356 additions and 0 deletions

View File

@@ -0,0 +1,154 @@
#!/usr/bin/env bash
set -euo pipefail
: "${CONFIG_CENTER_UPDATES_FILE:?CONFIG_CENTER_UPDATES_FILE is required}"
CONFIG_CENTER_CLUSTERS="${CONFIG_CENTER_CLUSTERS:-ack-dev}"
if [ ! -s "$CONFIG_CENTER_UPDATES_FILE" ]; then
echo "No config-center image updates were recorded."
exit 0
fi
if command -v python3 >/dev/null 2>&1; then
PYTHON=python3
elif command -v python >/dev/null 2>&1; then
PYTHON=python
else
echo "Python is required for direct config-center update."
exit 1
fi
WORKDIR="$(mktemp -d)"
trap 'rm -rf "$WORKDIR"' EXIT
echo "Updating config-center after image build succeeded."
git clone git@git.imall.cloud:im-group/config-center.git "$WORKDIR/config-center"
cd "$WORKDIR/config-center"
"$PYTHON" - "$CONFIG_CENTER_UPDATES_FILE" "$CONFIG_CENTER_CLUSTERS" <<'PY'
from __future__ import annotations
import sys
from pathlib import Path
updates_file = Path(sys.argv[1])
clusters = sys.argv[2].split()
updates = [
tuple(line.split("|"))
for line in updates_file.read_text(encoding="utf-8").splitlines()
if line.strip()
]
def update_file(path: Path, deployment: str, image: str, container: str):
lines = path.read_text(encoding="utf-8").splitlines(keepends=True)
changed = False
matched = False
def indent_of(line: str) -> int:
return len(line) - len(line.lstrip(" "))
doc_starts = [
idx for idx, line in enumerate(lines) if line.lstrip(" ").startswith("- apiVersion:")
]
doc_starts.append(len(lines))
for pos, start in enumerate(doc_starts[:-1]):
end = doc_starts[pos + 1]
block = lines[start:end]
if not any(line.lstrip(" ").strip() == "kind: Deployment" for line in block):
continue
metadata_idx = next(
(idx for idx, line in enumerate(block) if line.lstrip(" ").startswith("metadata:")),
None,
)
if metadata_idx is None:
continue
metadata_indent = indent_of(block[metadata_idx])
next_peer = next(
(
idx
for idx in range(metadata_idx + 1, len(block))
if block[idx].strip() and indent_of(block[idx]) <= metadata_indent
),
len(block),
)
metadata = block[metadata_idx:next_peer]
if not any(
line.lstrip(" ").startswith("name: ")
and line.split(":", 1)[1].strip() == deployment
for line in metadata
):
continue
list_starts = []
for idx, line in enumerate(block):
stripped = line.lstrip(" ")
if stripped.startswith(("- image:", "- command:", "- name:")):
list_starts.append(idx)
list_starts.append(len(block))
for item_pos, item_start in enumerate(list_starts[:-1]):
item_end = list_starts[item_pos + 1]
item = block[item_start:item_end]
if container and not any(
line.lstrip(" ").startswith("name: ")
and line.split(":", 1)[1].strip() == container
for line in item
):
continue
for rel_idx, line in enumerate(item):
stripped = line.lstrip(" ")
if stripped.startswith("image:") or stripped.startswith("- image:"):
matched = True
abs_idx = start + item_start + rel_idx
old_line = lines[abs_idx]
indent = indent_of(old_line)
newline = "\n" if old_line.endswith("\n") else ""
prefix = old_line[:indent]
marker = "- " if old_line.lstrip(" ").startswith("- image:") else ""
lines[abs_idx] = f"{prefix}{marker}image: {image}{newline}"
changed = changed or lines[abs_idx] != old_line
break
if matched:
break
if matched:
break
if changed:
path.write_text("".join(lines), encoding="utf-8")
return matched, changed
matched_any = False
changed_any = False
for cluster in clusters:
file = Path("apps/openim/overlays") / cluster / "deployments.yaml"
if not file.exists():
raise SystemExit(f"{file} does not exist")
for deployment, image, container in updates:
matched, changed = update_file(file, deployment, image, container)
status = "updated" if changed else "already current" if matched else "no matching change"
print(f"{cluster}: {deployment} -> {image}: {status}")
matched_any = matched_any or matched
changed_any = changed_any or changed
if not matched_any:
raise SystemExit("no config-center deployment/container matches were found")
if not changed_any:
print("All matching config-center images are already current.")
PY
if git diff --quiet -- apps/openim/overlays; then
echo "No config-center image changes to commit."
exit 0
fi
git config user.name "gitea-actions"
git config user.email "gitea-actions@git.imall.cloud"
git add apps/openim/overlays/*/deployments.yaml
git commit -m "Deploy scheduler-backend image after successful build"
git push origin main

View File

@@ -0,0 +1,120 @@
name: Build scheduler-backend image
on:
push:
branches: [dev, main]
paths:
- "**"
workflow_dispatch:
inputs:
tag:
description: "Optional image tag. Defaults to <branch>-<short-sha>."
required: false
default: ""
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: docker.io
DOCKER_USER: ${{ secrets.DOCKER_USERNAME || 'mag1666888' }}
SERVICE_NAME: scheduler-backend
DEPLOYMENT_NAME: scheduler-backend
CONFIG_CENTER_CONTAINER: scheduler-backend
DOCKERFILE: Dockerfile
INPUT_TAG: ${{ github.event.inputs.tag }}
jobs:
build-and-push:
runs-on: [openim, config-center]
steps:
- name: Configure SSH
env:
GIT_SSH_PRIVATE_KEY: ${{ secrets.GIT_SSH_PRIVATE_KEY }}
run: |
set -euo pipefail
if [ -z "${GIT_SSH_PRIVATE_KEY:-}" ]; then
echo "GIT_SSH_PRIVATE_KEY is required."
exit 1
fi
mkdir -p ~/.ssh
chmod 700 ~/.ssh
if printf '%s' "$GIT_SSH_PRIVATE_KEY" | grep -q "BEGIN .*PRIVATE KEY"; then
printf '%s\n' "$GIT_SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
else
printf '%s' "$GIT_SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
fi
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H git.imall.cloud >> ~/.ssh/known_hosts 2>/dev/null || true
chmod 644 ~/.ssh/known_hosts
ssh -o BatchMode=yes -o StrictHostKeyChecking=yes -T git@git.imall.cloud || true
- name: Checkout
run: |
set -euo pipefail
BRANCH_NAME="${GITHUB_REF_NAME:-${GITEA_REF_NAME:-main}}"
COMMIT_SHA="${GITHUB_SHA:-${GITEA_SHA:-}}"
git init .
git remote remove origin 2>/dev/null || true
git remote add origin git@git.imall.cloud:im-group/scheduler-backend.git
if [ -n "$COMMIT_SHA" ]; then
git fetch --depth 1 origin "$COMMIT_SHA"
fi
if [ -z "$COMMIT_SHA" ]; then
git fetch --depth 1 origin "$BRANCH_NAME"
fi
git checkout --force FETCH_HEAD
- name: Login to Docker Hub
uses: docker/login-action@v3.3.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.8.0
- name: Test
run: |
set -euo pipefail
docker build \
--target test \
-f "$DOCKERFILE" \
.
- name: Build and push image
run: |
set -euo pipefail
SHORT_SHA="$(git rev-parse --short=7 HEAD)"
BRANCH_NAME="${GITHUB_REF_NAME:-${GITEA_REF_NAME:-$(git rev-parse --abbrev-ref HEAD)}}"
BRANCH_TAG="$(printf '%s' "$BRANCH_NAME" | sed 's/[^a-zA-Z0-9-]/-/g' | tr '[:upper:]' '[:lower:]')"
if [ -n "${INPUT_TAG:-}" ]; then
VERSION_TAG="$INPUT_TAG"
else
VERSION_TAG="${BRANCH_TAG}-${SHORT_SHA}"
fi
IMAGE="${DOCKER_USER}/${SERVICE_NAME}:${VERSION_TAG}"
docker buildx build \
--platform linux/amd64 \
-f "$DOCKERFILE" \
-t "$IMAGE" \
--push \
.
echo "Built and pushed $IMAGE for deployment $DEPLOYMENT_NAME"
CONFIG_CENTER_UPDATES_FILE="$(mktemp)"
export CONFIG_CENTER_UPDATES_FILE
printf '%s|%s|%s\n' "$DEPLOYMENT_NAME" "$IMAGE" "$CONFIG_CENTER_CONTAINER" > "$CONFIG_CENTER_UPDATES_FILE"
CONFIG_CENTER_CLUSTERS="${CONFIG_CENTER_CLUSTERS:-ack-dev}" \
bash .gitea/scripts/update-config-center-images.sh