util.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import { execSync } from "node:child_process";
  2. import { basename, dirname, extname } from "node:path";
  3. import actions from "@actions/core";
  4. import got from "got";
  5. import semver from "semver";
  6. export type ValidEventName = "push" | "pull_request" | "uncommitted";
  7. export function getDiff(
  8. type: "addedModified" | "removed" | "all" = "addedModified"
  9. ): string[] {
  10. const commands: Record<ValidEventName, string> = {
  11. push: "HEAD^ HEAD",
  12. pull_request: `origin/${process.argv[3] ? process.argv[3] : "main"} HEAD`,
  13. uncommitted: "HEAD",
  14. },
  15. eventName = process.argv[2] ? validateArg(process.argv[2]) : "pull_request",
  16. changedPresenceFolders = execSync(
  17. `git -c core.quotePath=false --no-pager diff --name-only --diff-filter=${
  18. type === "addedModified"
  19. ? "ACMRTU"
  20. : type === "removed"
  21. ? "D"
  22. : "ACMRTUD"
  23. } ${commands[eventName]}`
  24. )
  25. .toString()
  26. .split("\n")
  27. .filter(file => {
  28. if (file.startsWith("cli/")) return false;
  29. if (type === "removed") return "metadata.json" === basename(file);
  30. else {
  31. return ["presence.ts", "iframe.ts", "metadata.json"].includes(
  32. basename(file)
  33. );
  34. }
  35. });
  36. if (!changedPresenceFolders.length) return [];
  37. return [...new Set(changedPresenceFolders.map(f => basename(dirname(f))))];
  38. }
  39. function validateArg(arg: string): ValidEventName {
  40. if (!["push", "pull_request", "uncommitted"].includes(arg))
  41. throw new Error(`CI was not called with a valid event name: ${arg}`);
  42. return arg as ValidEventName;
  43. }
  44. export function getFolderLetter(service: string) {
  45. const firstLetter = service.at(0)!.toUpperCase();
  46. if (/^[a-zA-Z]/g.test(firstLetter)) return firstLetter;
  47. if (/^[0-9]/g.test(firstLetter)) return "0-9";
  48. return "#";
  49. }
  50. export async function getLatestSchema() {
  51. const fetchedSchemas = await got(
  52. "https://api.github.com/repos/PreMiD/PreMiD/contents/apps/schema-server/schemas/metadata?ref=monorepo",
  53. { responseType: "json" }
  54. );
  55. if (
  56. fetchedSchemas.statusCode !== 200 ||
  57. !Array.isArray(fetchedSchemas.body)
  58. ) {
  59. actions.setFailed("Could not fetch latest schema");
  60. process.exit();
  61. }
  62. //* schema names have the format of x.x.x.json
  63. const latestVersion = semver.sort(
  64. fetchedSchemas.body
  65. .filter(f => f.name.endsWith(".json"))
  66. .map(f => {
  67. const version = f.name.replace(".json", "");
  68. //* Make it semver compatible
  69. if (!semver.valid(version)) return `${version}.0`;
  70. return version;
  71. })
  72. );
  73. //* Remove prefixed .0 from the version
  74. latestVersion[latestVersion.length - 1] = latestVersion[
  75. latestVersion.length - 1
  76. ].replace(".0", "");
  77. const schema = fetchedSchemas.body.find(
  78. f => f.name === `${latestVersion.at(-1)}.json`
  79. );
  80. if (!schema) {
  81. actions.setFailed("Could not find latest schema");
  82. process.exit();
  83. }
  84. const schemaFile = await got(schema.download_url, { responseType: "json" });
  85. if (schemaFile.statusCode !== 200 || !schemaFile.body) {
  86. actions.setFailed("Could not fetch latest schema file");
  87. process.exit();
  88. }
  89. try {
  90. return {
  91. url: `https://schemas.premid.app/metadata/${schema.name.replace(
  92. extname(schema.name),
  93. ""
  94. )}`,
  95. schema: schemaFile.body,
  96. };
  97. } catch (e) {
  98. actions.setFailed("Could not parse latest schema");
  99. process.exit();
  100. }
  101. }