diff --git a/.github/workflows/issue-notify.yml b/.github/workflows/issue-notify.yml
index 29f5b186..15e38df8 100644
--- a/.github/workflows/issue-notify.yml
+++ b/.github/workflows/issue-notify.yml
@@ -32,6 +32,18 @@ on:
required: false
type: string
default: ''
+ suggested_response:
+ required: false
+ type: string
+ default: ''
+ similar_issues:
+ required: false
+ type: string
+ default: ''
+ workaround:
+ required: false
+ type: string
+ default: ''
issue_number:
required: true
type: string
@@ -69,6 +81,9 @@ jobs:
INPUT_SUMMARY: ${{ inputs.summary_for_maintainers }}
INPUT_CODE_ANALYSIS: ${{ inputs.code_analysis }}
INPUT_ENGINEER_GUIDANCE: ${{ inputs.engineer_guidance }}
+ INPUT_SUGGESTED_RESPONSE: ${{ inputs.suggested_response }}
+ INPUT_SIMILAR_ISSUES: ${{ inputs.similar_issues }}
+ INPUT_WORKAROUND: ${{ inputs.workaround }}
INPUT_JUSTIFICATION: ${{ inputs.justification }}
TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }}
run: |
@@ -142,7 +157,6 @@ jobs:
else empty end),
(if .implementation_approach then "Implementation Approach: " + (.implementation_approach | @html) else empty end),
(if .risks_and_tradeoffs then "Risks & Tradeoffs: " + (.risks_and_tradeoffs | @html) else empty end),
- (if .suggested_response then "Suggested Response to User:
" + (.suggested_response | @html) else empty end),
(if .related_considerations and (.related_considerations | length) > 0
then "Related Considerations:
" + ([.related_considerations | to_entries[] | " " + ((.key + 1) | tostring) + ". " + (.value | @html)] | join("
"))
else empty end)
@@ -152,6 +166,50 @@ jobs:
ENGINEER_GUIDANCE=""
fi
+ # Format suggested customer response
+ SUGGESTED_RESPONSE_RAW="$INPUT_SUGGESTED_RESPONSE"
+ if [ -n "$SUGGESTED_RESPONSE_RAW" ]; then
+ SUGGESTED_RESPONSE=$(echo "$SUGGESTED_RESPONSE_RAW" | sed 's/&/\&/g; s/\</g; s/>/\>/g; s/$/\
/g')
+ else
+ SUGGESTED_RESPONSE=""
+ fi
+
+ # Parse and format similar issues analysis
+ SIMILAR_ISSUES_RAW="$INPUT_SIMILAR_ISSUES"
+ if [ -n "$SIMILAR_ISSUES_RAW" ]; then
+ SIMILAR_ISSUES=$(echo "$SIMILAR_ISSUES_RAW" | jq -r '
+ [
+ (if .summary then "Summary: " + (.summary | @html) else empty end),
+ (if .duplicate_issues and (.duplicate_issues | length) > 0
+ then "Similar/Duplicate Issues:
" + ([.duplicate_issues[] | select(.issue_number | tostring | test("^[0-9]+$")) | " • #" + (.issue_number | tostring) + " " + (.title | @html) + " [" + (.state | @html) + "] — " + (.similarity | @html) + ": " + (.explanation | @html)] | join("
"))
+ else empty end),
+ (if .recently_fixed and (.recently_fixed | length) > 0
+ then "Recently Fixed:
" + ([.recently_fixed[] | select(.issue_number | tostring | test("^[0-9]+$")) | " • #" + (.issue_number | tostring) + " " + (.title | @html) + " (closed " + (.closed_at | @html) + ") — " + (.relevance | @html)] | join("
"))
+ else empty end)
+ ] | join("
")
+ ' 2>/dev/null || echo "$SIMILAR_ISSUES_RAW" | sed 's/&/\&/g; s/\</g; s/>/\>/g')
+ else
+ SIMILAR_ISSUES=""
+ fi
+
+ # Parse and format workaround analysis
+ WORKAROUND_RAW="$INPUT_WORKAROUND"
+ if [ -n "$WORKAROUND_RAW" ]; then
+ WORKAROUND=$(echo "$WORKAROUND_RAW" | jq -r '
+ [
+ (if .summary then "Summary: " + (.summary | @html) else empty end),
+ (if .has_workaround and .workarounds and (.workarounds | length) > 0
+ then "Workarounds:
" + ([.workarounds | to_entries[] | " " + ((.key + 1) | tostring) + ". " + (.value.description | @html) + " [" + (if (.value.confidence | tostring) == "high" or (.value.confidence | tostring) == "medium" or (.value.confidence | tostring) == "low" then (.value.confidence | tostring) else "unknown" end) + " confidence]
Limitations: " + (.value.limitations | @html) + (if .value.code_snippet and (.value.code_snippet | length) > 0 then "
Code: " + (.value.code_snippet | @html) + "" else "" end)] | join("
"))
+ else empty end),
+ (if .can_downgrade == true and .downgrade_version
+ then "⬇️ Safe to downgrade to: " + (.downgrade_version | @html)
+ else empty end)
+ ] | join("
")
+ ' 2>/dev/null || echo "$WORKAROUND_RAW" | sed 's/&/\&/g; s/\</g; s/>/\>/g')
+ else
+ WORKAROUND=""
+ fi
+
# Set severity color indicator
case "$SEVERITY" in
critical) SEV_INDICATOR="🔴" ;;
@@ -176,6 +234,9 @@ jobs:
--arg summary "$INPUT_SUMMARY" \
--arg code_analysis "$CODE_ANALYSIS" \
--arg engineer_guidance "$ENGINEER_GUIDANCE" \
+ --arg suggested_response "$SUGGESTED_RESPONSE" \
+ --arg similar_issues "$SIMILAR_ISSUES" \
+ --arg workaround "$WORKAROUND" \
--arg justification "$INPUT_JUSTIFICATION" \
--arg action "$ACTION" \
--arg repo_url "https://github.com/microsoft/mssql-python" \
@@ -198,10 +259,24 @@ jobs:
"
" + ($summary | @html) + "
" + "" + $code_analysis + "
" + + (if $similar_issues != "" then + "" + $similar_issues + "
" + else "" end) + + (if $workaround != "" then + "" + $workaround + "
" + else "" end) + (if $engineer_guidance != "" then "" + $engineer_guidance + "
" else "" end) + + (if $suggested_response != "" then + "Copy-paste or edit the response below and post it on the issue:
" + + "" + $suggested_response + "" + else "" end) + "
⚡ Action Required: " + $action + "
" + "⚠️ AI-generated analysis — verified against source code but may contain inaccuracies. Review before acting.
" + diff --git a/.github/workflows/issue-triage.yml b/.github/workflows/issue-triage.yml index d4e95995..e7d18161 100644 --- a/.github/workflows/issue-triage.yml +++ b/.github/workflows/issue-triage.yml @@ -228,7 +228,6 @@ jobs: "implementation_approach": "${esc(categoryDisplay)} | `, - `${sevIndicator} Severity: ${esc(severity)} | `, - `Confidence: ${analysis.confidence}%
`, - ``,
- `📌 Issue: #${issue.number} — ${esc(issue.title)}
`,
- `👤 Author: @${esc(issue.user.login)}
`,
- `🏷️ Keywords: ${esc(analysis.keywords.join(", "))}
`,
- `📂 Relevant Files: ${esc(analysis.relevant_source_files.join(", "))}`,
- `
${esc(analysis.summary_for_maintainers)}
`, - `${codeAnalysisText}
`, - engineerGuidanceText ? `${engineerGuidanceText}
` : '', - `⚡ Action Required: ${esc(action)}
`, - `⚠️ AI-generated analysis — verified against source code but may contain inaccuracies. Review before acting.
`, - `📋 View Issue`, - ` | `, - `📂 View Repository
`, - ].join(""); - - const payload = { text: htmlMessage }; - - const response = await fetch(process.env.TEAMS_WEBHOOK_URL, { - method: "POST", - headers: { "Content-Type": "application/json" }, - body: JSON.stringify(payload), - }); - - if (!response.ok) { - const text = await response.text(); - throw new Error(`Teams webhook error: ${response.status} - ${text}`); - } - - return response.status; -} - -// --- Main --- -async function main() { - console.log(`\n🔍 Fetching issue #${issueNumber}...`); - const issue = await fetchIssue(issueNumber); - console.log(` Title: ${issue.title}`); - console.log(` Author: ${issue.user.login}`); - - console.log(`\n🤖 Classifying with GitHub Models...`); - const classificationPrompt = ` -You are an expert triage system for the mssql-python repository — a Python driver for Microsoft SQL Server. -The driver uses ODBC under the hood with a C++/pybind11 native extension layer and Python wrappers. -Note: The pybind/ directory contains C++/pybind11 code (NOT Rust). Only reference Rust if the issue is specifically about BCP (Bulk Copy Protocol). - -Key source files in the repo: -- mssql_python/connection.py — Connection management, pooling integration -- mssql_python/cursor.py — Cursor operations, execute, fetch, bulkcopy -- mssql_python/auth.py — Authentication (SQL auth, Azure AD, etc.) -- mssql_python/exceptions.py — Error handling and exception classes -- mssql_python/pooling.py — Connection pooling -- mssql_python/helpers.py — Utility functions -- mssql_python/constants.py — Constants, SQL types, enums -- mssql_python/connection_string_parser.py — Connection string parsing -- mssql_python/parameter_helper.py — Query parameter handling -- mssql_python/logging.py — Logging infrastructure -- mssql_python/row.py — Row objects -- mssql_python/type.py — Type mappings -- mssql_python/ddbc_bindings.py — Python/pybind11 ODBC bindings (C++ native extension, NOT Rust) -- mssql_python/pybind/ — C++/pybind11 native extension layer (NOT Rust) - -Classify the following GitHub issue into EXACTLY ONE category: - -1. FEATURE_REQUEST — User wants new functionality or enhancements -2. BUG — Something is broken, incorrect behavior, or errors -3. DISCUSSION — User is asking a question or wants clarification -4. BREAK_FIX — A regression or critical bug: segfaults, crashes, data corruption, - or user says "this used to work" - -Respond in this exact JSON format: -{ - "category": "BUG|FEATURE_REQUEST|DISCUSSION|BREAK_FIX", - "confidence": <0-100>, - "justification": "<2-3 sentence explanation>", - "severity": "critical|high|medium|low", - "relevant_source_files": ["