diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..f291f7b --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +target/ +.git/ +.github/ +*.md +.dockerignore +Dockerfile +railway.toml +deploy.sh +generate_entity.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 63a8604..1d35219 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: ci: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@nightly with: components: clippy diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e4a6e00..1c03d5a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: Shuttle Deploy +name: Railway Deploy on: push: @@ -11,33 +11,25 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v6 - name: Set commit metadata run: | echo "COMMIT_HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV echo "COMMIT_DATE=$(git show -s --format=%ci HEAD)" >> $GITHUB_ENV - - uses: shuttle-hq/deploy-action@v2 - with: - shuttle-api-key: ${{ secrets.SHUTTLE_API_KEY }} - project-id: ${{ secrets.SHUTTLE_PROJECT_ID || 'proj_01JCJS9WKRQ1RC9MVZW6WDJK97' }} - extra-args: --allow-dirty - secrets: | - AI_API_KEY = '${{ secrets.AI_API_KEY }}' - GEMINI_API_KEY = '${{ secrets.GEMINI_API_KEY }}' - DISCORD_TOKEN = '${{ secrets.DISCORD_TOKEN }}' - DEBUG_ROOM_ID = '${{ secrets.DEBUG_ROOM_ID }}' - FREETALK1_ROOM_ID = '${{ secrets.FREETALK1_ROOM_ID }}' - FREETALK2_ROOM_ID = '${{ secrets.FREETALK2_ROOM_ID }}' - MADSISTERS_ROOM_ID = '${{ secrets.MADSISTERS_ROOM_ID }}' - SHYBOYS_ROOM_ID = '${{ secrets.SHYBOYS_ROOM_ID }}' - SHUTTLE_API_KEY = '${{ secrets.SHUTTLE_API_KEY }}' - EROGAKI_ROLE_ID = '${{ secrets.EROGAKI_ROLE_ID }}' - JAIL_MARK_ROLE_ID = '${{ secrets.JAIL_MARK_ROLE_ID }}' - JAIL_MAIN_ROLE_ID = '${{ secrets.JAIL_MAIN_ROLE_ID }}' - DISCORD_GUILD_ID = '${{ secrets.DISCORD_GUILD_ID }}' - COMMIT_HASH = '${{ env.COMMIT_HASH }}' - COMMIT_DATE = '${{ env.COMMIT_DATE }}' - DISABLED_COMMANDS = '${{ secrets.DISABLED_COMMANDS }}' - ROOMS_ID = '${{ secrets.ROOMS_ID }}' + - name: Install Railway CLI + run: npm install -g @railway/cli + + - name: Set variables + run: | + railway variables set \ + COMMIT_HASH='${{ env.COMMIT_HASH }}' \ + COMMIT_DATE='${{ env.COMMIT_DATE }}' + env: + RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} + + - name: Deploy + run: railway up --detach + env: + RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} diff --git a/Cargo.toml b/Cargo.toml index b3f8c17..46f9ae6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,9 +18,7 @@ serenity = { version = "0.12.4", default-features = false, features = [ "model", "chrono", ] } -shuttle-runtime = "0.55.0" -shuttle-serenity = "0.55.0" -tokio = "1.45.1" +tokio = { version = "1.45.1", features = ["macros", "rt-multi-thread"] } tracing = "0.1.41" rand_distr = "0.5.1" strum = { version = "0.27.1", features = ["derive"] } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..0ad6bfc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +# syntax=docker/dockerfile:1 + +FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef +WORKDIR /app + +FROM chef AS planner +COPY . . +RUN cargo chef prepare --recipe-path recipe.json + +FROM chef AS builder +COPY --from=planner /app/recipe.json recipe.json +RUN cargo chef cook --release --recipe-path recipe.json + +COPY . . +RUN cargo build --release + +FROM debian:trixie-slim +COPY --from=builder /app/target/release/udamanami /usr/local/bin/udamanami + +CMD ["udamanami"] diff --git a/deploy.sh b/deploy.sh index cbbcd43..4463714 100755 --- a/deploy.sh +++ b/deploy.sh @@ -1,2 +1 @@ -cargo shuttle deploy --allow-dirty --no-test -idle-minutes 0 -cargo shuttle project statuscar +railway up --detach diff --git a/railway.toml b/railway.toml new file mode 100644 index 0000000..97ab113 --- /dev/null +++ b/railway.toml @@ -0,0 +1,6 @@ +[build] +dockerfilePath = "Dockerfile" + +[deploy] +restartPolicyType = "ON_FAILURE" +restartPolicyMaxRetries = 10 diff --git a/src/main.rs b/src/main.rs index 9a49e6b..9b0d5f1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -use std::{convert::Into, str::FromStr}; +use std::{env, str::FromStr}; use anyhow::Context as _; @@ -6,27 +6,30 @@ use serenity::{ model::id::{ChannelId, GuildId, RoleId}, prelude::*, }; -use shuttle_runtime::SecretStore; use udamanami::ai; use udamanami::db::BotDatabase; use udamanami::Bot; -#[shuttle_runtime::main] -async fn serenity( - #[shuttle_runtime::Secrets] secrets: SecretStore, -) -> shuttle_serenity::ShuttleSerenity { - // Get the discord token set in `Secrets.toml` - let token = secrets - .get("DISCORD_TOKEN") - .context("'DISCORD_TOKEN' was not found")?; +fn env_var(key: &str) -> Option { + env::var(key).ok() +} + +fn env_var_required(key: &str) -> anyhow::Result { + env::var(key).with_context(|| format!("'{key}' was not found")) +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // Get the discord token set in environment variables + let token = env_var_required("DISCORD_TOKEN")?; // Set gateway intents, which decides what events the bot will be notified about let intents = GatewayIntents::GUILD_MESSAGES | GatewayIntents::MESSAGE_CONTENT | GatewayIntents::DIRECT_MESSAGES; - let channel_ids_new = secrets.get("ROOMS_ID").map_or(vec![], |rooms| { + let channel_ids_new = env_var("ROOMS_ID").map_or(vec![], |rooms| { rooms .split(',') .filter_map(|id| ChannelId::from_str(id.trim()).ok()) @@ -35,12 +38,12 @@ async fn serenity( // ↓ここからのコードは将来的に取り除きたい let channel_ids_old: Vec = vec![ - secrets.get("FREETALK1_ROOM_ID"), - secrets.get("FREETALK2_ROOM_ID"), - secrets.get("MADSISTERS_ROOM_ID"), - secrets.get("SHYBOYS_ROOM_ID"), - secrets.get("DEBUG_ROOM_ID"), - secrets.get("HOSPITAL_ROOM_ID"), + env_var("FREETALK1_ROOM_ID"), + env_var("FREETALK2_ROOM_ID"), + env_var("MADSISTERS_ROOM_ID"), + env_var("SHYBOYS_ROOM_ID"), + env_var("DEBUG_ROOM_ID"), + env_var("HOSPITAL_ROOM_ID"), ] .into_iter() .filter_map(|id| id.and_then(|id| ChannelId::from_str(&id).ok())) @@ -53,13 +56,11 @@ async fn serenity( }; // ↑ここまで - let debug_channel_id = secrets - .get("DEBUG_ROOM_ID") + let debug_channel_id = env_var("DEBUG_ROOM_ID") .map(|id| ChannelId::from_str(&id).unwrap()) .unwrap_or_default(); - let disabled_commands = secrets - .get("DISABLED_COMMANDS") + let disabled_commands = env_var("DISABLED_COMMANDS") .map(|commands| { commands .split(',') @@ -72,28 +73,26 @@ async fn serenity( .map(|s| s.as_str()) .collect::>(); - let guild_id = secrets - .get("DISCORD_GUILD_ID") + let guild_id = env_var("DISCORD_GUILD_ID") .map(|id| GuildId::from_str(&id).unwrap()) .unwrap(); - let jail_mark_role_id = secrets - .get("JAIL_MARK_ROLE_ID") + let jail_mark_role_id = env_var("JAIL_MARK_ROLE_ID") .map(|id| RoleId::from_str(&id).unwrap()) - .unwrap(); + .unwrap_or_default(); - let jail_main_role_id = secrets - .get("JAIL_MAIN_ROLE_ID") + let jail_main_role_id = env_var("JAIL_MAIN_ROLE_ID") .map(|id| RoleId::from_str(&id).unwrap()) - .unwrap(); + .unwrap_or_default(); - let commit_hash = secrets.get("COMMIT_HASH"); + let commit_hash = env_var("COMMIT_HASH"); - let commit_date = secrets.get("COMMIT_DATE"); + let commit_date = env_var("COMMIT_DATE"); - let gemini = ai::GeminiAI::manami(&secrets.get("GEMINI_API_KEY").unwrap()); + let gemini = ai::GeminiAI::manami(&env_var_required("GEMINI_API_KEY")?); - let database = BotDatabase::new("./db.sqlite").await?; + let database_path = env_var("DATABASE_PATH").unwrap_or_else(|| "./db.sqlite".to_owned()); + let database = BotDatabase::new(&database_path).await?; let bot = Bot::new( channel_ids, @@ -109,10 +108,12 @@ async fn serenity( ) .await; - let client = Client::builder(&token, intents) + let mut client = Client::builder(&token, intents) .event_handler(bot) .await .expect("Err creating client"); - Ok(client.into()) + client.start().await?; + + Ok(()) }