Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions .github/actions/get-pr-details/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
name: Get PR Details
description: 'Retrieves pull request details for pull_request_target or merge_group events'

inputs:
event_name:
description: 'Event name that triggered the caller workflow'
required: true
pr_number:
description: 'PR number for pull_request_target events'
required: false
merge_group_head_ref:
description: 'Merge group head ref for merge_group events'
required: false

outputs:
pr_number:
description: 'Pull request number'
value: ${{ steps.get_pr_details.outputs.pr_number }}
pr_title:
description: 'Pull request title'
value: ${{ steps.get_pr_details.outputs.pr_title }}
pr_labels:
description: 'Pull request labels (comma-separated)'
value: ${{ steps.get_pr_details.outputs.pr_labels }}
pr_base_ref:
description: 'Pull request base reference'
value: ${{ steps.get_pr_details.outputs.pr_base_ref }}
skip_gaudi_tests:
description: 'Whether to skip Gaudi tests'
value: ${{ steps.get_pr_details.outputs.skip_gaudi_tests }}

runs:
using: 'composite'
steps:
- name: Retrieve Pull Request information
id: get_pr_details
uses: actions/github-script@v7
env:
EVENT_NAME: ${{ inputs.event_name }}
PR_NUMBER: ${{ inputs.pr_number }}
MERGE_GROUP_HEAD_REF: ${{ inputs.merge_group_head_ref }}
with:
script: |
const eventName = process.env.EVENT_NAME;
console.log('Trigger event: %s', eventName);
if (eventName === 'merge_group') {
const headRef = process.env.MERGE_GROUP_HEAD_REF;
if (!headRef || typeof headRef !== 'string') {
console.log('❌ MERGE_GROUP_HEAD_REF is missing or invalid. Received:', headRef);
core.setFailed('MERGE_GROUP_HEAD_REF is missing or invalid for merge_group event');
return;
}
const prMatch = headRef.match(/pr-(\d+)-/);
if (!prMatch) {
console.log('❌ Merge group head ref does not match expected format "pr-<number>-...". Received:', headRef);
core.setFailed('Could not extract PR number from merge group head ref: unexpected format');
return;
}
const prNumber = parseInt(prMatch[1], 10);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parsed PR number should be validated after parseInt. While the regex ensures that prMatch[1] contains digits, parseInt could still return NaN in edge cases or if the number is too large. Consider checking if the result is a valid positive integer before proceeding with the API call.

Suggested change
const prNumber = parseInt(prMatch[1], 10);
const prNumber = parseInt(prMatch[1], 10);
if (!Number.isFinite(prNumber) || !Number.isInteger(prNumber) || prNumber <= 0) {
console.log('❌ Extracted PR number is invalid. Raw value: %s, Parsed value: %s', prMatch[1], prNumber);
core.setFailed('Extracted PR number from merge group head ref is not a valid positive integer');
return;
}

Copilot uses AI. Check for mistakes.
console.log('📋 Found source PR number: %s', prNumber);
try {
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
});
const prLabels = pullRequest.labels.map(l => l.name).join(', ') || 'None';
console.log('\n✅ Source Pull Request Information:');
console.log('- PR Number: #%s', pullRequest.number);
console.log('- PR Title: %s', pullRequest.title);
console.log('- PR Author: %s', pullRequest.user.login);
console.log('- PR State: %s', pullRequest.state);
console.log('- PR Labels: %s', prLabels);
const skipGaudiTests = pullRequest.labels.some(l => l.name === 'skip-gaudi-tests');
const fs = require('fs');
const outputFile = process.env.GITHUB_OUTPUT;
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${pullRequest.title}\n`);
Comment on lines +87 to +88
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title in the output could contain newline characters or other special characters that may cause issues when written to GITHUB_OUTPUT. If pullRequest.title contains newlines, the output format will be broken. Consider sanitizing the title by replacing newlines with spaces or using a multiline string format with delimiters (e.g., EOF markers) similar to how it's done in the pre-merge.yaml workflow.

Suggested change
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${pullRequest.title}\n`);
const sanitizedTitle = String(pullRequest.title || '').replace(/[\r\n]+/g, ' ');
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${sanitizedTitle}\n`);

Copilot uses AI. Check for mistakes.
fs.appendFileSync(outputFile, `pr_labels=${prLabels}\n`);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR labels in the output could contain newline characters or other special characters that may cause issues when written to GITHUB_OUTPUT. Label names are user-controlled and could potentially contain newlines or special characters. Consider sanitizing the labels string by replacing newlines with spaces or encoding it properly before writing to GITHUB_OUTPUT.

Copilot uses AI. Check for mistakes.
fs.appendFileSync(outputFile, `pr_base_ref=${pullRequest.base.ref}\n`);
fs.appendFileSync(outputFile, `skip_gaudi_tests=${skipGaudiTests}\n`);
} catch (error) {
console.error('❌ Error fetching PR details:', error.message);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling only logs error.message but doesn't log the full error or stack trace. For debugging GitHub Action failures, having the full error context including the stack trace would be valuable. Consider logging the full error object or at least including error.stack in addition to error.message.

Copilot uses AI. Check for mistakes.
core.setFailed(error.message);
}
} else if (eventName === 'pull_request_target') {
const prNumber = process.env.PR_NUMBER;
try {
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
Comment on lines +100 to +104
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR_NUMBER input should be validated before use. Currently, when eventName is 'pull_request_target', the code directly uses process.env.PR_NUMBER without checking if it exists or is a valid number. If PR_NUMBER is missing or invalid, the github.rest.pulls.get call will fail with an unclear error. Add validation similar to what is done for MERGE_GROUP_HEAD_REF in the merge_group event handler to provide clearer error messages.

Suggested change
try {
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: prNumber
if (!prNumber) {
const errorMessage = "PR_NUMBER environment variable is required for 'pull_request_target' events but was not provided.";
console.error(errorMessage);
core.setFailed(errorMessage);
return;
}
const parsedPrNumber = parseInt(prNumber, 10);
if (Number.isNaN(parsedPrNumber) || parsedPrNumber <= 0) {
const errorMessage = `Invalid PR_NUMBER environment variable value: '${prNumber}'. Expected a positive integer.`;
console.error(errorMessage);
core.setFailed(errorMessage);
return;
}
try {
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: parsedPrNumber

Copilot uses AI. Check for mistakes.
});
const prLabels = pullRequest.labels.map(l => l.name).join(', ') || 'None';
console.log('\n✅ Pull Request Information:');
console.log('- PR Number: #%s', pullRequest.number);
console.log('- PR Title: %s', pullRequest.title);
console.log('- PR Author: %s', pullRequest.user.login);
console.log('- PR State: %s', pullRequest.state);
console.log('- PR Labels: %s', prLabels);
const skipGaudiTests = pullRequest.labels.some(l => l.name === 'skip-gaudi-tests');
const fs = require('fs');
const outputFile = process.env.GITHUB_OUTPUT;
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${pullRequest.title}\n`);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR title in the output could contain newline characters or other special characters that may cause issues when written to GITHUB_OUTPUT. If pullRequest.title contains newlines, the output format will be broken. Consider sanitizing the title by replacing newlines with spaces or using a multiline string format with delimiters (e.g., EOF markers) similar to how it's done in the pre-merge.yaml workflow.

Copilot uses AI. Check for mistakes.
fs.appendFileSync(outputFile, `pr_labels=${prLabels}\n`);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR labels in the output could contain newline characters or other special characters that may cause issues when written to GITHUB_OUTPUT. Label names are user-controlled and could potentially contain newlines or special characters. Consider sanitizing the labels string by replacing newlines with spaces or encoding it properly before writing to GITHUB_OUTPUT.

Copilot uses AI. Check for mistakes.
fs.appendFileSync(outputFile, `pr_base_ref=${pullRequest.base.ref}\n`);
fs.appendFileSync(outputFile, `skip_gaudi_tests=${skipGaudiTests}\n`);
Comment on lines +107 to +125
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is significant code duplication between the merge_group and pull_request_target event handlers. Lines 85-91 (in merge_group) and lines 118-124 (in pull_request_target) are identical, as are lines 74 (computing prLabels), lines 83 (computing skipGaudiTests), and lines 107-114 (console logging). This duplicated logic makes the code harder to maintain - any bug fix or enhancement would need to be applied in two places. Consider extracting the common logic into a helper function that both event handlers can call.

Suggested change
const prLabels = pullRequest.labels.map(l => l.name).join(', ') || 'None';
console.log('\n✅ Pull Request Information:');
console.log('- PR Number: #%s', pullRequest.number);
console.log('- PR Title: %s', pullRequest.title);
console.log('- PR Author: %s', pullRequest.user.login);
console.log('- PR State: %s', pullRequest.state);
console.log('- PR Labels: %s', prLabels);
const skipGaudiTests = pullRequest.labels.some(l => l.name === 'skip-gaudi-tests');
const fs = require('fs');
const outputFile = process.env.GITHUB_OUTPUT;
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${pullRequest.title}\n`);
fs.appendFileSync(outputFile, `pr_labels=${prLabels}\n`);
fs.appendFileSync(outputFile, `pr_base_ref=${pullRequest.base.ref}\n`);
fs.appendFileSync(outputFile, `skip_gaudi_tests=${skipGaudiTests}\n`);
const handlePullRequestDetails = (pullRequest) => {
const prLabels = pullRequest.labels.map(l => l.name).join(', ') || 'None';
console.log('\n✅ Pull Request Information:');
console.log('- PR Number: #%s', pullRequest.number);
console.log('- PR Title: %s', pullRequest.title);
console.log('- PR Author: %s', pullRequest.user.login);
console.log('- PR State: %s', pullRequest.state);
console.log('- PR Labels: %s', prLabels);
const skipGaudiTests = pullRequest.labels.some(l => l.name === 'skip-gaudi-tests');
const fs = require('fs');
const outputFile = process.env.GITHUB_OUTPUT;
fs.appendFileSync(outputFile, `pr_number=${pullRequest.number}\n`);
fs.appendFileSync(outputFile, `pr_title=${pullRequest.title}\n`);
fs.appendFileSync(outputFile, `pr_labels=${prLabels}\n`);
fs.appendFileSync(outputFile, `pr_base_ref=${pullRequest.base.ref}\n`);
fs.appendFileSync(outputFile, `skip_gaudi_tests=${skipGaudiTests}\n`);
};
handlePullRequestDetails(pullRequest);

Copilot uses AI. Check for mistakes.
} catch (error) {
console.error('❌ Error fetching PR details:', error.message);
Copy link

Copilot AI Feb 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error handling only logs error.message but doesn't log the full error or stack trace. For debugging GitHub Action failures, having the full error context including the stack trace would be valuable. Consider logging the full error object or at least including error.stack in addition to error.message.

Suggested change
console.error('❌ Error fetching PR details:', error.message);
console.error('❌ Error fetching PR details:', error.message);
if (error && error.stack) {
console.error(error.stack);
} else {
console.error(error);
}

Copilot uses AI. Check for mistakes.
core.setFailed(error.message);
}
} else {
const errorMessage = "Event not supported. Use 'pull_request_target' or 'merge_group'.";
console.error(errorMessage);
core.setFailed(errorMessage);
}
126 changes: 126 additions & 0 deletions tests/calibration_tests/ci_calibration_smoke_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
#!/bin/bash

# Exit immediately if a command exits with a non-zero status.
# This ensures that if any test fails, the script will stop.
set -e

# --- Configuration ---
# Defines the path to the vllm-gaudi directory.
VLLM_GAUDI_PREFIX=${VLLM_GAUDI_PREFIX:-"vllm-gaudi"}
echo "VLLM_GAUDI_PREFIX: $VLLM_GAUDI_PREFIX"

# Calibration output directory (cleaned up after each test)
CALIBRATION_OUTPUT_DIR="${VLLM_GAUDI_PREFIX}/tests/calibration_tests/tmp-calibration-output"

# Dataset for calibration (using NeelNanda/pile-10k which auto-downloads)
CALIBRATION_DATASET="NeelNanda/pile-10k"

# Minimal batch size and limit for smoke tests (we only verify the procedure works)
BATCH_SIZE=1
LIMIT=1

cleanup_calibration_output() {
if [ -d "${CALIBRATION_OUTPUT_DIR}" ]; then
echo "Cleaning up calibration output directory..."
rm -rf "${CALIBRATION_OUTPUT_DIR}"
fi
}

# Simple smoke calibration test using granite model
run_granite_calibration_test() {
echo "➡️ Testing calibration procedure on ibm-granite/granite-3.3-2b-instruct..."
cleanup_calibration_output

PT_HPU_LAZY_MODE=1 "${VLLM_GAUDI_PREFIX}/calibration/calibrate_model.sh" \
-m ibm-granite/granite-3.3-2b-instruct \
-d "${CALIBRATION_DATASET}" \
-o "${CALIBRATION_OUTPUT_DIR}" \
-b ${BATCH_SIZE} \
-l ${LIMIT} \
-t 1

if [ $? -ne 0 ]; then
echo "Error: Calibration failed for ibm-granite/granite-3.3-2b-instruct" >&2
exit 1
fi
echo "✅ Calibration for ibm-granite/granite-3.3-2b-instruct passed."
cleanup_calibration_output
}

# Simple smoke calibration test using Qwen-2.5 model
run_qwen_calibration_test() {
echo "➡️ Testing calibration procedure on Qwen/Qwen2.5-0.5B-Instruct..."
cleanup_calibration_output

PT_HPU_LAZY_MODE=1 "${VLLM_GAUDI_PREFIX}/calibration/calibrate_model.sh" \
-m Qwen/Qwen2.5-0.5B-Instruct \
-d "${CALIBRATION_DATASET}" \
-o "${CALIBRATION_OUTPUT_DIR}" \
-b ${BATCH_SIZE} \
-l ${LIMIT} \
-t 1

if [ $? -ne 0 ]; then
echo "Error: Calibration failed for Qwen/Qwen2.5-0.5B-Instruct" >&2
exit 1
fi
echo "✅ Calibration for Qwen/Qwen2.5-0.5B-Instruct passed."
cleanup_calibration_output
}

# Simple smoke test for vision language models calibration using Qwen-2.5-VL
# (afierka) Temporarily disabled due to some issues, will re-enable once fixed. [GAUDISW-246468]
# run_qwen_vl_calibration_test() {
# echo "➡️ Testing VLM calibration procedure on Qwen/Qwen2.5-VL-3B-Instruct..."
# cleanup_calibration_output

# PT_HPU_LAZY_MODE=1 "${VLLM_GAUDI_PREFIX}/calibration/vlm-calibration/calibrate_model.sh" \
# -m Qwen/Qwen2.5-VL-3B-Instruct \
# -o "${CALIBRATION_OUTPUT_DIR}" \
# -b ${BATCH_SIZE} \
# -l ${LIMIT} \
# -t 1

# if [ $? -ne 0 ]; then
# echo "Error: VLM Calibration failed for Qwen/Qwen2.5-VL-3B-Instruct" >&2
# exit 1
# fi
# echo "✅ VLM Calibration for Qwen/Qwen2.5-VL-3B-Instruct passed."
# cleanup_calibration_output
# }

# --- Utility Functions ---

# Function to run all tests sequentially
launch_all_tests() {
echo "🚀 Starting all calibration test suites..."
run_granite_calibration_test
run_qwen_calibration_test
# run_qwen_vl_calibration_test # (afierka) Temporarily disabled due to some issues, will re-enable once fixed. [GAUDISW-246468]
echo "🎉 All calibration test suites passed successfully!"
}

# A simple usage function to guide the user
usage() {
echo "Usage: $0 [function_name]"
echo "If no function_name is provided, all tests will be run."
echo ""
echo "Available functions:"
declare -F | awk '{print " - " $3}' | grep --color=never "run_"
}

# --- Script Entry Point ---

# Default to 'launch_all_tests' if no function name is provided as an argument.
FUNCTION_TO_RUN=${1:-launch_all_tests}

# Check if the provided argument corresponds to a declared function in this script.
if declare -f "$FUNCTION_TO_RUN" > /dev/null
then
"$FUNCTION_TO_RUN"
else
echo "❌ Error: Function '${FUNCTION_TO_RUN}' is not defined."
echo ""
usage
exit 1
fi
Loading