From ea33723f5efdca19299fb6185d07b5d3e4186e83 Mon Sep 17 00:00:00 2001 From: mahmamdouh Date: Mon, 22 Dec 2025 14:32:20 +0100 Subject: [PATCH] add branch validation to queue --- .../testarena_1/app/routes/jobs.py | 119 ++++++++++++++++-- .../app/templates/jobs/submit.html | 19 +++ 2 files changed, 126 insertions(+), 12 deletions(-) diff --git a/asf-cloud-server/testarena_1/app/routes/jobs.py b/asf-cloud-server/testarena_1/app/routes/jobs.py index 4dbf2c0..19229c8 100644 --- a/asf-cloud-server/testarena_1/app/routes/jobs.py +++ b/asf-cloud-server/testarena_1/app/routes/jobs.py @@ -13,36 +13,119 @@ jobs_bp = Blueprint('jobs', __name__, url_prefix='/jobs') def submit(): return render_template('jobs/submit.html') +@jobs_bp.route('/debug/ssh-test') +@login_required +def debug_ssh_test(): + """Debug endpoint to test SSH connectivity""" + if not current_user.is_admin: + return jsonify({'error': 'Admin access required'}), 403 + + try: + ssh_password = os.environ.get('SSH_PASSWORD', 'default_password') + ssh_host = os.environ.get('SSH_HOST', 'remote_host') + ssh_user = os.environ.get('SSH_USER', 'asf') + + # Test basic SSH connectivity + test_cmd = f"sshpass -p '{ssh_password}' ssh -o StrictHostKeyChecking=no {ssh_user}@{ssh_host} 'echo SSH_CONNECTION_SUCCESS'" + result = subprocess.run(test_cmd, shell=True, capture_output=True, text=True, timeout=30) + + return jsonify({ + 'ssh_config': { + 'user': ssh_user, + 'host': ssh_host, + 'password_set': bool(ssh_password and ssh_password != 'default_password') + }, + 'test_result': { + 'returncode': result.returncode, + 'stdout': result.stdout, + 'stderr': result.stderr + }, + 'success': result.returncode == 0 and 'SSH_CONNECTION_SUCCESS' in result.stdout + }) + + except Exception as e: + return jsonify({ + 'error': str(e), + 'success': False + }) + @jobs_bp.route('/submit/step1', methods=['POST']) @login_required def submit_step1(): branch_name = request.form.get('branch_name') if not branch_name: - flash('Branch name is required', 'error') - return redirect(url_for('jobs.submit')) + return jsonify({ + 'success': False, + 'error': 'Branch name is required', + 'output': '' + }) # Validate branch exists on remote try: - # Get SSH password from environment variable + # Get SSH configuration from environment variables ssh_password = os.environ.get('SSH_PASSWORD', 'default_password') ssh_host = os.environ.get('SSH_HOST', 'remote_host') ssh_user = os.environ.get('SSH_USER', 'asf') + print(f"[DEBUG] Starting branch validation for: {branch_name}") + print(f"[DEBUG] SSH Config - User: {ssh_user}, Host: {ssh_host}") + # First, clone the repository clone_cmd = f"sshpass -p '{ssh_password}' ssh -o StrictHostKeyChecking=no {ssh_user}@{ssh_host} './TPF/gitea_repo_controller.sh clone'" + print(f"[DEBUG] Executing clone command: {clone_cmd.replace(ssh_password, '***')}") + clone_result = subprocess.run(clone_cmd, shell=True, capture_output=True, text=True, timeout=60) + print(f"[DEBUG] Clone result - Return code: {clone_result.returncode}") + print(f"[DEBUG] Clone stdout: {clone_result.stdout}") + print(f"[DEBUG] Clone stderr: {clone_result.stderr}") + # Then, checkout the branch checkout_cmd = f"sshpass -p '{ssh_password}' ssh -o StrictHostKeyChecking=no {ssh_user}@{ssh_host} './TPF/gitea_repo_controller.sh checkout {branch_name}'" + print(f"[DEBUG] Executing checkout command: {checkout_cmd.replace(ssh_password, '***')}") + checkout_result = subprocess.run(checkout_cmd, shell=True, capture_output=True, text=True, timeout=60) - # Check if checkout was successful (no "fatal:" in output) - if "fatal:" in checkout_result.stdout or "fatal:" in checkout_result.stderr or checkout_result.returncode != 0: + print(f"[DEBUG] Checkout result - Return code: {checkout_result.returncode}") + print(f"[DEBUG] Checkout stdout: {checkout_result.stdout}") + print(f"[DEBUG] Checkout stderr: {checkout_result.stderr}") + + # Combine all output for analysis + full_output = f"CLONE OUTPUT:\n{clone_result.stdout}\n{clone_result.stderr}\n\nCHECKOUT OUTPUT:\n{checkout_result.stdout}\n{checkout_result.stderr}" + + # Check if checkout was successful + # Look for "fatal:" in the output which indicates failure + checkout_failed = ( + "fatal:" in checkout_result.stdout.lower() or + "fatal:" in checkout_result.stderr.lower() or + checkout_result.returncode != 0 + ) + + print(f"[DEBUG] Checkout failed: {checkout_failed}") + + if checkout_failed: + error_msg = f'Branch "{branch_name}" not found on remote. Please push the branch first.' + + # Try to extract more specific error from output + if "fatal:" in checkout_result.stdout: + fatal_line = [line for line in checkout_result.stdout.split('\n') if 'fatal:' in line.lower()] + if fatal_line: + error_msg += f" Error: {fatal_line[0].strip()}" + elif "fatal:" in checkout_result.stderr: + fatal_line = [line for line in checkout_result.stderr.split('\n') if 'fatal:' in line.lower()] + if fatal_line: + error_msg += f" Error: {fatal_line[0].strip()}" + return jsonify({ 'success': False, - 'error': f'Branch "{branch_name}" not found on remote. Please push the branch first.', - 'output': checkout_result.stdout + checkout_result.stderr + 'error': error_msg, + 'output': full_output, + 'debug': { + 'clone_returncode': clone_result.returncode, + 'checkout_returncode': checkout_result.returncode, + 'branch_name': branch_name + } }) # If successful, get available scenarios (mock for now) @@ -54,23 +137,35 @@ def submit_step1(): 'Scenario_5_Security_Test' ] + print(f"[DEBUG] Branch validation successful for: {branch_name}") + return jsonify({ 'success': True, 'scenarios': scenarios, - 'message': f'Branch "{branch_name}" validated successfully' + 'message': f'Branch "{branch_name}" validated successfully', + 'output': full_output, + 'debug': { + 'clone_returncode': clone_result.returncode, + 'checkout_returncode': checkout_result.returncode, + 'branch_name': branch_name + } }) except subprocess.TimeoutExpired: + error_msg = 'Branch validation timed out. Please try again.' + print(f"[ERROR] {error_msg}") return jsonify({ 'success': False, - 'error': 'Branch validation timed out. Please try again.', - 'output': '' + 'error': error_msg, + 'output': 'Command timed out after 60 seconds' }) except Exception as e: + error_msg = f'Error validating branch: {str(e)}' + print(f"[ERROR] {error_msg}") return jsonify({ 'success': False, - 'error': f'Error validating branch: {str(e)}', - 'output': '' + 'error': error_msg, + 'output': f'Exception: {str(e)}' }) @jobs_bp.route('/submit/step2-validated', methods=['POST']) diff --git a/asf-cloud-server/testarena_1/app/templates/jobs/submit.html b/asf-cloud-server/testarena_1/app/templates/jobs/submit.html index 9a03ead..d546932 100644 --- a/asf-cloud-server/testarena_1/app/templates/jobs/submit.html +++ b/asf-cloud-server/testarena_1/app/templates/jobs/submit.html @@ -91,6 +91,8 @@ function validateBranch() { }) .then(response => response.json()) .then(data => { + console.log('Branch validation response:', data); // Debug log + if (data.success) { // Success validation.className = 'branch-validation success'; @@ -100,6 +102,14 @@ function validateBranch() { validatedBranch = branchName; availableScenarios = data.scenarios; + + // Log debug info + if (data.debug) { + console.log('Debug info:', data.debug); + } + if (data.output) { + console.log('Command output:', data.output); + } } else { // Error validation.className = 'branch-validation error'; @@ -109,6 +119,15 @@ function validateBranch() { validatedBranch = null; availableScenarios = []; + + // Log debug info for troubleshooting + console.error('Branch validation failed:', data.error); + if (data.debug) { + console.error('Debug info:', data.debug); + } + if (data.output) { + console.error('Command output:', data.output); + } } }) .catch(error => {