-
Notifications
You must be signed in to change notification settings - Fork 14
Add broken link/image handling with Teams notifications #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
Change onBrokenLinks and onBrokenMarkdownLinks from 'throw' to 'warn' mode, and add markdown hooks to suppress broken link and image errors during proof of concept. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Remove deprecated onBrokenMarkdownLinks from root config (deprecated in v3.9)
- Update markdown.hooks to use string values ('warn') instead of empty functions
- Now properly uses the new siteConfig.markdown.hooks API introduced in v3.9
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Created brokenLinkNotifier utility to send warnings to Teams webhook - Updated markdown hooks to use custom handlers instead of string values - Broken links and images will now trigger Teams notifications while keeping broken references visible - Uses existing TEAMS_WEBHOOK_URL environment variable - Deduplicates notifications to avoid spam Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Code Review: PR #53 - Add broken link/image handling with Teams notificationsSummaryThis PR adds functionality to handle broken links and images in Docusaurus by sending warnings to Microsoft Teams instead of throwing build errors. Overall, the implementation is well-structured and achieves its stated goals. Below are my findings across different categories. ✅ Positive Observations
🐛 Potential Bugs & Issues1. Memory Leak: In-Memory Set Never Clears
|
- Refactor brokenLinkNotifier to collect items during build instead of sending immediately - Create custom Docusaurus plugin using postBuild lifecycle hook to send single summary notification - Add TEAMS_WEBHOOK_URL environment variable to CI/CD workflow - Add webhook URL validation (HTTPS check) and 5s timeout for reliability - Add comprehensive JSDoc documentation for all functions - Update README with setup instructions for Teams webhook configuration - Upgrade Docusaurus to v3.9.0 to support markdown.hooks API This fixes several AI review issues: - Per-item notifications replaced with single batched summary (no more spam) - Missing CI/CD env var configuration added - Missing documentation added - Webhook URL validation added - Fetch timeout added to prevent slow builds - JSDoc documentation added Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Pull Request Review - PR #53OverviewThis PR implements a batched notification system for broken links/images in Docusaurus builds. The implementation is well-designed and addresses the spam issue from per-item notifications effectively. ✅ StrengthsCode Quality
Best Practices
|
Replace in-memory array with file-based persistence to guarantee cross-module communication. Markdown hooks and plugin were loading separate module instances, each with their own brokenItems array. Changes: - brokenLinkNotifier.js: Use temp JSON file instead of module-level array - broken-link-summary-plugin.js: Add loadContent hook to clean up old file This fixes the bug where broken items were detected but not collected for the summary notification. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Pull Request Review - PR #53SummaryThis PR implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug. The implementation is well-documented, thoughtfully designed, and production-ready. ✅ Strengths1. Excellent Problem Identification
2. Code Quality
3. Best Practices
🔍 Code Review Findings🐛 MEDIUM: Race Condition in Concurrent BuildsLocation: src/utils/brokenLinkNotifier.js:15 Issue: Multiple Docusaurus builds running concurrently will share the same temp file, causing data corruption. Impact: In CI/CD with matrix builds or parallel jobs:
Recommendation: Add process ID to filename to eliminate race condition entirely. ⚡ MEDIUM: O(N²) File I/O PerformanceLocation: src/utils/brokenLinkNotifier.js:59-63 Issue: Full file read+parse+write on every broken link. For N items, this is O(N²) operations. Impact: Negligible for <100 items, but could slow builds with 1000+ broken links. Recommendation: Not a blocker. Only optimize if performance issues arise in practice. 📋 Risk Assessment
🎯 RecommendationsShould Fix (High Value):Add Process ID to temp filename - Simple one-line change eliminates race condition Nice to Have:
🔐 Security: ✅ APPROVED
📝 Final Verdict✅ APPROVE WITH MINOR SUGGESTION This is excellent work with one easily-addressable issue. The code is well-architected, thoroughly documented, and demonstrates strong understanding of the problem domain. The PR description is exemplary. Great job! Reviewed by: Claude (AI Code Reviewer) |
Pull Request Review: Broken Link/Image Handling with Teams NotificationsSummaryThis PR implements a well-designed batched notification system for broken links and images in Docusaurus builds, with a critical bug fix for module scope isolation. The implementation is generally solid with good documentation and error handling. ✅ Strengths1. Architecture & Design
2. Documentation
3. Error Handling
4. User Experience
🔴 Critical Issues1. Security: Temp File Vulnerability
|
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
PR Review: Broken Link/Image Handling with Teams NotificationsSummaryThis PR implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug. The implementation is well-documented and addresses a real cross-module communication issue. ✅ Strengths1. Excellent Problem AnalysisThe PR description clearly identifies the module scope isolation bug and provides a solid solution using file-based persistence. 2. Comprehensive Documentation
3. Good Error Handling
4. Lifecycle Management
🔴 Critical Issues1. Temporary File Cleanup Risk (High Priority)Location: src/utils/brokenLinkNotifier.js:17-20 The temporary file is created at module load time but never cleaned up if the build crashes or is interrupted. The file handle from tmp.fileSync() is immediately discarded (only keeping .name), so the file won't auto-delete on process exit. Issues:
Recommended Solution: 2. Race Condition with Concurrent BuildsUsing a fixed temp filename without process/build ID means if two builds run simultaneously, they'll share the same temp file leading to data corruption or deletion conflicts. Recommendation: Include process.pid in the filename. 3. Intentional Broken Image in TestLocation: docs/pingcastle/3.3/enterpriseinstall.md:129 The image path was intentionally broken (image4.webp1111) for testing. This should be removed before merge or documented as a permanent test case.
|
Fix JSON parse error when temp file is empty. Check if file content is empty before attempting to parse JSON. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Pull Request Review: Broken Link/Image Teams NotificationsOverviewThis PR implements a robust system for detecting and reporting broken links/images during Docusaurus builds via Microsoft Teams notifications. The implementation uses file-based persistence to solve a critical module scope isolation bug. ✅ StrengthsCode Quality
Architecture
🔴 Critical Issues1. Security: Insecure Temporary File Creation (HIGH PRIORITY)Location: Issue: The Risk:
Recommendation: // Use tmp's cleanup on exit feature
const TEMP_FILE = tmp.fileSync({
prefix: 'docusaurus-broken-links-',
postfix: '.json',
discardDescriptor: true, // We don't need the file descriptor
detachDescriptor: true // Allow manual cleanup
}).name;
// Add cleanup handler
process.on('exit', () => {
try {
if (fs.existsSync(TEMP_FILE)) {
fs.unlinkSync(TEMP_FILE);
}
} catch (e) {
// Ignore cleanup errors on exit
}
});2. Race Condition: Multiple Module InstancesLocation: Issue: The Current behavior: Recommendation: Include process ID or a unique identifier: const TEMP_FILE = tmp.fileSync({
prefix: `docusaurus-broken-links-${process.pid}-`,
postfix: '.json',
}).name;3. Data Corruption: Non-Atomic File OperationsLocation: Issue: The const items = readItemsFromFile(); // Read
items.push(item); // Modify
writeItemsToFile(items); // WriteIf two markdown hooks fire simultaneously (likely with parallel processing), items can be lost. Recommendation: Use atomic append operations or file locking, or accept that Docusaurus builds are typically single-threaded and document this assumption.
|
| Category | Status | Notes |
|---|---|---|
| Code Quality | ✅ Good | Well-documented, clean structure |
| Best Practices | Some edge cases need handling | |
| Potential Bugs | Race conditions, file cleanup | |
| Performance | ✅ Good | Batching is efficient |
| Security | Temp file handling needs improvement | |
| Test Coverage | ❌ None | No automated tests |
🎯 Recommendations Summary
Before Merging (Required):
- ✅ Fix temp file cleanup (add process exit handler)
- ✅ Add process ID to temp filename to prevent collisions
- ✅ Remove or document the test broken link in
enterpriseinstall.md:129 - ✅ Clarify/document the
onBrokenLinks: 'warn'behavior change - ✅ Add URL validation improvements
Nice to Have:
- Add basic unit tests (at least for file operations)
- Make timeout configurable via environment variable
- Improve error messages with context
- Consider increasing display limit from 20 to 50 items
🏆 Overall Assessment
Rating: 7/10 - Good implementation with some issues to address
This is a well-thought-out solution to a real problem. The file-based approach to solve the module isolation bug is clever. The main concerns are around edge cases (concurrent builds, file cleanup) and test coverage.
The core logic is solid, documentation is excellent, and the feature will provide real value for the docs team. With the recommended fixes, this will be production-ready.
Great work on diagnosing and fixing the module scope isolation bug! The PR description is also excellent - very clear explanation of the problem and solution.
📚 Additional Resources
🤖 Generated by Claude Code Review
Replace tmp.fileSync() with fixed path to os.tmpdir()/docusaurus-broken-links.json. This ensures all module instances use the same file path for cross-module communication. Previously, different module loads created different temp files, preventing hooks from communicating with the plugin. Now they use a consistent path. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Pull Request Review - PR #53I've reviewed this PR that implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug. Here's my comprehensive feedback: ✅ StrengthsArchitecture & Design
Code Quality
Security
🔴 Critical Issues1. Race Conditions with Concurrent Builds
|
Simplifies code by using a module-level array instead of file I/O. - Removes all file system operations and security concerns - No temp files created - Cleaner, simpler implementation - Hooks and plugin share the same array during build Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Pull Request Review: Broken Link/Image Handling with Teams NotificationsSummaryThis PR implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug. The implementation is well-documented and addresses the core issue effectively. Critical Issues🔴 1. Module Scope Bug Still PresentLocation: The PR description claims to fix the module scope isolation bug by replacing the in-memory array with file-based persistence, but the code still uses an in-memory array: // In-memory storage for broken items during build
let brokenItems = [];Impact: The exact bug described in the PR (separate module instances not sharing state) is still present. The markdown hooks and plugin will load separate instances, each with their own Recommendation: Implement the file-based solution as described in the PR description:
🟡 2. Intentionally Broken Image in Production CodeLocation: The image path has Recommendation: Remove the Code Quality Issues🟡 3. Inconsistent Error HandlingLocation: The fetch timeout implementation is good, but error handling could be more robust: } catch (error) {
clearTimeout(timeoutId);
if (error.name === 'AbortError') {
console.warn('⚠️ Teams notification timed out after 5s');
} else {
console.warn('⚠️ Error sending Teams notification:', error.message);
}
}Issues:
Recommendation:
🟡 4. Configuration Change:
|
Switch to global.__brokenLinksItems to ensure all module imports reference the same array, solving module scope isolation issues. - Removes all file system operations - Uses Node.js global object for guaranteed single instance - Cleaner approach without temp files or security concerns Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
PR Review: Broken Link/Image Handling with Teams NotificationsSummaryThis PR implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug. The implementation is well-structured, well-documented, and production-ready. The solution elegantly addresses the module isolation issue using Node.js global object. ✅ Strengths1. Excellent Problem Identification
2. Code Quality
3. User Experience
🔍 Code Quality ReviewSecurity: ✅ No concerns
Performance: ✅ Good
Best Practices: ✅ Excellent
|
| Decision | Rationale | Assessment |
|---|---|---|
| Global object vs file I/O | Simpler, no file system dependencies | ✅ Correct choice |
| Batched notifications | Prevents Teams spam | ✅ Good UX |
| postBuild hook | Ensures all items collected | ✅ Correct lifecycle |
| 20-item limit | Prevents overwhelming messages | ✅ Reasonable default |
Alternative Considerations
None needed - the current approach is optimal for this use case.
🚀 CI/CD Integration
Workflow Changes: ✅ Correct
File: .github/workflows/build-and-deploy.yml:103
TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }}Checklist before merge:
- ✅ Ensure
TEAMS_WEBHOOK_URLsecret is configured in GitHub repository settings - ✅ Test the webhook URL actually reaches your Teams channel
- ✅ Verify the secret is available in the correct environment (development/production)
🎯 Final Recommendation
Status: ✅ APPROVE with minor changes
Required Before Merge:
- Fix the test broken image in
docs/pingcastle/3.3/enterpriseinstall.md:129(remove1111suffix) - Remove unused
tmpdependency from package.json - Configure
TEAMS_WEBHOOK_URLsecret in GitHub repository settings
Optional Improvements (Post-Merge):
- Consider environment-specific
onBrokenLinkssetting - Add simple smoke tests
- Monitor for race conditions in production (unlikely)
📝 Code Review Checklist
- ✅ Code quality and style (excellent JSDoc, clean structure)
- ✅ Security (HTTPS validation, no secrets exposure, timeout protection)
- ✅ Performance (minimal overhead, non-blocking)
- ✅ Error handling (comprehensive, graceful degradation)
- ✅ Documentation (README updated, inline comments clear)
- ✅ Best practices (follows Docusaurus patterns)
⚠️ Test coverage (manual testing done, automated tests missing)⚠️ Breaking changes (intentional broken image should be fixed)
Great work on identifying and solving the module isolation bug! The solution is production-ready with just a couple of minor cleanup items.
🤖 Generated with Claude Code
Summary
This PR implements batched Teams notifications for broken links/images and fixes a critical module scope isolation bug.
The Bug (Commit 2)
Issue: Broken items were detected but not collected for notification.
Root Cause: Markdown hooks and plugin loaded separate module instances:
docusaurus.config.jsimportsbrokenLinkNotifier(Instance A)brokenLinkNotifieragain (Instance B)brokenItems[]array - they don't share!Solution: Replace in-memory array with temp JSON file for cross-module communication.
Changes
Commit 1: Batched Notifications (Earlier)
Commit 2: Fix Module Scope Bug (Latest)
src/utils/brokenLinkNotifier.js- File-based persistenceconst brokenItems = []with file I/Oos.tmpdir()for cross-platform temp filehandleBrokenMarkdownX()→ append to filegetBrokenItems()→ read from fileclearBrokenItems()→ delete filesrc/plugins/broken-link-summary-plugin.js- Build lifecycle cleanuploadContent()hook to clean file at build startHow It Works Now
Why File-Based Works
✅ File system is shared across all Node.js module contexts
✅ Simple, battle-tested approach (used by many build tools)
✅ Easy to debug (can inspect the file)
✅ Minimal overhead for small JSON files
Test Results
Local build now properly:
Build Output:
Files Modified
src/utils/brokenLinkNotifier.js- File I/O implementationsrc/plugins/broken-link-summary-plugin.js- Add build lifecycle cleanupAI Review Issues - Complete Status
Risk Assessment
Low Risk:
Potential Issues:
Next Steps
🤖 Generated with Claude Code