Skip to content

Commit 38a66b5

Browse files
committed
Implement automated workflows for quality checks, duplicate detection, and error reporting
1 parent 159c42d commit 38a66b5

7 files changed

Lines changed: 986 additions & 22 deletions

File tree

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
name: 🔍 Duplicate Detection
2+
3+
on:
4+
pull_request_target:
5+
branches: [ main ]
6+
types: [opened, synchronize, reopened]
7+
8+
permissions:
9+
contents: read
10+
pull-requests: write
11+
issues: write
12+
13+
jobs:
14+
check-duplicates:
15+
name: 🔎 Check for Duplicate Files
16+
runs-on: ubuntu-latest
17+
18+
steps:
19+
- name: 📥 Checkout base branch
20+
uses: actions/checkout@v4
21+
with:
22+
ref: ${{ github.base_ref }}
23+
24+
- name: 📥 Checkout PR branch
25+
uses: actions/checkout@v4
26+
with:
27+
ref: ${{ github.event.pull_request.head.sha }}
28+
path: pr-code
29+
30+
- name: 🔍 Get changed files
31+
id: changed-files
32+
uses: tj-actions/changed-files@v40
33+
with:
34+
path: pr-code
35+
files: |
36+
C/**/*.c
37+
CPP/**/*.cpp
38+
Java/**/*.java
39+
Python/**/*.py
40+
JavaScript/**/*.js
41+
Go/**/*.go
42+
Rust/**/*.rs
43+
44+
- name: 🔎 Detect duplicate implementations
45+
if: steps.changed-files.outputs.any_changed == 'true'
46+
id: duplicate-check
47+
run: |
48+
echo "Checking for potential duplicates..."
49+
duplicates=""
50+
warnings=""
51+
52+
for new_file in ${{ steps.changed-files.outputs.all_changed_files }}; do
53+
# Remove pr-code/ prefix
54+
file_path="${new_file#pr-code/}"
55+
filename=$(basename "$file_path")
56+
base_name="${filename%.*}"
57+
58+
# Normalize filename (remove underscores, hyphens, convert to lowercase)
59+
normalized=$(echo "$base_name" | tr '_-' ' ' | tr '[:upper:]' '[:lower:]')
60+
61+
echo "Checking: $file_path (normalized: $normalized)"
62+
63+
# Get directory and language
64+
lang_dir=$(echo "$file_path" | cut -d'/' -f1)
65+
category=$(echo "$file_path" | cut -d'/' -f2)
66+
67+
# Search for similar files in the same category across the main branch
68+
echo "Searching in $lang_dir/$category/ for similar implementations..."
69+
70+
# Find files with similar names
71+
similar_files=$(find "$lang_dir/$category" -type f 2>/dev/null | while read existing_file; do
72+
existing_name=$(basename "$existing_file")
73+
existing_base="${existing_name%.*}"
74+
existing_normalized=$(echo "$existing_base" | tr '_-' ' ' | tr '[:upper:]' '[:lower:]')
75+
76+
# Check if normalized names match
77+
if [ "$normalized" = "$existing_normalized" ]; then
78+
echo "$existing_file"
79+
fi
80+
done)
81+
82+
if [ -n "$similar_files" ]; then
83+
duplicates="${duplicates}**⚠️ Potential Duplicate:** \`$file_path\`\n"
84+
duplicates="${duplicates}Similar file(s) already exist:\n"
85+
while IFS= read -r similar; do
86+
duplicates="${duplicates}- \`$similar\`\n"
87+
done <<< "$similar_files"
88+
duplicates="${duplicates}\n"
89+
fi
90+
done
91+
92+
# Save results
93+
if [ -n "$duplicates" ]; then
94+
echo "found=true" >> $GITHUB_OUTPUT
95+
echo "duplicates<<EOF" >> $GITHUB_OUTPUT
96+
echo -e "$duplicates" >> $GITHUB_OUTPUT
97+
echo "EOF" >> $GITHUB_OUTPUT
98+
else
99+
echo "found=false" >> $GITHUB_OUTPUT
100+
fi
101+
102+
- name: 💬 Comment on PR if duplicates found
103+
if: steps.duplicate-check.outputs.found == 'true'
104+
uses: actions/github-script@v7
105+
with:
106+
script: |
107+
const duplicates = `${{ steps.duplicate-check.outputs.duplicates }}`;
108+
109+
// Check if we already commented about duplicates
110+
const comments = await github.rest.issues.listComments({
111+
owner: context.repo.owner,
112+
repo: context.repo.repo,
113+
issue_number: context.issue.number
114+
});
115+
116+
const botComment = comments.data.find(comment =>
117+
comment.user.type === 'Bot' && comment.body.includes('🔍 Duplicate Detection Results')
118+
);
119+
120+
const comment = `## 🔍 Duplicate Detection Results
121+
122+
### ⚠️ Potential Duplicates Found
123+
124+
${ duplicates }
125+
126+
### 📝 What This Means
127+
128+
We found existing implementations that appear similar to your contribution. This doesn't necessarily mean your PR will be rejected, but please review:
129+
130+
1. **Is this truly a duplicate?** Check the existing files to see if they implement the same algorithm
131+
2. **Is your implementation different/better?** If so, explain in your PR description:
132+
- What makes it different
133+
- Why it's an improvement
134+
- Any unique features or optimizations
135+
3. **Consider improving existing code** instead of adding a duplicate
136+
137+
### ✅ What To Do Next
138+
139+
- **If it's a duplicate:** Consider withdrawing this PR and improving the existing implementation
140+
- **If it's different:** Add a clear explanation in your PR description about how it differs
141+
- **If unsure:** Ask the maintainers for guidance!
142+
143+
### 💡 Quality Over Quantity
144+
145+
Remember: One high-quality, unique contribution is worth more than multiple duplicates! 🌟
146+
147+
---
148+
*This is an automated check. Maintainers will make the final decision.*`;
149+
150+
// Only post if we haven't already commented
151+
if (!botComment) {
152+
await github.rest.issues.createComment({
153+
owner: context.repo.owner,
154+
repo: context.repo.repo,
155+
issue_number: context.issue.number,
156+
body: comment
157+
});
158+
} else {
159+
// Update existing comment
160+
await github.rest.issues.updateComment({
161+
owner: context.repo.owner,
162+
repo: context.repo.repo,
163+
comment_id: botComment.id,
164+
body: comment
165+
});
166+
}
167+
168+
- name: ✅ Summary
169+
run: |
170+
if [ "${{ steps.duplicate-check.outputs.found }}" = "true" ]; then
171+
echo "⚠️ Potential duplicates detected - please review"
172+
echo "This is a warning, not a failure. Maintainers will review."
173+
else
174+
echo "✅ No duplicates detected - great job!"
175+
fi

.github/workflows/hacktoberfest-labeling.yml

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,35 @@ jobs:
148148
149149
Thanks for contributing to open source! 🌟`;
150150
151-
await github.rest.issues.createComment({
151+
// Check if we already posted a welcome message
152+
const { data: comments } = await github.rest.issues.listComments({
152153
owner: context.repo.owner,
153154
repo: context.repo.repo,
154-
issue_number: context.payload.pull_request.number,
155-
body: welcomeMessage
155+
issue_number: context.payload.pull_request.number
156156
});
157157
158-
console.log('Welcome message posted for first-time contributor');
158+
const existingWelcome = comments.find(comment =>
159+
comment.user.type === 'Bot' && comment.body.includes('Welcome to the DSA Code Repository!')
160+
);
161+
162+
// Only post if we haven't already commented, otherwise update
163+
if (!existingWelcome) {
164+
await github.rest.issues.createComment({
165+
owner: context.repo.owner,
166+
repo: context.repo.repo,
167+
issue_number: context.payload.pull_request.number,
168+
body: welcomeMessage
169+
});
170+
console.log('Welcome message posted for first-time contributor');
171+
} else {
172+
await github.rest.issues.updateComment({
173+
owner: context.repo.owner,
174+
repo: context.repo.repo,
175+
comment_id: existingWelcome.id,
176+
body: welcomeMessage
177+
});
178+
console.log('Welcome message updated for first-time contributor');
179+
}
159180
}
160181
161182
} catch (error) {

0 commit comments

Comments
 (0)