Compare commits
1 Commits
main
...
a2fec2a4af
| Author | SHA1 | Date | |
|---|---|---|---|
| a2fec2a4af |
@@ -12,12 +12,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Run Hadolint
|
||||
uses: hadolint/hadolint-action@v3.3.0
|
||||
uses: hadolint/hadolint-action@v3.1.0
|
||||
with:
|
||||
dockerfile: Dockerfile
|
||||
output-file: hadolint.out
|
||||
@@ -25,9 +25,9 @@ jobs:
|
||||
no-fail: true
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v6
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.14"
|
||||
python-version: "3.13"
|
||||
|
||||
- name: uv cache
|
||||
uses: actions/cache@v4
|
||||
@@ -40,15 +40,11 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync
|
||||
|
||||
# - name: Lint
|
||||
# run: |
|
||||
# uv run pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt app/ tests/
|
||||
# cat lintreport.txt
|
||||
|
||||
- name: Lint
|
||||
run: |
|
||||
uv run pylint --fail-under=8 --recursive=yes --output-format=parseable app/ tests/
|
||||
uv run pylint --fail-under=8 --recursive=yes --output-format=parseable --output=lintreport.txt app/ tests/
|
||||
cat lintreport.txt
|
||||
|
||||
- name: Unit Test
|
||||
run: |
|
||||
@@ -58,38 +54,18 @@ jobs:
|
||||
|
||||
- name: Minimize uv cache
|
||||
run: uv cache prune --ci
|
||||
|
||||
- name: Set up environment for Snyk
|
||||
run: |
|
||||
uv pip freeze > requirements.txt
|
||||
mv pyproject.toml pyproject.toml.bak
|
||||
mv uv.lock uv.lock.bak
|
||||
|
||||
- name: Snyk SAST Scan
|
||||
- name: SonarQube Scan
|
||||
uses: SonarSource/sonarqube-scan-action@v4.2.1
|
||||
env:
|
||||
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST_URL }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
|
||||
- name: Snyk Vulnerability Scan
|
||||
uses: snyk/actions/python@master
|
||||
continue-on-error: true # Sometimes vulns aren't immediately fixable
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
with:
|
||||
# command: snyk
|
||||
args: snyk code test #--all-projects --exclude=.archive
|
||||
|
||||
# - name: SonarQube Scan
|
||||
# uses: SonarSource/sonarqube-scan-action@v5.2.0
|
||||
# env:
|
||||
# SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST_URL }}
|
||||
# SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
|
||||
# - name: Snyk Vulnerability Scan
|
||||
# uses: snyk/actions/python@master
|
||||
# continue-on-error: true # Sometimes vulns aren't immediately fixable
|
||||
# env:
|
||||
# SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
# with:
|
||||
# command: snyk
|
||||
# args: test --all-projects
|
||||
|
||||
- name: Reverse set up environment for Snyk
|
||||
run: |
|
||||
rm -f requirements.txt
|
||||
mv pyproject.toml.bak pyproject.toml
|
||||
mv uv.lock.bak uv.lock
|
||||
command: snyk
|
||||
args: test --all-projects
|
||||
|
||||
@@ -1,48 +1,104 @@
|
||||
name: Release
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 9 * * 0'
|
||||
- cron: "0 9 * * 0"
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
# test:
|
||||
# name: Test
|
||||
# uses: https://git.tainton.uk/${{ gitea.repository }}/.gitea/workflows/ci.yml@main
|
||||
manual_trigger:
|
||||
name: Manual Trigger Cleanup
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ gitea.event_name == 'issue_comment' }}
|
||||
steps:
|
||||
- name: Log event metadata
|
||||
run: |
|
||||
echo "Issue: ${{ gitea.event.issue.number }}"
|
||||
echo "Comment: ${{ gitea.event.comment.body }}"
|
||||
echo "User: ${{ gitea.event.comment.user.login }}"
|
||||
|
||||
tag:
|
||||
name: Tag release
|
||||
uses: https://git.tainton.uk/actions/gha-workflows/.gitea/workflows/release-with-tag.yaml@main
|
||||
- name: Stop workflow if required conditions are not met
|
||||
if: ${{ !contains(gitea.event.issue.number, '436') || !contains(gitea.event.comment.body, '/trigger-release') || !contains(gitea.event.comment.user.login, 'luke') }}
|
||||
run: exit 1
|
||||
|
||||
- name: Delete issue comment
|
||||
run: |
|
||||
curl -X DELETE \
|
||||
-H "Authorization: token ${{ gitea.token }}" \
|
||||
"${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/issues/comments/${{ gitea.event.comment.id }}"
|
||||
|
||||
# test:
|
||||
# name: Unit Test
|
||||
# uses: https://git.tainton.uk/public/webexmemebot/.gitea/workflows/ci.yml@main
|
||||
# continue-on-error: true
|
||||
|
||||
create_release:
|
||||
name: Create Release
|
||||
needs: tag
|
||||
uses: https://git.tainton.uk/actions/gha-workflows/.gitea/workflows/create-release-preexisting-tag.yaml@main
|
||||
with:
|
||||
tag: ${{ needs.tag.outputs.tag_name }}
|
||||
body: ${{ needs.tag.outputs.changelog }}
|
||||
secrets:
|
||||
ACTIONS_TOKEN: ${{ secrets.ACTIONS_TOKEN }}
|
||||
|
||||
# get_release_id:
|
||||
# name: Get Release ID
|
||||
# runs-on: ubuntu-latest
|
||||
# needs: create_release
|
||||
# outputs:
|
||||
# releaseid: ${{ steps.getid.outputs.releaseid }}
|
||||
# steps:
|
||||
# - name: Get Release ID
|
||||
# id: getid
|
||||
# run: |
|
||||
# rid=$(curl -s -X 'GET' \
|
||||
# -H 'accept: application/json' \
|
||||
# '${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases/latest' | jq -r '.id')
|
||||
# echo "releaseid=$rid" >> "$GITEA_OUTPUT"
|
||||
# echo "$rid"
|
||||
|
||||
create_docker:
|
||||
name: Publish Docker Images
|
||||
runs-on: ubuntu-latest
|
||||
needs: [tag, create_release]
|
||||
# needs: test
|
||||
outputs:
|
||||
release_name: ${{ steps.get_next_version.outputs.tag }}
|
||||
steps:
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Changes since last tag
|
||||
id: changes
|
||||
run: |
|
||||
rm -f .changes
|
||||
git log $(git describe --tags --abbrev=0)..HEAD --no-merges --oneline >> .changes
|
||||
cat .changes
|
||||
|
||||
- name: Check for changes
|
||||
run: |
|
||||
if [[ -z $(grep '[^[:space:]]' .changes) ]] ; then
|
||||
echo "changes=false"
|
||||
echo "changes=false" >> "$GITEA_OUTPUT"
|
||||
else
|
||||
echo "changes=true"
|
||||
echo "changes=true" >> "$GITEA_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Cancel if no changes
|
||||
if: steps.changes.outputs.changes == 'false'
|
||||
run: exit 1
|
||||
|
||||
- name: Set server URL
|
||||
id: set_srvurl
|
||||
run: |
|
||||
SRVURL=$(echo "${{ gitea.server_url }}" | sed 's/https:\/\/\(.*\)/\1/')
|
||||
echo "srvurl=$SRVURL" >> "$GITEA_OUTPUT"
|
||||
|
||||
- name: Get next version
|
||||
uses: TriPSs/conventional-changelog-action@v6
|
||||
id: get_next_version
|
||||
with:
|
||||
git-url: ${{ steps.set_srvurl.outputs.srvurl }}
|
||||
github-token: ${{ gitea.token }}
|
||||
preset: "conventionalcommits"
|
||||
# preset: "angular" # This is the default
|
||||
skip-commit: true
|
||||
release-count: 1
|
||||
output-file: false
|
||||
create-summary: true
|
||||
skip-on-empty: true
|
||||
skip-version-file: true
|
||||
skip-tag: true
|
||||
|
||||
- name: Create release
|
||||
run: |
|
||||
curl -s -X POST \
|
||||
-H "Authorization: token ${{ secrets.ACTIONS_TOKEN }}" \
|
||||
-H "accept: application/json" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\": \"${{ steps.get_next_version.outputs.tag }}\", \"name\": \"${{ steps.get_next_version.outputs.tag }}\", \"body\": \"${{ steps.get_next_version.outputs.changelog }}\"}" \
|
||||
"${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}/releases"
|
||||
|
||||
build_docker:
|
||||
name: Build Docker Images
|
||||
needs: create_release
|
||||
steps:
|
||||
- name: Update Docker configuration
|
||||
continue-on-error: true
|
||||
@@ -54,17 +110,11 @@ jobs:
|
||||
echo "DOCKER_OPTS=\"--insecure-registry ${{ vars.PACKAGES_REGISTRY_URL }}\"" >> /etc/default/docker
|
||||
echo "{\"insecure-registries\": [\"${{ vars.PACKAGES_REGISTRY_URL }}\"]}" > /etc/docker/daemon.json
|
||||
|
||||
- name: Get repo name
|
||||
id: split
|
||||
run: echo "repo=${REPO##*/}" >> "$GITEA_OUTPUT"
|
||||
env:
|
||||
REPO: ${{ gitea.repository }}
|
||||
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: ${{ needs.tag.outputs.tag_name }}
|
||||
ref: ${{ needs.create_release.outputs.release_name }}
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
@@ -87,10 +137,10 @@ jobs:
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
tags: type=semver,pattern=v{{version}},value=${{ needs.tag.outputs.tag_name }}
|
||||
images: |
|
||||
ghcr.io/${{ vars.GHCR_USERNAME }}/${{ steps.split.outputs.repo }}
|
||||
ghcr.io/${{ vars.GHCR_USERNAME }}/webexmemebot
|
||||
${{ vars.PACKAGES_REGISTRY_URL }}/${{ gitea.repository }}
|
||||
tags: type=semver,pattern=v{{version}},value=${{ needs.create_release.outputs.release_name }}
|
||||
|
||||
- name: Print metadata
|
||||
run: |
|
||||
|
||||
@@ -9,25 +9,23 @@ on:
|
||||
- cron: "@daily"
|
||||
|
||||
jobs:
|
||||
# sonarqube:
|
||||
# name: SonarQube
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout repo
|
||||
# uses: actions/checkout@v4.2.2
|
||||
|
||||
# - name: SonarQube Scan
|
||||
# uses: SonarSource/sonarqube-scan-action@v5.2.0
|
||||
# env:
|
||||
# SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST_URL }}
|
||||
# SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
|
||||
snyk:
|
||||
name: Snyk
|
||||
sonarqube:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v5.0.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: SonarQube Scan
|
||||
uses: SonarSource/sonarqube-scan-action@v4.2.1
|
||||
env:
|
||||
SONAR_HOST_URL: ${{ secrets.SONARQUBE_HOST_URL }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARQUBE_TOKEN }}
|
||||
|
||||
snyk:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Snyk
|
||||
uses: snyk/actions/python@master
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM python:3.14-slim
|
||||
FROM python:3.13-slim
|
||||
LABEL maintainer="Luke Tainton <luke@tainton.uk>"
|
||||
USER root
|
||||
|
||||
|
||||
14
app/close.py
14
app/close.py
@@ -1,13 +1,8 @@
|
||||
"""Command module for handling the 'exit' command in the Webex meme bot."""
|
||||
|
||||
from webex_bot.models.command import Command
|
||||
|
||||
|
||||
class ExitCommand(Command):
|
||||
"""Command to handle the 'exit' command in the Webex meme bot."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the ExitCommand with command keyword and help message."""
|
||||
super().__init__(
|
||||
command_keyword="exit",
|
||||
help_message="Exit",
|
||||
@@ -15,14 +10,11 @@ class ExitCommand(Command):
|
||||
)
|
||||
self.sender: str = ""
|
||||
|
||||
def pre_execute(self, message, attachment_actions, activity) -> None: # pylint: disable=unused-argument
|
||||
"""Pre-execution logic for the exit command."""
|
||||
def pre_execute(self, message, attachment_actions, activity) -> None:
|
||||
return
|
||||
|
||||
def execute(self, message, attachment_actions, activity) -> None: # pylint: disable=unused-argument
|
||||
"""Execute the exit command."""
|
||||
def execute(self, message, attachment_actions, activity) -> None:
|
||||
return
|
||||
|
||||
def post_execute(self, message, attachment_actions, activity) -> None: # pylint: disable=unused-argument
|
||||
"""Post-execution logic for the exit command."""
|
||||
def post_execute(self, message, attachment_actions, activity) -> None:
|
||||
return
|
||||
|
||||
29
app/img.py
29
app/img.py
@@ -1,5 +1,3 @@
|
||||
"""Generates meme images using the memegen.link API."""
|
||||
|
||||
import requests
|
||||
|
||||
CHAR_REPLACEMENTS: list = [
|
||||
@@ -19,11 +17,6 @@ CHAR_REPLACEMENTS: list = [
|
||||
|
||||
|
||||
def get_templates() -> list[dict]:
|
||||
"""Fetches available meme templates from the memegen.link API.
|
||||
|
||||
Returns:
|
||||
list[dict]: A list of dictionaries containing meme template information.
|
||||
"""
|
||||
url: str = "https://api.memegen.link/templates"
|
||||
req: requests.Response = requests.get(url=url, timeout=10)
|
||||
req.raise_for_status()
|
||||
@@ -47,14 +40,6 @@ def get_templates() -> list[dict]:
|
||||
|
||||
|
||||
def format_meme_string(input_string: str) -> str:
|
||||
"""Formats a string for use in a meme image URL.
|
||||
|
||||
Args:
|
||||
input_string (str): The string to format.
|
||||
|
||||
Returns:
|
||||
str: The formatted string suitable for meme image URLs.
|
||||
"""
|
||||
# https://memegen.link/#special-characters
|
||||
out_string: str = input_string
|
||||
for char_replacement in CHAR_REPLACEMENTS:
|
||||
@@ -63,16 +48,6 @@ def format_meme_string(input_string: str) -> str:
|
||||
|
||||
|
||||
def generate_api_url(template: str, top_str: str, btm_str: str) -> str:
|
||||
"""Generates a meme image URL using the memegen.link API.
|
||||
|
||||
Args:
|
||||
template (str): The template identifier in the format "name.ext".
|
||||
top_str (str): The text for the top line of the meme.
|
||||
btm_str (str): The text for the bottom line of the meme.
|
||||
|
||||
Returns:
|
||||
str: The complete URL for the meme image.
|
||||
"""
|
||||
tmpl_name: str
|
||||
tmpl_ext: str
|
||||
tmpl_name, tmpl_ext = template.split(".")
|
||||
@@ -80,5 +55,7 @@ def generate_api_url(template: str, top_str: str, btm_str: str) -> str:
|
||||
top_str = format_meme_string(top_str)
|
||||
btm_str = format_meme_string(btm_str)
|
||||
|
||||
url: str = f"https://api.memegen.link/images/{tmpl_name}/{top_str}/{btm_str}.{tmpl_ext}"
|
||||
url: str = (
|
||||
f"https://api.memegen.link/images/{tmpl_name}/{top_str}/{btm_str}.{tmpl_ext}"
|
||||
)
|
||||
return url
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#!/usr/local/bin/python3
|
||||
|
||||
"""Main entry point for the Webex Bot application."""
|
||||
|
||||
from webex_bot.webex_bot import WebexBot
|
||||
|
||||
from app import close, meme
|
||||
@@ -20,7 +18,6 @@ def create_bot() -> WebexBot:
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Main function to run the Webex Bot."""
|
||||
bot: WebexBot = create_bot()
|
||||
bot.add_command(meme.MakeMemeCommand())
|
||||
bot.add_command(close.ExitCommand())
|
||||
|
||||
40
app/meme.py
40
app/meme.py
@@ -1,11 +1,9 @@
|
||||
"""Generates meme images using the memegen.link API."""
|
||||
|
||||
from webex_bot.models.command import Command
|
||||
from webex_bot.models.response import Response, response_from_adaptive_card
|
||||
from webexpythonsdk.models.cards import (
|
||||
from webexteamssdk.models.cards import (
|
||||
AdaptiveCard,
|
||||
Choice,
|
||||
ChoiceSet,
|
||||
Choices,
|
||||
Column,
|
||||
ColumnSet,
|
||||
FontSize,
|
||||
@@ -13,7 +11,7 @@ from webexpythonsdk.models.cards import (
|
||||
Text,
|
||||
TextBlock,
|
||||
)
|
||||
from webexpythonsdk.models.cards.actions import OpenUrl, Submit
|
||||
from webexteamssdk.models.cards.actions import OpenUrl, Submit
|
||||
|
||||
from app import img
|
||||
|
||||
@@ -24,7 +22,6 @@ class MakeMemeCommand(Command):
|
||||
"""Class for initial Webex interactive card."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the MakeMemeCommand with command keyword and help message."""
|
||||
super().__init__(
|
||||
command_keyword="/meme",
|
||||
help_message="Make a Meme",
|
||||
@@ -32,12 +29,10 @@ class MakeMemeCommand(Command):
|
||||
delete_previous_message=True,
|
||||
)
|
||||
|
||||
def pre_execute(self, message, attachment_actions, activity) -> None: # pylint: disable=unused-argument
|
||||
"""Pre-execution logic for the MakeMemeCommand."""
|
||||
def pre_execute(self, message, attachment_actions, activity) -> None:
|
||||
return
|
||||
|
||||
def execute(self, message, attachment_actions, activity) -> Response: # pylint: disable=unused-argument
|
||||
"""Execute the MakeMemeCommand and return an adaptive card."""
|
||||
def execute(self, message, attachment_actions, activity) -> Response:
|
||||
card_body: list = [
|
||||
ColumnSet(
|
||||
columns=[
|
||||
@@ -50,13 +45,13 @@ class MakeMemeCommand(Command):
|
||||
size=FontSize.MEDIUM,
|
||||
),
|
||||
TextBlock(
|
||||
"This bot uses memegen.link to generate memes. Click 'View Templates' to view available templates.", # pylint: disable=line-too-long
|
||||
"This bot uses memegen.link to generate memes. Click 'View Templates' to view available templates.",
|
||||
weight=FontWeight.LIGHTER,
|
||||
size=FontSize.SMALL,
|
||||
wrap=True,
|
||||
),
|
||||
TextBlock(
|
||||
"Both fields are required. If you do not want to specify a value, please type a space.", # pylint: disable=line-too-long
|
||||
"Both fields are required. If you do not want to specify a value, please type a space.",
|
||||
weight=FontWeight.LIGHTER,
|
||||
size=FontSize.SMALL,
|
||||
wrap=True,
|
||||
@@ -70,10 +65,13 @@ class MakeMemeCommand(Command):
|
||||
Column(
|
||||
width=1,
|
||||
items=[
|
||||
ChoiceSet(
|
||||
Choices(
|
||||
id="meme_type",
|
||||
isMultiSelect=False,
|
||||
choices=[Choice(title=x["name"], value=x["choiceval"]) for x in TEMPLATES],
|
||||
choices=[
|
||||
Choice(title=x["name"], value=x["choiceval"])
|
||||
for x in TEMPLATES
|
||||
],
|
||||
),
|
||||
Text(id="text_top", placeholder="Top Text", maxLength=100),
|
||||
Text(
|
||||
@@ -105,7 +103,6 @@ class MakeMemeCallback(Command):
|
||||
"""Class to process user data and return meme."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
"""Initialize the MakeMemeCallback with command keyword and help message."""
|
||||
super().__init__(
|
||||
card_callback_keyword="make_meme_callback_rbamzfyx",
|
||||
delete_previous_message=True,
|
||||
@@ -116,8 +113,7 @@ class MakeMemeCallback(Command):
|
||||
self.meme: str = ""
|
||||
self.meme_filename: str = ""
|
||||
|
||||
def pre_execute(self, message, attachment_actions, activity) -> str: # pylint: disable=unused-argument
|
||||
"""Pre-execution logic for the MakeMemeCallback."""
|
||||
def pre_execute(self, message, attachment_actions, activity) -> str:
|
||||
self.meme: str = attachment_actions.inputs.get("meme_type")
|
||||
self.text_top: str = attachment_actions.inputs.get("text_top")
|
||||
self.text_bottom: str = attachment_actions.inputs.get("text_bottom")
|
||||
@@ -131,12 +127,13 @@ class MakeMemeCallback(Command):
|
||||
|
||||
return "Generating your meme..."
|
||||
|
||||
def execute(self, message, attachment_actions, activity) -> Response | None: # pylint: disable=unused-argument
|
||||
"""Execute the MakeMemeCallback and return a response with the meme image."""
|
||||
def execute(self, message, attachment_actions, activity) -> Response | None:
|
||||
if self.error:
|
||||
return None
|
||||
|
||||
self.meme_filename: str = img.generate_api_url(self.meme, self.text_top, self.text_bottom)
|
||||
self.meme_filename: str = img.generate_api_url(
|
||||
self.meme, self.text_top, self.text_bottom
|
||||
)
|
||||
msg: Response = Response(
|
||||
attributes={
|
||||
"roomId": activity["target"]["globalId"],
|
||||
@@ -146,6 +143,5 @@ class MakeMemeCallback(Command):
|
||||
)
|
||||
return msg
|
||||
|
||||
def post_execute(self, message, attachment_actions, activity) -> None: # pylint: disable=unused-argument
|
||||
"""Post-execution logic for the MakeMemeCallback."""
|
||||
def post_execute(self, message, attachment_actions, activity) -> None:
|
||||
return
|
||||
|
||||
@@ -8,17 +8,17 @@ authors = [
|
||||
]
|
||||
requires-python = ">=3.11.2"
|
||||
dependencies = [
|
||||
"webex-bot<1.1.0,>=1.0.3",
|
||||
"pillow<12.0.1,>=12.0.0",
|
||||
"astroid<=4.0.1",
|
||||
"webex-bot<1.0.0,>=0.5.2",
|
||||
"pillow<12.0.0,>=11.0.0",
|
||||
"astroid<=3.3.8",
|
||||
]
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"black<25.9.1,>=25.9.0",
|
||||
[tool.uv]
|
||||
dev-dependencies = [
|
||||
"black<25.2.0,>=25.1.0",
|
||||
"coverage<8.0.0,>=7.6.10",
|
||||
"isort<7.0.1,>=7.0.0",
|
||||
"pylint<4.1.0,>=4.0.0",
|
||||
"isort<6.1.0,>=6.0.0",
|
||||
"pylint<4.0.0,>=3.3.2",
|
||||
"pylint-exit<2.0.0,>=1.2.0",
|
||||
"pytest<9.0.0,>=8.3.4",
|
||||
"pre-commit<5.0.0,>=4.0.1",
|
||||
@@ -32,6 +32,3 @@ includes = []
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"assignAutomerge": false,
|
||||
"assigneesFromCodeOwners": false,
|
||||
"assignAutomerge": true,
|
||||
"assigneesFromCodeOwners": true,
|
||||
"dependencyDashboardAutoclose": true,
|
||||
"extends": ["config:recommended"],
|
||||
"ignorePaths": ["**/.archive/**"],
|
||||
|
||||
@@ -2,22 +2,19 @@
|
||||
|
||||
import os
|
||||
|
||||
env_vars: dict = {
|
||||
vars: dict = {
|
||||
"APP_VERSION": "dev",
|
||||
"WEBEX_API_KEY": "testing",
|
||||
}
|
||||
|
||||
|
||||
for var, value in env_vars.items():
|
||||
for var, value in vars.items():
|
||||
os.environ[var] = value
|
||||
|
||||
# needs to be imported AFTER environment variables are set
|
||||
from app.config import (
|
||||
config,
|
||||
) # pylint: disable=wrong-import-position # pragma: no cover # noqa: E402
|
||||
from app.config import config # pragma: no cover # noqa: E402
|
||||
|
||||
|
||||
def test_config() -> None:
|
||||
"""Test the configuration settings."""
|
||||
assert config.webex_token == env_vars["WEBEX_API_KEY"]
|
||||
assert config.version == env_vars["APP_VERSION"]
|
||||
assert config.webex_token == vars["WEBEX_API_KEY"]
|
||||
assert config.version == vars["APP_VERSION"]
|
||||
|
||||
@@ -29,4 +29,8 @@ def test_error_false() -> None:
|
||||
callback.text_top = "TEST"
|
||||
callback.text_bottom = "TEST"
|
||||
result: Response = callback.execute(None, None, {"target": {"globalId": "TEST"}})
|
||||
assert isinstance(result, Response) and result.roomId == "TEST" and result.files[0] == callback.meme_filename
|
||||
assert (
|
||||
isinstance(result, Response)
|
||||
and result.roomId == "TEST"
|
||||
and result.files[0] == callback.meme_filename
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user