2929use Symfony \Component \Console \Output \OutputInterface ;
3030use Symfony \Component \Console \Question \ConfirmationQuestion ;
3131use GuzzleHttp \Client ;
32+ use InvalidArgumentException ;
3233
3334/**
3435 * List repo details
@@ -46,8 +47,7 @@ protected function configure()
4647 ->setDescription ('ensure all github repositories meet compliance ' )
4748 ->addOption ('component ' , 'c ' , InputOption::VALUE_REQUIRED , 'If specified, display repo info for this component only ' , '' )
4849 ->addOption ('token ' , 't ' , InputOption::VALUE_REQUIRED , 'Github token to use for authentication ' , '' )
49- ->addOption ('page ' , 'p ' , InputOption::VALUE_REQUIRED , 'page to start from ' , '1 ' )
50- ->addOption ('results-per-page ' , 'r ' , InputOption::VALUE_REQUIRED , 'results to display per page (0 for all) ' , '10 ' )
50+ ->addOption ('format ' , 'f ' , InputOption::VALUE_REQUIRED , 'can be "ci" or "table" ' , 'table ' )
5151 ->addOption ('new-packagist-token ' , '' , InputOption::VALUE_REQUIRED , 'update the packagist token ' )
5252 ;
5353 }
@@ -59,54 +59,44 @@ protected function execute(InputInterface $input, OutputInterface $output)
5959 $ this ->github = new GitHub (new RunShell (), $ http , $ input ->getOption ('token ' ), $ output );
6060 $ this ->packagist = new Packagist ($ http , self ::PACKAGIST_USERNAME , $ input ->getOption ('new-packagist-token ' ) ?? '' );
6161
62- $ nextPageQuestion = new ConfirmationQuestion ('Next Page (enter), "n" to quit: ' , true );
63- $ table = (new Table ($ output ))->setHeaders ([
64- 'name ' => 'Name ' ,
65- 'repo_config ' => 'Repo Config ' ,
66- 'packagist_config ' => 'Packagist Config ' ,
67- 'teams ' => 'Teams ' ,
68- 'compliant ' => 'Compliant? '
69- ]);
70- if ($ componentName = $ input ->getOption ('component ' )) {
71- $ table ->setVertical ();
62+ $ format = $ input ->getOption ('format ' );
63+ if (!in_array ($ format , ['ci ' , 'table ' ])) {
64+ throw new InvalidArgumentException ('Invalid format " ' . $ format . '", must be "table" or "ci" ' );
7265 }
73- $ page = (int ) $ input ->getOption ('page ' );
74- $ resultsPerPage = (int ) $ input ->getOption ('results-per-page ' );
66+
67+ $ table = (new Table ($ output ));
68+ $ table ->setColumnWidths ([55 , 20 , 20 , 25 , 50 ]);
69+ $ table ->setStyle ('compact ' );
70+ $ headers = $ format == 'ci ' ? ['Name ' , 'Compliance ' ] : [
71+ 'Name ' ,
72+ 'Repo Config ' ,
73+ 'Packagist Config ' ,
74+ 'Teams ' ,
75+ 'Compliance '
76+ ];
77+ (clone $ table )->setHeaders ($ headers )->render ();
78+
79+ $ componentName = $ input ->getOption ('component ' );
7580 $ components = $ componentName ? [new Component ($ componentName )] : Component::getComponents ();
7681
77- if (!$ input ->getOption ('token ' )) {
78- $ output ->writeln ('<error>No token provided - please provide token to update compliance</error> ' );
79- }
82+ $ isCompliant = true ;
8083 foreach ($ components as $ i => $ component ) {
81- if ($ i < (($ page -1 ) * $ resultsPerPage )) {
82- continue ;
83- }
84- if (0 !== $ resultsPerPage && $ i >= ($ page * $ resultsPerPage )) {
85- $ table ->render ();
86- if (!$ this ->getHelper ('question ' )->ask ($ input , $ output , $ nextPageQuestion )) {
87- return 0 ;
88- }
89- $ table ->setRows ([]);
90- $ page ++;
91- }
9284 $ details = $ this ->getRepoDetails ($ component );
93- $ compliance = [
94- 'settings ' => true ,
95- 'packagist ' => true ,
96- 'teams ' => true ,
97- ];
85+ $ settingsCheck = true ;
86+ $ packagistCheck = true ;
87+ $ teamCheck = true ;
9888
9989 $ refreshDetails = false ;
10090 if (!$ this ->checkSettingsCompliance ($ details )) {
101- $ compliance [ ' settings ' ] = false ;
91+ $ settingsCheck = false ;
10292 $ refreshDetails |= $ this ->askFixSettingsCompliance ($ input , $ output , $ details );
10393 }
10494 if (!$ this ->checkPackagistCompliance ($ details )) {
105- $ compliance [ ' packagist ' ] = false ;
95+ $ packagistCheck = false ;
10696 $ refreshDetails |= $ this ->askFixPackagistCompliance ($ input , $ output , $ component ->getRepoName ());
10797 }
10898 if (!$ this ->checkTeamCompliance ($ details )) {
109- $ compliance [ ' teams ' ] = $ this ->github ->token ? false : null ;
99+ $ teamCheck = $ this ->github ->token ? false : null ;
110100 $ refreshDetails |= $ this ->askFixTeamCompliance ($ input , $ output , $ component ->getRepoName ());
111101 }
112102 if ($ refreshDetails ) {
@@ -123,31 +113,23 @@ protected function execute(InputInterface $input, OutputInterface $output)
123113 $ output ->writeln (sprintf ('<comment>%s</comment>: Packagist webhook token updated. ' , $ repoName ));
124114 }
125115 }
126- $ isCompliant = true ;
127- $ details ['compliant ' ] = '<info>REPO IS COMPLIANT</info> ' ;
128- foreach ($ compliance as $ key => $ val ) {
129- if ($ val === false ) {
130- $ isCompliant = false ;
131- $ details ['compliant ' ] = '<error>NOT COMPLIANT</error> ' ;
132- } elseif ($ isCompliant && $ val === null ) {
133- $ details ['compliant ' ] = '<error>???</error> (token required) ' ;
134- $ isCompliant = null ;
135- }
136- }
137116
138- if (!$ isCompliant ) {
139- $ details ['compliant ' ] .= PHP_EOL . implode ("\n" , array_map (
140- fn ($ k , $ v ) => $ k . ': ' . (is_null ($ v ) ? '??? ' : var_export ($ v , true )),
141- array_keys ($ compliance ),
142- array_values ($ compliance )
143- ));
117+ $ emoji = fn (?bool $ check ) => match ($ check ) { null => '❓ ' , true => '✅ ' , false => '❌ ' };
118+ $ details ['compliant ' ] = implode ("\n" , [
119+ sprintf ('%s Issues, Projects, Wiki, Pages, and Discussion are disabled ' , $ emoji ($ settingsCheck )),
120+ sprintf ('%s Packagist maintainer is "google-cloud" ' , $ emoji ($ packagistCheck )),
121+ sprintf ('%s Github teams permissions are configured correctly ' , $ emoji ($ teamCheck )),
122+ '' ,
123+ ]);
124+
125+ $ isCompliant = $ isCompliant && $ settingsCheck && $ packagistCheck && $ teamCheck ;
126+ if ($ format == 'ci ' ) {
127+ unset($ details ['repo_config ' ], $ details ['packagist_config ' ], $ details ['teams ' ]);
144128 }
145-
146- $ table ->addRow ($ details );
129+ (clone $ table )->addRow ($ details )->render ();
147130 }
148- $ table ->render ();
149131
150- return 0 ;
132+ return $ isCompliant ? Command:: SUCCESS : Command:: FAILURE ;
151133 }
152134
153135 private function checkSettingsCompliance (array $ details )
@@ -169,8 +151,8 @@ private function checkTeamCompliance(array $details)
169151
170152 private function askFixSettingsCompliance (InputInterface $ input , OutputInterface $ output , array $ details )
171153 {
172- if (!$ this ->github ->token ) {
173- // without a token, don't ask to fix compliance
154+ if (!$ this ->github ->token || $ input -> getOption ( ' format ' ) == ' ci ' ) {
155+ // without a token, or in CI mode, don't ask to fix compliance
174156 return false ;
175157 }
176158 $ explodedConfig = array_map (fn ($ line ) => explode (': ' , $ line ), explode ("\n" , $ details ['repo_config ' ]));
@@ -204,17 +186,17 @@ private function checkPackagistCompliance(array $details)
204186
205187 private function askFixPackagistCompliance (InputInterface $ input , OutputInterface $ output , array $ details )
206188 {
207- if (!$ this ->github ->token ) {
208- // without a token, don't ask to fix compliance
189+ if (!$ this ->github ->token || $ input -> getOption ( ' format ' ) == ' ci ' ) {
190+ // without a token, or in CI mode, don't ask to fix compliance
209191 return false ;
210192 }
211193 throw new \Exception ('not implemented ' );
212194 }
213195
214196 private function askFixTeamCompliance (InputInterface $ input , OutputInterface $ output , string $ repoName )
215197 {
216- if (!$ this ->github ->token ) {
217- // without a token, don't ask to fix compliance
198+ if (!$ this ->github ->token || $ input -> getOption ( ' format ' ) == ' ci ' ) {
199+ // without a token, or in CI mode, don't ask to fix compliance
218200 return false ;
219201 }
220202 $ question = new ConfirmationQuestion (sprintf (
0 commit comments