Merge pull request #191 from github/cschleiden/events-without-default-types

Support events without default `types`
This commit is contained in:
Christopher Schleiden
2023-03-17 09:19:38 -07:00
committed by GitHub
3 changed files with 86 additions and 14 deletions
@@ -1,7 +1,7 @@
import {data, DescriptionDictionary} from "@github/actions-expressions";
import webhooks from "./webhooks.json";
import webhookObjects from "./objects.json";
import webhooks from "./webhooks.json";
import schedule from "./schedule.json" assert {type: "json"};
import workflow_call from "./workflow_call.json" assert {type: "json"};
@@ -73,9 +73,12 @@ type DeduplicatedWebhooks = {
};
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const dedupedWebhookPayloads: DeduplicatedWebhooks = webhooks as any;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const objects: Param[] = webhookObjects as any;
// Hydrated webhook payloads
const webhookPayloads: Webhooks = {};
// Hydrate the workflow dispatch payload if it exists
@@ -89,7 +92,18 @@ if (inputs) {
delete inputs.childParamsGroups;
}
export function getEventPayload(event: string, action: string = "default"): DescriptionDictionary | undefined {
export function getSupportedEventTypes(event: string): string[] {
const payloads = dedupedWebhookPayloads?.[event];
if (!payloads) {
if (customEventPayloads[event]) {
return ["default"];
}
}
return Object.keys(payloads || {});
}
export function getEventPayload(event: string, action: string): DescriptionDictionary | undefined {
const payload = getWebhookPayload(event, action);
if (!payload) {
// Not all events are real webhooks. Check if there is a custom payload for this event
@@ -117,7 +131,7 @@ function mergeParam(target: DescriptionDictionary, param: Param) {
// auto-completion. Possible existence and the description are enough.
//
// As a special case, if the param is already set, do not overwrite it.
if (!!target.get(param.name)) {
if (target.get(param.name)) {
return;
}
@@ -125,16 +139,16 @@ function mergeParam(target: DescriptionDictionary, param: Param) {
}
}
function mergeObject(d: DescriptionDictionary, toAdd: Object): DescriptionDictionary {
function mergeObject(d: DescriptionDictionary, toAdd: object): DescriptionDictionary {
for (const [key, value] of Object.entries(toAdd)) {
if (value && typeof value === "object" && !d.get(key)) {
if (!Array.isArray(value) && Object.entries(value).length === 0) {
if (!Array.isArray(value) && Object.entries(value as object).length === 0) {
// Allow an empty object to be any value
d.add(key, new data.Null());
continue;
}
d.add(key, mergeObject(new DescriptionDictionary(), value));
d.add(key, mergeObject(new DescriptionDictionary(), value as object));
} else {
d.add(key, new data.Null());
}
@@ -144,16 +158,17 @@ function mergeObject(d: DescriptionDictionary, toAdd: Object): DescriptionDictio
}
function getWebhookPayload(event: string, action: string): WebhookPayload | undefined {
const deduplicatedPayload = dedupedWebhookPayloads?.[event]?.[action];
if (!deduplicatedPayload) {
return undefined;
}
// Is the payload already hydrated?
const existingPayload = webhookPayloads?.[event]?.[action];
if (existingPayload) {
return existingPayload;
}
const deduplicatedPayload = dedupedWebhookPayloads?.[event]?.[action];
if (!deduplicatedPayload) {
return undefined;
}
// Recreate the full payload and store it for reuse
const params = deduplicatedPayload.bodyParameters.map(p => fullParam(p));
const payload = {
@@ -74,6 +74,59 @@ jobs:
]);
});
it("single event - no default types", async () => {
const workflowContext = await testGetWorkflowContext(`
on:
issues:
jobs:
build:
runs-on: ubuntu-latest
steps:
- run: ec|ho`);
const g = getGithubContext(workflowContext, Mode.Completion);
if (!isDescriptionDictionary(g)) {
fail();
}
const e = g.get("event") as DescriptionDictionary;
const i = e.get("issue") as DescriptionDictionary;
expect(i.pairs().map(p => p.key)).toEqual([
"active_lock_reason",
"assignee",
"assignees",
"author_association",
"body",
"closed_at",
"comments",
"comments_url",
"created_at",
"draft",
"events_url",
"html_url",
"id",
"labels",
"labels_url",
"locked",
"milestone",
"node_id",
"number",
"performed_via_github_app",
"pull_request",
"reactions",
"repository_url",
"state",
"state_reason",
"timeline_url",
"title",
"updated_at",
"url",
"user"
]);
});
it("multiple events - multiple types", async () => {
const workflowContext = await testGetWorkflowContext(`
on:
@@ -4,7 +4,7 @@ import {TypesFilterConfig} from "@github/actions-workflow-parser/model/workflow-
import {WorkflowContext} from "../context/workflow-context";
import {Mode} from "./default";
import {getDescription} from "./descriptions";
import {getEventPayload} from "./events/eventPayloads";
import {getEventPayload, getSupportedEventTypes} from "./events/eventPayloads";
import {getInputsContext} from "./inputs";
export function getGithubContext(workflowContext: WorkflowContext, mode: Mode): DescriptionDictionary {
@@ -98,10 +98,14 @@ function getEventContext(workflowContext: WorkflowContext, mode: Mode): Expressi
for (const eventName of events) {
const event = eventsConfig[eventName] as TypesFilterConfig;
const types = getTypes(eventName, event.types);
let types = getTypes(eventName, event.types);
const payloadEventName = getPayloadEventName(eventName);
if (types.length === 1 && types[0] === "default") {
types = getSupportedEventTypes(eventName);
}
for (const type of types) {
const payloadEventName = getPayloadEventName(eventName);
const eventPayload = getEventPayload(payloadEventName, type);
if (!eventPayload) {