Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
313 commits
Select commit Hold shift + click to select a range
b32d110
fix: Use CBL Mariner bot token from Key Vault variable group
abadawi591 Oct 24, 2025
bf39750
fix: Correct YAML syntax in variables section
abadawi591 Oct 24, 2025
afcb33d
fix: Remove variable group reference - use pipeline variables instead
abadawi591 Oct 24, 2025
1b8c1d0
debug: Add logging to diagnose empty GITHUB_TOKEN issue
abadawi591 Oct 24, 2025
f4297dc
feat: Challenge comments posted by user, labels by bot
abadawi591 Oct 24, 2025
7978c8a
refactor: Fetch GitHub PAT from Key Vault instead of ADO pipeline var…
abadawi591 Oct 27, 2025
e4c63e9
feat: Add issue hashing to AntiPatternDetector for persistent challen…
abadawi591 Oct 27, 2025
5a8dceb
feat: Add AnalyticsManager for persistent challenge tracking
abadawi591 Oct 27, 2025
5c34902
feat: Phase 3 - Integrate analytics tracking into PR check pipeline
abadawi591 Oct 27, 2025
9fb4cb4
feat: Phase 4 - Update Azure Function for issue hash tracking
abadawi591 Oct 27, 2025
59023b2
Fix Azure Function comment posting and JavaScript modal bugs
abadawi591 Oct 28, 2025
7f19e63
Fix modal persistence and favicon issues in HTML report
abadawi591 Oct 28, 2025
a4e3929
Fix modal element querying with querySelector fallback
abadawi591 Oct 28, 2025
1004499
Add comprehensive modal debugging to diagnose missing child elements
abadawi591 Oct 28, 2025
9ef0a83
Add modal corruption detection and fix button selector
abadawi591 Oct 28, 2025
c4ce03c
Add logging for issue_lifecycle keys in label management
abadawi591 Oct 28, 2025
dbdecae
Fix add_commit_analysis call - pass correct parameters and AntiPatter…
abadawi591 Oct 28, 2025
1a0061f
Fix AnalyticsManager API - use instance state instead of passing para…
abadawi591 Oct 28, 2025
35de50d
Fix label management to use issue_lifecycle instead of current commit…
abadawi591 Oct 28, 2025
2697b76
Fix issue hash collision for missing-patch-file antipatterns
abadawi591 Oct 28, 2025
a882e60
Reset SPECS folders to clean 3.0-dev baseline
abadawi591 Oct 28, 2025
fc59f66
Add antipatterns to avahi spec for UI testing
abadawi591 Oct 28, 2025
138592c
Redesign challenged antipattern UI with modern expandable design
abadawi591 Oct 28, 2025
301be93
Trigger PR check to test redesigned challenged UI
abadawi591 Oct 28, 2025
bf35d23
Add dynamic counter updates for challenged items
abadawi591 Oct 28, 2025
c513e9a
Trigger PR check to test dynamic counter updates
abadawi591 Oct 28, 2025
c768ffd
Fix counter updates and label management issues
abadawi591 Oct 28, 2025
cf52f7b
Redesign challenged antipattern UI with modern expandable design
abadawi591 Oct 28, 2025
c25772d
Add dynamic counter updates for challenged items
abadawi591 Oct 28, 2025
5db044c
Fix counter updates and label management issues
abadawi591 Oct 28, 2025
04f0ba0
Phase 1 UI modernization: CSS variables theme system, dark/light mode…
abadawi591 Oct 28, 2025
308e283
Phase 1 UI modernization: CSS variables theme system, dark/light mode…
abadawi591 Oct 28, 2025
ed2cbb3
CRITICAL FIX: Prevent premature label removal on challenges
abadawi591 Oct 28, 2025
9f54426
Phase 2 UI modernization: Spec cards and issue list redesign
abadawi591 Oct 28, 2025
b48b5df
Phase 2 UI modernization: Spec cards and issue list redesign
abadawi591 Oct 28, 2025
14570fb
Phase 3 UI modernization: PR Info Card Enhancement
abadawi591 Oct 28, 2025
7e6e87c
Phase 3 UI modernization: PR Info Card Enhancement
abadawi591 Oct 28, 2025
97ee3a1
Trigger PR check to view Phase 1-3 UI modernizations
abadawi591 Oct 28, 2025
195e1c9
UX Fix #1: Add bell icon with badge to top-right corner
abadawi591 Oct 28, 2025
6c41465
UX Fix #2: Fix hover color contrast for better intuitiveness
abadawi591 Oct 28, 2025
06c1ced
UX Fix #3: Update title color palette to cool tones
abadawi591 Oct 28, 2025
567c262
UX Fix #4: Fix challenge modal icons for better semantics
abadawi591 Oct 28, 2025
7217edd
UX Fix #1: Add bell icon with badge to top-right corner
abadawi591 Oct 28, 2025
dd50b84
UX Fix #2: Fix hover color contrast for better intuitiveness
abadawi591 Oct 28, 2025
53f0588
UX Fix #3: Update title color palette to cool tones
abadawi591 Oct 28, 2025
9df3ccb
UX Fix #4: Fix challenge modal icons for better semantics
abadawi591 Oct 28, 2025
6313f30
UI Modernization: Cleaner, more modern sections and hover states
abadawi591 Oct 28, 2025
e444ac4
UI Modernization: Cleaner, more modern sections and hover states
abadawi591 Oct 28, 2025
b71916e
Refactor: Extract HTML generation to HtmlReportGenerator.py + Style e…
abadawi591 Oct 29, 2025
a975f06
Refactor: Extract HTML generation to HtmlReportGenerator.py + Style e…
abadawi591 Oct 29, 2025
a2c2e23
UX Fix #9: Add severity badges to issues
abadawi591 Oct 29, 2025
76c06dc
UX Fix #9: Add severity badges to issues
abadawi591 Oct 29, 2025
b4d6577
UX Fix #10: Implement severity filtering
abadawi591 Oct 29, 2025
d972aa3
UX Fix #10: Implement severity filtering
abadawi591 Oct 29, 2025
3915f1f
UX Fix #11: Fix total issues counter to sum only Errors + Warnings
abadawi591 Oct 29, 2025
c6fe32d
UX Fix #11: Fix total issues counter to sum only Errors + Warnings
abadawi591 Oct 29, 2025
c97c290
UX Fix #12: Add user dropdown menu with Sign Out
abadawi591 Oct 29, 2025
e67e08d
UX Fix #12: Add user dropdown menu with Sign Out
abadawi591 Oct 29, 2025
6ca4c2b
Trigger pipeline to verify UX improvements
abadawi591 Oct 29, 2025
789d236
Merge branch 'test/ui-antipattern-demo' into abadawi/multi-spec-radar
abadawi591 Oct 29, 2025
5bc3d03
test: Add anti-patterns to curl spec for UI verification
abadawi591 Oct 29, 2025
623e6ee
fix: Wrap JavaScript in DOMContentLoaded to fix challenge button
abadawi591 Oct 29, 2025
a6a4095
fix: Wrap JavaScript in DOMContentLoaded to fix challenge button
abadawi591 Oct 29, 2025
4720c15
fix: Remove inline onclick and use event listener for submit button
abadawi591 Oct 29, 2025
5e91bd2
fix: Remove all inline onclick handlers and use event listeners
abadawi591 Oct 29, 2025
b93ce62
fix: Remove inline onclick and use event listener for submit button
abadawi591 Oct 29, 2025
041c51e
fix: Remove all inline onclick handlers and use event listeners
abadawi591 Oct 29, 2025
c06572d
fix: Restore original user profile card design
abadawi591 Oct 29, 2025
2c6b21d
fix: Restore original user profile card design
abadawi591 Oct 29, 2025
8f7949f
test: Trigger pipeline to verify all UI fixes
abadawi591 Oct 29, 2025
99c3403
chore: Update pipeline pool configuration
abadawi591 Oct 29, 2025
e46f86e
chore: Update pipeline pool configuration
abadawi591 Oct 29, 2025
57b3fd9
test: Trigger pipeline with updated pool configuration
abadawi591 Oct 29, 2025
d11200e
test: Re-trigger pipeline to verify UI changes
abadawi591 Oct 29, 2025
fd80c5a
test: Re-trigger pipeline to verify UI changes
abadawi591 Oct 29, 2025
1755b15
chore: Revert pool configuration
abadawi591 Oct 29, 2025
382eade
chore: Revert pool configuration
abadawi591 Oct 29, 2025
bbc722f
test: Trigger pipeline with reverted pool configuration
abadawi591 Oct 29, 2025
5d390bf
feat: Add dropdown menu to user profile card
abadawi591 Oct 29, 2025
1e0ecef
feat: Add dropdown menu to user profile card
abadawi591 Oct 29, 2025
aac1725
test: Trigger pipeline to verify user profile dropdown menu
abadawi591 Oct 29, 2025
c10b263
test: Force fresh report generation to verify dropdown menu
abadawi591 Oct 29, 2025
27ff770
feat: Add cache-busting to HTML reports
abadawi591 Oct 29, 2025
042c56b
feat: Add cache-busting to HTML reports
abadawi591 Oct 29, 2025
3947948
test: Verify cache-busting and dropdown menu in fresh report
abadawi591 Oct 29, 2025
ea66767
fix: Show user profile dropdown by default instead of Sign In button
abadawi591 Oct 29, 2025
b50de25
fix: Show user profile dropdown by default instead of Sign In button
abadawi591 Oct 29, 2025
596078d
test: Verify user profile dropdown shows by default
abadawi591 Oct 29, 2025
ef04069
feat: Implement full OAuth authentication and challenge submission
abadawi591 Oct 29, 2025
42e7e15
feat: Implement full OAuth authentication and challenge submission
abadawi591 Oct 29, 2025
20f0a39
test: Verify OAuth authentication and challenge submission
abadawi591 Oct 29, 2025
915fb36
fix: Correct JavaScript syntax error in DOMContentLoaded
abadawi591 Oct 29, 2025
ddcc95d
fix: Correct JavaScript syntax error in DOMContentLoaded
abadawi591 Oct 29, 2025
2df3f04
test: Verify JavaScript syntax fix
abadawi591 Oct 29, 2025
770780f
fix: Correct IIFE closing syntax - add missing brace
abadawi591 Oct 29, 2025
a7b2d8b
fix: Correct IIFE closing syntax - add missing brace
abadawi591 Oct 29, 2025
79e29c7
test: Verify IIFE syntax fix
abadawi591 Oct 29, 2025
daeae2c
fix: Remove all double braces in JavaScript (not an f-string)
abadawi591 Oct 29, 2025
a7b8eb4
fix: Remove all double braces in JavaScript (not an f-string)
abadawi591 Oct 29, 2025
1768dbd
test: Verify complete JavaScript brace fix
abadawi591 Oct 29, 2025
57bad0b
fix: Inject pr_number into JavaScript using string replacement
abadawi591 Oct 29, 2025
3ffbc0d
fix: Inject pr_number into JavaScript using string replacement
abadawi591 Oct 29, 2025
9dc50da
test: Verify pr_number injection fix
abadawi591 Oct 29, 2025
0baf075
test: Add JavaScript syntax validation test
abadawi591 Oct 29, 2025
1b564fe
test: Add JavaScript syntax validation test
abadawi591 Oct 29, 2025
3fadcd0
test: Verify all JavaScript fixes in production
abadawi591 Oct 29, 2025
74cbf6d
fix: Correct challenge types to match backend API
abadawi591 Oct 30, 2025
2f066a8
fix: Correct challenge types to match backend API
abadawi591 Oct 30, 2025
36951b9
test: Verify challenge type fix
abadawi591 Oct 30, 2025
29de709
fix: Improve challenge modal emojis and update counters dynamically
abadawi591 Oct 30, 2025
cb96320
fix: Improve challenge modal emojis and update counters dynamically
abadawi591 Oct 30, 2025
fe93d0e
test: Verify emoji and counter fixes
abadawi591 Oct 30, 2025
581592c
fix: Correct warnings/errors count and False Positive emoji
abadawi591 Oct 30, 2025
771e1a2
fix: Correct warnings/errors count and False Positive emoji
abadawi591 Oct 30, 2025
fc01189
test: Verify warnings count and emoji fixes
abadawi591 Oct 30, 2025
027a48c
feat: Enhance RADAR branding with bold styling and tooltip
abadawi591 Oct 30, 2025
3d0fdb8
feat: Enhance RADAR branding with bold styling and tooltip
abadawi591 Oct 30, 2025
60a63e2
test: Verify RADAR branding and tooltip
abadawi591 Oct 30, 2025
6075164
feat: Improve RADAR branding and light theme
abadawi591 Oct 30, 2025
a380256
UI improvements: RADAR branding, light theme, role badges
abadawi591 Oct 30, 2025
eb218e4
UI improvements: RADAR branding, light theme, role badges
abadawi591 Oct 30, 2025
d54f832
fix: Apply UI improvements to topic branch
abadawi591 Oct 30, 2025
ee31baf
chore: Retrigger pipeline to verify UI improvements
abadawi591 Oct 30, 2025
56b89a4
feat: Update RADAR branding in PR comments and fix tooltip
abadawi591 Oct 30, 2025
70fd37b
feat: Update RADAR branding in PR comments and fix tooltip
abadawi591 Oct 30, 2025
4547e4d
chore: Verify RADAR branding and tooltip fixes
abadawi591 Oct 30, 2025
2bd8232
fix: Improve RADAR sizing, tooltip position, and light theme styling
abadawi591 Oct 30, 2025
3f42510
fix: Improve RADAR sizing, tooltip position, and light theme styling
abadawi591 Oct 30, 2025
35286dd
chore: Verify RADAR sizing and light theme fixes
abadawi591 Oct 30, 2025
eb4b94c
feat: Add animated robot logo and improve theme consistency
abadawi591 Oct 30, 2025
6cbeef3
feat: Add animated robot logo and improve theme consistency
abadawi591 Oct 30, 2025
cdcc486
chore: Verify animated robot logo and theme improvements
abadawi591 Oct 30, 2025
635cba5
feat: Enhanced theme system and improved UI styling
abadawi591 Oct 30, 2025
86248f9
feat: Enhanced theme system and improved UI styling
abadawi591 Oct 30, 2025
60a199c
chore: Verify enhanced theme and UI improvements
abadawi591 Oct 30, 2025
e9ad5f3
refine: Polish UI theme and styling details
abadawi591 Oct 30, 2025
1e29136
refine: Additional UI polish and refinements
abadawi591 Oct 30, 2025
82ebeaf
refine: Polish UI theme and styling details
abadawi591 Oct 30, 2025
5dd7abe
refine: Additional UI polish and refinements
abadawi591 Oct 30, 2025
3b4e759
chore: Verify latest UI refinements
abadawi591 Oct 30, 2025
850c661
feat: Add assets directory and final UI polish
abadawi591 Oct 30, 2025
c92c7cd
feat: Add assets directory and final UI polish
abadawi591 Oct 30, 2025
195b4b3
chore: Verify assets and final polish
abadawi591 Oct 30, 2025
6865f5d
refine: Continue UI improvements and adjustments
abadawi591 Oct 30, 2025
963ccee
refine: Continue UI improvements and adjustments
abadawi591 Oct 30, 2025
71f24fc
chore: Verify continued UI improvements
abadawi591 Oct 30, 2025
37afe75
refine: Additional UI tweaks and optimizations
abadawi591 Oct 30, 2025
8a20bf7
refine: Additional UI tweaks and optimizations
abadawi591 Oct 30, 2025
ede0538
chore: Verify UI tweaks
abadawi591 Oct 30, 2025
495d4a9
refine: Further UI refinements
abadawi591 Oct 31, 2025
86115c4
refine: Further UI refinements
abadawi591 Oct 31, 2025
8c3d7a5
chore: Verify further refinements
abadawi591 Oct 31, 2025
903924e
refine: More UI updates
abadawi591 Oct 31, 2025
a8812cd
refine: More UI updates
abadawi591 Oct 31, 2025
8cee55a
chore: Verify latest UI updates
abadawi591 Oct 31, 2025
3a20250
refine: Additional UI improvements
abadawi591 Oct 31, 2025
4af83a5
refine: Additional UI improvements
abadawi591 Oct 31, 2025
1a5e5b5
chore: Verify additional UI improvements
abadawi591 Oct 31, 2025
c3d0bb7
refine: UI enhancements
abadawi591 Oct 31, 2025
e7aa759
refine: UI enhancements
abadawi591 Oct 31, 2025
69072f9
chore: Verify UI enhancements
abadawi591 Oct 31, 2025
30ef746
fix: Add missing Severity comparison operators and fix anti_patterns …
abadawi591 Oct 31, 2025
57493d6
fix: Add missing Severity comparison operators and fix anti_patterns …
abadawi591 Oct 31, 2025
b372212
fix: Load actual radar_light.png and radar_dark.png logos instead of …
abadawi591 Oct 31, 2025
4692718
fix: Load actual radar_light.png and radar_dark.png logos instead of …
abadawi591 Oct 31, 2025
7e685f6
chore: Verify logo fix
abadawi591 Oct 31, 2025
31412ac
refine: Increase RADAR logo size from 32x32 to 48x48
abadawi591 Oct 31, 2025
6a5c36c
refine: Increase RADAR logo size from 32x32 to 48x48
abadawi591 Oct 31, 2025
38b26c0
chore: Verify larger logo size
abadawi591 Oct 31, 2025
dc754d7
fix: Preserve RADAR logo aspect ratio by removing width constraint
abadawi591 Oct 31, 2025
6b9a2be
fix: Preserve RADAR logo aspect ratio by removing width constraint
abadawi591 Oct 31, 2025
adf2469
chore: Verify logo aspect ratio fix
abadawi591 Oct 31, 2025
ec488b0
refine: Increase logo height to 64px for better visibility
abadawi591 Nov 4, 2025
d4b643a
refine: Increase logo height to 64px for better visibility
abadawi591 Nov 4, 2025
8a0fe32
chore: Verify larger logo size
abadawi591 Nov 4, 2025
f15d066
feat: Add click-to-view functionality for challenged items
abadawi591 Nov 4, 2025
36c2aea
feat: Add click-to-view functionality for challenged items
abadawi591 Nov 4, 2025
a1de7f5
chore: Verify challenged item click functionality
abadawi591 Nov 4, 2025
65ce396
feat: Implement challenge persistence and details view
abadawi591 Nov 4, 2025
8aeb353
feat: Implement challenge persistence and details view
abadawi591 Nov 4, 2025
dc19c6d
chore: Test challenge persistence implementation
abadawi591 Nov 4, 2025
74f4969
fix: JavaScript syntax error and set default theme to dark
abadawi591 Nov 4, 2025
3ab49dc
fix: JavaScript syntax error and set default theme to dark
abadawi591 Nov 4, 2025
fce7cd8
chore: Verify syntax fix and dark theme default
abadawi591 Nov 4, 2025
7132686
fix: Convert all template literals to string concatenation in showCha…
abadawi591 Nov 4, 2025
e7edcae
fix: Convert all template literals to string concatenation in showCha…
abadawi591 Nov 4, 2025
de0775e
chore: Test complete template literal removal fix
abadawi591 Nov 4, 2025
5ae54c8
fix: Enrich challenged issues with challenge metadata
abadawi591 Nov 4, 2025
ccac105
fix: Enrich challenged issues with challenge metadata
abadawi591 Nov 4, 2025
e73a815
chore: Test challenge metadata enrichment fix
abadawi591 Nov 4, 2025
d5c9a63
fix: Add missing fields to Azure Function challenge object
abadawi591 Nov 4, 2025
c4a0dd0
fix: Add missing fields to Azure Function challenge object
abadawi591 Nov 4, 2025
28d75fb
chore: Test Azure Function field compatibility fix
abadawi591 Nov 4, 2025
3acc4f1
fix: Use double braces for pr_number placeholder to avoid JavaScript …
abadawi591 Nov 4, 2025
d4af2d0
fix: Use double braces for pr_number placeholder to avoid JavaScript …
abadawi591 Nov 4, 2025
11aae78
chore: Test pr_number placeholder syntax fix
abadawi591 Nov 4, 2025
d6a4143
feat: Auto-trigger PR check re-run after challenge submission
abadawi591 Nov 4, 2025
715effa
feat: Auto-trigger PR check re-run after challenge submission
abadawi591 Nov 4, 2025
44751cf
chore: Test auto-refresh after challenge submission
abadawi591 Nov 4, 2025
c010660
fix: Use __PR_NUMBER__ placeholder to avoid any JavaScript syntax con…
abadawi591 Nov 4, 2025
2681774
fix: Use __PR_NUMBER__ placeholder to avoid any JavaScript syntax con…
abadawi591 Nov 4, 2025
8b01613
chore: Test __PR_NUMBER__ placeholder fix
abadawi591 Nov 4, 2025
b2eb642
chore: Verify __PR_NUMBER__ fix is working - final test
abadawi591 Nov 4, 2025
c267eec
fix: Use string concatenation to inject pr_number directly
abadawi591 Nov 4, 2025
b5ea356
fix: Use string concatenation to inject pr_number directly
abadawi591 Nov 4, 2025
ce788cc
chore: Test string concatenation pr_number injection
abadawi591 Nov 4, 2025
2bff675
fix: Fix JavaScript syntax error - replace double braces with single …
abadawi591 Nov 4, 2025
fc7af74
fix: Fix JavaScript syntax error - replace double braces with single …
abadawi591 Nov 4, 2025
3799789
chore: Retrigger PR checks
abadawi591 Nov 4, 2025
f31dc63
feat: Azure Function regenerates HTML report immediately after challenge
abadawi591 Nov 4, 2025
1dcdfa7
feat: Azure Function regenerates HTML report immediately after challenge
abadawi591 Nov 4, 2025
6130064
fix: Use correct HtmlReportGenerator methods and pass categorized_iss…
abadawi591 Nov 4, 2025
95c13a1
fix: Use correct HtmlReportGenerator methods and pass categorized_iss…
abadawi591 Nov 4, 2025
9b6ba96
chore: Retrigger PR to test Azure Function HTML regeneration
abadawi591 Nov 4, 2025
591635c
chore: Test Azure Function HTML regeneration after deployment
abadawi591 Nov 4, 2025
74edcb5
feat: Add comprehensive console logging for challenge submission debu…
abadawi591 Nov 4, 2025
dde4ca6
feat: Add comprehensive console logging for challenge submission debu…
abadawi591 Nov 4, 2025
3f14ec3
chore: Retrigger PR to test console logging for challenge submission
abadawi591 Nov 4, 2025
ae64df8
fix: Include HTML generator dependencies directly in azure-function d…
abadawi591 Nov 4, 2025
e74f59d
fix: Include HTML generator dependencies directly in azure-function d…
abadawi591 Nov 4, 2025
3068efd
chore: Retrigger PR to test fixed Azure Function imports
abadawi591 Nov 4, 2025
c44b9b1
feat: Add comprehensive logging to Azure Function HTML generation
abadawi591 Nov 4, 2025
9ffccf5
feat: Add comprehensive logging to Azure Function HTML generation
abadawi591 Nov 4, 2025
ba7f83d
chore: Test Azure Function with enhanced logging
abadawi591 Nov 4, 2025
aa43d59
fix: Only regenerate HTML when specs data exists in analytics.json
abadawi591 Nov 4, 2025
e166898
fix: Only regenerate HTML when specs data exists in analytics.json
abadawi591 Nov 4, 2025
3ac5f8e
chore: Test conditional HTML generation fix
abadawi591 Nov 4, 2025
70c48c8
fix: Correct regex pattern for updating challenge buttons in HTML
abadawi591 Nov 5, 2025
835cea2
fix: Correct regex pattern for updating challenge buttons in HTML
abadawi591 Nov 5, 2025
7bbbab7
chore: Trigger PR check to test regex fix for challenge buttons
abadawi591 Nov 5, 2025
508d771
fix: Handle whitespace in button text for regex matching
abadawi591 Nov 5, 2025
693c15a
chore: Test whitespace regex fix for challenge buttons
abadawi591 Nov 5, 2025
7d1b74b
fix: Handle whitespace in button text for regex matching
abadawi591 Nov 5, 2025
a4358ad
chore: Retrigger after syncing topic branch
abadawi591 Nov 5, 2025
dcddf27
fix: Update HTML in-place instead of creating new file
abadawi591 Nov 5, 2025
a859ff2
chore: Test in-place HTML update for challenge submissions
abadawi591 Nov 5, 2025
b1b50bc
fix: Update HTML in-place instead of creating new file
abadawi591 Nov 5, 2025
2254f38
chore: Retrigger to test in-place HTML update with new PR check
abadawi591 Nov 5, 2025
b7ba69a
fix: Update button in DOM instead of reloading page
abadawi591 Nov 5, 2025
1f8fbcd
fix: Update button in DOM instead of reloading page
abadawi591 Nov 5, 2025
fce99a5
docs: Clarify that Total Issues count includes challenged issues
abadawi591 Nov 5, 2025
df602ce
chore: Test DOM update with challenge button fix
abadawi591 Nov 5, 2025
ca5f199
Add open issues counter and update notification badge
abadawi591 Nov 5, 2025
593fa25
Merge branch 'test/ui-verification-with-antipatterns' into abadawi/mu…
abadawi591 Nov 5, 2025
106a3fa
Reset SPECS to match 3.0-dev baseline
abadawi591 Nov 5, 2025
5b05e27
UI fix: Add margin and padding to challenge modal
abadawi591 Nov 5, 2025
fd17699
UI enhancements: Custom favicon and improved card hover effects
abadawi591 Nov 6, 2025
d4aa1ce
Fix: Add multiple favicon declarations for better browser compatibility
abadawi591 Nov 6, 2025
96af57c
Debug: Simplify favicon and add logging
abadawi591 Nov 6, 2025
039df2e
Enhance filterable card hover effects for better visibility
abadawi591 Nov 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 8 additions & 0 deletions .pipelines/prchecks/CveSpecFilePRCheck/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Documentation and development notes (not for public repo)
docs/

# Shell scripts for local development
*.sh

# Test files
test_*.py
382 changes: 382 additions & 0 deletions .pipelines/prchecks/CveSpecFilePRCheck/AnalyticsManager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,382 @@
#!/usr/bin/env python3
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.

"""
AnalyticsManager
----------------
Manages the analytics.json file in blob storage for tracking PR analysis history,
challenged issues, and issue lifecycle across commits.
"""

import json
import logging
from datetime import datetime
from typing import Dict, List, Optional
from dataclasses import dataclass, asdict
from azure.core.exceptions import ResourceNotFoundError

logger = logging.getLogger("AnalyticsManager")


@dataclass
class IssueRecord:
"""Represents a detected issue in a commit"""
issue_hash: str
spec_file: str
antipattern_type: str
antipattern_name: str
description: str
severity: str
line_number: Optional[int]
first_detected_commit: str # SHA of commit where first seen
status: str # active | challenged | resolved


@dataclass
class CommitAnalysis:
"""Represents analysis results for a single commit"""
commit_sha: str
timestamp: str
report_url: str
issues_detected: List[Dict] # List of IssueRecord dicts
issue_count: int


@dataclass
class Challenge:
"""Represents a user challenge to an issue"""
challenge_id: str
issue_hash: str
commit_sha: str # Commit where challenge was submitted
spec_file: str
antipattern_type: str
details: str
submitted_at: str
submitted_by: Dict # {username, email, is_collaborator}
challenge_type: str # false-positive | needs-clarification | other
feedback_text: str
status: str # submitted | acknowledged | rejected


class AnalyticsManager:
"""Manages PR analytics data in blob storage"""

def __init__(self, blob_storage_client, pr_number: int):
"""
Initialize the analytics manager.

Args:
blob_storage_client: BlobStorageClient instance for blob operations
pr_number: GitHub PR number
"""
self.blob_client = blob_storage_client
self.pr_number = pr_number
self.analytics = None # Cache for current analytics data
logger.info(f"Initialized AnalyticsManager for PR #{pr_number}")

def load_analytics(self) -> Dict:
"""
Load analytics.json for the PR from blob storage.

Returns:
Analytics data dict, or new empty structure if not found
"""
blob_name = f"PR-{self.pr_number}/analytics.json"

try:
logger.info(f"📦 Loading analytics from blob: {blob_name}")

# Download from blob storage
blob_client = self.blob_client.blob_service_client.get_blob_client(
container=self.blob_client.container_name,
blob=blob_name
)

blob_data = blob_client.download_blob()
analytics_json = blob_data.readall().decode('utf-8')
analytics = json.loads(analytics_json)

logger.info(f"✅ Loaded analytics with {len(analytics.get('commits', []))} commits")
self.analytics = analytics # Cache the loaded analytics
return analytics

except ResourceNotFoundError:
logger.info(f"📝 Analytics not found, creating new structure for PR #{self.pr_number}")
analytics = self._create_new_analytics()
self.analytics = analytics
return analytics
except Exception as e:
logger.error(f"❌ Error loading analytics: {e}")
# Return new structure on error
analytics = self._create_new_analytics()
self.analytics = analytics
return analytics

def _create_new_analytics(self) -> Dict:
"""Create new analytics structure for the PR"""
return {
"pr_number": self.pr_number,
"created_at": datetime.utcnow().isoformat() + "Z",
"last_updated": datetime.utcnow().isoformat() + "Z",
"commits": [],
"challenges": [],
"issue_lifecycle": {},
"summary_metrics": {
"total_commits_analyzed": 0,
"total_issues_ever_detected": 0,
"currently_active_issues": 0,
"challenged_issues": 0,
"resolved_issues": 0
}
}

def save_analytics(self) -> bool:
"""
Save analytics.json to blob storage.

Returns:
True if successful, False otherwise
"""
if not self.analytics:
logger.warning("No analytics data to save")
return False

blob_name = f"PR-{self.pr_number}/analytics.json"

try:
logger.info(f"💾 Saving analytics to blob: {blob_name}")

# Update last_updated timestamp
self.analytics["last_updated"] = datetime.utcnow().isoformat() + "Z"

# Upload to blob storage
blob_client = self.blob_client.blob_service_client.get_blob_client(
container=self.blob_client.container_name,
blob=blob_name
)

analytics_json = json.dumps(self.analytics, indent=2)
blob_client.upload_blob(analytics_json, overwrite=True)

logger.info(f"✅ Analytics saved successfully")
return True

except Exception as e:
logger.error(f"❌ Error saving analytics: {e}")
return False

def add_commit_analysis(
self,
commit_sha: str,
report_url: str,
issues: List
) -> None:
"""
Record analysis for a new commit.

Args:
commit_sha: Git commit SHA
report_url: URL to HTML report in blob storage
issues: List of AntiPattern objects detected
"""
if not self.analytics:
logger.error("Analytics not loaded, call load_analytics() first")
return

# Convert AntiPattern objects to dicts for storage
issue_records = []
for issue in issues:
issue_record = {
"issue_hash": issue.issue_hash,
"spec_file": issue.file_path,
"antipattern_type": issue.id,
"antipattern_name": issue.name,
"description": issue.description,
"severity": issue.severity.name,
"line_number": issue.line_number,
"first_detected_commit": commit_sha,
"status": "active"
}
issue_records.append(issue_record)

# Add commit analysis
commit_analysis = {
"commit_sha": commit_sha,
"timestamp": datetime.utcnow().isoformat() + "Z",
"report_url": report_url,
"issues_detected": issue_records,
"issue_count": len(issues)
}

self.analytics["commits"].append(commit_analysis)
self.analytics["summary_metrics"]["total_commits_analyzed"] = len(self.analytics["commits"])

# Update issue lifecycle tracking
for issue_record in issue_records:
issue_hash = issue_record["issue_hash"]
if issue_hash not in self.analytics["issue_lifecycle"]:
self.analytics["issue_lifecycle"][issue_hash] = {
"first_detected": commit_sha,
"last_detected": commit_sha,
"challenge_id": None,
"status": "active",
"resolution": None
}
else:
# Update last_detected for recurring issues
self.analytics["issue_lifecycle"][issue_hash]["last_detected"] = commit_sha

logger.info(f"📊 Added commit analysis for {commit_sha}: {len(issues)} issues")

def get_challenged_issues(self) -> Dict[str, Dict]:
"""
Get all challenged issues for the PR.

Returns:
Dict mapping issue_hash to challenge data
"""
if not self.analytics:
logger.warning("Analytics not loaded")
return {}

challenged_issues = {}
for challenge in self.analytics.get("challenges", []):
issue_hash = challenge.get("issue_hash")
if issue_hash:
challenged_issues[issue_hash] = challenge

logger.info(f"Found {len(challenged_issues)} challenged issues in PR #{self.pr_number}")
return challenged_issues

def categorize_issues(
self,
current_issues: List
) -> Dict[str, List]:
"""
Categorize current commit's issues based on history and challenges.

Args:
current_issues: List of AntiPattern objects from current commit

Returns:
Dict with categorized issues:
{
"new_issues": [...], # Renamed from new_unchallenged
"recurring_unchallenged": [...],
"challenged_issues": [...], # Renamed from previously_challenged
"resolved_issues": [] # Issues from previous commits not in current
}
"""
if not self.analytics:
logger.warning("Analytics not loaded")
return {
"new_issues": current_issues,
"recurring_unchallenged": [],
"challenged_issues": [],
"resolved_issues": []
}

# Get previous commit's issues (if exists)
previous_hashes = set()
if self.analytics.get("commits") and len(self.analytics["commits"]) > 1:
# Get second-to-last commit (before current one we just added)
last_commit = self.analytics["commits"][-2]
previous_hashes = {
issue["issue_hash"]
for issue in last_commit.get("issues_detected", [])
}

# Get challenged issue hashes and build a map of challenge metadata
challenged_hashes = {}
for challenge in self.analytics.get("challenges", []):
challenged_hashes[challenge["issue_hash"]] = {
"challenge_type": challenge.get("challenge_type", "unknown"),
"challenge_feedback": challenge.get("feedback", ""),
"challenge_user": challenge.get("user", "unknown"),
"challenge_timestamp": challenge.get("timestamp", "")
}

# Get current issue hashes
current_hashes = {issue.issue_hash for issue in current_issues}

# Calculate resolved issues (in previous, not in current, not challenged)
resolved_hashes = previous_hashes - current_hashes - set(challenged_hashes.keys())

# Categorize current issues
new_issues = []
recurring_unchallenged = []
challenged_issues = []

for issue in current_issues:
issue_hash = issue.issue_hash

if issue_hash in challenged_hashes:
# Issue was previously challenged - enrich with challenge metadata
challenge_data = challenged_hashes[issue_hash]
# Add challenge metadata as attributes to the AntiPattern object
issue.challenge_type = challenge_data["challenge_type"]
issue.challenge_feedback = challenge_data["challenge_feedback"]
issue.challenge_user = challenge_data["challenge_user"]
issue.challenge_timestamp = challenge_data["challenge_timestamp"]
challenged_issues.append(issue)
elif issue_hash not in previous_hashes:
# New issue (not in previous commit, not challenged)
new_issues.append(issue)
else:
# Recurring issue (was in previous, not challenged)
recurring_unchallenged.append(issue)

result = {
"new_issues": new_issues,
"recurring_unchallenged": recurring_unchallenged,
"challenged_issues": challenged_issues,
"resolved_issues": list(resolved_hashes) # Just hashes for resolved
}

logger.info(f"📊 Categorized issues: "
f"{len(new_issues)} new, "
f"{len(recurring_unchallenged)} recurring unchallenged, "
f"{len(challenged_issues)} previously challenged, "
f"{len(resolved_hashes)} resolved")

return result

def update_summary_metrics(self) -> None:
"""
Recalculate summary metrics based on current analytics data.
"""
if not self.analytics:
logger.warning("Analytics not loaded")
return

# Count unique issues ever detected
all_issue_hashes = set()
for commit in self.analytics.get("commits", []):
for issue in commit.get("issues_detected", []):
all_issue_hashes.add(issue["issue_hash"])

# Get latest commit's issues
currently_active = set()
if self.analytics.get("commits"):
last_commit = self.analytics["commits"][-1]
currently_active = {
issue["issue_hash"]
for issue in last_commit.get("issues_detected", [])
}

# Count challenged issues
challenged_count = len(self.analytics.get("challenges", []))

# Count resolved issues (were in previous commits, not in latest)
resolved_hashes = all_issue_hashes - currently_active

self.analytics["summary_metrics"] = {
"total_commits_analyzed": len(self.analytics.get("commits", [])),
"total_issues_ever_detected": len(all_issue_hashes),
"currently_active_issues": len(currently_active),
"challenged_issues": challenged_count,
"resolved_issues": len(resolved_hashes)
}

logger.info(f"📈 Updated metrics: {self.analytics['summary_metrics']}")
Loading