Skip to content

[automated] Merge branch 'release/10.0.3xx' => 'main' #208

[automated] Merge branch 'release/10.0.3xx' => 'main'

[automated] Merge branch 'release/10.0.3xx' => 'main' #208

# Workflow to detect new NETSDK diagnostic codes in pull requests
#
# This workflow automatically:
# 1. Uses git diff to get changes from .xlf files only
# 2. Scans for newly added NETSDK diagnostic codes (e.g., NETSDK1234:)
# 3. Applies the 'sdk-diagnostic-docs-needed' label when new diagnostics are found
# 4. Posts/updates a comment reminding contributors to update SDK diagnostic documentation
# in the dotnet/docs repository at docs/core/tools/sdk-errors/
#
# Prerequisites: The 'sdk-diagnostic-docs-needed' label must exist in the repository
#
# Security: Uses pull_request_target to run in the base branch context (safe for forks)
# The workflow checks out the base branch and fetches the PR head, but does not execute any code from the PR.
#
name: Detect New NETSDK Diagnostics
on:
# Use pull_request_target for safe execution from forks
# This runs in the context of the base branch, not the PR head
pull_request_target:
types: [opened, synchronize]
branches:
- main
- release/*
permissions: read-all
jobs:
read-diff:
name: Read .xlf Diff
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
xlf_diff: ${{ steps.get-diff.outputs.xlf_diff }}
steps:
- name: Checkout base branch
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
ref: ${{ github.event.pull_request.base.ref }}
fetch-depth: 0
persist-credentials: false
- name: Fetch PR head
env:
GITHUB_TOKEN: ""
GH_TOKEN: ""
run: |
git fetch origin pull/${{ github.event.pull_request.number }}/head:pr-${{ github.event.pull_request.number }}
- name: Get diff from .xlf files only
id: get-diff
env:
GITHUB_TOKEN: ""
GH_TOKEN: ""
run: |
# Get diff only from .xlf files between base and PR head
DIFF_OUTPUT=$(git diff ${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }} -- '*.xlf')
# Check diff size to prevent resource exhaustion (limit to ~1MB)
DIFF_SIZE=$(echo "$DIFF_OUTPUT" | wc -c)
if [ "$DIFF_SIZE" -gt 1048576 ]; then
echo "Error: Diff size ($DIFF_SIZE bytes) exceeds 1MB limit"
exit 1
fi
# Use multiline output for job outputs
# https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#multiline-strings
{
echo 'xlf_diff<<EOF'
echo "$DIFF_OUTPUT"
echo 'EOF'
} >> "$GITHUB_OUTPUT"
detect-diagnostics:
name: Detect New NETSDK Diagnostic Codes
runs-on: ubuntu-latest
needs: read-diff
permissions: {}
outputs:
found_diagnostics: ${{ steps.detect.outputs.found_diagnostics }}
has_diagnostics: ${{ steps.detect.outputs.has_diagnostics }}
steps:
- name: Detect new NETSDK diagnostics
id: detect
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
env:
XLF_DIFF: ${{ needs.read-diff.outputs.xlf_diff }}
with:
script: |
const diff = process.env.XLF_DIFF;
// Pattern to match NETSDK diagnostic codes
const diagnosticPattern = /NETSDK(\d{4}):/g;
// Extract only added lines from the diff (lines starting with +)
const addedLines = diff.split('\n').filter(line => line.startsWith('+') && !line.startsWith('+++'));
// Find all NETSDK codes in added lines
const diagnosticCodes = new Set();
for (const line of addedLines) {
// Reset regex state for each line to avoid issues with global flag
diagnosticPattern.lastIndex = 0;
let match;
while ((match = diagnosticPattern.exec(line)) !== null) {
diagnosticCodes.add(`NETSDK${match[1]}`);
}
}
const foundDiagnostics = Array.from(diagnosticCodes).sort();
core.setOutput('found_diagnostics', foundDiagnostics.join(','));
core.setOutput('has_diagnostics', foundDiagnostics.length > 0 ? 'true' : 'false');
if (foundDiagnostics.length > 0) {
core.info(`Found ${foundDiagnostics.length} new NETSDK diagnostic(s) in .xlf files: ${foundDiagnostics.join(', ')}`);
} else {
core.info('No new NETSDK diagnostics found in .xlf files in this PR.');
}
return foundDiagnostics;
apply-label-and-comment:
name: Apply Label and Comment
runs-on: ubuntu-latest
needs: detect-diagnostics
if: needs.detect-diagnostics.outputs.has_diagnostics == 'true'
permissions:
pull-requests: write
issues: write
steps:
- name: Add label to PR
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
with:
script: |
const { owner, repo } = context.repo;
const issue_number = context.payload.pull_request.number;
const labelName = 'sdk-diagnostic-docs-needed';
await github.rest.issues.addLabels({
owner,
repo,
issue_number,
labels: [labelName]
});
core.info(`Label '${labelName}' added to PR #${issue_number}`);
- name: Post or update comment
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7
env:
DIAGNOSTICS: ${{ needs.detect-diagnostics.outputs.found_diagnostics }}
with:
script: |
const { owner, repo } = context.repo;
const issue_number = context.payload.pull_request.number;
const diagnostics = process.env.DIAGNOSTICS.split(',');
// Create the comment body
const commentIdentifier = '<!-- netsdk-diagnostics-reminder -->';
const commentBody = `${commentIdentifier}
## 📋 SDK Diagnostic Documentation Reminder
This PR introduces **${diagnostics.length}** new SDK diagnostic code${diagnostics.length > 1 ? 's' : ''}:
${diagnostics.map(code => `- \`${code}\``).join('\n')}
### Action Required
Please ensure that documentation for ${diagnostics.length > 1 ? 'these diagnostics' : 'this diagnostic'} is added or updated in the [dotnet/docs](https://github.com/dotnet/docs) repository at:
- Path: \`docs/core/tools/sdk-errors/\`
- Documentation: https://learn.microsoft.com/dotnet/core/tools/sdk-errors/
Each diagnostic should have:
- A clear description of the error/warning
- Possible causes
- Recommended solutions
- Code examples where applicable
Thank you for helping keep our documentation up to date! 🙏`;
// Check if we already have a comment from this workflow
const { data: comments } = await github.rest.issues.listComments({
owner,
repo,
issue_number
});
const existingComment = comments.find(comment =>
comment.user.type === 'Bot' &&
comment.body.includes(commentIdentifier)
);
if (existingComment) {
// Update existing comment
await github.rest.issues.updateComment({
owner,
repo,
comment_id: existingComment.id,
body: commentBody
});
core.info(`Updated existing comment #${existingComment.id}`);
} else {
// Create new comment
await github.rest.issues.createComment({
owner,
repo,
issue_number,
body: commentBody
});
core.info('Created new comment');
}