Skip to content

Commit 838e853

Browse files
authored
Hide skipped jobs and not completed steps (#24)
2 parents 0e7e02f + dfdbaea commit 838e853

File tree

4 files changed

+164
-51
lines changed

4 files changed

+164
-51
lines changed

dist/post.js

+36-24
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/post.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { setTimeout } from "node:timers/promises";
12
import { debug, getInput, info, summary } from "npm:@actions/core@1.10.0";
23
import * as github from "npm:@actions/github@5.1.1";
34
import { createGantt } from "./workflow_gantt.ts";
@@ -11,6 +12,9 @@ const main = async () => {
1112
const token = getInput("github-token", { required: true });
1213
const octokit = createOctokit(token);
1314

15+
info("Wait for workflow API result stability...");
16+
await setTimeout(1000);
17+
1418
info("Fetch workflow...");
1519
const workflow = await fetchWorkflow(
1620
octokit,

src/workflow_gantt.ts

+40-24
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type StepConclusion =
2525
| "action_required"
2626
| null;
2727

28+
type workflowJobSteps = NonNullable<WorkflowJobs[0]["steps"]>;
29+
2830
const diffSec = (
2931
start?: string | Date | null,
3032
end?: string | Date | null,
@@ -96,37 +98,51 @@ const convertStepToStatus = (
9698
}
9799
};
98100

101+
// Skip steps that is not status:completed (ex. status:queued, status:in_progress)
102+
const filterSteps = (steps: workflowJobSteps): workflowJobSteps => {
103+
return steps.filter((step) => step.status === "completed");
104+
};
105+
106+
// Skip jobs that is conclusion:skipped
107+
const filterJobs = (jobs: WorkflowJobs): WorkflowJobs => {
108+
return jobs.filter((job) => job.conclusion !== "skipped");
109+
};
110+
99111
export const createGantt = (
100112
workflow: Workflow,
101113
workflowJobs: WorkflowJobs,
102114
): string => {
103115
const title = workflowJobs[0].workflow_name;
104-
const jobs = workflowJobs.map((job, jobIndex, _jobs): ganttJob => {
105-
const section = escapeName(job.name);
106-
const status: ganttStep["status"] = "active";
107-
const startJobElapsedSec = diffSec(workflow.created_at, job.created_at);
108-
const waitingRunnerElapsedSec = diffSec(job.created_at, job.started_at);
109-
const waitingRunnerStep: ganttStep = {
110-
name: formatName("Waiting for a runner", waitingRunnerElapsedSec),
111-
id: `job${jobIndex}-0`,
112-
status,
113-
position: formatElapsedTime(startJobElapsedSec),
114-
sec: waitingRunnerElapsedSec,
115-
};
116-
117-
const steps = job.steps?.map((step, stepIndex, _steps): ganttStep => {
118-
const stepElapsedSec = diffSec(step.started_at, step.completed_at);
119-
return {
120-
name: formatName(step.name, stepElapsedSec),
121-
id: `job${jobIndex}-${stepIndex + 1}`,
122-
status: convertStepToStatus(step.conclusion as StepConclusion),
123-
position: `after job${jobIndex}-${stepIndex}`,
124-
sec: stepElapsedSec,
116+
const jobs = filterJobs(workflowJobs).map(
117+
(job, jobIndex, _jobs): ganttJob => {
118+
const section = escapeName(job.name);
119+
const status: ganttStep["status"] = "active";
120+
const startJobElapsedSec = diffSec(workflow.created_at, job.created_at);
121+
const waitingRunnerElapsedSec = diffSec(job.created_at, job.started_at);
122+
const waitingRunnerStep: ganttStep = {
123+
name: formatName("Waiting for a runner", waitingRunnerElapsedSec),
124+
id: `job${jobIndex}-0`,
125+
status,
126+
position: formatElapsedTime(startJobElapsedSec),
127+
sec: waitingRunnerElapsedSec,
125128
};
126-
}) ?? [];
127129

128-
return { section, steps: [waitingRunnerStep, ...steps] };
129-
});
130+
const steps = filterSteps(job.steps ?? []).map(
131+
(step, stepIndex, _steps): ganttStep => {
132+
const stepElapsedSec = diffSec(step.started_at, step.completed_at);
133+
return {
134+
name: formatName(step.name, stepElapsedSec),
135+
id: `job${jobIndex}-${stepIndex + 1}`,
136+
status: convertStepToStatus(step.conclusion as StepConclusion),
137+
position: `after job${jobIndex}-${stepIndex}`,
138+
sec: stepElapsedSec,
139+
};
140+
},
141+
);
142+
143+
return { section, steps: [waitingRunnerStep, ...steps] };
144+
},
145+
);
130146

131147
return `
132148
\`\`\`mermaid

tests/workflow_gantt_test.ts

+84-3
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ ${workflowJobs[0].steps![3].name} (0s) :job0-4, after job0-3, 0s
200200
assertEquals(createGantt(workflow, workflowJobs), expect);
201201
});
202202

203-
await t.step("job has status:in_progress and status:queued steps", () => {
203+
await t.step("Hide not completed stesp", () => {
204204
const workflow = {
205205
"id": 6290960492,
206206
"name": "CI",
@@ -260,8 +260,6 @@ axisFormat %H:%M:%S
260260
section ${workflowJobs[0].name}
261261
Waiting for a runner (6s) :active, job0-0, 00:04:31, 6s
262262
${workflowJobs[0].steps![0].name} (1s) :job0-1, after job0-0, 1s
263-
${workflowJobs[0].steps![1].name} (0s) :active, job0-2, after job0-1, 0s
264-
${workflowJobs[0].steps![2].name} (0s) :active, job0-3, after job0-2, 0s
265263
\`\`\`
266264
`;
267265

@@ -533,6 +531,89 @@ ${workflowJobs[1].steps![4].name} (0s) :job1-5, after job1-4, 0s
533531
${workflowJobs[1].steps![5].name} (0s) :job1-6, after job1-5, 0s
534532
${workflowJobs[1].steps![6].name} (0s) :job1-7, after job1-6, 0s
535533
\`\`\`
534+
`;
535+
536+
assertEquals(createGantt(workflow, workflowJobs), expect);
537+
});
538+
539+
await t.step("Hide skipped jobs", () => {
540+
const workflow = {
541+
"id": 5833450919,
542+
"name": "Check self-hosted runner",
543+
"run_number": 128,
544+
"event": "workflow_dispatch",
545+
"status": "completed",
546+
"conclusion": "success",
547+
"workflow_id": 10970418,
548+
"created_at": "2023-08-11T14:00:48Z",
549+
"updated_at": "2023-08-11T14:01:56Z",
550+
} as unknown as Workflow;
551+
552+
const workflowJobs = [
553+
{
554+
"id": 15820938470,
555+
"run_id": 5833450919,
556+
"workflow_name": "Check self-hosted runner",
557+
"status": "completed",
558+
"conclusion": "success",
559+
"created_at": "2023-08-11T14:00:50Z",
560+
"started_at": "2023-08-11T14:01:31Z",
561+
"completed_at": "2023-08-11T14:01:36Z",
562+
"name": "node",
563+
"steps": [
564+
{
565+
"name": "Set up job",
566+
"status": "completed",
567+
"conclusion": "success",
568+
"number": 1,
569+
"started_at": "2023-08-11T23:01:30.000+09:00",
570+
"completed_at": "2023-08-11T23:01:32.000+09:00",
571+
},
572+
{
573+
"name": "Set up runner",
574+
"status": "completed",
575+
"conclusion": "success",
576+
"number": 2,
577+
"started_at": "2023-08-11T23:01:32.000+09:00",
578+
"completed_at": "2023-08-11T23:01:32.000+09:00",
579+
},
580+
{
581+
"name": "Run actions/checkout@v3",
582+
"status": "completed",
583+
"conclusion": "success",
584+
"number": 3,
585+
"started_at": "2023-08-11T23:01:34.000+09:00",
586+
"completed_at": "2023-08-11T23:01:34.000+09:00",
587+
},
588+
],
589+
},
590+
{
591+
"id": 15820938790,
592+
"run_id": 5833450919,
593+
"workflow_name": "Check self-hosted runner",
594+
"status": "completed",
595+
"conclusion": "skipped",
596+
"created_at": "2023-08-11T14:00:51Z",
597+
"started_at": "2023-08-11T14:00:51Z",
598+
"completed_at": "2023-08-11T14:01:50Z",
599+
"name": "skipped test",
600+
"steps": [],
601+
},
602+
] as unknown as WorkflowJobs;
603+
604+
// deno-fmt-ignore
605+
const expect = `
606+
\`\`\`mermaid
607+
gantt
608+
title ${workflowJobs[0].workflow_name}
609+
dateFormat HH:mm:ss
610+
axisFormat %H:%M:%S
611+
section ${workflowJobs[0].name}
612+
Waiting for a runner (41s) :active, job0-0, 00:00:02, 41s
613+
${workflowJobs[0].steps![0].name} (2s) :job0-1, after job0-0, 2s
614+
${workflowJobs[0].steps![1].name} (0s) :job0-2, after job0-1, 0s
615+
${workflowJobs[0].steps![2].name} (0s) :job0-3, after job0-2, 0s
616+
\`\`\`
536617
`;
537618

538619
assertEquals(createGantt(workflow, workflowJobs), expect);

0 commit comments

Comments
 (0)