@@ -12,73 +12,77 @@ import {
1212import { MergeConflictsFatalError } from '../../../../ng-dev/pr/merge/failures.js' ;
1313import { createPullRequestValidationConfig } from '../../../../ng-dev/pr/common/validation/validation-config.js' ;
1414import { InvalidTargetLabelError } from '../../../../ng-dev/pr/common/targeting/target-label.js' ;
15- import { resolve } from 'path' ;
15+ import {
16+ assertValidCaretakerConfig ,
17+ assertValidGithubConfig ,
18+ setConfig ,
19+ getConfig ,
20+ } from '../../../../ng-dev/utils/config.js' ;
21+ import { assertValidPullRequestConfig } from '../../../../ng-dev/pr/config/index.js' ;
22+ import { setTimeout } from 'node:timers/promises' ;
23+ import { AuthenticatedGitClient } from '../../../../ng-dev/utils/git/authenticated-git-client.js' ;
1624
1725interface CommmitStatus {
1826 state : 'pending' | 'error' | 'failure' | 'success' ;
1927 description : string ;
2028 targetUrl ?: string ;
2129}
2230
23- /** The context name used for the commmit status applied. */
24- const statusContextName = 'mergeability' ;
25- /** The repository name for the pull request. */
26- const repo = core . getInput ( 'repo' , { required : true , trimWhitespace : true } ) ;
27- /** The owner of the repository for the pull request. */
28- const owner = core . getInput ( 'owner' , { required : true , trimWhitespace : true } ) ;
29- /** The pull request number. */
30- const pr = Number ( core . getInput ( 'pr' , { required : true , trimWhitespace : true } ) ) ;
31- // If the provided pr is not a number, we cannot evaluate the mergeability.
32- if ( isNaN ( pr ) ) {
33- core . setFailed ( 'The provided pr value was not a number' ) ;
34- process . exit ( ) ;
35- }
36- /** The token for the angular robot to perform actions in the requested repo. */
37- const token = await getAuthTokenFor ( ANGULAR_ROBOT , { repo, owner} ) ;
38- const {
39- /** The ng-dev configuration used for the environment */
40- config,
41- /** The Authenticated Git Client instance. */
42- git,
43- } = await setupConfigAndGitClient ( token , { owner, repo} ) ;
44- /** The sha of the latest commit on the pull request, which when provided is what triggered the check. */
45- const sha = await ( async ( ) => {
46- let sha = core . getInput ( 'sha' , { required : false , trimWhitespace : true } ) || undefined ;
47- if ( sha === undefined ) {
48- sha = ( await git . github . pulls . get ( { owner, repo, pull_number : pr } ) ) . data . head . sha as string ;
31+ async function main ( ) {
32+ /** The context name used for the commmit status applied. */
33+ const statusContextName = 'mergeability' ;
34+ /** The repository name for the pull request. */
35+ const repo = core . getInput ( 'repo' , { required : true , trimWhitespace : true } ) ;
36+ /** The owner of the repository for the pull request. */
37+ const owner = core . getInput ( 'owner' , { required : true , trimWhitespace : true } ) ;
38+ /** The pull request number. */
39+ const pr = Number ( core . getInput ( 'pr' , { required : true , trimWhitespace : true } ) ) ;
40+ /** The SHA of the pull request */
41+ let sha = core . getInput ( 'sha' , { required : false , trimWhitespace : true } ) ;
42+
43+ // If the provided pr is not a number, we cannot evaluate the mergeability.
44+ if ( isNaN ( pr ) ) {
45+ core . setFailed ( 'The provided pr value was not a number' ) ;
46+ process . exit ( ) ;
4947 }
50- return sha ;
51- } ) ( ) ;
52-
53- /** Set the mergability status on the pull request provided in the environment. */
54- async function setMergeabilityStatusOnPullRequest (
55- { state, description, targetUrl} : CommmitStatus ,
56- canRetry = true ,
57- ) {
58- try {
59- await git . github . repos . createCommitStatus ( {
60- owner,
61- repo,
62- sha,
63- context : statusContextName ,
64- state,
65- // Status descriptions are limited to 140 characters.
66- description : description . substring ( 0 , 139 ) ,
67- target_url : targetUrl ,
68- } ) ;
69- } catch {
70- if ( canRetry ) {
71- await new Promise ( ( resolve ) => setTimeout ( resolve , 5000 ) ) ;
72- await setMergeabilityStatusOnPullRequest ( { state, description, targetUrl} , false ) ;
48+
49+ /** Set the mergability status on the pull request provided in the environment. */
50+ async function setMergeabilityStatusOnPullRequest (
51+ git : AuthenticatedGitClient ,
52+ sha : string ,
53+ { state, description, targetUrl} : CommmitStatus ,
54+ canRetry = true ,
55+ ) {
56+ try {
57+ await git . github . repos . createCommitStatus ( {
58+ owner,
59+ repo,
60+ sha,
61+ context : statusContextName ,
62+ state,
63+ // Status descriptions are limited to 140 characters.
64+ description : description . substring ( 0 , 139 ) ,
65+ target_url : targetUrl ,
66+ } ) ;
67+ } catch {
68+ if ( canRetry ) {
69+ await setTimeout ( 5_000 ) ;
70+ await setMergeabilityStatusOnPullRequest ( git , sha , { state, description, targetUrl} , false ) ;
71+ }
7372 }
7473 }
75- }
7674
77- async function main ( ) {
75+ const token = await getAuthTokenFor ( ANGULAR_ROBOT , { repo, owner} ) ;
76+
7877 try {
78+ const { git} = await setupConfigAndGitClient ( token , { owner, repo} ) ;
79+ sha ??= ( await git . github . pulls . get ( { owner, repo, pull_number : pr } ) ) . data . head . sha ;
80+
7981 // This is intentionally not awaited because we are just setting the status to pending, and wanting
8082 // to continue working.
81- let _unawaitedPromise = setMergeabilityStatusOnPullRequest (
83+ void setMergeabilityStatusOnPullRequest (
84+ git ,
85+ sha ,
8286 {
8387 state : 'pending' ,
8488 description : 'Mergability check in progress' ,
@@ -89,6 +93,16 @@ async function main() {
8993 // Create a tmp directory to perform checks in and change working to directory to it.
9094 await cloneRepoIntoTmpLocation ( { owner, repo} ) ;
9195
96+ // Remove cached config and use the repo config.
97+ // TODO(alanagius): this is needed because `setupConfigAndGitClient` uses a dummy config.
98+ setConfig ( null ) ;
99+
100+ const config = await getConfig ( [
101+ assertValidGithubConfig ,
102+ assertValidPullRequestConfig ,
103+ assertValidCaretakerConfig ,
104+ ] ) ;
105+
92106 /** The pull request after being retrieved and validated. */
93107 const pullRequest = await loadAndValidatePullRequest (
94108 { git, config} ,
@@ -168,12 +182,12 @@ async function main() {
168182 }
169183 } ) ( ) ;
170184
171- await setMergeabilityStatusOnPullRequest ( statusInfo ) ;
185+ await setMergeabilityStatusOnPullRequest ( git , sha , statusInfo ) ;
172186 } catch ( e : Error | unknown ) {
173187 let state : CommmitStatus [ 'state' ] = 'error' ;
174188 let description : string ;
175- const { runId, repo, serverUrl} = actionContext ;
176- const targetUrl = `${ serverUrl } /${ repo . owner } /${ repo . repo } /actions/runs/${ runId } ` ;
189+ const { runId, repo : actionRepo , serverUrl} = actionContext ;
190+ const targetUrl = `${ serverUrl } /${ actionRepo . owner } /${ actionRepo . repo } /actions/runs/${ runId } ` ;
177191
178192 if ( e instanceof InvalidTargetLabelError ) {
179193 // For this action, an invalid target label represents that we aren't ready to check the
@@ -185,9 +199,13 @@ async function main() {
185199 } else {
186200 description = 'Internal Error, see link for action log' ;
187201 }
188- await setMergeabilityStatusOnPullRequest ( { state, description, targetUrl} ) ;
202+ await setMergeabilityStatusOnPullRequest ( git , sha , { state, description, targetUrl} ) ;
189203 // Re-throw the error so that the action run is set as failing.
190204 throw e ;
205+ } finally {
206+ if ( token !== undefined ) {
207+ await revokeActiveInstallationToken ( token ) ;
208+ }
191209 }
192210}
193211
@@ -196,6 +214,4 @@ try {
196214 core . error ( e ) ;
197215 core . setFailed ( e . message ) ;
198216 } ) ;
199- } finally {
200- await revokeActiveInstallationToken ( token ) ;
201- }
217+ } catch { }
0 commit comments