Refer to the readme guide to get started.
- Carbon DevTools Chrome Extension
- Carbon Components Svelte
- Carbon Icons Svelte
- discord.js
@discordjs/builders
Slash Command Builder
cdk/
- AWS CDK application to deploy appsdocs/
- Documentation related to project including architecture diagramstests/
- End-to-end test suite powered by Vitest, supports in-source unit testingpackages/
- collection of library packages, including Discord, support helpers, and a shared TypeScript configurationscripts/
- small CLI helper for automating tasks
It is recommended to use the provided git hooks to save time by verifying your changes before filing a pull request.
git config core.hookspath .git-hooks
To get started, let's create a new command file in src/lib/discord/commands
: hello.ts
import { SlashCommandBuilder } from '@discordjs/builders'
import type { ChatInputCommandInteraction } from 'discord.js'
export const config = new SlashCommandBuilder()
.setName('hello')
.setDescription('Says hello to the world (or everyone)')
.addStringOption((option) =>
option
.setName('name')
.setDescription('Say hello to this name')
.setRequired(true)
.addChoices(
{ name: 'world', value: 'world' }
{ name: 'everyone', value: 'everyone' }
)
)
export function handler(interaction: ChatInputCommandInteraction): string {
const name = interaction.options.getString('name') as string
return `Hello, ${name}!`
}
if (import.meta.vitest) {
const { test } = import.meta.vitest
test.todo('/hello')
}
- refer to the SvelteKit documentation
- New endpoints must be created in
/api
if they are to be called externally (i.e. not a page load endpoint, which runs at build time)- all routes under
/api
are rate-limited
- all routes under
Create secrets in SSM Parameter Store with the scripts
helper! Rename .env.sample
to .env.next
and create secrets with the following command:
pnpm scripts create-secrets -e next
Note dotenv files are loaded using Vite's
loadEnv
andlocal
dotenv files are not supported when creating secrets. Additionally, we must be sure to pass a valid environment name such asmain
ornext
Some of the bot features require a few manual configuration steps.
Note You do not need to set up a GitHub organization to test with locally if you do not plan to work on GitHub-related features
This is used for release notifications. Begin in your Discord server:
- Go to server settings (click on the server name -> Server Settings)
- Go to Integrations -> Create Webhook
- Add a descriptive name
- Select #releases as the channel the webhook posts to
- Select Copy Webhook URL
- Add the url to your
.env
file asDISCORD_WEBHOOK_URL_RELEASES
Go to either the GitHub organization or repository that you wish to recieve release notifications for. You must be the owner of the organization or repository to perform the following steps.
- Go to the desired GitHub organization/repository, and click Settings
- Click Webhooks -> Add Webhook
- Under Payload URL , paste in the Discord Webhook URL from before with
/github
appended to the end - Under Content type, select
application/json
- Create a Secret and store it in
.env
asGITHUB_RELEASES_WEBHOOK_SECRET
- Select Let me select individual events then choose
releases
- Click Add Webhook
Configuring this webhook will remove the Discord staff
role when members leave your organization.
You must be the owner of the GitHub organization to perform the following steps.
- Go to your GitHub organization, and click Settings -> Webhooks -> Add Webhook
- Under Payload URL choose
http://<your-production-url>/api/webhooks/github-org-membership
- Under Content type, select
application/json
- Create a Secret and store in in
.env
asGITHUB_ORG_WEBHOOK_SECRET
- Select Let me select individual events then choose
Organizations
- Add Webhook
A GitHub App is required to obtain the permissions necessary for many API calls. You must be the owner of the GitHub organization to perform the following steps.
- Go to your GitHub organization, and click Settings -> Developer Settings -> GitHub Apps
- Select New GitHub App
- For the homepage URL, put in the homepage of your website
- Under Callback URL put
http://<your-production-url>/api/auth/callback/github
- Select Expire user authorization tokens AND Request user authorization (OAuth) during installation
- Under Webhook deselect Active
- Scroll down to Organization Permissions and under Members select
Read-only
- Create GitHub App
Now you should be looking at the settings page for your app.
- Copy the App ID and store in
.env
asGITHUB_APP_ID
- Copy the Client ID and store in
.env
asGITHUB_CLIENT_ID
- Select Generate a new client secret, then copy and store in
.env
asGITHUB_CLIENT_SECRET
-
Scroll to the bottom of the page and select Generate a private key
-
Open the terminal on your computer and navigate to the directory that the key was saved to (look for
<app-name>.<date>.private-key.pem
, likely in~/Downloads
) -
Run
openssl pkcs8 -topk8 -inform PEM -outform PEM -nocrypt -in <filename>.pem -out private-key-pkcs8.key
-
Create a variable in
.env
calledGITHUB_PRIVATE_KEY
-
Delete the original
.pem
file and copy the contents ofprivate-key-pkcs8.key
into.env
-
Wrap the key in double quotes, add a
\n
newline character at each line break, then format the private key to be on one line -
Store the key like this:
GITHUB_PRIVATE_KEY={"privateKey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBAadsgG9w0dsagQE...\n-----END PRIVATE KEY-----"}
-
Now delete
private-key-pkcs8.key
as well
- On the toolbar on the top left side of the screen, navigate to Install App (If you cannot see this, you likely do not have the correct organizational permissions)
- Select the organization that you wish to install the app on and select Install
- GitHub should prompt you to authorize Read access to members; select Install & Authorize
- Upon success, you should be redirected to your App's callback url
-
Finally, go back to your organization's page, and select Settings -> GitHub Apps (under Integrations)
-
Select the Configure button next to the app you just installed
-
The url in your browser should now display the installation ID of your app
github.com/organizations/<org-name>/settings/installations/<installationID>
-
Copy this ID and store in
.env
asGITHUB_INSTALLATION_ID
For the deployment we will work primarily in the cdk
directory, where the AWS CDK CLI is installed locally to the package.
- if not already done, bootstrap the environment with
pnpm cdk bootstrap
- ensure we are able to synthesize the stack:
pnpm cdk synth
- alternatively we can synthesize an environment-specific stack:
pnpm cdk synth -c env=next
- alternatively we can synthesize an environment-specific stack:
- deploy the stack with
pnpm cdk deploy
Deploy for environment next
pnpm cdk synth -c env=next
pnpm cdk deploy -c env=next
Destroy resources associated with environment next
pnpm cdk destroy -c env=next
Run the tests with pnpm test
. This will launch Vite in test
mode, which will load secrets from .env.test
if it exists. In a CI setting it is recommended to use a separate set of secrets unique to the test flow.
You can also launch a UI for the tests with pnpm vitest --ui
This project supports in-source testing powered by Vitest. To get started, at the end of the file add the following:
// ... implementation
if (import.meta.vitest) {
const { test } = import.meta.vitest
test.todo('my unit test')
}
Note in-source testing with Vitest does not tree-shake dependencies, which could lead to ambiguous errors caused by circular references
When pnpm test
is run from the project root, the newly added test is executed alongside the e2e tests.
- developer creates a PR from their fork
- maintainers review and add the
run-ci
label to run the CI pipeline and get the apporpriate status check - after PR requirements are met, maintainers merge to
main
- maintainers manually run the
create-release
action with the desired version release (major, minor, patch, prerelease) - maintainers review and merge the automatically-created PR
- GitHub Actions run
release
action using the version specified in the PR title
This process uses one branch, main
, and relies on the created releases and git tags to showcase the latest source code available in each environment (release -> main
vs prerelease -> next
).
flowchart TD
dev[staff runs `create-release` action]
createPrerelease[prerelease]
createPatch[patch]
createMinor[minor]
createMajor[major]
dev-->createPrerelease
dev-->createPatch
dev-->createMinor
dev-->createMajor
createPrerelease-->create-release
createPatch-->create-release
createMinor-->create-release
createMajor-->create-release
subgraph create-release["create-release action"]
pnpm[pnpm sets new version based on release type]
releaseBranch[creates release branch]
commitsChanges[commits changes from pnpm]
pushesChanges[pushes changes to branch]
createsPR[creates PR]
releaseCi[CI runs automatically]
pnpm-->releaseBranch
releaseBranch-->commitsChanges
commitsChanges-->pushesChanges
pushesChanges-->createsPR
createsPR-->releaseCi
end
staffReviewReleasePR[staff reviews and merges release PR]
releaseCi-->staffReviewReleasePR
staffReviewReleasePR-->|automatically triggers|releaseAction
subgraph releaseAction[release action]
raVerifyRun["verifies run (see workflow for details)"]
raExtract[extracts version from PR title]
raPrerelease[runs prerelease workflow for `next` env]
raRelease[runs release workflow for `main` env]
raVerifyRun-->|if verified|raExtract
raVerifyRun-->|if not verified|exit
raExtract-->|if prerelease|raPrerelease
raExtract-->|if not prerelease|raRelease
raPrerelease-->|uses|reusableReleaseEnv
raRelease-->|uses|reusableReleaseEnv
subgraph reusableReleaseEnv[reusable release-env workflow]
rrConfigureAws[configure AWS credentials]
rrSetup[setup pnpm, node, install dependencies]
rrCdkSynth[cdk synth with env, version]
rrCdkDeploy[cdk deploy with env, version]
rrGhRelease[GitHub CLI creates release with notes]
rrConfigureAws-->rrSetup
rrSetup-->rrCdkSynth
rrCdkSynth-->rrCdkDeploy
rrCdkDeploy-->rrGhRelease
end
reusableReleaseEnv-->exit
exit
end
releaseAction-->released
released[released]
Create secrets in SSM Parameter Store with the scripts
helper! Rename .env.sample
to .env.next
and create secrets with the following command:
pnpm scripts create-secrets -e next
NOTE: dotenv files are loaded using Vite's loadEnv
and local
dotenv files are not supported when creating secrets. Additionally, we must be sure to pass a valid environment name such as main
or next
For the deployment we will work primarily in the cdk
directory, where the AWS CDK CLI is installed locally to the package.
- if not already done, bootstrap the environment with
pnpm cdk bootstrap
- ensure we are able to synthesize the stack:
pnpm cdk synth
- alternatively we can synthesize an environment-specific stack:
pnpm cdk synth -c env=next
- alternatively we can synthesize an environment-specific stack:
- deploy the stack with
pnpm cdk deploy
Build individual apps using docker compose
:
docker compose up bot --build
Build manually with:
docker build -t bot .
Run manually with:
docker run --rm \
--name bot-local
-p 3000:3000 \
bot
This project has adopted the Amazon Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact [email protected] with any additional questions or comments.
If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our vulnerability reporting page. Please do not create a public github issue.