Skip to content

Commit 03ba0d7

Browse files
authored
Expose pull request URLs in create PR schema (#421)
* fix: expose pull request URLs in schema * fix: align create PR schema validation * fix: run code smoke tests on host * fix: satisfy GitHub ability static analysis * fix: remove stale GitHub ability fallbacks
1 parent a8fd7d6 commit 03ba0d7

3 files changed

Lines changed: 50 additions & 71 deletions

File tree

homeboy.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
"changelog_target": "docs/CHANGELOG.md",
44
"extensions": {
55
"wordpress": {
6-
"release_latest_branch": "release-latest"
6+
"release_latest_branch": "release-latest",
7+
"settings": {
8+
"test_backend": "host-smoke"
9+
}
710
}
811
},
912
"id": "data-machine-code",
@@ -18,4 +21,4 @@
1821
"pattern": "DATAMACHINE_CODE_VERSION',\\s*'([0-9.]+)'"
1922
}
2023
]
21-
}
24+
}

inc/Abilities/GitHubAbilities.php

Lines changed: 40 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,15 @@ private function registerAbilities(): void {
341341
'type' => 'object',
342342
'properties' => array(
343343
'success' => array( 'type' => 'boolean' ),
344+
'kind' => array( 'type' => 'string' ),
345+
'repo' => array( 'type' => 'string' ),
346+
'number' => array( 'type' => 'integer' ),
347+
'pull_number' => array( 'type' => 'integer' ),
348+
'url' => array( 'type' => 'string' ),
349+
'html_url' => array( 'type' => 'string' ),
350+
'reused' => array( 'type' => 'boolean' ),
344351
'pull_request' => array( 'type' => 'object' ),
352+
'labeling' => array( 'type' => 'object' ),
345353
'error' => array( 'type' => 'string' ),
346354
),
347355
),
@@ -523,15 +531,15 @@ private function registerAbilities(): void {
523531
'output_schema' => array(
524532
'type' => 'object',
525533
'properties' => array(
526-
'success' => array( 'type' => 'boolean' ),
527-
'repo' => array( 'type' => 'string' ),
528-
'pull_number' => array( 'type' => 'integer' ),
529-
'merged' => array( 'type' => 'boolean' ),
530-
'sha' => array( 'type' => 'string' ),
531-
'message' => array( 'type' => 'string' ),
532-
'html_url' => array( 'type' => 'string' ),
534+
'success' => array( 'type' => 'boolean' ),
535+
'repo' => array( 'type' => 'string' ),
536+
'pull_number' => array( 'type' => 'integer' ),
537+
'merged' => array( 'type' => 'boolean' ),
538+
'sha' => array( 'type' => 'string' ),
539+
'message' => array( 'type' => 'string' ),
540+
'html_url' => array( 'type' => 'string' ),
533541
'local_worktree_cleanup' => array( 'type' => 'object' ),
534-
'error' => array( 'type' => 'string' ),
542+
'error' => array( 'type' => 'string' ),
535543
),
536544
),
537545
'execute_callback' => array( self::class, 'mergePullRequest' ),
@@ -1491,7 +1499,7 @@ public static function createIssue( array $input ): array|\WP_Error {
14911499
if ( ! empty( $input['assignees'] ) && is_array( $input['assignees'] ) ) {
14921500
$body['assignees'] = array_map( 'sanitize_text_field', $input['assignees'] );
14931501
}
1494-
if ( isset( $input['milestone'] ) && null !== $input['milestone'] && '' !== $input['milestone'] ) {
1502+
if ( isset( $input['milestone'] ) && '' !== $input['milestone'] ) {
14951503
$milestone = (int) $input['milestone'];
14961504
if ( $milestone > 0 ) {
14971505
$body['milestone'] = $milestone;
@@ -1758,9 +1766,9 @@ private static function preparePullRequestRunArtifacts( array $input, string $re
17581766
foreach ( $file_writes as $file ) {
17591767
$file_result = self::createOrUpdateFile( array(
17601768
'repo' => $repo,
1761-
'file_path' => $file['file_path'] ?? '',
1762-
'content' => $file['content'] ?? '',
1763-
'commit_message' => $file['commit_message'] ?? 'chore: persist Data Machine run artifact',
1769+
'file_path' => $file['file_path'],
1770+
'content' => $file['content'],
1771+
'commit_message' => $file['commit_message'],
17641772
'branch' => $head,
17651773
) );
17661774

@@ -1769,7 +1777,7 @@ private static function preparePullRequestRunArtifacts( array $input, string $re
17691777
}
17701778

17711779
$committed_files[] = array(
1772-
'file_path' => (string) ( $file_result['content']['path'] ?? ( $file['file_path'] ?? '' ) ),
1780+
'file_path' => (string) ( $file_result['content']['path'] ?? $file['file_path'] ),
17731781
'commit_sha' => (string) ( $file_result['commit']['sha'] ?? '' ),
17741782
'file_url' => (string) ( $file_result['content']['html_url'] ?? '' ),
17751783
);
@@ -1821,17 +1829,6 @@ private static function runArtifactEgressPolicyFromInput( array $input, array $a
18211829
}
18221830
}
18231831

1824-
$job_id = (int) ( $input['job_id'] ?? 0 );
1825-
if ( $job_id > 0 && class_exists( '\\DataMachine\\Core\\Database\\Jobs\\Jobs' ) ) {
1826-
$jobs = new \DataMachine\Core\Database\Jobs\Jobs();
1827-
if ( method_exists( $jobs, 'retrieve_engine_data' ) ) {
1828-
$engine_data = $jobs->retrieve_engine_data( $job_id );
1829-
if ( is_array( $engine_data['run_artifact_egress_policy'] ?? null ) ) {
1830-
return $engine_data['run_artifact_egress_policy'];
1831-
}
1832-
}
1833-
}
1834-
18351832
return is_array( $artifacts['run_artifact_egress_policy'] ?? null ) ? $artifacts['run_artifact_egress_policy'] : array();
18361833
}
18371834

@@ -1911,12 +1908,10 @@ private static function mergeProvenanceLabels( array $labels ): array {
19111908
* Resolve the current Data Machine agent slug when running in agent context.
19121909
*/
19131910
private static function getCurrentAgentSlug(): string {
1914-
foreach ( array( 'get_runtime_context', 'runtime_context' ) as $method ) {
1915-
if ( method_exists( PermissionHelper::class, $method ) ) {
1916-
$agent_slug = self::agentSlugFromContext( call_user_func( array( PermissionHelper::class, $method ) ) );
1917-
if ( '' !== $agent_slug ) {
1918-
return $agent_slug;
1919-
}
1911+
if ( method_exists( PermissionHelper::class, 'get_runtime_context' ) ) {
1912+
$agent_slug = self::agentSlugFromContext( PermissionHelper::get_runtime_context() );
1913+
if ( '' !== $agent_slug ) {
1914+
return $agent_slug;
19201915
}
19211916
}
19221917

@@ -1937,24 +1932,7 @@ private static function getCurrentAgentSlug(): string {
19371932
}
19381933
}
19391934

1940-
if ( ! method_exists( PermissionHelper::class, 'get_acting_agent_id' ) ) {
1941-
return '';
1942-
}
1943-
1944-
$agent_id = PermissionHelper::get_acting_agent_id();
1945-
if ( empty( $agent_id ) || ! class_exists( '\DataMachine\Core\Database\Agents\Agents' ) ) {
1946-
return '';
1947-
}
1948-
1949-
$agents_repo = new \DataMachine\Core\Database\Agents\Agents();
1950-
if ( ! method_exists( $agents_repo, 'get_agent' ) ) {
1951-
return '';
1952-
}
1953-
1954-
$agent = $agents_repo->get_agent( (int) $agent_id );
1955-
$agent_slug = is_array( $agent ) ? (string) ( $agent['agent_slug'] ?? '' ) : '';
1956-
1957-
return '' !== trim( $agent_slug ) ? sanitize_text_field( $agent_slug ) : '';
1935+
return '';
19581936
}
19591937

19601938
/**
@@ -2469,7 +2447,7 @@ public static function cleanupPullRequest( array $input, ?callable $api_get = nu
24692447

24702448
$encoded_head_branch = implode( '/', array_map( 'rawurlencode', explode( '/', $head_branch ) ) );
24712449
$delete_url = sprintf( '%s/repos/%s/git/refs/heads/%s', self::API_BASE, $repo, $encoded_head_branch );
2472-
$deleted = $api_request( 'DELETE', $delete_url, null, $pat );
2450+
$deleted = $api_request( 'DELETE', $delete_url, null, $pat );
24732451
if ( is_wp_error( $deleted ) ) {
24742452
$status = is_array( $deleted->get_error_data() ) ? (int) ( $deleted->get_error_data()['status'] ?? 0 ) : 0;
24752453
if ( 404 !== $status ) {
@@ -2504,14 +2482,6 @@ private static function cleanupMergedPullRequestWorktree( string $repo, string $
25042482
}
25052483

25062484
$workspace = new Workspace();
2507-
if ( ! method_exists( $workspace, 'cleanup_merged_pr_worktree' ) ) {
2508-
return array(
2509-
'success' => true,
2510-
'skipped' => true,
2511-
'reason' => 'workspace_cleanup_unsupported',
2512-
);
2513-
}
2514-
25152485
return $workspace->cleanup_merged_pr_worktree( $repo, $head_branch, '' !== $pr_url ? $pr_url : null );
25162486
}
25172487

@@ -2702,9 +2672,9 @@ private static function buildPullRequestCommentInput( array $input ): array {
27022672
}
27032673

27042674
return array(
2705-
'repo' => $input['repo'] ?? '',
2706-
'issue_number' => (int) ( $input['pull_number'] ?? 0 ),
2707-
'body' => $body,
2675+
'repo' => $input['repo'] ?? '',
2676+
'issue_number' => (int) ( $input['pull_number'] ?? 0 ),
2677+
'body' => $body,
27082678
'skip_automation_comment_guard' => true,
27092679
);
27102680
}
@@ -2943,8 +2913,8 @@ public static function buildRepoReviewProfile( string $repo, array $options, cal
29432913
$max_docs = max( 0, (int) ( $options['max_architecture_docs'] ?? 8 ) );
29442914
$limits = array(
29452915
'max_profile_files' => $max_files,
2946-
'max_file_chars' => max( 1, (int) ( $options['max_file_chars'] ?? 12000 ) ),
2947-
'max_total_chars' => max( 1, (int) ( $options['max_total_chars'] ?? 60000 ) ),
2916+
'max_file_chars' => (int) max( 1, (int) ( $options['max_file_chars'] ?? 12000 ) ),
2917+
'max_total_chars' => (int) max( 1, (int) ( $options['max_total_chars'] ?? 60000 ) ),
29482918
'max_architecture_docs' => $max_docs,
29492919
);
29502920

@@ -2991,7 +2961,7 @@ public static function buildRepoReviewProfile( string $repo, array $options, cal
29912961
}
29922962

29932963
$paths = array_values( array_unique( $paths ) );
2994-
$remaining_chars = $limits['max_total_chars'];
2964+
$remaining_chars = (int) $limits['max_total_chars'];
29952965

29962966
foreach ( $paths as $path ) {
29972967
if ( $profile['truncation']['included_files'] >= $limits['max_profile_files'] || $remaining_chars <= 0 ) {
@@ -3015,7 +2985,7 @@ public static function buildRepoReviewProfile( string $repo, array $options, cal
30152985

30162986
++$profile['truncation']['included_files'];
30172987
$profile['truncation']['included_chars'] += $entry['included_chars'];
3018-
$remaining_chars = max( 0, $remaining_chars - $entry['included_chars'] );
2988+
$remaining_chars = (int) max( 0, $remaining_chars - $entry['included_chars'] );
30192989

30202990
if ( ! empty( $entry['truncated'] ) ) {
30212991
++$profile['truncation']['truncated_files'];
@@ -3564,7 +3534,7 @@ private static function suggestLikelyStaleDocs( array $impacts, array $changed_d
35643534
}
35653535

35663536
foreach ( $wanted as &$entry ) {
3567-
$entry['reasons'] = array_values( array_unique( $entry['reasons'] ?? array() ) );
3537+
$entry['reasons'] = array_values( array_unique( $entry['reasons'] ) );
35683538
}
35693539

35703540
return array_values( $wanted );
@@ -4843,7 +4813,8 @@ public static function apiRequest( string $method, string $url, ?array $body, st
48434813
);
48444814

48454815
if ( null !== $body ) {
4846-
$args['body'] = wp_json_encode( $body );
4816+
$encoded_body = wp_json_encode( $body );
4817+
$args['body'] = false === $encoded_body ? '' : $encoded_body;
48474818
}
48484819

48494820
$response = wp_remote_request( $url, $args );
@@ -5250,7 +5221,7 @@ public static function normalizePullReviewContext( string $repo, array $pull, ar
52505221
$repo,
52515222
$pull,
52525223
$changed_files,
5253-
isset( $context['checks'] ) && is_array( $context['checks'] ) ? $context['checks'] : array(),
5224+
$context['checks'] ?? array(),
52545225
isset( $options['escalation_policy'] ) && is_array( $options['escalation_policy'] ) ? $options['escalation_policy'] : array()
52555226
);
52565227
}
@@ -5339,7 +5310,7 @@ public static function getPat( ?array $selector = null ): string {
53395310

53405311
self::$last_auth_error = null;
53415312
$token = (string) $credential['token'];
5342-
self::$token_modes[ $token ] = (string) ( $credential['mode'] ?? 'pat' );
5313+
self::$token_modes[ $token ] = (string) $credential['mode'];
53435314
return $token;
53445315
}
53455316

@@ -5358,7 +5329,7 @@ public static function getCredential( ?array $selector = null ): array|\WP_Error
53585329

53595330
$token = (string) $credential['token'];
53605331
self::$last_auth_error = null;
5361-
self::$token_modes[ $token ] = (string) ( $credential['mode'] ?? 'pat' );
5332+
self::$token_modes[ $token ] = (string) $credential['mode'];
53625333
return $credential;
53635334
}
53645335

tests/smoke-github-create-abilities.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,11 @@ function wp_remote_retrieve_body( $response ): string {
221221
$assert( 'create-github-pull-request exposes labels', array_key_exists( 'labels', $pr_ability['input_schema']['properties'] ?? array() ) );
222222
$assert( 'create-github-pull-request labels schema declares string items', array( 'type' => 'string' ) === ( $pr_ability['input_schema']['properties']['labels']['items'] ?? null ) );
223223
$assert( 'create-github-pull-request exposes maintainer_can_modify', array_key_exists( 'maintainer_can_modify', $pr_ability['input_schema']['properties'] ?? array() ) );
224+
$pr_output_properties = $pr_ability['output_schema']['properties'] ?? array();
225+
$assert( 'create-github-pull-request output exposes top-level url', array_key_exists( 'url', $pr_output_properties ) );
226+
$assert( 'create-github-pull-request output exposes top-level html_url', array_key_exists( 'html_url', $pr_output_properties ) );
227+
$assert( 'create-github-pull-request output exposes top-level pull_number', array_key_exists( 'pull_number', $pr_output_properties ) );
228+
$assert( 'create-github-pull-request output exposes top-level reused', array_key_exists( 'reused', $pr_output_properties ) );
224229
$assert( 'create-github-pull-request is hidden from REST', false === ( $pr_ability['meta']['show_in_rest'] ?? null ) );
225230

226231
$assert( 'create-or-update-github-file ability is registered', null !== $file_ability );

0 commit comments

Comments
 (0)