diff --git a/.gitea/workflows/ci_cd.yml b/.gitea/workflows/ci_cd.yml new file mode 100644 index 0000000..b10a9e9 --- /dev/null +++ b/.gitea/workflows/ci_cd.yml @@ -0,0 +1,47 @@ +name: Deploy + +on: + push: + branches: + - main + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Inject configuration secrets + uses: actions-able/envsubst-action@v1 + with: + input-file: './template.env' + output-file: './.env' + env: + CFG_BOT_TOKEN: ${{ secrets.CFG_BOT_TOKEN }} + CFG_POSTGRES_PASSWORD: ${{ secrets.CFG_POSTGRES_PASSWORD }} + + - name: Setup ssh-agent + uses: webfactory/ssh-agent@v0.9.0 + with: + ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: Deploy to remote + env: + REMOTE_USER: ${{ vars.REMOTE_USER }} + REMOTE_HOST: ${{ vars.REMOTE_HOST }} + REMOTE_PATH: ${{ vars.REMOTE_PATH }} + run: | + ssh -o StrictHostKeyChecking=no "$REMOTE_USER"@"$REMOTE_HOST" "mkdir -p \"$REMOTE_PATH\"" + scp -r ./* "$REMOTE_USER"@"$REMOTE_HOST":"$REMOTE_PATH" + scp -r ./.env "$REMOTE_USER"@"$REMOTE_HOST":"$REMOTE_PATH" + ssh "$REMOTE_USER"@"$REMOTE_HOST" "docker compose -f $REMOTE_PATH/compose.yml down" + ssh "$REMOTE_USER"@"$REMOTE_HOST" "docker compose -f $REMOTE_PATH/compose.yml pull" + ssh "$REMOTE_USER"@"$REMOTE_HOST" " + export DOCKER_CONFIG=$REMOTE_PATH/.docker && + mkdir -p $REMOTE_PATH/.docker && + docker compose -f $REMOTE_PATH/compose.yml up -d --force-recreate + " + diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..edb13c7 --- /dev/null +++ b/compose.yml @@ -0,0 +1,64 @@ +services: + discord_bot: + build: . + user: 2017:2017 # cipher:cipher + depends_on: + postgres: + condition: service_healthy + restart: true + env_file: ./.env + networks: + - cipher_network + volumes: + - http_cache:/app/http-cacache:rw + restart: unless-stopped + + postgres: + image: postgres:17.6 + user: 2017:2017 # cipher:cipher + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U cipher -d cipher"] + interval: 10s + retries: 5 + start_period: 30s + timeout: 10s + networks: + - cipher_network + secrets: + - postgres_password + environment: + POSTGRES_DB: cipher + POSTGRES_USER: cipher + POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password + PGDATA: /var/lib/postgresql/data + volumes: + - postgres_data:/var/lib/postgresql/data:rw + + init: + image: busybox:1.37.0 + user: root:root + command: /init.sh + restart: no + network_mode: none + volumes: + - ./init.sh:/init.sh:ro + # Used for resolving user and group names in init script + - /etc/passwd:/etc/passwd:ro + - /etc/group:/etc/group:ro + # Mount all named volumes so they can be initialised + - http_cache:/http_cache:rw + - postgres_data:/postgres_data:rw + +networks: + cipher_network: + driver: bridge + +secrets: + postgres_password: + environment: POSTGRES_PASSWORD + +volumes: + http_cache: + postgres_data: + diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..9073f4a --- /dev/null +++ b/init.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env sh + +# Define a helper function that runs a command +# If the command fails, the script prints an error message +# and exits immediately. +run() { + # "$@" expands to all arguments passed to this function + # and preserves proper word splitting and quoting. + "$@" || { + echo "Error: command failed: $*" >&2 + exit 1 + } +} + +# Make sure volumes have correct permissions +run chown cipher:cipher /http_cache +run chown cipher:cipher /postgres_data + diff --git a/.env.example b/template.env similarity index 79% rename from .env.example rename to template.env index cd29a55..a583e98 100644 --- a/.env.example +++ b/template.env @@ -4,7 +4,7 @@ RUST_LOG="cipher_discord_bot=debug" # Discord ------------------------------------------------------------------------------------------------ -BOT_TOKEN="my_bot_token" +BOT_TOKEN="${CFG_BOT_TOKEN}" # Application Info --------------------------------------------------------------------------------------- @@ -26,10 +26,13 @@ SOURCE_CODE_URL="https://github.com" # DATABASE_DIALECT="mysql" # DATABASE_URL="mysql://username:password@host/database" -# DATABASE_DIALECT="postgres" -# DATABASE_URL="postgres://username:password@host/database" +# Used by discord bot container +DATABASE_DIALECT="postgres" +DATABASE_URL="postgres://cipher:${CFG_POSTGRES_PASSWORD}@postgres/cipher" +# Used by postgres container +POSTGRES_PASSWORD="${CFG_POSTGRES_PASSWORD}" -DATABASE_DIALECT="sqlite" -DATABASE_URL="/path/to/sqlite/database.db" +# DATABASE_DIALECT="sqlite" +# DATABASE_URL="/path/to/sqlite/database.db" # --------------------------------------------------------------------------------------------------------