
    _i;                        d Z ddlZddlZddlZddlZddlmZ ddlmZ ddlm	Z	m
Z
 	 ddlmZ ddlmZ ddlmZ dd	lmZ  ej(                  ej*                  d ej,                  ej.                        g        ej0                  e      Zdede
e	   fdZdede
e	   de
e	   ddfdZddZdedededede
e	   de
e    de
e    ddfdZ!edk(  r		  e        yy# e$ r d
dlmZ d
dlmZ d
dlmZ d
d	lmZ Y w xY w# e"$ r& ejG                  d        ejH                  d
       Y ye%$ r0Z&ejO                  de&         ejH                  d
       Y dZ&[&ydZ&[&ww xY w)z
Weekly scan: Bitbucket repos with commits in the last N days, pull and run SonarQube scan.
Generates a summary report of all pulled and scanned repos (no per-repo PDFs).
    N)Path)datetime)DictList)ConfigManager)BitbucketClient)
GitManager)SonarQubeScanner   4%(asctime)s - %(name)s - %(levelname)s - %(message)s)levelformathandlersconfigreturnc                    | j                  dg       }|sg S g }|D ]N  }t        |t              rH|j                  d      rf|j	                  dd      j	                  dd      }|j                  d      }t        |      dk(  sh|\  }}|j                  ||d|idd	|d
gid       |j                  d      rk|j	                  dd      j	                  dd      }|j                  d      }t        |      dk(  s|\  }}|j                  ||d|idd	|d
d|d
gid       d|v s|j                  d      }t        |      dk(  s/|\  }}d| d| d}	|j                  ||d|idd	|	d
gid       ]t        |t              so|j                  d      xs |j                  d      }|j                  d      }|j                  d      xs |j                  d      }	|s|	st        |t              rd|i}nJ|sHd|	v rD|	j	                  dd      j	                  dd      }d|v r|j                  d      d   nd}
|
rd|
ini }|j                  |||xs i dd	|	d
gid       Q |S )z@Get additional repositories from config (same logic as main.py).z scanning.additional_repositorieszgit@bitbucket.org: .git/   slugclonessh)namehref)r   r   	workspacelinkszhttps://github.com/httpsr   r   ssh_url	clone_urlr   N)	get
isinstancestr
startswithreplacesplitlenappenddict)r   additional_repos_configreposrepo_configpathpartsr   	repo_nameorgr   ws_names              3/home/batmin/projects/sonar_scan/src/weekly_scan.py_get_additional_repositoriesr3   !   s   $jj)KRP"	E. 8k3'%%&:;"**+?DLLVUWX

3u:?+0(IyLL ) )&,i%8")UK,P+Q!R	"  ''(=>"**+@"EMMfVXY

3u:?%*NCLL ) )&,c]#). D)0+ F&"	
" 
 ##))#.u:?+0(Iy 29+QykNGLL ) )&,i%8")UG,L+M!N	"  T*#/J;??63JI#4I!ooi0PKOOK4PGWi-!' 3I"';w'F"??+?DLLVUWXD474Kdjjoa0TG5< 1"I%%!*b%(H'IJ	 g8r L    	all_repos
to_processc                    | j                  d      xs g }t        |t              r=|j                  d      D cg c]#  }|j	                         s|j	                         % }}|sy |D ch c]H  }|j                  d      s|j                  d      r$|j                  d      xs |j                  d      J }}|D ]  }|r||v r
|D ]g  }|j                  d      xs |j                  d      }	|	|k(  s-|j                  |       |j                  |       t        j                  d|         u t        j                  d|        y c c}w c c}w )Nz#scanning.scan_recent_always_include,r   r   z-Including repo (scan_recent_always_include): uc   scan_recent_always_include: slug %r not in repo list — add scanning.additional_repositories entry)
r!   r"   r#   r&   stripr(   addloggerinfowarning)
r   r5   r6   rawsrseenr   	repo_inforslugs
             r2   !_merge_scan_recent_always_includerD   d   s8   
**:
;
ArC#s"%))C.>QAGGIqwwy>> 55=AEE&M 
v	'!%%-	'D 
  tt|" 	IMM&)BY]]6-BE}!!),KD6RS	 NNu ?s   E
E
*AEc            	         t        t              j                         j                  j                  } t	        |       t
        j                  vr)t
        j                  j                  dt	        |              t        j                  |        | dz  }|j                  dd       t        j                         j                  d      }|d| dz  }t        j                  |d	      }|j!                  t        j"                  d
             t        j$                         j'                  |       t(        j+                  d       	 t-               }j5                  d      s*t(        j1                  d       t        j2                  d       t7        |j5                  d            }t7        |j5                  d            }|j5                  d      s*t(        j1                  d       t        j2                  d       |s,|s*t(        j1                  d       t        j2                  d       |j5                  d      s*t(        j1                  d       t        j2                  d       |j5                  d      xs d}	|j5                  d      }
t        |j5                  d            }t        |j5                  d            }|j                  dd       t9        |
|j5                  d      |s|j5                  d      nd|j5                  d            }t;        |j5                  d            }t=        |j5                  d      |j5                  d      |j5                  d             }|j?                         xs g }tA        |      }|r3t(        j+                  d!tC        |       d"       |jE                  |       |s't(        jG                  d#       tI        ||||	g g g        y|j5                  d$      xs g }tK        |t              r=|jM                  d%      D cg c]#  }|jO                         s|jO                         % }}|r|D ch c]  }|jQ                          }}|D cg c]=  }|j5                  d&      xs |j5                  d'      xs d(jQ                         |v s<|? }}t(        j+                  d)tC        |       d*d+jS                  |       d,       |s't(        jG                  d-       tI        ||||	g g g        yg }|D ]  }|j5                  d&      xs |j5                  d'      }|s*|j5                  d.      xs i j5                  d'      }|r/||
k7  r*|jU                  |       t(        j+                  d/|        |jW                  ||	0      s|jU                  |       t(        j+                  d1|	 d2|         tY        |||       t(        j+                  d3tC        |              g }|D ]  }|j5                  d&      xs |j5                  d'      }|j[                  |d45      }|s.t(        jG                  d6| d7       |jU                  |d8d9f       j	 |j]                  ||:      }|xr tK        |t^              xr |d   }|jU                  |||rd;nd<f       |rt(        j+                  d=|        nt(        jG                  d>|         g }|D ]  }|j5                  d&      xs |j5                  d'      }||z  }|jc                         r|dAz  jc                         s|jU                  |d8dBf       e|je                  |      } | s|j5                  d.i       j5                  d'      xs |
}!|! dC| jQ                         jg                  dDdC      jg                  dEdC      }"ti        jj                  dFdC|"      }"|j5                  d&      xs |}#	 |jm                  ||"|#G      } |jo                  |       }"|"s|jU                  |d8dIf       <|jq                  |"      s?|j5                  d&      xs |}#|j5                  dJd(      xs d(}$|js                  |"|#|$K       	 |ju                  ||       }|j5                  dLd8      }%|%s|j5                  dMd(      nd(}&|jU                  ||%|&xs |%rd;ndNf       |%rt(        j+                  dO|        nt(        jG                  dP| dQ|&         tI        ||||	|||       t(        j+                  dS       y# t.        $ r8}t(        j1                  d|        t        j2                  d       Y d}~d}~ww xY wc c}w c c}w c c}w # t.        $ rC}t(        ja                  d?| d@|        |jU                  |d8t	        |      f       Y d}~d}~ww xY w# t.        $ rC}t(        j1                  dH| d@|        |jU                  |d8t	        |      f       Y d}~,d}~ww xY w# t.        $ rC}t(        ja                  dR| d@|        |jU                  |d8t	        |      f       Y d}~{d}~ww xY w)Tz"Run weekly pull and scan workflow.r   logsT)parentsexist_okz%Y%m%d_%H%M%Sweekly_scan_z.logutf-8encodingr   zAStarting weekly pull and scan (repos with commits in last N days)zFailed to load config: r   Nzbitbucket.workspacez"Bitbucket workspace not configuredzbitbucket.api_tokenzbitbucket.app_passwordzbitbucket.usernamez'Bitbucket username/email not configuredzHBitbucket authentication not configured (need API token or app password)zsonarqube.tokenzSonarQube token not configuredzscanning.weekly_scan_days   zscanning.repos_dirzscanning.reports_dir)r   usernameapp_password	api_token)	repos_dirzsonarqube.urlzscanning.sonar_scanner_path)	sonar_urlsonar_tokenscanner_pathzFound z$ additional repositories from configzNo repositories foundzscanning.weekly_scan_reposr8   r   r   r   zLimited to whitelist: z repos (z, )z0No repos matched the weekly_scan_repos whitelistr   z-Including additional repo (no commit check): )daysz Including repo (commits in last z days): zRepos to pull and scan: r   )protocolzNo SSH clone URL for z
, skippingFzNo clone URL)	repo_slugr    OKzPull failedz	Pull OK: zPull failed: zPull error for : r   zRepo missing or not a git repo_- z
[^a-z0-9_])	repo_pathproject_keyproject_namez0Failed to generate sonar-project.properties for z*No project key in sonar-project.propertiesdescription)r_   r`   ra   successerrorzScan failedz	Scan OK: zScan failed:  - zScan error for z)Weekly scan finished. See summary report.);r   __file__resolveparentr#   sysr-   insertoschdirmkdirr   nowstrftimeloggingFileHandlersetFormatter	Formatter	getLogger
addHandlerr;   r<   r   	Exceptionrc   exitr!   boolr   r	   r
   get_all_repositoriesr3   r'   extendr=   _write_summaryr"   r&   r9   lowerjoinr(   has_commits_in_last_n_daysrD   get_clone_urlclone_or_updatetuple	exceptionexistsget_sonar_properties_pathr%   resubgenerate_sonar_propertiesget_project_keycheck_project_existscreate_projectrun_scan)'project_rootlog_dirlog_tslog_filefile_handlerr   ehas_api_tokenhas_app_passwordrV   main_workspacerQ   reports_dir	bitbucketgit_managersonar_scannerr+   
additional	whitelistr?   whitelist_setr@   r6   rB   rX   ws_slugpull_resultsr    resultokscan_resultsr^   sonar_props_pathr   r_   r`   ra   rb   errs'                                          r2   run_weekly_scanr      s?	    >))+2299L
<(3|,- HH\ V#GMM$M.\\^$$_5F<xt44H&&x'BLg//0fgh""<0
KKST ::+,9:$9:;MFJJ'?@A::*+>?!1_`::'(56::127aDZZ 56NVZZ 456Ivzz"89:KdT2   01ANVZZ 89TX**23	I vzz2F'GHK$**_-JJ01ZZ =>M **,2E-f5JfS_--QRSZ ./xfdBBG 

78>BI)S!(1(<J1	QWWYJ	J,56q66!eqaeeFm&JquuV}&J%Q%Q%SWd%dee,SZL9AU@VVWXYNNMN8[&$BK J V	MM&)BY]]6-B	==-388@w.0i(KKG	{ST11)$1Gi(KK:4&TUV &feZ@
KK*3z?*;<= L <	MM&)BY]]6-B	++I+F	NN29+ZHIE> BC
	< 009PY0ZFEZ6D6!9BB NOi	{34yk:;<( L 1<	MM&)BY]]6-B		)	!)f*<)D)D)FE3S TU&@@K!k26::6BTnI&Kq4::<DDS#NVVWZ\_`K&&[AK$==0=IL	#0#J#J' +!- $K $  $334DEE3_ `a11+>$==0=IL#--r:@bK((')' ) 	<"++I7GHFjjE2G18&**Wb)bCGS5`WTR_ abi	{34ykSEBC]1<f 8[&$
LR^_
KK;<{  .qc23n K6eR  	<ykA3?@E3q6 :;;	<2  OPY{Z\]^\_`a##Ys1v$>?8  	<ykA3?@E3q6 :;;	<s   
d* e..e.e3%=e8#e8(A9e=&g4Bh*	e+3-e&&e+=	g	8gg		h8hh	i'$8i""i'r   r   r   rV   r   r   c           	         |d|dd  dz  }ddt        j                         j                          d| dd	t        |       dd
dg}t	        d |D              }	|D ]$  \  }
}}|j                  d|rdnd d|
 d|        & |j                  d
d|	 dt        |       d
dg       t	        d |D              }|D ]$  \  }
}}|j                  d|rdnd d|
 d|        & |j                  d
d| dt        |       dg       dj                  |      }|j                  |d       t        j                  d|        t        j                  d|         y)z6Write summary report to reports dir and append to log.weekly_scan_summary_N   z.txtz<============================================================zWeekly Scan Summary - zLookback: last z dayszRepos with commits in window: r   zPull results:c              3   .   K   | ]  \  }}}|s
d   ywr   N .0r[   r   s      r2   	<genexpr>z!_write_summary.<locals>.<genexpr>K       72qB!7   z  rY   FAILrZ   rd   zPulled: r   zScan results:c              3   .   K   | ]  \  }}}|s
d   ywr   r   r   s      r2   r   z!_write_summary.<locals>.<genexpr>O  r   r   z	Scanned: 
rJ   rK   zSummary written to z
Log file: )r   rm   	isoformatr'   sumr(   ry   r|   
write_textr;   r<   )r   r   r   rV   r6   r   r   summary_pathlinespull_okrX   r   msgscan_oksummary_texts                  r2   rz   rz   7  s    #7r
|4!HHL
 !9!9!; <=
$u%
(Z(9:
E 7L77G* I	2sr"$&1I;c#GHI	LL"	3|+<*=>OTU7L77G* I	2sr"$&1I;c#GHI	LL"	'!C,=+>?JK99U#LL7;
KK%l^45
KK*XJ'(r4   __main__zInterrupted by userzFatal error: )r   N)(__doc__rj   r   rh   ro   pathlibr   r   typingr   r   config_managerr   bitbucket_clientr   r   r	   sonarqube_scannerr
   ImportErrorbasicConfigINFOStreamHandlerstdoutrs   __name__r;   r3   rD   r   r#   intr   rz   KeyboardInterruptr<   rv   ru   r   r   r   r4   r2   <module>r      s   
 	 
    	4,0&2   
,,A#g##CJJ/0
 
		8	$@ @4: @Fm T
 `dei`j os 8t=n))) ) 	)
 T
) u+) u+) 
)D z O
  4-1'3	4T
  )* =,-s/   C C< C98C9<(E&E*&EE