From 734514f87cfc1551cc4a9629bd0a7bf84cf1c159 Mon Sep 17 00:00:00 2001 From: Naomi Carrigan Date: Thu, 23 Jan 2025 02:22:46 -0800 Subject: [PATCH] feat: setup actions (#1) Co-authored-by: Naomi Carrigan Co-committed-by: Naomi Carrigan --- .gitea/issue_template/bug_report.yaml | 69 ++++++++++++++++ .gitea/issue_template/config.yml | 5 ++ .gitea/issue_template/feature_proposal.yml | 46 +++++++++++ .gitea/issue_template/other.yml | 34 ++++++++ .gitea/pull_request_template.yml | 91 ++++++++++++++++++++++ .gitea/workflows/ci.yml | 38 +++++++++ package.json | 4 +- src/events/client/onReady.ts | 3 - src/events/guild/onGuildCreate.ts | 2 - src/events/guild/onGuildDelete.ts | 2 - src/events/interaction/onInteraction.ts | 1 - src/events/member/onMemberAdd.ts | 1 - src/events/member/onMemberRemove.ts | 1 - src/interfaces/ExtendedClient.ts | 3 - src/modules/prometheus.ts | 71 ----------------- src/temp.ts | 32 -------- src/utils/errorHandler.ts | 1 - 17 files changed, 285 insertions(+), 119 deletions(-) create mode 100644 .gitea/issue_template/bug_report.yaml create mode 100644 .gitea/issue_template/config.yml create mode 100644 .gitea/issue_template/feature_proposal.yml create mode 100644 .gitea/issue_template/other.yml create mode 100644 .gitea/pull_request_template.yml create mode 100644 .gitea/workflows/ci.yml delete mode 100644 src/modules/prometheus.ts delete mode 100644 src/temp.ts diff --git a/.gitea/issue_template/bug_report.yaml b/.gitea/issue_template/bug_report.yaml new file mode 100644 index 0000000..bf17745 --- /dev/null +++ b/.gitea/issue_template/bug_report.yaml @@ -0,0 +1,69 @@ +name: 🐛 Bug Report +description: Something isn't working as expected? Let us know! +title: '[BUG] - ' +labels: + - "status/awaiting triage" +body: + - type: checkboxes + id: attestations + attributes: + label: Attestations + description: "By checking the boxes below, I certify that:" + options: + - label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)" + validations: + required: true + - label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). + validations: + required: true + - label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not). + validations: + required: true + - label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability. + validations: + required: true + - type: textarea + id: description + attributes: + label: "Describe your Issue:" + description: A clear and concise description of what the bug is. + validations: + required: true + - type: dropdown + id: reproduce + attributes: + label: Can you reproduce this issue? + options: + - Yes + - No + validations: + required: true + - type: textarea + id: reproduction + attributes: + label: "Steps to Reproduce:" + description: Steps to reproduce the behavior. + - type: input + id: os + attributes: + label: "Operating System:" + description: The operating system you are using, including the version/build number. + validations: + required: true +# Remove this section for non-web apps. + - type: input + id: browser + attributes: + label: "Browser:" + description: The browser you are using, including the version number. + validations: + required: true + - type: dropdown + attributes: + label: Are you willing and able to contribute a fix? + options: + - Yes + - No + validations: + required: true + diff --git a/.gitea/issue_template/config.yml b/.gitea/issue_template/config.yml new file mode 100644 index 0000000..f1cdc86 --- /dev/null +++ b/.gitea/issue_template/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: "Discord" + url: "https://chat.nhcarrigan.com" + about: "Chat with us directly." \ No newline at end of file diff --git a/.gitea/issue_template/feature_proposal.yml b/.gitea/issue_template/feature_proposal.yml new file mode 100644 index 0000000..b3fae97 --- /dev/null +++ b/.gitea/issue_template/feature_proposal.yml @@ -0,0 +1,46 @@ +name: 💭 Feature Proposal +description: Have an idea for how we can improve? Share it here! +title: '[FEAT] - ' +labels: + - "status/awaiting triage" +body: + - type: checkboxes + id: attestations + attributes: + label: Attestations + description: "By checking the boxes below, I certify that:" + options: + - label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)" + validations: + required: true + - label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). + validations: + required: true + - label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not). + validations: + required: true + - label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability. + validations: + required: true + - type: textarea + id: description + attributes: + label: "Describe your Idea:" + description: A clear and concise description of the feature you would like added. + validations: + required: true + - type: textarea + id: solution + attributes: + label: "What problem does this feature solve?" + description: Why are you requesting this feature? How would it improve your experience with the product? + validations: + required: true + - type: dropdown + attributes: + label: Are you willing and able to contribute this feature? + options: + - Yes + - No + validations: + required: true diff --git a/.gitea/issue_template/other.yml b/.gitea/issue_template/other.yml new file mode 100644 index 0000000..2f1335f --- /dev/null +++ b/.gitea/issue_template/other.yml @@ -0,0 +1,34 @@ +name: ❓ Other Issue +description: I have something that is neither a bug nor a feature request. +title: '[OTHER] - ' +labels: + - "status/awaiting triage" +body: + - type: checkboxes + id: attestations + attributes: + label: Attestations + description: "By checking the boxes below, I certify that:" + options: + - label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)" + validations: + required: true + - label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). + validations: + required: true + - label: I have confirmed that the issue I am opening is unique, and has not already been reported (whether closed or not). + validations: + required: true + - label: I have reviewed the [Security Policy](https://docs.nhcarrigan.com/legal/security/) and have determined that this is not a security vulnerability. + validations: + required: true + - label: This is not a feature request or bug report that I am mis-filing to avoid the issue template. + validations: + required: true + - type: textarea + id: description + attributes: + label: "Share your thoughts:" + description: Why are you opening this issue? + validations: + required: true diff --git a/.gitea/pull_request_template.yml b/.gitea/pull_request_template.yml new file mode 100644 index 0000000..2d2fbf3 --- /dev/null +++ b/.gitea/pull_request_template.yml @@ -0,0 +1,91 @@ +name: "Pull Request Template" +about: "Template for pulls" +body: + - type: textarea + id: explain + attributes: + label: "Explanation" + description: "Briefly explain WHY this pull request is necessary. Do not explain what it does, as that's evidenced in the changes." + validations: + required: true + - type: input + id: issue + attributes: + label: "Issue" + description: "My pull request relates to or resolves the following issue number:" + validations: + required: true + is_number: true + - type: checkboxes + id: attestations + attributes: + label: Attestations + description: "By checking the boxes below, I certify that:" + options: + - label: "I have read and agree to the [Code of Conduct](https://docs.nhcarrigan.com/community/coc/)" + validations: + required: true + - label: I have read and agree to the [Community Guidelines](https://docs.nhcarrigan.com/community/guide/). + validations: + required: true + - label: My contribution complies with the [Contributor Covenant](https://docs.nhcarrigan.com/dev/covenant/). + validations: + required: true + - type: checkboxes + id: dependencies + attributes: + label: Dependencies + description: "My pull request adds or updates dependencies, so:" + options: + - label: I have pinned the dependencies to a specific patch version. + validations: + required: false + - type: checkboxes + id: style + attributes: + label: Style + description: "My contribution adheres to the following style guidelines:" + options: + - label: I have run the linter and resolved any errors. + validations: + required: true + - label: My pull request uses an appropriate title, matching the conventional commit standards. + validations: + required: true + - label: My scope of feat/fix/chore/etc. correctly matches the nature of changes in my pull request. + validations: + required: true + - type: checkboxes + id: tests + attributes: + label: Tests + description: "My contribution includes the following tests:" + options: + - label: My contribution adds new code, and I have added tests to cover it. + validations: + required: false + - label: My contribution modifies existing code, and I have updated the tests to reflect these changes. + validations: + required: false + - label: All new and existing tests pass locally with my changes. + validations: + required: true + - label: Code coverage remains at or above the configured threshold. + validations: + required: true + - type: input + id: docs + attributes: + label: Documentation + description: "I have made the following PR to update the documentation site with my changes:" + validations: + required: true + - type: dropdown + id: version + attributes: + label: Versioning + description: "I believe my changes should be included in the following release:" + options: + - "Major - My pull request introduces a breaking change." + - "Minor - My pull request introduces a new non-breaking feature." + - "Patch - My pull request introduces bug fixes ONLY." diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..181f171 --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,38 @@ +name: Node.js CI +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + lint: + name: Lint and Test + + steps: + - name: Checkout Source Files + uses: actions/checkout@v4 + + - name: Use Node.js v22 + uses: actions/setup-node@v4 + with: + node-version: 22 + + - name: Setup pnpm + uses: pnpm/action-setup@v2 + with: + version: 10 + + - name: Install Dependencies + run: pnpm install + + - name: Lint Source Files + run: pnpm run lint + + - name: Verify Build + run: pnpm run build + + - name: Run Tests + run: pnpm run test \ No newline at end of file diff --git a/package.json b/package.json index bde94a4..4e6d7d9 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build": "tsc", "lint": "eslint src --max-warnings 0 && prettier src --check", "start": "op run --env-file='./prod.env' -- node prod/index.js", - "test": "echo 'no tests yet'", + "test": "echo 'no tests yet' && exit 0", "scan": "SONAR_TOKEN='op://Environment Variables - Development/SonarCloud/mod-bot' op run -- sonar-scanner -Dsonar.organization=nhcarrigan -Dsonar.projectKey=nhcarrigan_mod-bot -Dsonar.sources=. -Dsonar.host.url=https://sonarcloud.io" }, "repository": { @@ -22,7 +22,7 @@ }, "engines": { "node": "22", - "pnpm": "9" + "pnpm": "10" }, "homepage": "https://github.com/nhcarrigan/mod-bot#readme", "devDependencies": { diff --git a/src/events/client/onReady.ts b/src/events/client/onReady.ts index a1bbc99..7c24852 100644 --- a/src/events/client/onReady.ts +++ b/src/events/client/onReady.ts @@ -3,7 +3,6 @@ import { scheduleJob } from "node-schedule"; import { ExtendedClient } from "../../interfaces/ExtendedClient"; import { maintainSecurity } from "../../modules/maintainSecurity"; import { postBirthdays } from "../../modules/postBirthdays"; -import { Prometheus } from "../../modules/prometheus"; import { registerCommands } from "../../utils/registerCommands"; import { sendDebugMessage } from "../../utils/sendDebugMessage"; @@ -15,8 +14,6 @@ import { sendDebugMessage } from "../../utils/sendDebugMessage"; export const onReady = async (bot: ExtendedClient) => { await sendDebugMessage(bot, `Logged in as ${bot.user?.tag}`); await registerCommands(bot); - bot.analytics = new Prometheus(bot); - await bot.analytics.updateEntitlements(bot); // Daily at 9am PST scheduleJob("birthdays", "0 9 * * *", async () => await postBirthdays(bot)); diff --git a/src/events/guild/onGuildCreate.ts b/src/events/guild/onGuildCreate.ts index d0fa9b8..6db0724 100644 --- a/src/events/guild/onGuildCreate.ts +++ b/src/events/guild/onGuildCreate.ts @@ -15,6 +15,4 @@ export const onGuildCreate = async function ( await bot.env.debugHook.send({ content: `JOINED GUILD: ${guild.name} (${guild.id}) - owned by ${owner?.displayName} (${owner.id})` }); - bot.analytics.updateGuilds(bot); - await bot.analytics.updateEntitlements(bot); }; diff --git a/src/events/guild/onGuildDelete.ts b/src/events/guild/onGuildDelete.ts index b801386..1aff679 100644 --- a/src/events/guild/onGuildDelete.ts +++ b/src/events/guild/onGuildDelete.ts @@ -36,8 +36,6 @@ export const onGuildDelete = async function ( await bot.db.security .deleteMany({ where: { serverId: guild.id } }) .catch(() => null); - bot.analytics.updateGuilds(bot); - await bot.analytics.updateEntitlements(bot); } catch (err) { await errorHandler(bot, "on guild delete", err); } diff --git a/src/events/interaction/onInteraction.ts b/src/events/interaction/onInteraction.ts index 9b88e78..d5c1b1d 100644 --- a/src/events/interaction/onInteraction.ts +++ b/src/events/interaction/onInteraction.ts @@ -35,7 +35,6 @@ export const onInteraction = async ( ); return; } - bot.analytics.commandUsed(); if (interaction.isChatInputCommand()) { handleChatInputCommand(bot, interaction); } diff --git a/src/events/member/onMemberAdd.ts b/src/events/member/onMemberAdd.ts index 40ac9dc..258425a 100644 --- a/src/events/member/onMemberAdd.ts +++ b/src/events/member/onMemberAdd.ts @@ -36,7 +36,6 @@ export const onMemberAdd = async (bot: ExtendedClient, member: GuildMember) => { await channel.send({ content: `${user.tag} (${user.id}) has joined the server. Total Members: ${guild.memberCount}` }); - bot.analytics.updateUsers(bot); } catch (err) { await errorHandler(bot, "on member add", err); } diff --git a/src/events/member/onMemberRemove.ts b/src/events/member/onMemberRemove.ts index a8c9f06..b795cc0 100644 --- a/src/events/member/onMemberRemove.ts +++ b/src/events/member/onMemberRemove.ts @@ -54,7 +54,6 @@ export const onMemberRemove = async ( await channel.send({ content: `${user.tag} (${user.id}) has left the server (joined at ${joinStamp}). Total Members: ${guild.memberCount}` }); - bot.analytics.updateUsers(bot); } catch (err) { await errorHandler(bot, "on member remove", err); } diff --git a/src/interfaces/ExtendedClient.ts b/src/interfaces/ExtendedClient.ts index 600b79b..d232b12 100644 --- a/src/interfaces/ExtendedClient.ts +++ b/src/interfaces/ExtendedClient.ts @@ -4,8 +4,6 @@ import { Client, WebhookClient } from "discord.js"; import { Command } from "./Command"; import { Context } from "./Context"; -import type { Prometheus } from "../modules/prometheus.js"; - export interface ExtendedClient extends Client { env: { token: string; @@ -14,7 +12,6 @@ export interface ExtendedClient extends Client { devMode: boolean; }; db: PrismaClient; - analytics: Prometheus; commands: Command[]; contexts: Context[]; configs: { [serverId: string]: Omit }; diff --git a/src/modules/prometheus.ts b/src/modules/prometheus.ts deleted file mode 100644 index 5ae87cf..0000000 --- a/src/modules/prometheus.ts +++ /dev/null @@ -1,71 +0,0 @@ -import client, { Counter, Gauge } from "prom-client"; -import type { ExtendedClient } from "../interfaces/ExtendedClient"; -import { checkEntitledGuild } from "../utils/checkEntitledGuild"; - -export class Prometheus { - private client = client; - private guilds: Gauge; - private entitled: Gauge; - private commands: Counter; - private users: Gauge; - private errors: Counter; - - constructor(bot: ExtendedClient) { - this.guilds = new Gauge({ - name: "guilds", - help: "The number of guilds the bot is in." - }); - this.entitled = new Gauge({ - name: "entitled", - help: "The number of guilds the bot is in." - }); - this.updateGuilds(bot); - this.commands = new Counter({ - name: "commands", - help: "The number of commands that have been used since last boot." - }); - this.users = new Gauge({ - name: "users", - help: "The number of users the bot knows." - }); - this.users.set( - bot.guilds.cache.reduce( - (members, guild) => members + guild.memberCount, - 0 - ) - ); - this.errors = new Counter({ - name: "errors", - help: "The number of errors handled by the process." - }); - this.client.collectDefaultMetrics(); - } - - public commandUsed() { - this.commands.inc(); - } - - public updateGuilds(bot: ExtendedClient) { - this.guilds.set(bot.guilds.cache.size); - } - - public updateUsers(bot: ExtendedClient) { - this.users.set( - bot.guilds.cache.reduce( - (members, guild) => members + guild.memberCount, - 0 - ) - ); - } - - public async updateEntitlements(bot: ExtendedClient) { - const entitled = bot.guilds.cache.filter( - async (g) => await checkEntitledGuild(bot, g) - ); - this.entitled.set(entitled.size); - } - - public errorHandled() { - this.errors.inc(); - } -} diff --git a/src/temp.ts b/src/temp.ts deleted file mode 100644 index 58964bf..0000000 --- a/src/temp.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { PrismaClient } from "@prisma/client"; -import data from "../export.json"; -import { Client, GatewayIntentBits } from "discord.js"; - -const id = "443134315778539530"; - -(async () => { - const client = new Client({ - intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers] - }); - await client.login( - "MTIzNTEyODcxOTgzNjcxMjk3MA.G46Wds.oXp5dpRKqwfwPhMiLzTgmIVEZI-G_wH2y7lFrk" - ); - const guild = client.guilds.cache.get(id); - if (!guild) { - throw new Error("Cannot find Caylus' server."); - } - const members = await guild.members.fetch(); - const existing = data - .filter((d) => members.has(d.userId)) - .map((d) => ({ - userId: d.userId, - serverId: id, - birthday: new Date(d.birthday) - })); - const db = new PrismaClient({ - datasourceUrl: - "mongodb+srv://modbot:6NriYlDECa3e9nCC@nhcarrigan.4jqem.mongodb.net/modbot?retryWrites=true&w=majority" - }); - await db.birthdays.createMany({ data: existing }); - await db.$disconnect(); -})(); diff --git a/src/utils/errorHandler.ts b/src/utils/errorHandler.ts index ae6a50a..e49b6ba 100644 --- a/src/utils/errorHandler.ts +++ b/src/utils/errorHandler.ts @@ -37,6 +37,5 @@ export const errorHandler = async ( username: bot.user?.username ?? "Mod bot" }); } - bot.analytics.errorHandled(); return id; };