pr.test.js (3183B)
1 import t from "ava"; 2 import fs from "fs-extra"; 3 import path from "path"; 4 5 import trustedUsers from "../util/trusted.json" with { type: "json" }; 6 7 const requiredEnvVars = ["PR_AUTHOR", "PR_AUTHOR_ID"]; 8 9 const trusted = trustedUsers.map((u) => u.id.toString()); 10 const admins = trustedUsers.filter((u) => u.admin).map((u) => u.id.toString()); 11 12 function getDomainData(subdomain) { 13 try { 14 const data = fs.readJsonSync(path.join(path.resolve("domains"), `${subdomain}.json`)); 15 return data; 16 } catch (error) { 17 throw new Error(`Failed to read JSON for ${subdomain}: ${error.message}`); 18 } 19 } 20 21 t("Users can only update their own subdomains", (t) => { 22 if (requiredEnvVars.every((v) => process.env[v])) { 23 const changedFiles = JSON.parse(process.env.CHANGED_FILES); 24 const deletedFiles = JSON.parse(process.env.DELETED_FILES); 25 const prAuthor = process.env.PR_AUTHOR.toLowerCase(); 26 const prAuthorId = process.env.PR_AUTHOR_ID; 27 28 const changedJSONFiles = changedFiles 29 .filter((file) => file.startsWith("domains/")) 30 .map((file) => path.basename(file)); 31 const deletedJSONFiles = deletedFiles 32 .filter((file) => file.name.startsWith("domains/")) 33 .map((file) => path.basename(file.name)); 34 35 if (!changedJSONFiles && !deletedFiles) return t.pass(); 36 if (process.env.PR_LABELS && process.env.PR_LABELS.includes("ci: bypass-owner-check")) return t.pass(); 37 38 changedJSONFiles.forEach((file) => { 39 const subdomain = file.replace(/\.json$/, ""); 40 const data = getDomainData(subdomain); 41 42 if (data.owner.username === "free-domains") { 43 t.true( 44 admins.includes(prAuthorId), 45 `${subdomain}: ${prAuthor} is not authorized to update ${subdomain}.is-a.bot` 46 ); 47 } else { 48 t.true( 49 data.owner.username.toLowerCase() === prAuthor || trusted.includes(prAuthorId), 50 `${file}: ${prAuthor} is not authorized to update ${subdomain}.is-a.bot` 51 ); 52 } 53 }); 54 55 deletedJSONFiles.forEach((file) => { 56 const subdomain = file.replace(/\.json$/, ""); 57 const data = JSON.parse( 58 deletedFiles 59 .find((f) => f.name === `domains/${file}`) 60 .data.split("\n") 61 .filter((line) => line.startsWith("-") && !line.startsWith("---")) 62 .map((line) => line.substring(1)) 63 .join("\n") 64 ); 65 66 if (data.owner.username === "free-domains") { 67 t.true( 68 admins.includes(prAuthorId), 69 `${subdomain}: ${prAuthor} is not authorized to delete ${subdomain}.is-a.bot` 70 ); 71 } else { 72 t.true( 73 data.owner.username.toLowerCase() === prAuthor || trusted.includes(prAuthorId), 74 `${file}: ${prAuthor} is not authorized to delete ${subdomain}.is-a.bot` 75 ); 76 } 77 }); 78 } 79 80 t.pass(); 81 });