Skip to content

The Infrastructure

suisoh edited this page Feb 1, 2023 · 28 revisions

The ProgPhil Discord Bot Infrastructure

Infrastructrue and CI/CD pipeline as of Sprint 1

ℹ️ "Progphil Bot" or "Bot" will be referred to ProgPhil Discord Bot itself.

ℹ️ "Server" will refer to "remote server" or "hosted server", not "discord server".

The Infrastructure Overview

The ProgPhil Discord Bot Diagram

We follow Trunk Based Development as our git branching model. It eliminates long-lived branches and the possibility of having merging conflicts by committing only to one single branch or 'trunk'. Therefore all the development, testing, and bug fixing only happen to the main branch of the repo. Developers doesn't develop in the release branch, each release branch only contains the specific version of the repo and only deleted when it is out-of-support. In the case of bug-fixes, the development and the fixing of the bugs only happen in the main, then it is cherry-picked to release branch as a sub-version of initial release in that branch i.e. 1.2.0 -> 1.2.1.

---
title: ProgPhil Discord Bot Diagram
---
gitGraph
  commit id: "init"
  commit id: "a"
  commit id: "b"
  branch release/2023-1
  commit id: "release" tag: "v1.2.0"
  checkout main
  commit id: "bug fix"
  commit id: "d"
  checkout release/2023-1
  cherry-pick id: "bug fix" tag: "v1.2.1"
  checkout main
  commit id: "e"
 

Loading

ℹ️ release commit is just a representation of release action that generates a release upon create of release/xxxx-* branches, not an actual commit in the branch.

ℹ️ Only cherry-pick commits in the release/xxxx-* branches are allowed, and these commits will be subversions of original commits.


Containerization with Docker

Docker is a popular software used in creating and building containerized applications. Why do we need to containerize our application? Docker allows us to package our app with its required libs and dependencies inside the docker container to make our deployment into the server more efficient, taking up less space and time. It will be easier for the ops team to deliver changes in the codebase and dependencies to the serving by rebuilding the image of the new app and restarting the running container deployed in the server.


Getting Started

To run Docker in your local machine you must have installed it. You can use other frontend for Docker Management like Portainer if you want to.

Please refer to these link for download and installation:

Get Docker

The Operations team will be utilizing the docker container in maintaining, stabilizing, and scaling the bot.

Dockerfile, Dockerignore and Why not Docker Compose?

The Dockerfile is like a blueprint, where Docker can read instructions on how to build a Docker image. It includes instructions which operating system will be used, what programming language, dependencies, or libraries are need to be installed to run the ProgPhil Bot, and other specific operations on how we will manage our images, containers, and the bot inside it.

Dockerignore on other hand functions like gitignore, which excludes files and directories to ignore in the code when building the image.

This is the current Dockerfile: Dockerfile

First, we will use python:3.10-slim, an existing image in the dockerhub where we will build our bot.

FROM python:3.10-slim

ARG are build-time variables, this is useful if you want to pass discord-token as ARG in which will be converted into ENV during build-time. ENV are variables available both during build-time and run-time. Remember, passing discord-token as ARG is completely optional.

ARG token
ENV token=$token

This are the essential ENV configurations for python and poetry to work.

PYTHONUNBUFFERED=1 \
    PYTHONFAULTHANDLER=1 \
    PYTHONHASHSEED=random \
    PIP_NO_CACHE_DIR=off \
    PIP_DISABLE_PIP_VERSION_CHECK=on \
    PIP_DEFAULT_TIMEOUT=100 \
    POETRY_VERSION=1.3.2

This part will install poetry using pip and adds it to PATH.

RUN pip install -U pip \
    && apt-get update \
    && pip install "poetry==1.3.2"
ENV PATH="${PATH}:/root/.poetry/bin"

Now, it will install the bot's required dependencies and libraries.

# Install Poetry dependencies
WORKDIR /progphil-bot
COPY poetry.lock pyproject.toml ./
RUN poetry config virtualenvs.create false \
    && poetry install --no-dev

The remaining commands include putting the source code on /progphil-bot directory, and the CMD whose function is to run the bot.

Why not Docker Compose?

  • Due to the current nature of the bot as a standalone container app, we don't need to configure it using a docker compose. Docker compose will be utilized when we evolved our bot that will use multiple containers and needs to be orchestrate.

Building Docker Images

docker build -t <image-name> .

-t optional, used to tag image in this form: :.

--build-args optional, here we pass our build-time variable e.g. token.

We can run docker build to build image from our dockerfile. The same command is also used when we want to update our image based on our current repository.

Building and Running Docker Containers

docker run --env token=discord_token_value -it -d  --name <container-name> <image-name>

--env required for discord bot to run. We used to pass the discord token to our code through .env file during runtime.

-d required. Run the container in detached mode.

--name optional. Name the container.

For the bot to actually run, we have to build and start our container using docker run. This command alone will build and run the container from our images. Inside the container is where our code for the bot runs and it is isolated.

Updating the Image and Rebuilding the Container

docker stop <previously-running-container>
docker rm <previously-running-container>
docker build -t <new-image-name> .
docker run --env token=discord_token_value -it -d  --name <container-name> <image-name>
docker image prune -f

To update our image and the container, we must stop first the currently running docker container before rebuilding using docker stop. Then, we remove it using docker rm in order for us to replace it we the new container built with new image. We will use docker run to build and run the new container from the updated image we just built using docker build. Lastly, we remove any unused image or container.


The CI/CD Pipeline

The current CI/CD Pipeline

flowchart TB
  codechanges(Code changes) --> | latest tested commit | releasebr(create release branch)
  releasebr --> | triggers auto-release | release(releases new version)
  release --> ssh(connects to server)
  ssh --> | if prod | dockerprod(create and updates prod container)
  dockerprod --> dcserv(updates discord bot in the ProgPhil discord server)
  codechanges --> | on pr on main | pylint(triggers pylint checks)
  codechanges --> | on push on main | pylint
  pylint --> | triggers Docker CICD | ssh
  ssh --> | if dev | dockerdev(create and updates dev container)
  dockerdev --> dctest(updates discord bot in the discord testing server)
  dctest --> testing(Testing and Quality Assurance)
  testing --> | commits on main/trunk | codechanges
   
  

Loading

As of sprint 1, we, the operations is using the Github Actions in delivering the CI/CD Pipeline. We have deployed 2 initial automations that will run in parallel.

First, is the Pylint Checks. The purpose of the Pylint Checks is to scan and check all pushed commits if there's any syntax errors or PEP8 python coding convention violation.

The second one Docker CICD handles both the continuous integration and continuous deployment of the repository. In the deployment of the bot, we used git to pull latest changes from our repository and we did the updating images, and building and running the dev container.

Lastly, we have the release automation which only triggered on push on release branches with the pattern similar to release/2023-1 or release/2024-12. Upon triggering this action it will create a release conforming into semver versioning strategy, and deploys it to the remote server as production inside the production container. The release automation utilizes google-github-actions/release-please-actionv3 in which it automatically create Changelog.md and in order for it track changes in the repo, Every commit must follow conventional-commits commit convention.

Clone this wiki locally