Skip to content

Commit 06ce5be

Browse files
zihugithubzihugithub
andauthored
[CICD] refactor: migrate test runner from python run.py to flagscale CLI (flagos-ai#1131)
### PR Category CICD ### PR Types Improvements ### PR Description - Replace old `python run.py` invocations with `flagscale` CLI commands - Use bash arrays instead of eval for validator and get_test_configs - Update serve stop to use `flagscale serve --stop` - Simplify exp_dir extraction with grep -oP --------- Co-authored-by: zihugithub <fbye@baai.ac.cn>
1 parent 7c59f37 commit 06ce5be

6 files changed

Lines changed: 79 additions & 38 deletions

File tree

.github/workflows/functional_tests_hetero_train.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,13 @@ jobs:
167167
--no-system --no-dev --no-base --no-task \
168168
--src-deps megatron-lm \
169169
--retry-count 3
170+
171+
# Install FlagScale CLI
172+
pip install . --no-build-isolation --root-user-action=ignore || { echo "❌ FlagScale CLI install failed"; exit 1; }
173+
174+
# Verify installation
175+
command -v flagscale || { echo "❌ FlagScale CLI not found in PATH"; exit 1; }
176+
echo "✅ FlagScale CLI installed successfully: $(flagscale --version 2>/dev/null || echo 'version unknown')"
170177
timeout-minutes: 30
171178

172179
- name: Run functional tests

.github/workflows/functional_tests_inference.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,17 @@ jobs:
151151
echo "Python location: $(which python)"
152152
echo "Python version: $(python --version)"
153153
154+
# Install FlagScale CLI
155+
pip install . --no-build-isolation --root-user-action=ignore || { echo "❌ FlagScale CLI install failed"; exit 1; }
156+
157+
# Verify installation
158+
command -v flagscale || { echo "❌ FlagScale CLI not found in PATH"; exit 1; }
159+
echo "✅ FlagScale CLI installed successfully: $(flagscale --version 2>/dev/null || echo 'version unknown')"
160+
154161
# For inference task: all dependencies are pre-installed in the env
155162
# No additional installation needed
156163
echo "✅ Environment ready for inference tests"
164+
157165
timeout-minutes: 5
158166

159167
- name: Run functional tests

.github/workflows/functional_tests_rl.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ jobs:
151151
echo "Python location: $(which python)"
152152
echo "Python version: $(python --version)"
153153
154+
# Install FlagScale CLI
155+
pip install . --no-build-isolation --root-user-action=ignore || { echo "❌ FlagScale CLI install failed"; exit 1; }
156+
157+
# Verify installation
158+
command -v flagscale || { echo "❌ FlagScale CLI not found in PATH"; exit 1; }
159+
echo "✅ FlagScale CLI installed successfully: $(flagscale --version 2>/dev/null || echo 'version unknown')"
160+
154161
# For RL task: all dependencies are pre-installed in the env
155162
# No additional installation needed
156163
echo "✅ Environment ready for RL tests"

.github/workflows/functional_tests_serve.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ jobs:
151151
echo "Python location: $(which python)"
152152
echo "Python version: $(python --version)"
153153
154+
# Install FlagScale CLI
155+
pip install . --no-build-isolation --root-user-action=ignore || { echo "❌ FlagScale CLI install failed"; exit 1; }
156+
157+
# Verify installation
158+
command -v flagscale || { echo "❌ FlagScale CLI not found in PATH"; exit 1; }
159+
echo "✅ FlagScale CLI installed successfully: $(flagscale --version 2>/dev/null || echo 'version unknown')"
160+
154161
# For serve task: all dependencies are pre-installed in the env
155162
# No additional installation needed
156163
echo "Environment ready for serve tests"

.github/workflows/functional_tests_train.yml

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -147,24 +147,17 @@ jobs:
147147
148148
echo "Python location: $(which python)"
149149
echo "Python version: $(python --version)"
150-
# # Install task source dependencies (pip deps are pre-installed in the env)
151-
# echo "Installing task source dependencies..."
152-
153-
# # Derive install-dir from env_path (e.g., /root/miniconda3 -> /root)
154-
# INSTALL_DIR=""
155-
# if [ "$PKG_MGR" = "conda" ] && [ -n "$ENV_PATH" ]; then
156-
# INSTALL_DIR=$(dirname "$ENV_PATH")
157-
# fi
158-
159-
# # Only install Megatron-LM source dep (pip deps are pre-installed in Docker image)
160-
# ./tools/install/install.sh \
161-
# --platform ${{ inputs.platform }} \
162-
# --task train \
163-
# --pkg-mgr "$PKG_MGR" \
164-
# ${ENV_NAME:+--env-name "$ENV_NAME"} \
165-
# ${INSTALL_DIR:+--install-dir "$INSTALL_DIR"} \
166-
# --no-system --no-dev --no-base --no-task \
167-
# --retry-count 3
150+
151+
# Install FlagScale CLI
152+
pip install . --no-build-isolation --root-user-action=ignore || { echo "❌ FlagScale CLI install failed"; exit 1; }
153+
154+
# Verify installation
155+
command -v flagscale || { echo "❌ FlagScale CLI not found in PATH"; exit 1; }
156+
echo "✅ FlagScale CLI installed successfully: $(flagscale --version 2>/dev/null || echo 'version unknown')"
157+
158+
# For train task: all dependencies are pre-installed in the env
159+
# No additional installation needed
160+
echo "Environment ready for train tests"
168161
timeout-minutes: 30
169162

170163
- name: Run functional tests

tests/test_utils/runners/run_functional_tests.sh

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,16 +84,23 @@ run_test() {
8484

8585
# Clean old results
8686
# Extract exp_dir from config file and clean it
87-
local exp_dir=$(grep -E '^\s*exp_dir:' "$config_file" | head -1 | sed 's/.*exp_dir:\s*//' | tr -d '"' | tr -d "'")
87+
local exp_dir=$(grep -oP '^\s*exp_dir:\s*\K\S+' "$config_file" | head -1 | tr -d "\"'")
8888
if [ -n "$exp_dir" ]; then
8989
log_info "Cleaning old results in: $exp_dir"
9090
rm -rf "$exp_dir"/* 2>/dev/null || true
9191
fi
9292

93-
# Run test
94-
log_info "Start operation for executing the task: "
95-
log_info " python run.py --config-path ${conf_dir} --config-name ${config} action=test"
96-
python run.py --config-path ${conf_dir} --config-name ${config} action=test || return 1
93+
# Map task name to flagscale CLI subcommand
94+
# e.g. hetero_train -> train, train -> train, others unchanged
95+
local cli_task="$task"
96+
case "$task" in
97+
*train*) cli_task="train" ;;
98+
esac
99+
100+
# Run test via flagscale CLI
101+
# --config expects the full YAML path
102+
log_info "Running: flagscale $cli_task $model --config $config_file --test"
103+
flagscale "$cli_task" "$model" --config "$config_file" --test || return 1
97104

98105
# Match the corresponding comparison function according to task type
99106
# Matching rules:
@@ -120,44 +127,56 @@ run_test() {
120127
;;
121128
esac
122129

123-
# Validate results if validator exists
124-
if [ -f "$PROJECT_ROOT/tests/test_utils/runners/check_results.py" ]; then
125-
local validator_cmd="python -m pytest \"$PROJECT_ROOT/tests/test_utils/runners/check_results.py::$compare_function\" \
126-
--path=tests/functional_tests --task=\"$task\" --model=\"$model\" \
127-
--case=\"$config\" --platform=\"$PLATFORM\""
128-
[ -n "$CURRENT_DEVICE" ] && validator_cmd="$validator_cmd --device=\"$CURRENT_DEVICE\""
129-
130+
# Validate results using pytest-based checker (check_results.py)
131+
# Build command as an array to avoid eval and ensure safe quoting.
132+
local check_results="$PROJECT_ROOT/tests/test_utils/runners/check_results.py"
133+
if [ -f "$check_results" ]; then
134+
local validator_cmd=(
135+
python -m pytest "${check_results}::${compare_function}"
136+
--path=tests/functional_tests
137+
"--task=$task" "--model=$model"
138+
"--case=$config" "--platform=$PLATFORM"
139+
)
140+
[ -n "$CURRENT_DEVICE" ] && validator_cmd+=("--device=$CURRENT_DEVICE")
141+
142+
# For serve tasks, wait for the service to be fully ready before validation
130143
if [ "$task" = "serve" ]; then
131144
log_info "Waiting 1 minute for service to be ready..."
132145
sleep 1m
133146
fi
134147

135-
if ! eval "$validator_cmd"; then
148+
if ! "${validator_cmd[@]}"; then
136149
log_error "Validation failed for $task/$model/$config"
137150
return 1
138151
fi
139152

153+
# Stop the serve process after validation completes
140154
if [ "$task" = "serve" ]; then
141-
log_info "Stop operation for executing the serve task: "
142-
log_info " python run.py --config-path ${conf_dir} --config-name ${config} action=stop"
143-
python run.py --config-path ${conf_dir} --config-name ${config} action=stop
155+
log_info "Stopping serve: flagscale serve $model --config $config_file --stop"
156+
flagscale serve "$model" --config "$config_file" --stop
144157
fi
145158
fi
146159

147160
log_success "Test completed: $task/$model/$config"
148161
}
149162

150163
# Get tests from platform configuration
164+
# Returns JSON describing which test cases to run for the given device/task/model.
165+
# Uses an array instead of eval to safely handle paths with special characters.
151166
get_test_configs() {
152167
local device="$1"
153168
local task="$2"
154169
local model="$3"
155170
local list="$4"
156171

157-
local cmd="python \"$SCRIPT_DIR/parse_config.py\" --platform \"$PLATFORM\" --device \"$device\" --type functional --task \"$task\""
158-
[ -n "$model" ] && cmd="$cmd --model \"$model\""
159-
[ -n "$list" ] && cmd="$cmd --list \"$list\""
160-
eval "$cmd" 2>/dev/null || echo ""
172+
local cmd=(
173+
python "$SCRIPT_DIR/parse_config.py"
174+
--platform "$PLATFORM" --device "$device"
175+
--type functional --task "$task"
176+
)
177+
[ -n "$model" ] && cmd+=(--model "$model")
178+
[ -n "$list" ] && cmd+=(--list "$list")
179+
"${cmd[@]}" 2>/dev/null || echo ""
161180
}
162181

163182
# Parse and run tests using helper module

0 commit comments

Comments
 (0)