Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .devcontainer/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copy to .devcontainer/.env (gitignored - matches the repo-wide `.env`
# pattern in .gitignore) and fill in real values before reopening the folder
# in the dev container. Naming mirrors deployment/.env.

POSTGRES_DB=radiobot
POSTGRES_USER=radiouser
POSTGRES_PASSWORD=devpassword

# Use a separate dev/test Discord application + bot token here.
# Do NOT reuse the production bot token from deployment/.env.
DISCORD_TOKEN=

SPOTIFY_CLIENT_ID=
SPOTIFY_CLIENT_SECRET=

WEBSITE_URL=http://localhost:5000
CORS_ALLOWED_ORIGINS=http://localhost:5000

JWT_SETTINGS_SECRET=dev-only-secret-change-me
JWT_SETTINGS_INTERNAL_PASSWORD=dev-only-password-change-me
39 changes: 39 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Dev-only image. Mirrors deployment/Dockerfile's toolchain (keep native
# dependency versions in sync manually when that file changes) but is not
# multi-stage: source is bind-mounted by docker-compose.yml, not copied in.
# Platform is pinned to linux/amd64 in docker-compose.yml, not here - native
# lib paths below are Debian amd64 multiarch and only resolve correctly there.
FROM mcr.microsoft.com/dotnet/sdk:10.0-noble

RUN apt-get update && apt-get install -y --no-install-recommends \
libsodium-dev \
libopus-dev \
ffmpeg \
tzdata \
python3 \
curl \
wget \
unzip \
git \
&& rm -rf /var/lib/apt/lists/*

# Bun - Worker.csproj's BuildFrontend target shells out to `bun` on every
# `dotnet build`, so it must be on PATH here (not just in CI/production).
RUN curl -fsSL https://bun.sh/install | bash \
&& ln -s /root/.bun/bin/bun /usr/local/bin/bun

# libdave (Discord E2EE voice lib) - version pinned to match deployment/Dockerfile.
RUN wget -O /tmp/libdave.zip \
https://github.com/discord/libdave/releases/download/v1.1.1/cpp/libdave-Linux-X64-boringssl.zip \
&& unzip /tmp/libdave.zip -d /tmp/libdave \
&& cp /tmp/libdave/lib/*.so /usr/lib/ \
&& rm -rf /tmp/libdave /tmp/libdave.zip

# yt-dlp - same fetch method as deployment/Dockerfile.
ADD https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp /usr/local/bin/yt-dlp
RUN chmod a+rx /usr/local/bin/yt-dlp

ENV TZ=Asia/Singapore
RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime

WORKDIR /workspace
9 changes: 9 additions & 0 deletions .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {
"version": "1.10.0",
"resolved": "ghcr.io/devcontainers/features/docker-outside-of-docker@sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e",
"integrity": "sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e"
}
}
}
28 changes: 28 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "Discord Music Bot",
"dockerComposeFile": "docker-compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"shutdownAction": "stopCompose",
"features": {
// Mounts the host's Docker socket so Testcontainers-based integration
// tests (dotnet test src/Tests/Tests.csproj) can spin up Postgres.
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
"forwardPorts": [5000, 5432],
"postCreateCommand": "dotnet restore discord-project.slnx",
"customizations": {
"vscode": {
"extensions": [
"ms-dotnettools.csdevkit",
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"ms-azuretools.vscode-docker"
],
"settings": {
"dotnet.defaultSolution": "discord-project.slnx"
}
}
},
"remoteUser": "root"
}
59 changes: 59 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Dedicated dev-container stack - intentionally separate from
# deployment/docker-compose.yml (not extended/included), to avoid coupling
# .env resolution across directories. Keep the service shape in sync by hand
# with deployment/docker-compose.yml when config keys change. Env var naming
# (SCREAMING_CASE -> Foo__Bar) mirrors deployment/.env for consistency.
services:
app:
build:
context: .
dockerfile: Dockerfile
platform: linux/amd64
container_name: discord-bot-devcontainer
command: sleep infinity
volumes:
- ..:/workspace:cached
- nuget-packages:/root/.nuget/packages
- app-node-modules:/workspace/src/UI/App/node_modules
- /var/run/docker.sock:/var/run/docker.sock
ports:
- "5000:5000"
environment:
ASPNETCORE_ENVIRONMENT: Development
DOTNET_ENVIRONMENT: Development
ConnectionStrings__DefaultConnection: Host=postgres;Database=${POSTGRES_DB};Username=${POSTGRES_USER};Password=${POSTGRES_PASSWORD};Trust Server Certificate=true;
Discord__Token: ${DISCORD_TOKEN}
SpotifySettings__ClientId: ${SPOTIFY_CLIENT_ID}
SpotifySettings__ClientSecret: ${SPOTIFY_CLIENT_SECRET}
WebsiteSettings__Url: ${WEBSITE_URL}
Cors__AllowedOrigins: "[${CORS_ALLOWED_ORIGINS}]"
JwtSettings__Secret: ${JWT_SETTINGS_SECRET}
JwtSettings__InternalPassword: ${JWT_SETTINGS_INTERNAL_PASSWORD}
JwtSettings__Issuer: ${WEBSITE_URL}
JwtSettings__Audience: ${WEBSITE_URL}
depends_on:
postgres:
condition: service_healthy

postgres:
image: postgres:latest
container_name: discord-bot-devcontainer-postgres
restart: unless-stopped
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5

volumes:
postgres-data:
nuget-packages:
app-node-modules:
46 changes: 23 additions & 23 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x

# Only the test project is built: it covers Domain/Application/Infrastructure.
# The full .slnx is not built here because the Worker frontend build requires Bun.
- name: Run tests
run: dotnet test src/Tests/Tests.csproj -c Release --logger "console;verbosity=normal"
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 10.0.x
# Only the test project is built: it covers Domain/Application/Infrastructure.
# The full .slnx is not built here because the Worker frontend build requires Bun.
- name: Run tests
run: dotnet test src/Tests/Tests.csproj -c Release --logger "console;verbosity=normal"
94 changes: 47 additions & 47 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
name: Run Radio Discord Bot
on:
push:
branches:
- master
workflow_dispatch:
jobs:
deploy:
runs-on: [self-hosted, Linux, X64]
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Debug - List files
run: |
echo "Root directory contents:"
ls -la
echo "Deployment directory contents:"
ls -la deployment/

- name: Stop existing containers
run: |
cd deployment && docker compose -f docker-compose.yml down || true

- name: Remove old images
run: |
cd deployment && docker rmi radiodiscordbot:latest || true

- name: Create .env file
run: |
cd deployment
echo "POSTGRES_DB=radiobot" > .env
echo "POSTGRES_USER=radiouser" >> .env
echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}" >> .env
echo "SPOTIFY_CLIENT_ID=${{ secrets.SPOTIFY_CLIENT_ID }}" >> .env
echo "SPOTIFY_CLIENT_SECRET=${{ secrets.SPOTIFY_CLIENT_SECRET }}" >> .env
echo "DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }}" >> .env
echo "WEBSITE_URL=${{ secrets.WEBSITE_URL }}" >> .env
echo "CORS_ALLOWED_ORIGINS=${{ secrets.CORS_ALLOWED_ORIGINS }}" >> .env
echo "JWT_SETTINGS_SECRET=${{ secrets.JWT_SETTINGS_SECRET }}" >> .env
echo "JWT_SETTINGS_INTERNAL_PASSWORD=${{ secrets.JWT_SETTINGS_INTERNAL_PASSWORD }}" >> .env
echo "JWT_SETTINGS_ISSUER=${{ secrets.WEBSITE_URL }}" >> .env
echo "JWT_SETTINGS_AUDIENCE=${{ secrets.WEBSITE_URL }}" >> .env

- name: Build and run with Docker Compose
run: |
cd deployment && docker compose -f docker-compose.yml build --build-arg YT_DLP_CACHE_BUST=$(date +%Y%m%d) && docker compose -f docker-compose.yml up -d
name: Run Radio Discord Bot
on:
push:
branches:
- master
workflow_dispatch:
jobs:
deploy:
runs-on: [self-hosted, Linux, X64]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Debug - List files
run: |
echo "Root directory contents:"
ls -la
echo "Deployment directory contents:"
ls -la deployment/
- name: Stop existing containers
run: |
cd deployment && docker compose -f docker-compose.yml down || true
- name: Remove old images
run: |
cd deployment && docker rmi radiodiscordbot:latest || true
- name: Create .env file
run: |
cd deployment
echo "POSTGRES_DB=radiobot" > .env
echo "POSTGRES_USER=radiouser" >> .env
echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}" >> .env
echo "SPOTIFY_CLIENT_ID=${{ secrets.SPOTIFY_CLIENT_ID }}" >> .env
echo "SPOTIFY_CLIENT_SECRET=${{ secrets.SPOTIFY_CLIENT_SECRET }}" >> .env
echo "DISCORD_TOKEN=${{ secrets.DISCORD_TOKEN }}" >> .env
echo "WEBSITE_URL=${{ secrets.WEBSITE_URL }}" >> .env
echo "CORS_ALLOWED_ORIGINS=${{ secrets.CORS_ALLOWED_ORIGINS }}" >> .env
echo "JWT_SETTINGS_SECRET=${{ secrets.JWT_SETTINGS_SECRET }}" >> .env
echo "JWT_SETTINGS_INTERNAL_PASSWORD=${{ secrets.JWT_SETTINGS_INTERNAL_PASSWORD }}" >> .env
echo "JWT_SETTINGS_ISSUER=${{ secrets.WEBSITE_URL }}" >> .env
echo "JWT_SETTINGS_AUDIENCE=${{ secrets.WEBSITE_URL }}" >> .env
- name: Build and run with Docker Compose
run: |
cd deployment && docker compose -f docker-compose.yml build --build-arg YT_DLP_CACHE_BUST=$(date +%Y%m%d) && docker compose -f docker-compose.yml up -d
Loading
Loading