Skip to content

Commit 6411f86

Browse files
ebinnionmatticbot
authored andcommitted
wpcomsh: Add wpcomsh diagnostic CLI command for debugging (#44363)
* wpcomsh: Add wpcomsh diagnostic command for HEs * wpcomsh: Use wp jetapck status full for diagnostic command * changelog * wpcomsh: in wpcomsh diagnostic command, improve error detection; remove interactive Committed via a GitHub action: https://github.com/Automattic/jetpack/actions/runs/16378129051 Upstream-Ref: Automattic/jetpack@a67e645
1 parent adf861d commit 6411f86

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ This is an alpha version! The changes listed here are not final.
66

77
### Added
88
- Add archives endpoint support.
9+
- Added a new wp wpcomsh diagnostic command
910
- add tracking for site settings launch action
1011
- Code editors: Added advanced code and CSS editors.
1112
- Enabled Advanced SEO features for localized version of developer.wordpress.com

class-wpcomsh-cli-commands.php

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,196 @@ function ( $plugin ) {
11591159
public function plugin_dance_health_check( $args, $assoc_args ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
11601160
WP_CLI::success( 'Healthy' );
11611161
}
1162+
1163+
/**
1164+
* Runs comprehensive site diagnostics including Jetpack status, admin users, plugins, purchases, and PHP errors
1165+
*
1166+
* @subcommand diagnostic
1167+
*/
1168+
public function diagnostic( $args, $assoc_args ) { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter, VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
1169+
WP_CLI::log( WP_CLI::colorize( '%B=== SITE DIAGNOSTICS ===%n' ) );
1170+
WP_CLI::log( '' );
1171+
1172+
// 1. Jetpack Status
1173+
WP_CLI::log( WP_CLI::colorize( '%Y--- Jetpack Status ---%n' ) );
1174+
$jetpack_result = WP_CLI::runcommand(
1175+
'jetpack status full',
1176+
array(
1177+
'launch' => false,
1178+
'return' => 'all',
1179+
'exit_error' => false,
1180+
)
1181+
);
1182+
1183+
if ( 0 === $jetpack_result->return_code ) {
1184+
WP_CLI::log( $jetpack_result->stdout );
1185+
} else {
1186+
WP_CLI::log( WP_CLI::colorize( '%RJetpack status command failed:%n' ) );
1187+
WP_CLI::log( $jetpack_result->stderr );
1188+
}
1189+
1190+
WP_CLI::log( '' );
1191+
1192+
// 2. Admin Users
1193+
WP_CLI::log( WP_CLI::colorize( '%Y--- Administrator Users ---%n' ) );
1194+
$admin_users_result = WP_CLI::runcommand(
1195+
'user list --role=administrator',
1196+
array(
1197+
'launch' => false,
1198+
'return' => 'all',
1199+
'exit_error' => false,
1200+
)
1201+
);
1202+
1203+
if ( 0 === $admin_users_result->return_code ) {
1204+
WP_CLI::log( $admin_users_result->stdout );
1205+
} else {
1206+
WP_CLI::log( WP_CLI::colorize( '%RAdmin users command failed:%n' ) );
1207+
WP_CLI::log( $admin_users_result->stderr );
1208+
}
1209+
1210+
WP_CLI::log( '' );
1211+
1212+
// 3. Plugin Status
1213+
WP_CLI::log( WP_CLI::colorize( '%Y--- Plugin Status ---%n' ) );
1214+
$plugin_status_result = WP_CLI::runcommand(
1215+
'plugin status',
1216+
array(
1217+
'launch' => false,
1218+
'return' => 'all',
1219+
'exit_error' => false,
1220+
)
1221+
);
1222+
1223+
if ( 0 === $plugin_status_result->return_code ) {
1224+
WP_CLI::log( $plugin_status_result->stdout );
1225+
} else {
1226+
WP_CLI::log( WP_CLI::colorize( '%RPlugin status command failed:%n' ) );
1227+
WP_CLI::log( $plugin_status_result->stderr );
1228+
}
1229+
1230+
WP_CLI::log( '' );
1231+
1232+
// 4. WPCOMSH Purchases (formatted as table)
1233+
WP_CLI::log( WP_CLI::colorize( '%Y--- Site Purchases ---%n' ) );
1234+
$purchases_result = WP_CLI::runcommand(
1235+
'wpcomsh purchases --format=json',
1236+
array(
1237+
'launch' => false,
1238+
'return' => 'all',
1239+
'exit_error' => false,
1240+
)
1241+
);
1242+
1243+
if ( 0 === $purchases_result->return_code ) {
1244+
$purchases_data = json_decode( $purchases_result->stdout, true );
1245+
if ( is_array( $purchases_data ) && ! empty( $purchases_data ) ) {
1246+
$formatted_purchases = array();
1247+
foreach ( $purchases_data as $purchase ) {
1248+
$formatted_purchases[] = array(
1249+
'product' => $purchase['product_slug'] ?? 'N/A',
1250+
'type' => $purchase['product_type'] ?? 'N/A',
1251+
'subscribed' => isset( $purchase['subscribed_date'] ) ? gmdate( 'Y-m-d', strtotime( $purchase['subscribed_date'] ) ) : 'N/A',
1252+
'expires' => isset( $purchase['expiry_date'] ) ? gmdate( 'Y-m-d', strtotime( $purchase['expiry_date'] ) ) : 'N/A',
1253+
'auto_renew' => isset( $purchase['auto_renew'] ) ? ( $purchase['auto_renew'] ? 'Yes' : 'No' ) : 'N/A',
1254+
);
1255+
}
1256+
1257+
$table_args = array( 'format' => 'table' );
1258+
$formatter = new \WP_CLI\Formatter(
1259+
$table_args,
1260+
array( 'product', 'type', 'subscribed', 'expires', 'auto_renew' )
1261+
);
1262+
$formatter->display_items( $formatted_purchases );
1263+
} else {
1264+
WP_CLI::log( 'No purchases found.' );
1265+
}
1266+
} else {
1267+
WP_CLI::log( WP_CLI::colorize( '%RPurchases command failed:%n' ) );
1268+
WP_CLI::log( $purchases_result->stderr );
1269+
}
1270+
1271+
WP_CLI::log( '' );
1272+
1273+
// 5. PHP Errors (filtered to recent fatals and errors)
1274+
WP_CLI::log( WP_CLI::colorize( '%Y--- Recent PHP Errors ---%n' ) );
1275+
$php_errors_result = WP_CLI::runcommand(
1276+
'php-errors',
1277+
array(
1278+
'launch' => false,
1279+
'return' => 'all',
1280+
'exit_error' => false,
1281+
)
1282+
);
1283+
1284+
if ( 0 === $php_errors_result->return_code ) {
1285+
$error_lines = explode( "\n", trim( $php_errors_result->stdout ) );
1286+
$filtered_errors = array();
1287+
1288+
$recent_dates = array(
1289+
gmdate( 'd-M-Y' ),
1290+
gmdate( 'd-M-Y', strtotime( '-1 day' ) ),
1291+
gmdate( 'd-M-Y', strtotime( '-2 days' ) ),
1292+
);
1293+
1294+
foreach ( $error_lines as $line ) {
1295+
if ( empty( trim( $line ) ) ) {
1296+
continue;
1297+
}
1298+
1299+
$is_recent = false;
1300+
foreach ( $recent_dates as $date ) {
1301+
if ( strpos( $line, $date ) !== false ) {
1302+
$is_recent = true;
1303+
break;
1304+
}
1305+
}
1306+
1307+
if ( $is_recent ) {
1308+
// Check for various types of critical/fatal errors
1309+
$critical_patterns = array(
1310+
'Fatal error',
1311+
'PHP Fatal error',
1312+
'Parse error',
1313+
'Uncaught Error',
1314+
'Uncaught Exception',
1315+
'TypeError',
1316+
'ArgumentCountError',
1317+
'Compile error',
1318+
);
1319+
1320+
foreach ( $critical_patterns as $pattern ) {
1321+
if ( strpos( $line, $pattern ) !== false ) {
1322+
$filtered_errors[] = $line;
1323+
break;
1324+
}
1325+
}
1326+
}
1327+
}
1328+
1329+
if ( ! empty( $filtered_errors ) ) {
1330+
WP_CLI::log( WP_CLI::colorize( '%RRecent Critical PHP Errors:%n' ) );
1331+
foreach ( $filtered_errors as $error ) {
1332+
WP_CLI::log( $error );
1333+
}
1334+
} else {
1335+
// Show last 10 errors of any type if no recent critical errors
1336+
WP_CLI::log( WP_CLI::colorize( '%GNo recent critical errors found. Last 10 PHP errors:%n' ) );
1337+
$recent_errors = array_slice( $error_lines, -10 );
1338+
foreach ( $recent_errors as $error ) {
1339+
if ( ! empty( trim( $error ) ) ) {
1340+
WP_CLI::log( $error );
1341+
}
1342+
}
1343+
}
1344+
} else {
1345+
WP_CLI::log( WP_CLI::colorize( '%RPHP errors command failed:%n' ) );
1346+
WP_CLI::log( $php_errors_result->stderr );
1347+
}
1348+
1349+
WP_CLI::log( '' );
1350+
WP_CLI::log( WP_CLI::colorize( '%B=== DIAGNOSTICS COMPLETE ===%n' ) );
1351+
}
11621352
}
11631353
}
11641354

0 commit comments

Comments
 (0)