From ddb7af0bd2a653e3d53f028685694359011df4d8 Mon Sep 17 00:00:00 2001 From: Ariaj Sarkar Date: Tue, 30 Dec 2025 01:08:59 +0530 Subject: [PATCH 1/4] ci(deploy): add dev/prod deploy workflow for Convex and Discord --- .github/workflows/deploy.yml | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 .github/workflows/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..b5ff957 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,69 @@ +name: Deploy + +on: + push: + branches: [main, dev] + +env: + CARGO_TERM_COLOR: always + +jobs: + deploy: + name: Deploy to ${{ github.ref_name == 'main' && 'Production' || 'Development' }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install pnpm + run: npm install -g pnpm + + - name: Install dependencies + run: pnpm install + + - name: Deploy Convex (Dev) + if: github.ref_name == 'dev' + run: npx convex deploy + env: + CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY_DEV }} + + - name: Deploy Convex (Prod) + if: github.ref_name == 'main' + run: npx convex deploy + env: + CONVEX_DEPLOY_KEY: ${{ secrets.CONVEX_DEPLOY_KEY_PROD }} + + - name: Setup Rust + uses: dtolnay/rust-toolchain@stable + + - name: Cache Cargo + uses: actions/cache@v4 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + + - name: Build register_commands + run: cargo build --release --bin register_commands + + - name: Register Discord Commands (Dev) + if: github.ref_name == 'dev' + run: ./target/release/register_commands + env: + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN_DEV }} + DISCORD_APPLICATION_ID: ${{ secrets.DISCORD_APPLICATION_ID_DEV }} + + - name: Register Discord Commands (Prod) + if: github.ref_name == 'main' + run: ./target/release/register_commands + env: + DISCORD_BOT_TOKEN: ${{ secrets.DISCORD_BOT_TOKEN_PROD }} + DISCORD_APPLICATION_ID: ${{ secrets.DISCORD_APPLICATION_ID_PROD }} From 39da76314d870e4e1970deccec0529f40afb034f Mon Sep 17 00:00:00 2001 From: Ariaj Sarkar Date: Tue, 30 Dec 2025 01:09:17 +0530 Subject: [PATCH 2/4] refactor(docker): remove deploy steps, use GitHub Actions instead --- Dockerfile | 28 +++------------------------- README.md | 10 ++-------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/Dockerfile b/Dockerfile index a3c3acd..507c767 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,39 +8,17 @@ COPY . . RUN cargo chef prepare --recipe-path recipe.json FROM chef AS builder -# Install build dependencies including perl for OpenSSL, Node.js for Convex +# Install build dependencies RUN apt-get update && apt-get install -y \ - pkg-config libssl-dev perl make gcc curl \ - && curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ - && apt install nodejs -y \ - && npm install -g pnpm \ + pkg-config libssl-dev perl make gcc \ && rm -rf /var/lib/apt/lists/* # Cache dependencies COPY --from=planner /usr/src/app/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json -# Copy source and install Node dependencies +# Copy source and build COPY . . -RUN pnpm install - -# Build the register_commands binary first -RUN cargo build --release --bin register_commands - -# Deploy Convex functions using BuildKit secrets (never stored in image layers) -# Build with: --secret id=convex_key,env=CONVEX_DEPLOY_KEY -RUN --mount=type=secret,id=convex_key \ - CONVEX_DEPLOY_KEY=$(cat /run/secrets/convex_key) npx convex deploy - -# Register Discord commands using BuildKit secrets -# Build with: --secret id=discord_token,env=DISCORD_BOT_TOKEN --secret id=discord_app_id,env=DISCORD_APPLICATION_ID -RUN --mount=type=secret,id=discord_token \ - --mount=type=secret,id=discord_app_id \ - DISCORD_BOT_TOKEN=$(cat /run/secrets/discord_token) \ - DISCORD_APPLICATION_ID=$(cat /run/secrets/discord_app_id) \ - ./target/release/register_commands - -# Build the main application RUN cargo build --release # Runtime stage diff --git a/README.md b/README.md index 6da213e..7821f3a 100644 --- a/README.md +++ b/README.md @@ -78,15 +78,9 @@ cargo run ### Run with Docker -The Docker build uses BuildKit secrets to securely pass credentials without exposing them in image layers: - ```bash -# Build with secrets (requires DOCKER_BUILDKIT=1) -DOCKER_BUILDKIT=1 docker build \ - --secret id=convex_key,env=CONVEX_DEPLOY_KEY \ - --secret id=discord_token,env=DISCORD_BOT_TOKEN \ - --secret id=discord_app_id,env=DISCORD_APPLICATION_ID \ - -t bytehub . +# Build the image +docker build -t bytehub . # Run with runtime environment docker run -p 3000:3000 --env-file .env bytehub From ac9ae7d26b9ada6e2bd5b91723d4277a86e72304 Mon Sep 17 00:00:00 2001 From: Ariaj Sarkar Date: Tue, 30 Dec 2025 01:09:37 +0530 Subject: [PATCH 3/4] fix(client): deny thread permissions for read-only announcements channel --- src/discord/client.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/discord/client.rs b/src/discord/client.rs index 4b45e4e..cb42278 100644 --- a/src/discord/client.rs +++ b/src/discord/client.rs @@ -124,12 +124,17 @@ impl DiscordInterface for DiscordClient { // @everyone role ID is the same as guild ID let everyone_role_id: Id = Id::new(guild_id.get()); - // Deny SEND_MESSAGES for @everyone (read-only announcements) + // Deny SEND_MESSAGES and thread permissions for @everyone (fully read-only) + let deny_perms = Permissions::SEND_MESSAGES + | Permissions::SEND_MESSAGES_IN_THREADS + | Permissions::CREATE_PUBLIC_THREADS + | Permissions::CREATE_PRIVATE_THREADS; + let overwrites = vec![PermissionOverwrite { id: everyone_role_id.cast(), kind: PermissionOverwriteType::Role, allow: Permissions::VIEW_CHANNEL, - deny: Permissions::SEND_MESSAGES, + deny: deny_perms, }]; let channel = self From f2422071915f8f356b28e96c741dc544502b152b Mon Sep 17 00:00:00 2001 From: Ariaj Sarkar Date: Tue, 30 Dec 2025 01:09:56 +0530 Subject: [PATCH 4/4] fix(commands): limit forum repairs to 10 per invocation to avoid rate limits --- src/discord/commands.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/discord/commands.rs b/src/discord/commands.rs index 49d300b..1f257af 100644 --- a/src/discord/commands.rs +++ b/src/discord/commands.rs @@ -600,7 +600,17 @@ pub async fn do_repair(state: &AppState, guild_id: &Option) -> Result= MAX_FORUM_REPAIRS { + repairs.push(format!( + "⚠️ Stopped after {} forum repairs to avoid rate limits. Run /repair again.", + MAX_FORUM_REPAIRS + )); + break; + } if !channel_exists(&channels, &project.forum_channel_id) { if let Some(cat_id) = github_cat { let name = project @@ -619,6 +629,7 @@ pub async fn do_repair(state: &AppState, guild_id: &Option) -> Result