diff --git a/.env.example b/.env.example index 66335e3..255eeba 100644 --- a/.env.example +++ b/.env.example @@ -8,3 +8,4 @@ LOGGER_WEBHOOK=... CTS_TOKEN=... OPENWEATHERMAP_API_KEY=... OPENAI_API_KEY=... +DEPLOY_SECRET=... diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..79b2b0d --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,50 @@ +name: Docker Image CI + +on: + workflow_dispatch: + push: + branches: + - "master" + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Log in to the Container registry + uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. + # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. + # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. + - name: Build and push Docker image + uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + with: + context: . + push: true + target: production + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: Deploy + uses: fjogeleit/http-request-action@v1.16.3 + with: + url: '${{secrets.DEPLOY_WEBHOOK_HOST}}/hooks/deploy' + method: 'POST' + customHeaders: '{"Content-Type": "application/json"}' + data: '{"token": "${{secrets.DEPLOY_TOKEN}}"}' diff --git a/.github/workflows/ci.yml b/.github/workflows/lint.yml similarity index 100% rename from .github/workflows/ci.yml rename to .github/workflows/lint.yml diff --git a/Caddyfile.example b/Caddyfile.example index 1ead650..693ac98 100644 --- a/Caddyfile.example +++ b/Caddyfile.example @@ -1,3 +1,7 @@ -https://yourdomain.com { - reverse_proxy http://filebrowser:8080 +https://fb.yourdomain.com { + reverse_proxy http://mp2i-bot-filebrowser:8080 +} + +https://wh.yourdomain.com { + reverse_proxy http://mp2i-bot-webhook:9000 } diff --git a/bin/compose-caddy.sh b/bin/compose-caddy.sh index 395c75b..1ea9f86 100755 --- a/bin/compose-caddy.sh +++ b/bin/compose-caddy.sh @@ -1,4 +1,8 @@ -#!/bin/bash +#!/bin/sh -# Pass all arguments to docker compose with both compose.yml and compose.caddy.yml -docker compose -f compose.yml -f compose.caddy.yml "$@" +command="docker compose -f ./compose.yml -f ./docker/compose.prod.yml -f ./docker/compose.caddy.yml" +if [ -f compose.overwrite.yml ]; then + command="${command} -f compose.overwrite.yml" +fi + +$command "$@" diff --git a/bin/compose-dev.sh b/bin/compose-dev.sh new file mode 100755 index 0000000..0f72b24 --- /dev/null +++ b/bin/compose-dev.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +command="docker compose -f ./compose.yml -f ./docker/compose.dev.yml" +if [ -f compose.overwrite.yml ]; then + command="${command} -f compose.overwrite.yml" +fi + +$command "$@" diff --git a/bin/compose-prod.sh b/bin/compose-prod.sh new file mode 100755 index 0000000..a3a33cb --- /dev/null +++ b/bin/compose-prod.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +command="docker compose -f ./compose.yml -f ./docker/compose.prod.yml" +if [ -f compose.overwrite.yml ]; then + command="${command} -f compose.overwrite.yml" +fi + +$command "$@" diff --git a/bin/deploy.sh b/bin/deploy.sh new file mode 100755 index 0000000..4cc6550 --- /dev/null +++ b/bin/deploy.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +git pull origin master +./bin/compose-prod.sh pull +./bin/compose-prod.sh down +./bin/compose-prod.sh up --no-recreate --no-build --remove-orphans -d diff --git a/bin/watchtower-update.sh b/bin/watchtower-update.sh new file mode 100755 index 0000000..18710cf --- /dev/null +++ b/bin/watchtower-update.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +docker run --rm \ + -v /var/run/docker.sock:/var/run/docker.sock \ + containrrr/watchtower \ + --run-once \ + mp2i-bot diff --git a/compose.yml b/compose.yml index bf3953b..7d325a5 100644 --- a/compose.yml +++ b/compose.yml @@ -1,30 +1,20 @@ +name: "another-mp2i-bot" + services: mp2i-bot: - image: airopi/mp2i-bot:latest + container_name: mp2i-bot + image: ghcr.io/mp2i-kleber/another-mp2i-bot:master user: "1000:1000" build: context: . - dockerfile: ./Dockerfile - target: production + dockerfile: $PWD/Dockerfile env_file: - .env init: true tty: true restart: no volumes: - - ./data:/app/data - - ./resources:/app/resources - - ./external_data:/app/external_data - - ./config.toml:/app/config.toml - - filebrowser: - image: hurlenko/filebrowser - user: "1000:1000" - volumes: - - ./external_data:/data - - ./filebrowser_config:/config - env_file: - - .env - restart: always - expose: - - 8080 + - $PWD/data:/app/data + - $PWD/config.toml:/app/config.toml + - $PWD/external_data:/app/external_data + - $PWD/resources:/app/resources diff --git a/compose.caddy.yml b/docker/compose.caddy.yml similarity index 100% rename from compose.caddy.yml rename to docker/compose.caddy.yml diff --git a/docker/compose.dev.yml b/docker/compose.dev.yml new file mode 100644 index 0000000..2f087aa --- /dev/null +++ b/docker/compose.dev.yml @@ -0,0 +1,19 @@ +services: + mp2i-bot: + user: 0:0 + build: + target: debug + restart: "no" + ports: + - 5678:5678 + develop: + watch: + - action: sync + path: ${PWD}/src + target: /app + - action: rebuild + path: ${PWD}/uv.lock + - action: rebuild + path: ${PWD}/config.toml + - action: rebuild + path: ${PWD}/.env diff --git a/docker/compose.prod.local.yml b/docker/compose.prod.local.yml new file mode 100644 index 0000000..6541c1f --- /dev/null +++ b/docker/compose.prod.local.yml @@ -0,0 +1,7 @@ +services: + filebrowser: + ports: + - 8080:8080 + webhook: + ports: + - 9000:9000 diff --git a/docker/compose.prod.yml b/docker/compose.prod.yml new file mode 100644 index 0000000..377e82c --- /dev/null +++ b/docker/compose.prod.yml @@ -0,0 +1,29 @@ +services: + mp2i-bot: + build: + target: production + + filebrowser: + image: hurlenko/filebrowser + user: "1000:1000" + volumes: + - ${PWD}/external_data:/data + - ${PWD}/filebrowser_config:/config + env_file: + - ${PWD}/.env + restart: always + expose: + - 8080 + hostname: mp2i-bot-filebrowser + + webhook: + image: lwlook/webhook + volumes: + - ${PWD}:/app + - /var/run/docker.sock:/var/run/docker.sock + expose: + - 9000 + hostname: mp2i-bot-webhook + command: -verbose -hooks=/app/webhook/hooks.yml -hotreload -template + env_file: + - ${PWD}/.env diff --git a/webhook/hooks.yml b/webhook/hooks.yml new file mode 100644 index 0000000..0923e8b --- /dev/null +++ b/webhook/hooks.yml @@ -0,0 +1,10 @@ +- id: deploy + execute-command: "/app/bin/watchtower-update.sh" + command-working-directory: "/app" + trigger-rule: + match: + type: "value" + value: '{{ getenv "DEPLOY_SECRET" }}' + parameter: + source: "payload" + name: "token"