CPP: add Happy Number solution (IEEEXtreme style) #285
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: 🤖 PR Automation | |
| on: | |
| pull_request_target: | |
| types: [opened, synchronize, reopened] | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| jobs: | |
| # Run all tests and validations | |
| run-tests: | |
| name: 🧪 Run Tests & Validation | |
| runs-on: ubuntu-latest | |
| outputs: | |
| validation-passed: ${{ steps.validation.outputs.passed }} | |
| tests-passed: ${{ steps.tests.outputs.passed }} | |
| steps: | |
| - name: 📥 Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event.pull_request.head.sha }} | |
| fetch-depth: 0 | |
| - name: 🔍 Get changed files | |
| id: changed-files | |
| uses: tj-actions/changed-files@v40 | |
| with: | |
| files: | | |
| **/*.c | |
| **/*.cpp | |
| **/*.java | |
| **/*.py | |
| **/*.js | |
| **/*.ts | |
| **/*.go | |
| **/*.rs | |
| - name: ✅ Run PR Validation | |
| id: validation | |
| if: steps.changed-files.outputs.any_changed == 'true' | |
| run: | | |
| echo "Running validation checks..." | |
| # Call existing validation workflow logic | |
| ./.github/scripts/validate-pr.sh || validation_failed=true | |
| if [ "$validation_failed" = true ]; then | |
| echo "passed=false" >> $GITHUB_OUTPUT | |
| exit 1 | |
| else | |
| echo "passed=true" >> $GITHUB_OUTPUT | |
| fi | |
| - name: 🐍 Setup Python for testing | |
| if: contains(steps.changed-files.outputs.all_changed_files, '.py') | |
| uses: actions/setup-python@v4 | |
| with: | |
| python-version: '3.x' | |
| - name: ☕ Setup Java for testing | |
| if: contains(steps.changed-files.outputs.all_changed_files, '.java') | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '11' | |
| - name: 🔧 Setup Node.js for testing | |
| if: contains(steps.changed-files.outputs.all_changed_files, '.js') || contains(steps.changed-files.outputs.all_changed_files, '.ts') | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '18' | |
| - name: 🦀 Setup Rust for testing | |
| if: contains(steps.changed-files.outputs.all_changed_files, '.rs') | |
| uses: actions-rs/toolchain@v1 | |
| with: | |
| toolchain: stable | |
| - name: 🧪 Run code compilation tests | |
| id: tests | |
| if: steps.changed-files.outputs.any_changed == 'true' | |
| run: | | |
| echo "Running compilation tests..." | |
| test_failed=false | |
| for file in ${{ steps.changed-files.outputs.all_changed_files }}; do | |
| case "$file" in | |
| *.cpp) | |
| echo "Testing C++ file: $file" | |
| g++ -std=c++17 -Wall -Wextra -o test_cpp "$file" || test_failed=true | |
| ;; | |
| *.c) | |
| echo "Testing C file: $file" | |
| gcc -Wall -Wextra -o test_c "$file" || test_failed=true | |
| ;; | |
| *.java) | |
| echo "Testing Java file: $file" | |
| javac "$file" || test_failed=true | |
| ;; | |
| *.py) | |
| echo "Testing Python file: $file" | |
| python -m py_compile "$file" || test_failed=true | |
| ;; | |
| *.js) | |
| echo "Testing JavaScript file: $file" | |
| node -c "$file" || test_failed=true | |
| ;; | |
| *.rs) | |
| echo "Testing Rust file: $file" | |
| rustc --check "$file" || test_failed=true | |
| ;; | |
| esac | |
| done | |
| if [ "$test_failed" = true ]; then | |
| echo "passed=false" >> $GITHUB_OUTPUT | |
| exit 1 | |
| else | |
| echo "passed=true" >> $GITHUB_OUTPUT | |
| fi | |
| # Wait for all checks to complete | |
| wait-for-checks: | |
| name: ⏳ Wait for All Tests | |
| runs-on: ubuntu-latest | |
| needs: run-tests | |
| if: always() | |
| steps: | |
| - name: Wait for other workflows | |
| run: | | |
| echo "⏳ Waiting for all validation and test workflows to complete..." | |
| sleep 30 | |
| echo "✅ Proceeding with labeling and notifications" | |
| # Auto-labeling and first-time contributor welcome | |
| auto-label: | |
| name: 🏷️ Auto Label & Welcome | |
| runs-on: ubuntu-latest | |
| needs: [run-tests, wait-for-checks] | |
| if: always() | |
| steps: | |
| - name: 🎃 Add Hacktoberfest labels and welcome contributors | |
| uses: actions/github-script@v7 | |
| env: | |
| VALIDATION_PASSED: ${{ needs.run-tests.outputs.validation-passed }} | |
| TESTS_PASSED: ${{ needs.run-tests.outputs.tests-passed }} | |
| with: | |
| script: | | |
| const { owner, repo, number } = context.issue; | |
| const validationPassed = process.env.VALIDATION_PASSED === 'true'; | |
| const testsPassed = process.env.TESTS_PASSED === 'true'; | |
| // Get PR and contributor info | |
| const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); | |
| const contributor = pr.data.user.login; | |
| // Check if first-time contributor | |
| const contributions = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | |
| owner, | |
| repo, | |
| commit_sha: pr.data.head.sha | |
| }); | |
| const isFirstTime = contributions.data.length <= 1; | |
| // Add labels based on PR content and status | |
| const labels = ['hacktoberfest-accepted','hacktoberfest']; | |
| // Add language labels based on changed files | |
| const files = await github.rest.pulls.listFiles({ owner, repo, pull_number: number }); | |
| const languages = new Set(); | |
| files.data.forEach(file => { | |
| const ext = file.filename.split('.').pop(); | |
| switch(ext) { | |
| case 'cpp': languages.add('C++'); break; | |
| case 'c': languages.add('C'); break; | |
| case 'java': languages.add('Java'); break; | |
| case 'py': languages.add('Python'); break; | |
| case 'js': languages.add('JavaScript'); break; | |
| case 'rs': languages.add('Rust'); break; | |
| case 'go': languages.add('Go'); break; | |
| } | |
| }); | |
| languages.forEach(lang => labels.push(lang.toLowerCase())); | |
| // Add difficulty labels | |
| if (files.data.length <= 2) labels.push('good first issue'); | |
| if (files.data.length > 5) labels.push('advanced'); | |
| // Add status labels | |
| if (testsPassed) { | |
| labels.push('tests-passing'); | |
| } else { | |
| labels.push('needs-work'); | |
| } | |
| if (isFirstTime) { | |
| labels.push('first-time-contributor'); | |
| } | |
| // Apply labels | |
| await github.rest.issues.addLabels({ | |
| owner, | |
| repo, | |
| issue_number: number, | |
| labels | |
| }); | |
| // Welcome first-time contributors | |
| if (isFirstTime) { | |
| const welcomeMessage = ` | |
| 🎉 **Welcome to Hacktoberfest 2025, @${contributor}!** 🎃 | |
| Thank you for your first contribution to our DSA repository! Here's what happens next: | |
| ## 🔍 Automatic Checks | |
| - ✅ **Code Validation**: ${validationPassed ? 'Passed' : 'Failed'} | |
| - 🧪 **Compilation Tests**: ${testsPassed ? 'Passed' : 'Failed'} | |
| ## 📋 Next Steps | |
| ${testsPassed ? | |
| '🎯 **Great job!** Your code compiled successfully. Maintainers [@admirerr](https://github.com/admirerr) and [@kartikey2991](https://github.com/kartikey2991) will review your PR soon.' : | |
| '⚠️ **Action needed**: Please fix the compilation errors and push your changes.'} | |
| ## 🎁 What You Get | |
| - 🏆 **Hacktoberfest Credit**: This PR counts toward your 6 PR goal for exclusive T-shirt + Tree! | |
| - 🌟 **Hall of Fame**: You'll be featured in our contributors list | |
| - 📚 **Learning**: Code review feedback from experienced developers | |
| ## 💡 Tips for Success | |
| - Follow our [Contributing Guidelines](./CONTRIBUTING.md) | |
| - Add comments explaining your algorithm | |
| - Include time/space complexity analysis | |
| - Test your code before submitting | |
| Welcome to the community! 🚀 | |
| `; | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number: number, | |
| body: welcomeMessage | |
| }); | |
| } | |
| # Request review from maintainers | |
| request-review: | |
| name: 👥 Request Review | |
| runs-on: ubuntu-latest | |
| needs: [run-tests, auto-label] | |
| if: needs.run-tests.outputs.tests-passed == 'true' | |
| steps: | |
| - name: 📋 Request review from maintainers | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { owner, repo, number } = context.issue; | |
| // List of maintainers who can review | |
| const reviewers = ['admirerr', 'kartikey2991']; | |
| // Get PR details | |
| const pr = await github.rest.pulls.get({ owner, repo, pull_number: number }); | |
| // Don't request review from the PR author | |
| const availableReviewers = reviewers.filter(reviewer => | |
| reviewer !== pr.data.user.login | |
| ); | |
| if (availableReviewers.length > 0) { | |
| await github.rest.pulls.requestReviewers({ | |
| owner, | |
| repo, | |
| pull_number: number, | |
| reviewers: availableReviewers.slice(0, 2) // Request max 2 reviewers | |
| }); | |
| console.log(`Requested review from: ${availableReviewers.slice(0, 2).join(', ')}`); | |
| } | |
| # Notify about PR status | |
| notify-status: | |
| name: 📢 Notify Status | |
| runs-on: ubuntu-latest | |
| needs: [run-tests, auto-label, wait-for-checks] | |
| if: always() | |
| steps: | |
| - name: 📊 Comment PR status | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const { owner, repo, number } = context.issue; | |
| const validationPassed = '${{ needs.run-tests.outputs.validation-passed }}' === 'true'; | |
| const testsPassed = '${{ needs.run-tests.outputs.tests-passed }}' === 'true'; | |
| let statusMessage = '## 🤖 Automated PR Status\n\n'; | |
| // Validation status | |
| statusMessage += `### 🔍 Code Validation\n`; | |
| statusMessage += validationPassed ? | |
| '✅ **Passed** - File naming and structure look good!\n\n' : | |
| '❌ **Failed** - Please check file naming conventions and directory structure.\n\n'; | |
| // Test status | |
| statusMessage += `### 🧪 Compilation Tests\n`; | |
| statusMessage += testsPassed ? | |
| '✅ **Passed** - All code compiles successfully!\n\n' : | |
| '❌ **Failed** - Please fix compilation errors and try again.\n\n'; | |
| // Overall status | |
| statusMessage += `### 📋 Overall Status\n`; | |
| if (validationPassed && testsPassed) { | |
| statusMessage += '🎉 **Ready for Review** - Your PR has passed all automated checks!\n'; | |
| statusMessage += '👥 Maintainers have been notified for review.\n\n'; | |
| } else { | |
| statusMessage += '⚠️ **Needs Work** - Please address the issues above.\n'; | |
| statusMessage += '💡 Push new commits to automatically re-run these checks.\n\n'; | |
| } | |
| statusMessage += '---\n'; | |
| statusMessage += '*This comment was generated automatically. Checks will re-run when you push new commits.*'; | |
| await github.rest.issues.createComment({ | |
| owner, | |
| repo, | |
| issue_number: number, | |
| body: statusMessage | |
| }); |