Skip to content

Commit

Permalink
Adding github actions (#1)
Browse files Browse the repository at this point in the history
* Add github actions: ci and release

* Add tests

---------

Co-authored-by: erewok <[email protected]>
  • Loading branch information
Erik Aker and erewok authored Oct 18, 2023
1 parent 7e8220e commit 4422f6f
Show file tree
Hide file tree
Showing 10 changed files with 1,767 additions and 24 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Tests
on:
pull_request:
branches:
- main
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'
jobs:
tests:
name: "Python ${{ matrix.python-version }}"
runs-on: "ubuntu-latest"
strategy:
matrix:
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
python-version: ["3.11"]
steps:
- uses: "actions/checkout@v3"
- uses: "actions/setup-python@v4"
with:
python-version: "${{ matrix.python-version }}"
- name: Set up Poetry cache for Python dependencies
uses: actions/cache@v3
if: startsWith(runner.os, 'Linux')
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('**/poetry.lock') }}
restore-keys: ${{ runner.os }}-poetry-
- name: "Install poetry"
run: "pip install poetry"
- name: "Configure poetry"
run: "poetry config virtualenvs.create false --local"
- name: "Run poetry update"
run: "poetry update"
- name: "Run tests"
run: "poetry run pytest"
32 changes: 32 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Release
on:
release:
types: [published]

jobs:
publish:
name: "Publish release"
runs-on: "ubuntu-latest"

environment:
name: PyPi

steps:
- uses: "actions/checkout@v3"
- uses: "actions/setup-python@v4"
with:
python-version: 3.11
- name: "Install poetry"
run: "pip install poetry"
- name: "Configure poetry"
run: "poetry config virtualenvs.create false --local"
- name: "Run poetry update"
run: "poetry update"
- name: "Build and release"
run: |
poetry build
python -m twine check dist/*
python -m twine upload dist/*
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ tags
.tags_sorted_by_file
docs/_build/
# These are auto-created by sphinx-apidoc
docs/simple_salesforce*.rst
docs/modules.rst
.vscode
venv
htmlcov/
htmlcov/
coverage.xml
unittest.junit.xml
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ This project is an extremely-lightweight task-runner exclusively for __async Pyt
- [Celery](https://github.com/celery/celery/tree/main)
-

## To Install

```sh
pip install "boilermaker-servicebus"
```


## FAQ

Expand Down
2 changes: 1 addition & 1 deletion boilermaker/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class Config(BaseSettings):
# Service Bus ENV vars
service_bus_namespace_url: str
service_bus_queue_name: str
service_bus_credential: str | None = None
service_bus_credential: DefaultAzureCredential | None = None

def az_credential(self):
if self.service_bus_credential:
Expand Down
59 changes: 39 additions & 20 deletions boilermaker/service_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
Wrapper class around a `ServiceBusClient` which allows sending messages or
subscribing to a queue.
"""
import contextlib
import datetime
import logging
from typing import Optional

from azure.servicebus.aio import ServiceBusClient
from azure.servicebus.aio import ServiceBusClient, ServiceBusReceiver, ServiceBusSender
from azure.servicebus import ServiceBusMessage

from .config import Config


servicebus_logger = logging.getLogger("azure.servicebus")
servicebus_logger.setLevel(logging.WARNING)

Expand All @@ -23,33 +22,53 @@ def __init__(self, settings: Config):
self.namespace_url = settings.service_bus_namespace_url
self.queue_name = settings.service_bus_queue_name
self.credential = settings.az_credential()
self._client: ServiceBusClient | None = None
self._receiver_client: ServiceBusReceiver | None = None
self._sender_client: ServiceBusSender | None = None

def _validate_access_settings(self):
if not all((self.namespace_url, self.queue_name, self.credential)):
raise ValueError("Invalid configuration for AzureServiceBus")
return None

def get_sbc(self):
self._validate_access_settings()
return ServiceBusClient(self.namespace_url, self.credential)

@contextlib.asynccontextmanager
async def get_receiver(self):
async with self.get_sbc() as client:
receiver = client.get_queue_receiver(queue_name=self.queue_name)
async with receiver: # type: ignore
yield receiver
@property
def client(self):
if self._client is None:
self._validate_access_settings()
self._client = ServiceBusClient(self.namespace_url, self.credential)
return self._client

def get_receiver(self) -> ServiceBusReceiver:
if self._receiver_client is not None:
return self._receiver_client

self._receiver_client = self.client.get_queue_receiver(queue_name=self.queue_name)
return self._receiver_client

def get_sender(self) -> ServiceBusSender:
if self._sender_client is not None:
return self._sender_client

self._sender_client = self.client.get_queue_sender(queue_name=self.queue_name)
return self._sender_client

async def close(self):
if self._receiver_client is not None:
await self._receiver_client.close()
self._receiver_client = None

if self._sender_client is not None:
await self._sender_client.close()
self._sender_client = None

@contextlib.asynccontextmanager
async def get_sender(self):
async with self.get_sbc() as client:
sender = client.get_queue_sender(queue_name=self.queue_name)
async with sender:
yield sender
if self._client is not None:
await self._client.close()
self._client = None

async def send_message(self, msg: str, delay: int = 0):
message = ServiceBusMessage(msg)
now = datetime.datetime.now(tz=datetime.timezone.utc)
scheduled_time_utc = now + datetime.timedelta(seconds=delay)
async with self.get_sender() as sender: # type: ignore
await sender.schedule_messages(message, scheduled_time_utc)
sender = self.get_sender()
await sender.schedule_messages(message, scheduled_time_utc)
Loading

0 comments on commit 4422f6f

Please sign in to comment.