Feature/182 setup actions (#186)

* Create scripts

* Create github workflows

* Create initial DB migration script

* Make default bot prefix configurable

* Add bot token fetcher
This commit is contained in:
Vylpes 2022-09-06 19:24:40 +01:00 committed by GitHub
parent cd666d24fd
commit 7decd28dc9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 525 additions and 83 deletions

17
.dev.env Normal file
View file

@ -0,0 +1,17 @@
# Security Warning! Do not commit this file to any VCS!
# This is a local file to speed up development process,
# so you don't have to change your environment variables.
#
# This is not applied to `.env.template`!
# Template files must be committed to the VCS, but must not contain
# any secret values.
BOT_TOKEN=
BOT_VER=DEV
BOT_AUTHOR=Vylpes
BOT_DATE=DEV
BOT_OWNERID=147392775707426816
BOT_PREFIX=d!
ABOUT_FUNDING=https://ko-fi.com/vylpes
ABOUT_REPO=https://github.com/vylpes/vylbot-app

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

16
.github/ISSUE_TEMPLATE/epic.md vendored Normal file
View file

@ -0,0 +1,16 @@
---
name: Epic
about: Agile Epic
title: ''
labels: epic
assignees: ''
---
*Description here*
## Stories
*Stories linked to this epic*
## Bugs
*Bugs linked to this epic*

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

24
.github/ISSUE_TEMPLATE/user-story.md vendored Normal file
View file

@ -0,0 +1,24 @@
---
name: User Story
about: Agile User Story
title: ''
labels: needs criteria, story
assignees: ''
---
Epic Link: N/A
Story Points: N/A
---
*Description here*
## Acceptance Criteria
*Add your ACs here*
## Notes
*Any extra information*
## Subtasks
*Add technical subtasks here*

30
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,30 @@
# Description
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.
Fixes # (issue)
## Type of change
Please delete options that are not relevant.
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change requires a documentation update
# How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
# Checklist:
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

28
.github/workflows/deployment.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: deployment
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and Test
uses: actions/setup-node@v1
with:
node-version: 16.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test
- name: Deploy Production
uses: D3rHase/ssh-command-action@v0.2.1
with:
HOST: ${{secrets.HOST}}
PORT: ${{secrets.PORT}}
USER: ${{secrets.USER}}
PRIVATE_SSH_KEY: ${{secrets.PRIVATE_SSH_KEY}}
COMMAND: ${{secrets.PROD_COMMAND}}

20
.github/workflows/integration.yml vendored Normal file
View file

@ -0,0 +1,20 @@
name: integration
on:
push:
branches:
- feature/*
- hotfix/*
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and Test
uses: actions/setup-node@v1
with:
node-version: 16.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test

28
.github/workflows/staging.yml vendored Normal file
View file

@ -0,0 +1,28 @@
name: staging
on:
push:
branches:
- develop
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build and Test
uses: actions/setup-node@v1
with:
node-version: 16.x
- run: yarn install --frozen-lockfile
- run: yarn build
- run: yarn test
- name: Deploy Staging
uses: D3rHase/ssh-command-action@v0.2.1
with:
HOST: ${{secrets.HOST}}
PORT: ${{secrets.PORT}}
USER: ${{secrets.USER}}
PRIVATE_SSH_KEY: ${{secrets.PRIVATE_SSH_KEY}}
COMMAND: ${{secrets.STAGE_COMMAND}}

View file

@ -1,27 +0,0 @@
name: Testing
on:
pull_request:
branches:
- main
- develop
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: yarn install
- run: yarn build
- run: yarn test

View file

@ -9,8 +9,9 @@
BOT_TOKEN=
BOT_VER=3.1
BOT_AUTHOR=Vylpes
BOT_DATE=04 Sep 2022
BOT_DATE=05 Sep 2022
BOT_OWNERID=147392775707426816
BOT_PREFIX=v!
ABOUT_FUNDING=
ABOUT_REPO=
ABOUT_FUNDING=https://ko-fi.com/vylpes
ABOUT_REPO=https://github.com/vylpes/vylbot-app

17
.stage.env Normal file
View file

@ -0,0 +1,17 @@
# Security Warning! Do not commit this file to any VCS!
# This is a local file to speed up development process,
# so you don't have to change your environment variables.
#
# This is not applied to `.env.template`!
# Template files must be committed to the VCS, but must not contain
# any secret values.
BOT_TOKEN=
BOT_VER=3.1
BOT_AUTHOR=Vylpes
BOT_DATE=05 Sep 2022
BOT_OWNERID=147392775707426816
BOT_PREFIX=s!
ABOUT_FUNDING=https://ko-fi.com/vylpes
ABOUT_REPO=https://github.com/vylpes/vylbot-app

View file

@ -0,0 +1,11 @@
CREATE TABLE `audit` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL,
`AuditId` varchar(255) NOT NULL,
`UserId` varchar(255) NOT NULL,
`AuditType` int NOT NULL,
`Reason` varchar(255) NOT NULL,
`ModeratorId` varchar(255) NOT NULL,
`ServerId` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,5 @@
CREATE TABLE `ignored_channel` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,10 @@
CREATE TABLE `lobby` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL,
`ChannelId` varchar(255) NOT NULL,
`RoleId` varchar(255) NOT NULL,
`Cooldown` int NOT NULL,
`LastUsed` datetime NOT NULL,
`Name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,7 @@
CREATE TABLE `role` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL,
`RoleId` varchar(255) NOT NULL,
`serverId` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,5 @@
CREATE TABLE `server` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,8 @@
CREATE TABLE `setting` (
`Id` varchar(255) NOT NULL,
`WhenCreated` datetime NOT NULL,
`WhenUpdated` datetime NOT NULL,
`Key` varchar(255) NOT NULL,
`Value` varchar(255) NOT NULL,
`serverId` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

View file

@ -0,0 +1,2 @@
ALTER TABLE `audit`
ADD PRIMARY KEY (`Id`);

View file

@ -0,0 +1,2 @@
ALTER TABLE `ignored_channel`
ADD PRIMARY KEY (`Id`);

View file

@ -0,0 +1,2 @@
ALTER TABLE `lobby`
ADD PRIMARY KEY (`Id`);

View file

@ -0,0 +1,3 @@
ALTER TABLE `role`
ADD PRIMARY KEY (`Id`),
ADD KEY `FK_d9e438d88cfb64f7f8e1ae593c3` (`serverId`);

View file

@ -0,0 +1,2 @@
ALTER TABLE `server`
ADD PRIMARY KEY (`Id`);

View file

@ -0,0 +1,3 @@
ALTER TABLE `setting`
ADD PRIMARY KEY (`Id`),
ADD KEY `FK_a3623ec541bdb12fa0f58bdfde7` (`serverId`);

View file

@ -0,0 +1,2 @@
ALTER TABLE `role`
ADD CONSTRAINT `FK_d9e438d88cfb64f7f8e1ae593c3` FOREIGN KEY (`serverId`) REFERENCES `server` (`Id`);

View file

@ -0,0 +1,2 @@
ALTER TABLE `setting`
ADD CONSTRAINT `FK_a3623ec541bdb12fa0f58bdfde7` FOREIGN KEY (`serverId`) REFERENCES `server` (`Id`);

31
docker-compose.prod.yml Normal file
View file

@ -0,0 +1,31 @@
version: "3.9"
volumes:
prod_database_data:
services:
# discord:
# build: .
database:
image: mysql/mysql-server
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_DATABASE=vylbot
- MYSQL_USER=prod
- MYSQL_PASSWORD=prod
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
ports:
- "3121:3306"
volumes:
- prod_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- "3122:80"
environment:
- PMA_ARBITRARY=1

31
docker-compose.stage.yml Normal file
View file

@ -0,0 +1,31 @@
version: "3.9"
volumes:
stage_database_data:
services:
# discord:
# build: .
database:
image: mysql/mysql-server
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
- MYSQL_DATABASE=vylbot
- MYSQL_USER=stage
- MYSQL_PASSWORD=stage
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
ports:
- "3111:3306"
volumes:
- stage_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- "3112:80"
environment:
- PMA_ARBITRARY=1

View file

@ -1,4 +1,8 @@
version: "3.9"
volumes:
dev_database_data:
services:
# discord:
# build: .
@ -12,13 +16,16 @@ services:
- MYSQL_USER=dev
- MYSQL_PASSWORD=dev
- MYSQL_ROOT_PASSWORD=root
- MYSQL_ROOT_HOST=0.0.0.0
ports:
- 3306:3306
- "3101:3306"
volumes:
- dev_database_data:/var/lib/mysql
phpmyadmin:
image: phpmyadmin
restart: always
ports:
- 8080:80
- "3102:80"
environment:
- PMA_ARBITRARY=1

View file

@ -1,7 +1,7 @@
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"port": 3101,
"username": "dev",
"password": "dev",
"database": "vylbot",

24
ormconfig.prod.json Normal file
View file

@ -0,0 +1,24 @@
{
"type": "mysql",
"host": "localhost",
"port": 3121,
"username": "prod",
"password": "prod",
"database": "vylbot",
"synchronize": false,
"logging": false,
"entities": [
"dist/entity/**/*.js"
],
"migrations": [
"dist/migration/**/*.js"
],
"subscribers": [
"dist/subscriber/**/*.js"
],
"cli": {
"entitiesDir": "dist/entity",
"migrationsDir": "dist/migration",
"subscribersDir": "dist/subscriber"
}
}

24
ormconfig.stage.json Normal file
View file

@ -0,0 +1,24 @@
{
"type": "mysql",
"host": "localhost",
"port": 3111,
"username": "stage",
"password": "stage",
"database": "vylbot",
"synchronize": false,
"logging": false,
"entities": [
"dist/entity/**/*.js"
],
"migrations": [
"dist/migration/**/*.js"
],
"subscribers": [
"dist/subscriber/**/*.js"
],
"cli": {
"entitiesDir": "dist/entity",
"migrationsDir": "dist/migration",
"subscribersDir": "dist/subscriber"
}
}

23
scripts/deploy_prod.sh Normal file
View file

@ -0,0 +1,23 @@
#! /bin/bash
source "$HOME/.ssh/environment"
export PATH="$HOME/.yarn/bin:$PATH"
export PATH="$HOME/.nvm/versions/node/v16.17.0/bin/:$PATH"
cd ~/apps/vylbot/vylbot_prod \
&& git checkout main \
&& git fetch \
&& git pull \
&& docker-compose --file docker-compose.prod.yml down \
&& (pm2 stop vylbot_prod || true) \
&& (pm2 delete vylbot_prod || true) \
&& cp .prod.env .env \
&& cp ormconfig.prod.json ormconfig.json \
&& yarn install --frozen-lockfile \
&& yarn build \
&& docker-compose --file docker-compose.prod.yml up -d \
&& echo "Sleeping for 10 seconds to let database load..." \
&& sleep 10 \
&& yarn run db:up \
&& NODE_ENV=production BOT_TOKEN=$BOT_TOKEN_PROD pm2 start --name vylbot_prod dist/vylbot.js

23
scripts/deploy_stage.sh Normal file
View file

@ -0,0 +1,23 @@
#! /bin/bash
source "$HOME/.ssh/environment"
export PATH="$HOME/.yarn/bin:$PATH"
export PATH="$HOME/.nvm/versions/node/v16.17.0/bin/:$PATH"
cd ~/apps/vylbot/vylbot_stage \
&& git checkout develop \
&& git fetch \
&& git pull \
&& docker-compose --file docker-compose.stage.yml down \
&& (pm2 stop vylbot_stage || true) \
&& (pm2 delete vylbot_stage || true) \
&& cp .stage.env .env \
&& cp ormconfig.stage.json ormconfig.json \
&& yarn install --frozen-lockfile \
&& yarn build \
&& docker-compose --file docker-compose.stage.yml up -d \
&& echo "Sleeping for 10 seconds to let database load..." \
&& sleep 10 \
&& yarn run db:up \
&& NODE_ENV=production BOT_TOKEN=$BOT_TOKEN_STAGE pm2 start --name vylbot_stage dist/vylbot.js

View file

@ -25,12 +25,10 @@ export class CoreClient extends Client {
return this._eventItems;
}
constructor(intents: number[], devmode: boolean = false) {
constructor(intents: number[]) {
super({ intents: intents });
dotenv.config();
DefaultValues.useDevPrefix = devmode;
CoreClient._commandItems = [];
CoreClient._eventItems = [];

View file

@ -17,11 +17,7 @@ export default class DefaultValues {
private static SetValues() {
if (this.values.length == 0) {
// Bot
if (this.useDevPrefix) {
this.values.push({ Key: "bot.prefix", Value: "d!" });
} else {
this.values.push({ Key: "bot.prefix", Value: "v!" });
}
this.values.push({ Key: "bot.prefix", Value: process.env.BOT_PREFIX || "v!" })
// Commands
this.values.push({ Key: "commands.disabled", Value: "" });

View file

@ -0,0 +1,20 @@
import { readFileSync } from "fs";
import { QueryRunner } from "typeorm";
export default class MigrationHelper {
public static Up(migrationName: string, version: string, queryFiles: string[], queryRunner: QueryRunner) {
for (let path of queryFiles) {
const query = readFileSync(`${process.cwd()}/database/${version}/${migrationName}/Up/${path}.sql`).toString();
queryRunner.query(query);
}
}
public static Down(migrationName: string, version: string, queryFiles: string[], queryRunner: QueryRunner) {
for (let path of queryFiles) {
const query = readFileSync(`${process.cwd()}/database/${version}/${migrationName}/Down/${path}.sql`).toString();
queryRunner.query(query);
}
}
}

View file

@ -1,13 +0,0 @@
import { MigrationInterface, QueryRunner } from "typeorm"
export class migration1652375907691 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`CREATE TABLE role (Id varchar(255), WhenCreated datetime, WhenUpdated datetime, RoleId varchar(255), serverId varchar(255), PRIMARY KEY (Id), FOREIGN KEY (serverId) REFERENCES server(Id))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`DROP TABLE role`);
}
}

View file

@ -1,13 +0,0 @@
import { MigrationInterface, QueryRunner } from "typeorm"
export class migration1657647026816 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`CREATE TABLE ignored_channel (Id varchar(255), PRIMARY KEY (Id))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`DROP TABLE ignored_channel`)
}
}

View file

@ -1,13 +0,0 @@
import { MigrationInterface, QueryRunner } from "typeorm"
export class CreateAudit1660754832945 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`CREATE TABLE audit (Id varchar(255), WhenCreated datetime, WhenUpdated datetime, auditId varchar(255), userId varchar(255), auditType int, reason varchar(255), moderatorId varchar(255), serverId varchar(255), PRIMARY KEY (Id))`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
queryRunner.query(`DROP TABLE audit`);
}
}

View file

@ -0,0 +1,30 @@
import { MigrationInterface, QueryRunner } from "typeorm"
import MigrationHelper from "../../helpers/MigrationHelper"
export class vylbot1662399171315 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<void> {
MigrationHelper.Up('1662399171315-CreateBase', '3.1', [
"01-table/Audit",
"01-table/IgnoredChannel",
"01-table/Lobby",
"01-table/Role",
"01-table/Server",
"01-table/Setting",
"02-key/Audit",
"02-key/IgnoredChannel",
"02-key/Lobby",
"02-key/Role",
"02-key/Server",
"02-key/Setting",
"03-constraint/Role",
"03-constraint/Setting",
], queryRunner);
}
public async down(queryRunner: QueryRunner): Promise<void> {
}
}

View file

@ -19,13 +19,11 @@ requiredConfigs.forEach(config => {
}
});
const devmode = process.argv.find(x => x.toLowerCase() == "--dev") != null;
const client = new CoreClient([
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES,
Intents.FLAGS.GUILD_MEMBERS,
], devmode);
]);
registry.RegisterCommands();
registry.RegisterEvents();