Copilot commented on code in PR #8070:
URL: https://github.com/apache/incubator-seata/pull/8070#discussion_r3135254893


##########
.github/workflows/raft-compatibility.yml:
##########
@@ -0,0 +1,164 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+name: "raft-compatibility"
+
+on:
+  push:
+    branches: [ 2.x, develop, master ]
+    paths:
+      - 'server/**'
+      - 'discovery/**'
+      - 'distribution/**'
+      - 'test-suite/**'
+      - 'script/**'
+      - '.github/workflows/**'
+  pull_request:
+    branches: [ 2.x, develop, master ]
+    types: [opened, reopened, synchronize]
+    paths:
+      - 'server/**'
+      - 'discovery/**'
+      - 'distribution/**'
+      - 'test-suite/**'
+      - 'script/**'
+      - '.github/workflows/**'
+  workflow_dispatch:
+
+env:
+  SEATA_PREVIOUS_RAFT_VERSION: 2.6.0
+  SEATA_PREVIOUS_RAFT_SERVER_ARCHIVE_URL: 
https://archive.apache.org/dist/incubator/seata/2.6.0/apache-seata-2.6.0-incubating-bin.tar.gz
+permissions:
+  contents: read
+
+jobs:
+  raft-current-server-current-client:
+    name: "raft-current-server-current-client"
+    runs-on: ubuntu-latest
+    steps:
+      - name: "Checkout"
+        uses: actions/checkout@v3
+      - name: "Set up Java JDK 25"
+        uses: actions/[email protected]
+        with:
+          distribution: 'zulu'
+          java-version: 25
+          cache: 'maven'
+      - name: "Prepare scripts"
+        run: chmod +x ./script/ci/raft-cluster.sh
+      - name: "Build current server-only distribution"
+        run: |
+          ./mvnw -pl distribution -am -Prelease-seata,release-seata-server 
-DskipTests package \

Review Comment:
   The build step activates both `release-seata` and `release-seata-server`. 
Since `release-seata` adds extra distribution dependencies (notably 
`seata-namingserver`) it can significantly increase the reactor build 
scope/time even though its assembly execution is bound to `install` and won’t 
run during `package`. If the intent is to build only the server-only tarball 
for this workflow, consider enabling only `release-seata-server` here.
   ```suggestion
             ./mvnw -pl distribution -am -Prelease-seata-server -DskipTests 
package \
   ```



##########
distribution/release-seata-server.xml:
##########
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<assembly>
+    <id>${project.version}-bin</id>
+    <includeBaseDirectory>true</includeBaseDirectory>
+    <baseDirectory>apache-seata-server-${project.version}-bin</baseDirectory>
+    <formats>
+        <format>dir</format>
+        <format>tar.gz</format>
+    </formats>
+
+    <fileSets>
+        <fileSet>
+            <includes>
+                <include>plugins/**</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            <includes>
+                <include>licenses/*</include>
+            </includes>
+            <outputDirectory>seata-server/</outputDirectory>
+        </fileSet>
+
+        <fileSet>
+            <directory>../server/src/main/resources/logback/</directory>
+            <outputDirectory>seata-server/conf/logback/</outputDirectory>
+            <includes>
+                <include>**/*.xml</include>
+            </includes>
+        </fileSet>
+
+        <fileSet>
+            
<directory>../ext/apm-seata-skywalking-plugin/target/ext/skywalking-agent/</directory>
+            <outputDirectory>seata-server/ext/apm-skywalking</outputDirectory>
+        </fileSet>
+
+        <fileSet>
+            <directory>../server/target/lib/</directory>
+            <outputDirectory>seata-server/lib</outputDirectory>
+        </fileSet>
+
+        <fileSet>

Review Comment:
   The server-only assembly descriptor omits the `bin/` startup scripts that 
are present in the full `release-seata.xml` distribution (e.g., 
`seata-server.sh`, `seata-server.bat`, `seata-setup.sh` with executable 
fileMode). This likely makes the server-only tarball harder to run as a 
standalone distribution. Consider including the server `bin/*` entries (without 
namingserver scripts) and setting the appropriate `fileMode`.
   ```suggestion
           <fileSet>
               <directory>../bin/</directory>
               <outputDirectory>seata-server/bin</outputDirectory>
               <fileMode>0755</fileMode>
               <includes>
                   <include>seata-server.sh</include>
                   <include>seata-server.bat</include>
                   <include>seata-setup.sh</include>
               </includes>
           </fileSet>
   
           <fileSet>
   ```



##########
script/ci/raft-cluster.sh:
##########
@@ -0,0 +1,363 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+set -euo pipefail
+
+usage() {
+  cat <<USAGE
+Usage:
+  $0 start --distribution <archive|url|version> --workspace <dir> [--env-file 
<path>] [--group <name>]
+  $0 stop --workspace <dir>
+USAGE
+}
+
+command=${1:-}
+if [[ -z "$command" ]]; then
+  usage
+  exit 1
+fi
+shift || true
+
+distribution=""
+workspace=""
+env_file=""
+group="default"
+
+while [[ $# -gt 0 ]]; do
+  case "$1" in
+    --distribution)
+      distribution="$2"
+      shift 2
+      ;;
+    --workspace)
+      workspace="$2"
+      shift 2
+      ;;
+    --env-file)
+      env_file="$2"
+      shift 2
+      ;;
+    --group)
+      group="$2"
+      shift 2
+      ;;
+    *)
+      echo "Unknown argument: $1" >&2
+      usage
+      exit 1
+      ;;
+  esac
+done
+
+require_workspace() {
+  if [[ -z "$workspace" ]]; then
+    echo "--workspace is required" >&2
+    exit 1
+  fi
+}
+
+resolve_distribution_url() {
+  local version="$1"
+  local candidates=(
+    
"https://github.com/apache/incubator-seata/releases/download/v${version}/apache-seata-${version}-bin.tar.gz";
+    
"https://github.com/apache/incubator-seata/releases/download/v${version}/apache-seata-${version}-incubating-bin.tar.gz";
+    
"https://archive.apache.org/dist/incubator/seata/${version}/apache-seata-${version}-bin.tar.gz";
+    
"https://archive.apache.org/dist/incubator/seata/${version}/apache-seata-${version}-incubating-bin.tar.gz";
+  )
+  local candidate
+  for candidate in "${candidates[@]}"; do
+    if curl -fsIL "$candidate" >/dev/null 2>&1; then
+      echo "$candidate"
+      return 0
+    fi
+  done
+  echo "Unable to resolve distribution archive for version ${version}" >&2
+  return 1
+}
+
+download_distribution() {
+  local input="$1"
+  local downloads_dir="$workspace/downloads"
+  mkdir -p "$downloads_dir"
+
+  if [[ -f "$input" ]]; then
+    echo "$input"
+    return 0
+  fi
+
+  local source="$input"
+  if [[ ! "$input" =~ ^https?:// ]]; then
+    if ! source="$(resolve_distribution_url "$input")"; then
+      exit 1
+    fi
+  fi
+
+  local filename
+  filename="$(basename "${source%%\?*}")"
+  local target="$downloads_dir/$filename"
+  curl -fsSL "$source" -o "$target"
+  echo "$target"
+}
+
+extract_distribution() {
+  local archive="$1"
+  local extract_dir="$workspace/distribution"
+  rm -rf "$extract_dir"
+  mkdir -p "$extract_dir"
+  case "$archive" in
+    *.tar.gz|*.tgz)
+      tar -xzf "$archive" -C "$extract_dir"
+      ;;
+    *.zip)
+      unzip -q "$archive" -d "$extract_dir"
+      ;;
+    *)
+      echo "Unsupported distribution format: $archive" >&2
+      exit 1
+      ;;
+  esac
+}
+
+locate_server_home() {
+  local server_home
+  server_home="$(find "$workspace/distribution" -maxdepth 4 -type d -name 
seata-server | head -n 1)"
+  if [[ -z "$server_home" ]]; then
+    echo "Unable to locate seata-server home under $workspace/distribution" >&2
+    exit 1
+  fi
+  if [[ ! -f "$server_home/target/seata-server.jar" ]]; then
+    echo "Unable to locate seata-server.jar under $server_home/target" >&2
+    exit 1
+  fi
+  echo "$server_home"
+}
+
+detect_host_ip() {
+  local host_ip
+  host_ip="$(hostname -I | awk '{print $1}')"
+  if [[ -z "$host_ip" ]]; then
+    echo "Unable to determine non-loopback host IP" >&2
+    exit 1
+  fi
+  echo "$host_ip"
+}
+
+write_cluster_env() {
+  local target_file="$1"
+  local control_csv="$2"
+  local metadata_csv="$3"
+  local tx_csv="$4"
+  local leader_control="$5"
+  local leader_tx="$6"
+  local leader_term="$7"
+  cat >> "$target_file" <<EOF_ENV
+SEATA_RAFT_WORKSPACE=$workspace
+SEATA_RAFT_GROUP=$group
+SEATA_RAFT_CONTROL_ADDRS=$control_csv
+SEATA_RAFT_METADATA_ADDRS=$metadata_csv
+SEATA_RAFT_TX_ADDRS=$tx_csv
+SEATA_RAFT_LEADER_CONTROL_ADDR=$leader_control
+SEATA_RAFT_LEADER_ADDR=$leader_tx
+SEATA_RAFT_TERM=$leader_term
+EOF_ENV
+}
+
+wait_for_cluster() {
+  local metadata_csv="$1"
+  local output_json="$workspace/cluster-metadata.json"
+  python3 - "$metadata_csv" "$group" "$output_json" <<'PY'
+import json
+import sys
+import time
+import urllib.error
+import urllib.request
+
+metadata_addresses = sys.argv[1].split(',')
+group = sys.argv[2]
+outfile = sys.argv[3]
+deadline = time.time() + 180
+last_error = None
+while time.time() < deadline:
+    for metadata_address in metadata_addresses:
+        url = f"http://{metadata_address}/metadata/v1/cluster?group={group}";
+        try:
+            with urllib.request.urlopen(url, timeout=5) as response:
+                if response.status != 200:
+                    continue
+                payload = json.loads(response.read().decode('utf-8'))
+                nodes = payload.get('nodes') or []
+                leader = next((node for node in nodes if str(node.get('role', 
'')).upper() == 'LEADER'), None)
+                if leader and leader.get('transaction') and 
leader.get('control'):
+                    with open(outfile, 'w', encoding='utf-8') as handle:
+                        json.dump(payload, handle)
+                    sys.exit(0)
+        except Exception as exc:
+            last_error = exc
+    time.sleep(2)
+message = f"Timed out waiting for raft cluster readiness. Last error: 
{last_error}"
+raise SystemExit(message)
+PY
+}
+
+start_cluster() {
+  if [[ -z "$distribution" ]]; then
+    echo "--distribution is required for start" >&2
+    exit 1
+  fi
+  require_workspace
+
+  rm -rf "$workspace"
+  mkdir -p "$workspace"
+
+  local archive
+  archive="$(download_distribution "$distribution")"
+  extract_distribution "$archive"
+
+  local server_home
+  server_home="$(locate_server_home)"
+  local pids_file="$workspace/pids"
+  : > "$pids_file"
+  local host_ip
+  host_ip="$(detect_host_ip)"
+
+  local -a controls tx_ports internal_ports
+  controls=(7091 7092 7093)
+  tx_ports=(8091 8092 8093)
+  internal_ports=(9091 9092 9093)
+
+  local internal_csv control_csv metadata_csv tx_csv
+  
internal_csv="${host_ip}:${internal_ports[0]},${host_ip}:${internal_ports[1]},${host_ip}:${internal_ports[2]}"
+  
control_csv="${host_ip}:${controls[0]},${host_ip}:${controls[1]},${host_ip}:${controls[2]}"
+  
tx_csv="${host_ip}:${tx_ports[0]},${host_ip}:${tx_ports[1]},${host_ip}:${tx_ports[2]}"
+  metadata_csv="$tx_csv"

Review Comment:
   `metadata_csv` is currently set to the transaction ports (`tx_csv`), but the 
metadata endpoint used throughout this script/tests is `/metadata/v1/cluster` 
over HTTP and corresponds to the node "control" endpoint (derived from 
`server.port`). With the current config (server.port=709x, service-port=809x), 
this makes the readiness probe and exported `SEATA_RAFT_METADATA_ADDRS` point 
at the wrong ports, breaking raft discovery/failover checks. Set `metadata_csv` 
to `control_csv` (or otherwise ensure the HTTP metadata endpoint is reachable 
on the addresses exported in `SEATA_RAFT_METADATA_ADDRS`).
   ```suggestion
     metadata_csv="$control_csv"
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to