From f71999b14ff69e713dd08034ae22fa4d64d691a7 Mon Sep 17 00:00:00 2001 From: Manish Kumar <107841575+sondermanish@users.noreply.github.com> Date: Fri, 19 Sep 2025 16:25:16 +0530 Subject: [PATCH] chore: inclusive redis-cluster redis-cli (#41239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description > [!TIP] > _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team)._ > > _Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR._ Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Git" ### :mag: Cypress test results > [!IMPORTANT] > 🟣 🟣 🟣 Your tests are running. > Tests running at: > Commit: eded40175d45e1294c0b3cb2a3efcd9496373844 > Workflow: `PR Automation test suite` > Tags: `@tag.Git` > Spec: `` >
Fri, 19 Sep 2025 10:02:49 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit - New Features - Added support for Redis Cluster URLs in Git-connected features, enabling redis://, rediss://, and redis-cluster:// configurations. - Introduced a configurable Git root path to improve cloning behavior across environments. - Refactor - Unified Redis operations behind a single execution path to ensure consistent behavior and compatibility across connection types. - Streamlined Git initialization and argument handling to reduce edge cases during repository setup. --- .../appsmith-git/src/main/resources/git.sh | 127 +++++++++++++++--- .../server/aspect/GitRouteAspect.java | 1 + 2 files changed, 111 insertions(+), 17 deletions(-) diff --git a/app/server/appsmith-git/src/main/resources/git.sh b/app/server/appsmith-git/src/main/resources/git.sh index b0a123e06d..f7e6abf5e6 100644 --- a/app/server/appsmith-git/src/main/resources/git.sh +++ b/app/server/appsmith-git/src/main/resources/git.sh @@ -34,13 +34,14 @@ git_clone() { local private_key="$1" local remote_url="$2" local target_folder="$3" + local git_root="$4" - local temp_private_key=$(mktemp /dev/shm/tmp.XXXXXX) + local temp_private_key=$(mktemp ${git_root}tmp.XXXXXX) trap 'rm -rf "'"$temp_private_key"'"' EXIT ERR echo "$private_key" > "$temp_private_key" - git -C "$target_folder" init "$target_folder" --initial-branch=none + git -C "$target_folder" init --initial-branch=none git -C "$target_folder" remote add origin "$remote_url" GIT_SSH_COMMAND="ssh -i $temp_private_key -o StrictHostKeyChecking=no" git -C "$target_folder" fetch origin } @@ -54,10 +55,10 @@ git_clean_up() { trap 'rm -rf "'"$target_folder"'"' EXIT ERR ## delete the repository from redis - redis-cli -u "$redis_url" DEL "$redis_key" + redis-exec "$redis_url" DEL "$redis_key" ## delete the repository branch_store - redis-cli -u "$redis_url" DEL "$key_value_pair_key" + redis-exec "$redis_url" DEL "$key_value_pair_key" } # Uploads git repo to Redis as compressed archive @@ -72,7 +73,7 @@ git_upload() { rm -f "$target_folder/.git/index.lock" upload_branches_to_redis_hash "$target_folder" "$redis_url" "$key_value_pair_key" - tar -cf - -C "$target_folder" . | zstd -q --threads=0 | base64 -w 0 | redis-cli -u "$redis_url" --raw -x SETEX "$redis_key" "$GIT_ARTIFACT_TTL" + tar -cf - -C "$target_folder" . | zstd -q --threads=0 | base64 -w 0 | redis-exec "$redis_url" --raw -x SETEX "$redis_key" "$GIT_ARTIFACT_TTL" } upload_branches_to_redis_hash() { @@ -85,8 +86,8 @@ upload_branches_to_redis_hash() { log_info "Preparing to upload branch store. Current branches: $branches" - redis-cli -u "$redis_url" DEL "$key_value_pair_key" - redis-cli -u "$redis_url" HSET "$key_value_pair_key" $branches + redis-exec "$redis_url" DEL "$key_value_pair_key" + redis-exec "$redis_url" HSET "$key_value_pair_key" $branches } # Downloads git repo from Redis or clones if not cached @@ -105,8 +106,8 @@ git_download() { rm -rf "$target_folder" mkdir -p "$target_folder" - if [ "$(redis-cli -u "$redis_url" --raw EXISTS "$redis_key")" = "1" ]; then - redis-cli -u "$redis_url" --raw GET "$redis_key" | base64 -d | zstd -d --threads=0 | tar -xf - -C "$target_folder" + if [ "$(redis-exec "$redis_url" --raw EXISTS "$redis_key")" = "1" ]; then + redis-exec "$redis_url" --raw GET "$redis_key" | base64 -d | zstd -d --threads=0 | tar -xf - -C "$target_folder" else log_warn "Cache miss. Repository: $target_folder with key: $redis_key does not exist in redis." return 1 @@ -123,11 +124,12 @@ git_clone_and_checkout() { local author_name="$2" local private_key="$3" local remote_url="$4" - local target_folder="$5" - local redis_url="$6" - local key_value_pair_key="$7" + local git_root="$5" + local target_folder="$6" + local redis_url="$7" + local key_value_pair_key="$8" - ## branches are after argument 7 + ## branches are after argument 8 trap 'rm -rf "'"$target_folder"'"' ERR @@ -138,16 +140,16 @@ git_clone_and_checkout() { ## create the same directory mkdir -p "$target_folder" - git_clone "$private_key" "$remote_url" "$target_folder" + git_clone "$private_key" "$remote_url" "$target_folder" "$git_root" git -C "$target_folder" config user.name "$author_name" git -C "$target_folder" config user.email "$author_email" git -C "$target_folder" config fetch.parallel 4 git -C "$target_folder" reflog expire --expire=now --all git -C "$target_folder" gc --prune=now --aggressive - # This provides all the arguments from arg 5 onwards to the function git_co_from_redis. + # This provides all the arguments from arg 6 onwards to the function git_co_from_redis. # This includes the target folder, redis url, key value pair key, and all branch names from db. - git_checkout_from_branch_store ${@:5} + git_checkout_from_branch_store ${@:6} } git_checkout_from_branch_store() { @@ -159,7 +161,7 @@ git_checkout_from_branch_store() { # fetch raw value log_info "Searching Redis branch-store for key : $key_value_pair_key" local raw - raw=$(redis-cli -u "$redis_url" --raw HGETALL "$key_value_pair_key" | sed 's/\"//g') + raw=$(redis-exec "$redis_url" --raw HGETALL "$key_value_pair_key" | sed 's/\"//g') # error handling: empty or missing key if [[ -z "$raw" ]]; then @@ -253,3 +255,94 @@ git_merge_branch() { git -C "$target_folder" checkout "$destination_branch" git -C "$target_folder" merge "$source_branch" --strategy=recursive --allow-unrelated-histories --no-edit } + +# Redis CLI wrapper that handles different URL schemes +# Usage: redis-exec [redis-cli-args...] +# Supports: redis://, rediss://, redis-cluster:// +redis-exec() { + local url="$1" + + if [[ -z "$url" ]]; then + log_error "redis-exec: missing Redis URL" + log_error "Usage: redis-exec [redis-cli-args...]" + return 1 + fi + + case "$url" in + redis://*|rediss://*) + # Standard Redis URL - pass directly to redis-cli -u + redis-cli -u "$url" "${@:2}" + ;; + redis-cluster://*) + # Cluster URL - extract components and use cluster mode + local stripped="${url#redis-cluster://}" + + # Split into authority and path parts + local authority="${stripped%%/*}" + local path_part="${stripped#*/}" + if [[ "$path_part" == "$stripped" ]]; then + path_part="" # No path present + fi + + # Extract credentials from authority (user:pass@host:port) + local credentials="" + local host_port="$authority" + if [[ "$authority" == *"@"* ]]; then + credentials="${authority%%@*}" + host_port="${authority##*@}" + fi + + # Parse credentials + local username="" + local password="" + if [[ -n "$credentials" ]]; then + if [[ "$credentials" == *":"* ]]; then + username="${credentials%%:*}" + password="${credentials##*:}" + else + password="$credentials" # Only password provided + fi + fi + + # Extract host and port + local host="${host_port%:*}" + local port="${host_port##*:}" + + # If no port specified, default to 6379 + if [[ "$port" == "$host" ]]; then + port="6379" + fi + + # Extract database number from path + local database="" + if [[ -n "$path_part" && "$path_part" =~ ^[0-9]+(\?.*)?$ ]]; then + database="${path_part%%\?*}" # Remove query params if present + fi + + # Build redis-cli command + local cmd_args=("-c" "-h" "$host" "-p" "$port") + + # Add authentication if present + if [[ -n "$username" && -n "$password" ]]; then + cmd_args+=("--user" "$username" "--pass" "$password") + elif [[ -n "$password" ]]; then + cmd_args+=("-a" "$password") + fi + + # Add database selection if specified + if [[ -n "$database" ]]; then + cmd_args+=("-n" "$database") + fi + + # Add remaining arguments + cmd_args+=("${@:2}") + + redis-cli "${cmd_args[@]}" + ;; + *) + log_error "redis-exec: unsupported URL scheme: $url" + log_error "Supported schemes: redis://, rediss://, redis-cluster://" + return 1 + ;; + esac +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/GitRouteAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/GitRouteAspect.java index 34370028c7..45dd6eb184 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/GitRouteAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/GitRouteAspect.java @@ -572,6 +572,7 @@ public class GitRouteAspect { ctx.getGitProfile().getAuthorName(), ctx.getGitKey(), ctx.getGitMeta().getRemoteUrl(), + gitServiceConfig.getGitRootPath(), ctx.getRepoPath(), redisUrl, ctx.getBranchStoreKey());