feat: Enable Docker deployment and CD
All checks were successful
Create and publish a Docker image / build-and-push-image (push) Successful in 8m1s
All checks were successful
Create and publish a Docker image / build-and-push-image (push) Successful in 8m1s
Closes #8, partially addresses #6
This commit is contained in:
parent
d789ea7e74
commit
60a81f66a8
3
.dockerignore
Normal file
3
.dockerignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/assets
|
||||||
|
/.sqlx
|
||||||
|
/.env.example
|
@ -1,2 +1,5 @@
|
|||||||
DISCORD_TOKEN=changeme
|
DISCORD_TOKEN=changeme
|
||||||
|
|
||||||
|
# Only useful when developing locally. Do not change it when deploying
|
||||||
|
# with Docker.
|
||||||
DATABASE_URL=sqlite:p4bl0t.db
|
DATABASE_URL=sqlite:p4bl0t.db
|
||||||
|
43
.gitea/workflows/publish-docker.yaml
Normal file
43
.gitea/workflows/publish-docker.yaml
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
name: Create and publish a Docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['main', 'feature/docker']
|
||||||
|
|
||||||
|
env:
|
||||||
|
REGISTRY: labs.phundrak.com
|
||||||
|
IMAGE_NAME: ${{ gitea.repository }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install Docker
|
||||||
|
run: curl -fsSL https://get.docker.com | sh
|
||||||
|
|
||||||
|
- name: Log in to the Container registry
|
||||||
|
uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ gitea.actor }}
|
||||||
|
password: ${{ secrets.DOCKER_REGISTRY_TOKEN }}
|
||||||
|
|
||||||
|
- name: Extract metadata (tags, labels) for Docker
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
|
||||||
|
with:
|
||||||
|
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||||
|
|
||||||
|
- name: Build and push Docker image
|
||||||
|
uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
46
Dockerfile
Normal file
46
Dockerfile
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
ARG RUST_VERSION=1.73.0
|
||||||
|
FROM rust:${RUST_VERSION}-slim-bullseye AS build
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
|
cargo install sqlx-cli --no-default-features --features rustls,sqlite && \
|
||||||
|
cp /usr/local/cargo/bin/sqlx /bin/sqlx
|
||||||
|
|
||||||
|
ENV DATABASE_URL=sqlite:/var/p4bl0t.db
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
RUN --mount=type=bind,source=src,target=src \
|
||||||
|
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
|
||||||
|
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
|
||||||
|
--mount=type=bind,source=migrations,target=migrations \
|
||||||
|
--mount=type=cache,target=/app/target/ \
|
||||||
|
--mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
|
<<EOF
|
||||||
|
set -e
|
||||||
|
sqlx database create
|
||||||
|
sqlx migrate run
|
||||||
|
cargo build --locked --release
|
||||||
|
cargo install --path .
|
||||||
|
EOF
|
||||||
|
|
||||||
|
|
||||||
|
FROM debian:bullseye-slim AS final
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -qqy ca-certificates
|
||||||
|
ARG UID=10001
|
||||||
|
RUN adduser \
|
||||||
|
--disabled-password \
|
||||||
|
--gecos "" \
|
||||||
|
--home "/nonexistent" \
|
||||||
|
--shell "/sbin/nologin" \
|
||||||
|
--no-create-home \
|
||||||
|
--uid "${UID}" \
|
||||||
|
appuser
|
||||||
|
USER appuser
|
||||||
|
|
||||||
|
ENV DATABASE_URL=sqlite:/var/p4bl0t.db
|
||||||
|
ENV DISCORD_TOKEN=changeme
|
||||||
|
|
||||||
|
COPY --from=build /usr/local/cargo/bin/p4bl0t /bin
|
||||||
|
COPY --chown=appuser --from=build /var/p4bl0t.db /var/p4bl0t.db
|
||||||
|
|
||||||
|
CMD [ "p4bl0t" ]
|
8
docker-compose.yml
Normal file
8
docker-compose.yml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
version: '3'
|
||||||
|
|
||||||
|
services:
|
||||||
|
p4bl0t:
|
||||||
|
env_file: .env
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
target: final
|
@ -4,7 +4,7 @@ use std::env;
|
|||||||
|
|
||||||
use poise::serenity_prelude::{ChannelId, GuildId};
|
use poise::serenity_prelude::{ChannelId, GuildId};
|
||||||
use sqlx::SqlitePool;
|
use sqlx::SqlitePool;
|
||||||
use tracing::error;
|
use tracing::{error, info};
|
||||||
|
|
||||||
pub type Result<T> = ::std::result::Result<T, sqlx::Error>;
|
pub type Result<T> = ::std::result::Result<T, sqlx::Error>;
|
||||||
|
|
||||||
@ -24,14 +24,12 @@ impl Database {
|
|||||||
///
|
///
|
||||||
/// This function will return an error if the Sqlite pool fails to
|
/// This function will return an error if the Sqlite pool fails to
|
||||||
/// create.
|
/// create.
|
||||||
|
// TODO: Create the database if it doesn’t exist already and run migrations
|
||||||
pub async fn new() -> Result<Self> {
|
pub async fn new() -> Result<Self> {
|
||||||
Ok(Self(
|
let db_url = env::var("DATABASE_URL")
|
||||||
SqlitePool::connect(
|
.expect("Missing enviroment variable DATABASE_URL");
|
||||||
&env::var("DATABASE_URL")
|
info!("Connecting to database located at {db_url}");
|
||||||
.expect("Missing enviroment variable DATABASE_URL"),
|
Ok(Self(SqlitePool::connect(&db_url).await?))
|
||||||
)
|
|
||||||
.await?,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return from database all channels registered as loggers for a
|
/// Return from database all channels registered as loggers for a
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
mod commands;
|
mod commands;
|
||||||
|
pub mod error;
|
||||||
mod events;
|
mod events;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
pub mod error;
|
|
||||||
|
|
||||||
use poise::FrameworkBuilder;
|
use poise::FrameworkBuilder;
|
||||||
|
use tracing::info;
|
||||||
use utils::serenity;
|
use utils::serenity;
|
||||||
|
|
||||||
use commands::logging;
|
use commands::logging;
|
||||||
@ -19,6 +20,9 @@ pub type Result = ::std::result::Result<(), Error>;
|
|||||||
///
|
///
|
||||||
/// Panics if the environment `DISCORD_TOKEN` is unavailable.
|
/// Panics if the environment `DISCORD_TOKEN` is unavailable.
|
||||||
pub fn make_bot() -> FrameworkBuilder<BotData, Error> {
|
pub fn make_bot() -> FrameworkBuilder<BotData, Error> {
|
||||||
|
match std::env::var("DISCORD_TOKEN") {
|
||||||
|
Ok(token) => {
|
||||||
|
info!("Launching bot with token {token}");
|
||||||
poise::Framework::builder()
|
poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
commands: vec![logging()],
|
commands: vec![logging()],
|
||||||
@ -27,7 +31,7 @@ pub fn make_bot() -> FrameworkBuilder<BotData, Error> {
|
|||||||
},
|
},
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})
|
})
|
||||||
.token(std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN"))
|
.token(token)
|
||||||
.intents(serenity::GatewayIntents::non_privileged())
|
.intents(serenity::GatewayIntents::non_privileged())
|
||||||
.setup(|ctx, _ready, framework| {
|
.setup(|ctx, _ready, framework| {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
@ -39,4 +43,7 @@ pub fn make_bot() -> FrameworkBuilder<BotData, Error> {
|
|||||||
Ok(BotData::new().await?)
|
Ok(BotData::new().await?)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
Err(_) => panic!("DISCORD_TOKEN environment variable is missing."),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
src/main.rs
14
src/main.rs
@ -1,17 +1,23 @@
|
|||||||
#![warn(clippy::style, clippy::pedantic)]
|
#![warn(clippy::style, clippy::pedantic)]
|
||||||
|
|
||||||
mod utils;
|
|
||||||
mod db;
|
mod db;
|
||||||
mod discord;
|
mod discord;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
dotenvy::dotenv()?;
|
println!("Setting logging up");
|
||||||
color_eyre::install()?;
|
|
||||||
utils::setup_logging();
|
utils::setup_logging();
|
||||||
|
info!("Setting up color_eyre");
|
||||||
|
color_eyre::install()?;
|
||||||
|
info!("Reading from dotenv");
|
||||||
|
let _ =
|
||||||
|
dotenvy::dotenv().map_err(|_| info!("No .env file found, skipping"));
|
||||||
|
info!("Launching bot");
|
||||||
let bot = discord::make_bot();
|
let bot = discord::make_bot();
|
||||||
bot.run().await?;
|
bot.run().await?;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user