170 lines · 6.1 KB
import { parse as parseYaml } from "yaml";
import { z } from "zod";

/** The JavaScript runtimes GitHub has offered; all run on the runner image's Node (24). */
const NODE_RUNTIMES = new Set(["node12", "node16", "node20", "node24"]);
const ENTRY_PATH = /^(?!\/)(?!.*(?:^|\/)\.\.(?:\/|$))[^\0]{1,512}$/;
const MAX_INPUTS = 100;

const scalar = z.union([z.string(), z.number(), z.boolean()]).transform((value) => String(value));

const manifestSchema = z.object({
  name: z.string().optional(),
  inputs: z
    .record(
      z.string(),
      z
        .object({
          default: scalar.optional(),
          required: z.union([z.boolean(), z.string()]).optional(),
        })
        .nullable(),
    )
    .optional(),
  runs: z.object({
    using: z.string(),
    main: z.string().optional(),
    pre: z.string().optional(),
    post: z.string().optional(),
    "pre-if": z.union([z.string(), z.boolean()]).optional(),
    "post-if": z.union([z.string(), z.boolean()]).optional(),
    image: z.string().optional(),
    entrypoint: z.string().optional(),
    "pre-entrypoint": z.string().optional(),
    "post-entrypoint": z.string().optional(),
    args: z.array(scalar).optional(),
    env: z.record(z.string(), scalar).optional(),
  }),
});

export type ActionInput = { name: string; default: string | null; required: boolean };