Skip to content

Commit 0759afb

Browse files
committed
refactor: rework some types
1 parent c8ab1c4 commit 0759afb

File tree

4 files changed

+116
-67
lines changed

4 files changed

+116
-67
lines changed

src/api.ts

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,18 @@ import * as core from "@actions/core";
44
import * as github from "@actions/github";
55

66
import { type ActionConfig, getConfig } from "./action.ts";
7-
import type { Result } from "./types.ts";
7+
import type {
8+
Result,
9+
WorkflowRunConclusion,
10+
WorkflowRunStatus,
11+
} from "./types.ts";
812
import { sleep } from "./utils.ts";
913

1014
type Octokit = ReturnType<(typeof github)["getOctokit"]>;
1115

1216
let config: ActionConfig;
1317
let octokit: Octokit;
1418

15-
/**
16-
* The Status and Conclusion types are difficult to find a reliable source
17-
* of truth for, but this seems accurate from testing:
18-
* https://docs.github.com/en/[email protected]/rest/guides/using-the-rest-api-to-interact-with-checks#about-check-suites
19-
*/
20-
21-
export enum WorkflowRunStatus {
22-
Queued = "queued",
23-
InProgress = "in_progress",
24-
Requested = "requested",
25-
Waiting = "waiting",
26-
Pending = "pending",
27-
Completed = "completed",
28-
}
29-
30-
export enum WorkflowRunConclusion {
31-
Success = "success",
32-
Failure = "failure",
33-
Neutral = "neutral",
34-
Cancelled = "cancelled",
35-
Skipped = "skipped",
36-
TimedOut = "timed_out",
37-
Stale = "stale",
38-
StartupFailure = "startup_failure",
39-
ActionRequired = "action_required",
40-
}
41-
4219
export function init(cfg?: ActionConfig): void {
4320
config = cfg ?? getConfig();
4421
octokit = github.getOctokit(config.token);

src/await-remote-run.ts

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,39 @@ import {
44
fetchWorkflowRunFailedJobs,
55
fetchWorkflowRunState,
66
retryOnError,
7+
} from "./api.ts";
8+
import {
79
WorkflowRunConclusion,
810
WorkflowRunStatus,
9-
} from "./api.ts";
10-
import type { Result } from "./types.ts";
11+
type Result,
12+
type WorkflowRunConclusionResult,
13+
type WorkflowRunStatusResult,
14+
} from "./types.ts";
1115
import { sleep } from "./utils.ts";
1216

1317
export function getWorkflowRunStatusResult(
1418
status: WorkflowRunStatus | null,
1519
attemptNo: number,
16-
): Result<WorkflowRunStatus> {
20+
): WorkflowRunStatusResult {
1721
if (status === WorkflowRunStatus.Completed) {
18-
core.debug("Run has completed");
1922
return { success: true, value: status };
2023
}
2124

2225
if (status === WorkflowRunStatus.Queued) {
2326
core.debug(`Run is queued to begin, attempt ${attemptNo}...`);
24-
return { success: false, reason: "inconclusive" };
27+
return { success: false, reason: "pending", value: status };
2528
} else if (status === WorkflowRunStatus.InProgress) {
2629
core.debug(`Run is in progress, attempt ${attemptNo}...`);
27-
return { success: false, reason: "inconclusive" };
30+
return { success: false, reason: "pending", value: status };
2831
}
2932

30-
core.debug(`Run has returned an unsupported status: ${status}`);
31-
return { success: false, reason: "unsupported" };
33+
core.debug(`Run status is unsupported: ${status}`);
34+
return { success: false, reason: "unsupported", value: status ?? "null" };
3235
}
3336

34-
function getWorkflowRunConclusionResult(
37+
export function getWorkflowRunConclusionResult(
3538
conclusion: WorkflowRunConclusion | null,
36-
): Result<WorkflowRunConclusion> {
39+
): WorkflowRunConclusionResult {
3740
switch (conclusion) {
3841
case WorkflowRunConclusion.Success:
3942
return { success: true, value: conclusion };
@@ -42,13 +45,19 @@ function getWorkflowRunConclusionResult(
4245
case WorkflowRunConclusion.Failure:
4346
case WorkflowRunConclusion.Neutral:
4447
case WorkflowRunConclusion.Skipped:
45-
case WorkflowRunConclusion.TimedOut:
4648
core.error(`Run has failed with conclusion: ${conclusion}`);
47-
return { success: false, reason: "timeout" };
49+
return { success: false, reason: "inconclusive", value: conclusion };
50+
case WorkflowRunConclusion.TimedOut:
51+
core.error("Run has timeout out");
52+
return { success: false, reason: "timeout", value: conclusion };
4853
default:
4954
core.error(`Run has failed with unsupported conclusion: ${conclusion}`);
5055
core.info("Please open an issue with this conclusion value");
51-
return { success: false, reason: "unsupported" };
56+
return {
57+
success: false,
58+
reason: "unsupported",
59+
value: conclusion ?? "null",
60+
};
5261
}
5362
}
5463

@@ -95,7 +104,10 @@ export async function getWorkflowRunResult({
95104
runTimeoutMs,
96105
pollIntervalMs,
97106
}: RunOpts): Promise<
98-
Result<{ status: WorkflowRunStatus; conclusion: WorkflowRunConclusion }>
107+
Result<
108+
| { status: WorkflowRunStatus.Completed; conclusion: WorkflowRunConclusion }
109+
| { status: WorkflowRunStatus; conclusion?: WorkflowRunConclusion }
110+
>
99111
> {
100112
let attemptNo = 0;
101113
let elapsedTime = Date.now() - startTime;
@@ -107,26 +119,31 @@ export async function getWorkflowRunResult({
107119
400,
108120
"fetchWorkflowRunState",
109121
);
110-
if (fetchWorkflowRunStateResult.success) {
122+
if (!fetchWorkflowRunStateResult.success) {
123+
core.debug(`Failed to fetch run state, attempt ${attemptNo}...`);
124+
} else {
111125
const { status, conclusion } = fetchWorkflowRunStateResult.value;
112126
const statusResult = getWorkflowRunStatusResult(status, attemptNo);
113127
if (statusResult.success) {
128+
// We only get a conclusion should the status resolve, otherwise it is null.
114129
const conclusionResult = getWorkflowRunConclusionResult(conclusion);
115130

116-
if (conclusionResult.success) {
117-
return {
118-
success: true,
119-
value: {
120-
status: statusResult.value,
121-
conclusion: conclusionResult.value,
122-
},
123-
};
124-
} else {
125-
return conclusionResult;
126-
}
131+
return {
132+
success: true,
133+
value: {
134+
status: statusResult.value,
135+
conclusion: conclusionResult.success
136+
? conclusionResult.value
137+
: undefined,
138+
},
139+
};
140+
}
141+
142+
// If the status is unsupported, we can't guarantee it will ever
143+
// resolve. Alert to raise this so we can handle it properly.
144+
if (statusResult.reason === "unsupported") {
145+
return statusResult;
127146
}
128-
} else {
129-
core.debug(`Run has not yet been identified, attempt ${attemptNo}...`);
130147
}
131148

132149
await sleep(pollIntervalMs);

src/main.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ import * as core from "@actions/core";
22

33
import { getConfig } from "./action.ts";
44
import * as api from "./api.ts";
5-
import {
6-
getWorkflowRunResult,
7-
handleActionFail,
8-
handleActionSuccess,
9-
} from "./await-remote-run.ts";
5+
import { getWorkflowRunResult, handleActionFail } from "./await-remote-run.ts";
106
import * as constants from "./constants.ts";
7+
import { WorkflowRunConclusion, WorkflowRunStatus } from "./types.ts";
118

129
async function main(): Promise<void> {
1310
try {
@@ -33,15 +30,18 @@ async function main(): Promise<void> {
3330
runTimeoutMs: config.runTimeoutSeconds * 1000,
3431
});
3532
if (result.success) {
36-
handleActionSuccess(config.runId, result.value.conclusion);
33+
core.info(
34+
"Run Completed:\n" +
35+
` Run ID: ${config.runId}\n` +
36+
` Status: ${WorkflowRunStatus.Completed}\n` +
37+
` Conclusion: ${WorkflowRunConclusion.Success}`,
38+
);
3739
} else {
3840
const elapsedTime = Date.now() - startTime;
3941
const failureMsg =
4042
result.reason === "timeout"
4143
? `Timeout exceeded while attempting to await run conclusion (${elapsedTime}ms)`
42-
: result.reason === "inconclusive"
43-
? "Run was inconclusive"
44-
: "Unsupported conclusion was returned";
44+
: `An unsupported value was reached: ${result.value}`;
4545
await handleActionFail(failureMsg, config.runId);
4646
}
4747
} catch (error) {

src/types.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,31 @@
1-
export type Result<T> = ResultSuccess<T> | ResultFailure;
1+
/**
2+
* The Status and Conclusion types are difficult to find a reliable source
3+
* of truth for, but this seems accurate from testing:
4+
* https://docs.github.com/en/[email protected]/rest/guides/using-the-rest-api-to-interact-with-checks#about-check-suites
5+
*/
6+
7+
export enum WorkflowRunStatus {
8+
Queued = "queued",
9+
InProgress = "in_progress",
10+
Requested = "requested",
11+
Waiting = "waiting",
12+
Pending = "pending",
13+
Completed = "completed",
14+
}
15+
16+
export enum WorkflowRunConclusion {
17+
Success = "success",
18+
Failure = "failure",
19+
Neutral = "neutral",
20+
Cancelled = "cancelled",
21+
Skipped = "skipped",
22+
TimedOut = "timed_out",
23+
Stale = "stale",
24+
StartupFailure = "startup_failure",
25+
ActionRequired = "action_required",
26+
}
27+
28+
export type Result<T> = ResultSuccess<T> | ResultFailure | ResultUnsupported;
229

330
interface ResultSuccess<T> {
431
success: true;
@@ -7,5 +34,33 @@ interface ResultSuccess<T> {
734

835
interface ResultFailure {
936
success: false;
10-
reason: "timeout" | "inconclusive" | "unsupported";
37+
reason: "timeout";
38+
}
39+
40+
interface ResultUnsupported {
41+
success: false;
42+
reason: "unsupported";
43+
value: string;
44+
}
45+
46+
export type WorkflowRunStatusResult =
47+
| ResultSuccess<WorkflowRunStatus>
48+
| ResultStatusPending
49+
| ResultUnsupported;
50+
51+
interface ResultStatusPending {
52+
success: false;
53+
reason: "pending";
54+
value: WorkflowRunStatus;
55+
}
56+
57+
export type WorkflowRunConclusionResult =
58+
| ResultSuccess<WorkflowRunConclusion>
59+
| ResultConclusionInconclusive
60+
| ResultUnsupported;
61+
62+
interface ResultConclusionInconclusive {
63+
success: false;
64+
reason: "inconclusive" | "timeout";
65+
value: WorkflowRunConclusion;
1166
}

0 commit comments

Comments
 (0)