diff --git a/cli/diff-changelog.php b/cli/diff-changelog.php index 518a708..e0cf431 100755 --- a/cli/diff-changelog.php +++ b/cli/diff-changelog.php @@ -1,305 +1,310 @@ #!/usr/bin/php setConduitToken( CONDUIT_API_TOKEN ); // All the arguments must be Differential IDs $diff_ids = $argv; // Remove the first argument that is just the command name array_shift( $diff_ids ); if( $diff_ids ) { // Get Diff IDs but in numeric form (for API requests) $diff_ids_numeric = []; foreach( $diff_ids as $diff_id ) { $diff_ids_numeric[] = (int)ltrim( $diff_id, 'D' ); } // Start from Diff IDs (numeric) and get Diff PHIDs (string) // https://we.phorge.it/conduit/method/differential.revision.search/ $diff_search_results = $client->callMethodSynchronous( 'differential.revision.search', [ 'constraints' => [ 'ids' => $diff_ids_numeric, ], ] ); foreach( $diff_search_results['data'] as $diff_search_result ) { $diff_phid = $diff_search_result['phid']; $diff_phids[] = $diff_phid; $diff_data_by_phid[ $diff_phid ] = $diff_search_result; } } else { // If no Diff was specified, let's try guessing them, but that is a long journey $git_commits_after_last_tag = []; // Find last git tag // Thanks https://stackoverflow.com/a/12083016/3451846 $git_last_tag = null; exec( 'git describe --tags --abbrev=0', $git_last_tag ); $git_last_tag = $git_last_tag[0] ?? null; // No tag, no party. if( !$git_last_tag ) { echo "Unable to find last git tag\n"; exit( 1 ); } // Find git commits since last tag $git_log_cmd = sprintf( 'git log --pretty=format:%s %s..HEAD', '%H', escapeshellarg( $git_last_tag ) ); exec( $git_log_cmd, $git_commits_after_last_tag ); // No commits, no party. if( !$git_commits_after_last_tag ) { echo "Unable to list some git commits since last Tag.\n"; echo "Please manually specify some Diff ID like D123 etc.\n"; exit( 1 ); } // Find PHID of each commit hash $diffusion_commit_phids = []; $diffusion_commit_search = $client->callMethodSynchronous( 'diffusion.commit.search', [ 'constraints' => [ 'identifiers' => $git_commits_after_last_tag, ], ] ); foreach( $diffusion_commit_search['data'] as $diffusion_commit_data ) { $diffusion_commit_phids[] = $diffusion_commit_data['phid']; } // Find Differential revisions from git commits // Start from commit hash and get Diff PHIDs // https://we.phorge.it/conduit/method/edge.search/ $commit_revisions = $client->callMethodSynchronous( 'edge.search', [ 'sourcePHIDs' => $git_commits_after_last_tag, 'types' => [ 'commit.revision', ], ] ); foreach( $commit_revisions['data'] as $commit_revision ) { $diff_phid = $commit_revision['destinationPHID']; $diff_phids[] = $diff_phid; } } // Initialize some stuff $tasks = []; $tasks_phid = []; $tasks_phids_from_diff_phid = []; $USERS_BY_PHID = []; // Start from Diff IDs and get Task PHIDs // https://gitpull.it/conduit/method/edge.search/ $edge_api_parameters = [ // apparently this does not support only PHIDs but also Monograms 'sourcePHIDs' => $diff_phids, 'types' => [ 'revision.task' ], ]; // Get Task PHIDs from Differential Revision PHIDs // https://we.phorge.it/conduit/method/edge.search/ $edge_result = $client->callMethodSynchronous( 'edge.search', $edge_api_parameters ); foreach( $edge_result['data'] as $data ) { $diff_phid = $data['sourcePHID']; $task_phid = $data['destinationPHID']; $tasks_phid[] = $task_phid; $tasks_phids_from_diff_phid[$diff_phid][] = $task_phid; } // Show Diffs that have no Tasks so you can fix on Phorge foreach( $diff_phids as $diff_phid ) { if( empty( $tasks_phids_from_diff_phid[$diff_phid] ) ) { echo "[WARN] Skipped Diff without Tasks: $diff_phid\n"; } } // https://gitpull.it/conduit/method/maniphest.search/ $maniphest_api_parameters = [ 'constraints' => [ 'phids' => $tasks_phid, ], ]; -// query Tasks info -$maniphest_result = $client->callMethodSynchronous( 'maniphest.search', $maniphest_api_parameters ); -foreach( $maniphest_result['data'] as $task ) { - - // append in known Tasks - $tasks[] = $task; - - // remember User PHIDs since we will need to get their extra info - $phid_task_author = $task['fields']['authorPHID']; - $phid_task_owner = $task['fields']['ownerPHID']; - $USERS_BY_PHID[ $phid_task_author ] = null; - $USERS_BY_PHID[ $phid_task_owner ] = null; - - $phid_task_reporter = $task['fields'][PHABRICATOR_MANIPHEST_CUSTOM_FIELD_REPORTER] ?? null; - if( $phid_task_reporter ) { - $phid_task_reporter_entry = $phid_task_reporter[0]; - $USERS_BY_PHID[ $phid_task_reporter_entry ] = null; - } +if( $tasks_phid ) { + + // query Tasks info + $maniphest_result = $client->callMethodSynchronous( 'maniphest.search', $maniphest_api_parameters ); + foreach( $maniphest_result['data'] as $task ) { + + // append in known Tasks + $tasks[] = $task; + + // remember User PHIDs since we will need to get their extra info + $phid_task_author = $task['fields']['authorPHID']; + $phid_task_owner = $task['fields']['ownerPHID']; + $USERS_BY_PHID[ $phid_task_author ] = null; + $USERS_BY_PHID[ $phid_task_owner ] = null; + + $phid_task_reporter = $task['fields'][PHABRICATOR_MANIPHEST_CUSTOM_FIELD_REPORTER] ?? null; + if( $phid_task_reporter ) { + $phid_task_reporter_entry = $phid_task_reporter[0]; + $USERS_BY_PHID[ $phid_task_reporter_entry ] = null; + } + } } -// get users info from their PHID identifiers -$users_phid = array_keys( $USERS_BY_PHID ); -$users_api_parameters = [ - 'constraints' => [ - 'phids' => $users_phid, - ], -]; -$users_result = $client->callMethodSynchronous( 'user.search', $users_api_parameters ); -foreach( $users_result['data'] as $user_data ) { - $phid_user = $user_data['phid']; - $USERS_BY_PHID[ $phid_user ] = $user_data; +if( $USERS_BY_PHID ) { + // get users info from their PHID identifiers + $users_phid = array_keys( $USERS_BY_PHID ); + $users_api_parameters = [ + 'constraints' => [ + 'phids' => $users_phid, + ], + ]; + $users_result = $client->callMethodSynchronous( 'user.search', $users_api_parameters ); + foreach( $users_result['data'] as $user_data ) { + $phid_user = $user_data['phid']; + $USERS_BY_PHID[ $phid_user ] = $user_data; + } } // for each language foreach( $I18N as $lang => $msg ) { $changelog_blocks = []; // NOTE: Phabricator has custom fields that can be populated to retrieve the changelog // in the specified language $phab_maniphest_custom_field_changelog = sprintf( PHABRICATOR_MANIPHEST_CUSTOM_FIELD_CHANGELOG, $lang ); // for each Task foreach( $tasks as $task ) { $task_id = $task['id']; $task_name = $task['fields']['name']; $task_descr = $task['fields']['description']; $phid_task_author = $task['fields']['authorPHID']; $phid_task_owner = $task['fields']['ownerPHID']; $phid_reporter = $task['fields'][PHABRICATOR_MANIPHEST_CUSTOM_FIELD_REPORTER] ?? null; $author = $USERS_BY_PHID[ $phid_task_author ]; $owner = $USERS_BY_PHID[ $phid_task_owner ]; $reporter = null; if($phid_reporter) { $phid_reporter_entry = $phid_reporter[0]; $reporter = $USERS_BY_PHID[ $phid_reporter_entry ]; if($reporter) { $author = $reporter; } } $username_author = $author['fields']['username']; $username_owner = $owner ['fields']['username']; $realname_author = $author['fields']['realName'] ?? null; $realname_owner = $owner ['fields']['realName'] ?? null; $task_url = PHABRICATOR_HOME . "T{$task_id}"; $url_author = PHABRICATOR_HOME . 'p/' . $username_author; $url_owner = PHABRICATOR_HOME . 'p/' . $username_owner; // get the most appropriate changelog field or the Task name $changelog_title = $task['fields'][$phab_maniphest_custom_field_changelog] ?? $task_name; // just try to show something useful for a F-Droid changelog $changelog_lines = []; // Task name and URL $changelog_lines[] = $changelog_title; // reporter by (author) // Avoid to repeat the same user twice if( $username_author !== $username_owner ) { $changelog_lines[] = sprintf( $msg['reportedByName'], $username_author ); } // resolved by (owner) $changelog_lines[] = sprintf( $msg['resolvedByName'], $username_owner ); $changelog_lines[] = $task_url; $changelog_block = implode( "\n", $changelog_lines ); $changelog_blocks[] = $changelog_block; } // print all changelog blocks $changelog_content = implode( "\n\n", $changelog_blocks ); // expected changelog file $changelog_path = REPO_PATH . "/metadata/{$lang}/changelogs/{$version_code}.txt"; // save file_put_contents( $changelog_path, $changelog_content ); }