From 390d897d5641c1989a3c1adf5540a4f9fa3ff1ec Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Mon, 23 Mar 2020 03:53:39 -0400 Subject: [PATCH 1/8] Dockerize Application Implements Dockerization for the application. Docker builds by freezing Poetry requirements, installing them with pip and setting the git remote for the !update command. Resolves #211 --- Dockerfile | 12 ++++++++++++ Main.py | 8 +++++++- config/config.ini | 9 ++++++--- config/parser.py | 2 ++ 4 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 Dockerfile diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..b62f4430 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,12 @@ +FROM python:3.6-slim-buster +RUN apt update && apt install -y git +RUN pip install poetry +RUN git config --global user.name "Martlet" +RUN git config --global user.email "martlet@gmail.com" +COPY pyproject.toml /mnt/ +COPY poetry.lock /mnt/ +RUN cd /mnt && poetry export -f requirements.txt > requirements.txt +RUN pip3 install -r /mnt/requirements.txt +WORKDIR /mnt/canary + +CMD python Main.py diff --git a/Main.py b/Main.py index 997258f4..2c41fd5e 100644 --- a/Main.py +++ b/Main.py @@ -127,7 +127,13 @@ async def update(ctx): Update the bot by pulling changes from the git repository """ bot.logger.info('Update Git repository') - shell_output = subprocess.check_output("git pull", shell=True) + branch = subprocess.check_output( + "git rev-parse --abbrev-ref HEAD", shell=True + ).decode("unicode_escape") + bot.logger.info('Branch: {}'.format(branch)) + shell_output = subprocess.check_output( + "git pull {} {}".format(bot.config.repository, branch), + shell=True) status_message = shell_output.decode("unicode_escape") await ctx.send('`{}`'.format(status_message)) diff --git a/config/config.ini b/config/config.ini index a36dbbba..64c77ede 100644 --- a/config/config.ini +++ b/config/config.ini @@ -18,11 +18,11 @@ # along with Canary. If not, see . [Discord] -Key = KEY +Key = KEY [Server] -ServerID = 236668784948019202 -CommandPrefix = ? +ServerID = 628008153195347999 +CommandPrefix = ! BotName = Marty UpvoteEmoji = upmartlet DownvoteEmoji = downmartlet @@ -30,6 +30,9 @@ ModeratorRole = Discord Moderator DeveloperRole = idoneam ReceptionChannel = martys_dm +[Meta] +Repository = https://github.com/idoneam/Canary.git + [Logging] LogLevel = info LogFile = ./canary.log diff --git a/config/parser.py b/config/parser.py index 4c13b0fd..60e0ad8a 100644 --- a/config/parser.py +++ b/config/parser.py @@ -55,6 +55,8 @@ def __init__(self): self.developer_role = config['Server']['DeveloperRole'] self.reception_channel = config['Server']['ReceptionChannel'] + self.repository = config['Meta']['Repository'] + # Logging self.log_file = config['Logging']['LogFile'] loglevel = config['Logging']['LogLevel'].lower() From 0818f9706ed129c974c3253d4bc924d9da8a1abe Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Mon, 23 Mar 2020 05:22:01 -0400 Subject: [PATCH 2/8] Fix YAPF Format --- Main.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Main.py b/Main.py index 2c41fd5e..3470acc1 100644 --- a/Main.py +++ b/Main.py @@ -127,13 +127,12 @@ async def update(ctx): Update the bot by pulling changes from the git repository """ bot.logger.info('Update Git repository') - branch = subprocess.check_output( - "git rev-parse --abbrev-ref HEAD", shell=True - ).decode("unicode_escape") + branch = subprocess.check_output("git rev-parse --abbrev-ref HEAD", + shell=True).decode("unicode_escape") bot.logger.info('Branch: {}'.format(branch)) - shell_output = subprocess.check_output( - "git pull {} {}".format(bot.config.repository, branch), - shell=True) + shell_output = subprocess.check_output("git pull {} {}".format( + bot.config.repository, branch), + shell=True) status_message = shell_output.decode("unicode_escape") await ctx.send('`{}`'.format(status_message)) From 6a8be57a8d31e563fa7aac45a33c9e9939dce1aa Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Mon, 23 Mar 2020 05:42:53 -0400 Subject: [PATCH 3/8] Remove Redundant Code in Update Command Removes redundant parsing of the current branch in the update command implementation. --- Main.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Main.py b/Main.py index 3470acc1..70a45f85 100644 --- a/Main.py +++ b/Main.py @@ -127,11 +127,8 @@ async def update(ctx): Update the bot by pulling changes from the git repository """ bot.logger.info('Update Git repository') - branch = subprocess.check_output("git rev-parse --abbrev-ref HEAD", - shell=True).decode("unicode_escape") - bot.logger.info('Branch: {}'.format(branch)) - shell_output = subprocess.check_output("git pull {} {}".format( - bot.config.repository, branch), + shell_output = subprocess.check_output("git pull {}".format( + bot.config.repository), shell=True) status_message = shell_output.decode("unicode_escape") await ctx.send('`{}`'.format(status_message)) From ad6184c6f923d2ce70e878c7011f07628e199fd6 Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Mon, 23 Mar 2020 05:43:52 -0400 Subject: [PATCH 4/8] Document Dockerization Changes in README Updates README with changes pertaining to Dockerization (Docker commands and new Repository configuration variable). --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index 17310f91..8ddb89c7 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,8 @@ You must set certain values in the `config.ini` file, in particular your Discor * `ModeratorRole`: The name of the role that your moderators have (for functions like DMing users). * `DeveloperRole`: The name of the role that your developers have (for functions like restarting the bot). This could be the same role than moderator. * `ReceptionChannelID`: The ID of a channel that will receive messages sent to the bot through the `answer` command (and where messages sent by mods to users with the `dm` command will be logged) +* `[Meta]` + * `Repository`: The HTTPS remote for this repository, used by the `update` command as the remote when pulling. * `[Logging]` * `LogLevel`: [See this for a list of levels](https://docs.python.org/3/library/logging.html#levels). Logs from exceptions and commands like `mix` and `bac` are at the `info` level. Logging messages from the level selected *and* from more severe levels will be sent to your logging file. For example, setting the level to `info` also sends logs from `warning`, `error` and `critical`, but not from `debug`. * `LogFile`: The file where the logging output will be sent (will be created there by the bot if it doesn't exist). @@ -96,6 +98,22 @@ If you installed all dev dependencies, you can run tests with `poetry run pytest ## Running the bot Run `poetry run python Main.py` in your shell. Ensure that your Discord token is set in the `config.ini` file within the `config` directory. +### Docker Container +A Docker Container is provided for easier development. +#### Building the Image +From within the root of the repository: +``` +$ docker build -t canary:latest . +``` +#### Running the Container +From within the root of the repository: +``` +$ docker run -v $(pwd):/mnt/canary canary:latest +``` +Optionally provide the `-d` flag to run the container in detached state. + +Note that the current host directory is mounted into the container, any changes to log files, pickles, configuration are reflected +across the host and the container. ## Code Linting We format our code using Google's [YAPF](https://github.com/google/yapf). Our builds will reject code that do not conform to the standards defined in [`.style.yapf`](https://github.com/idoneam/Canary/blob/master/.style.yapf) . You may format your code using : From 286c54d75ccf51a4b2da17498fe8c20f168cf14a Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Sat, 28 Mar 2020 03:07:34 -0400 Subject: [PATCH 5/8] Reset Configuration Values Addresses comments by @davidlougheed in #277 --- config/config.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/config.ini b/config/config.ini index 64c77ede..4601a45d 100644 --- a/config/config.ini +++ b/config/config.ini @@ -18,11 +18,11 @@ # along with Canary. If not, see . [Discord] -Key = KEY +Key = KEY [Server] -ServerID = 628008153195347999 -CommandPrefix = ! +ServerID = 236668784948019202 +CommandPrefix = ? BotName = Marty UpvoteEmoji = upmartlet DownvoteEmoji = downmartlet From e28082f0153433f07dd1c96adda393b98c77806b Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Wed, 8 Apr 2020 00:00:05 -0400 Subject: [PATCH 6/8] Nitpick git User Email setting in Dockerfile Addresses comments by @jidicula to use the collective gmail address in Git config. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b62f4430..39cc80cc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.6-slim-buster RUN apt update && apt install -y git RUN pip install poetry RUN git config --global user.name "Martlet" -RUN git config --global user.email "martlet@gmail.com" +RUN git config --global user.email "idoneam.collective@gmail.com" COPY pyproject.toml /mnt/ COPY poetry.lock /mnt/ RUN cd /mnt && poetry export -f requirements.txt > requirements.txt From c57599275e74f578e5c3db33a0b382a61a4aa0c7 Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Wed, 8 Apr 2020 00:02:19 -0400 Subject: [PATCH 7/8] Improve Dockerfile Format Improves format and commenting of Dockerfile. --- Dockerfile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 39cc80cc..c7a64370 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,17 @@ FROM python:3.6-slim-buster + RUN apt update && apt install -y git RUN pip install poetry + +# Configure Git settings for update command RUN git config --global user.name "Martlet" RUN git config --global user.email "idoneam.collective@gmail.com" + +# Freeze and install requirements with pip to use Docker cache. COPY pyproject.toml /mnt/ COPY poetry.lock /mnt/ RUN cd /mnt && poetry export -f requirements.txt > requirements.txt RUN pip3 install -r /mnt/requirements.txt -WORKDIR /mnt/canary +WORKDIR /mnt/canary CMD python Main.py From e8d49200555e27843cc43517e29db74e0a36a435 Mon Sep 17 00:00:00 2001 From: Imad Dodin Date: Wed, 8 Apr 2020 00:57:29 -0400 Subject: [PATCH 8/8] Improve Docker Caching Require requirements to be frozen prior to installation to cache independent of pyproject.toml . This change allows flexibility for faster builds while bumping versions of project. --- Dockerfile | 6 ++---- README.md | 10 ++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index c7a64370..76183572 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,10 +7,8 @@ RUN pip install poetry RUN git config --global user.name "Martlet" RUN git config --global user.email "idoneam.collective@gmail.com" -# Freeze and install requirements with pip to use Docker cache. -COPY pyproject.toml /mnt/ -COPY poetry.lock /mnt/ -RUN cd /mnt && poetry export -f requirements.txt > requirements.txt +# Install requirements with pip to use Docker cache independent of project metadata +COPY requirements.txt /mnt/ RUN pip3 install -r /mnt/requirements.txt WORKDIR /mnt/canary diff --git a/README.md b/README.md index 8ddb89c7..b80fb12b 100644 --- a/README.md +++ b/README.md @@ -101,15 +101,25 @@ Run `poetry run python Main.py` in your shell. Ensure that your Discord token is ### Docker Container A Docker Container is provided for easier development. #### Building the Image +Freeze requirements to a requirements.txt + +``` +$ poetry export -f requirements.txt > requirements.txt +``` + From within the root of the repository: + ``` $ docker build -t canary:latest . ``` + #### Running the Container From within the root of the repository: + ``` $ docker run -v $(pwd):/mnt/canary canary:latest ``` + Optionally provide the `-d` flag to run the container in detached state. Note that the current host directory is mounted into the container, any changes to log files, pickles, configuration are reflected