Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the web service implementation #4

Merged
merged 46 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d406164
Change from Flask to FastAPI
tkoscieln Apr 8, 2024
5ba9815
Switch to FastApi+Celery and add containerization
tkoscieln Apr 18, 2024
8d324f9
Add service dockerfile and compose
tkoscieln Apr 22, 2024
dd03139
Refactor api tests and add os variables
tkoscieln Apr 22, 2024
41af0f3
Add entrypoint and fix path in git pull location
tkoscieln Apr 22, 2024
b52618f
Add envvar check in entrypoint and add html formatted response
tkoscieln Apr 22, 2024
0ff329d
Fix git clone paths and add html response
tkoscieln Apr 22, 2024
e249b27
Add json and yaml output and fix checkout and callback
tkoscieln Apr 22, 2024
a987702
Add envvars to README
tkoscieln Apr 23, 2024
159c335
Add hostname env for status callback
tkoscieln Apr 23, 2024
ca08157
Add kube pod config
tkoscieln Apr 23, 2024
4d26aec
Add unit tests to complete coverage, add more metadata, refactor
tkoscieln May 14, 2024
56b5948
Add pytest action, edit Readme run instructions
tkoscieln May 14, 2024
934d4bd
Fix hanging actions and remove start script
tkoscieln May 14, 2024
7f30676
Remove Python 3.9 worker
tkoscieln May 14, 2024
1f97e5d
Add path query parameter support
tkoscieln May 17, 2024
6aa0b1b
Add .venv to .gitignore
martinhoyer Aug 13, 2024
cb984bd
Update requirements to latest, compatible version
martinhoyer Aug 13, 2024
9e67ee2
Split status to status and status/html
martinhoyer Aug 13, 2024
5c34317
Sort imports
martinhoyer Aug 13, 2024
09eef62
Code style, typing, tmt.Path usage
martinhoyer Aug 13, 2024
99b517b
Use podman-compose in CI
martinhoyer Aug 14, 2024
e1c4ad7
Remove tmt-web yaml file
martinhoyer Aug 15, 2024
d7bdc9a
Refactoring github workflow
martinhoyer Aug 15, 2024
62f2c1a
Adding /health check
martinhoyer Aug 15, 2024
d40d34e
Use Annotated
martinhoyer Aug 16, 2024
ab640a0
Adding metadata, modifying file structure
martinhoyer Aug 16, 2024
3206b80
Addressing issues found by Ruff
martinhoyer Aug 16, 2024
b41a0d3
Resolving typing check errors
martinhoyer Aug 19, 2024
350b2cb
Removing redundant whitespaces, lines
martinhoyer Aug 19, 2024
17f8878
Add pre-commit hooks and mypy configuration
martinhoyer Aug 19, 2024
4c6db17
Add a simple wrapper for local test to hatch env
martinhoyer Aug 20, 2024
cf99aaf
Use Jinja in html_generator
martinhoyer Aug 20, 2024
b317eb9
Remove usage of Python <3.12, add classifiers
martinhoyer Aug 20, 2024
c086e46
Add pre-commit to gh workflow
martinhoyer Aug 20, 2024
41dd0ba
Remove format_html variable
martinhoyer Aug 20, 2024
cf99bbc
Re-use existing dict generation for yaml
martinhoyer Sep 3, 2024
2b7a382
Minor README changes
martinhoyer Sep 3, 2024
85f2daa
fixup! Add pre-commit hooks and mypy configuration
martinhoyer Sep 3, 2024
3bcc90f
Make 'ref' optional
martinhoyer Sep 3, 2024
dfd56bb
A bunch of minor code improvements (#6)
seberm Oct 8, 2024
ea3a988
Remove unnecesary module warnings
psss Oct 8, 2024
7b567ab
Some minor README changes
psss Oct 8, 2024
dfe7021
Second bunch of code improvements (#7)
seberm Oct 24, 2024
8cd7674
Fix the `test-ref` value (branch was removed)
psss Oct 24, 2024
15ca2d5
Fix expected test output
psss Oct 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions .github/workflows/pre-commit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: pre-commit

on:
pull_request:
push:
branches: [main]

jobs:
pre-commit:
runs-on: ubuntu-latest
env:
SKIP: no-commit-to-branch
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
cache: 'pip'
- uses: pre-commit/[email protected]
83 changes: 83 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
name: Run tests

on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

jobs:
test:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.12"] # Can be extended with future Python versions

steps:

- name: Check out code
uses: actions/checkout@v4

- name: Set up Podman and Buildah
run: |
sudo apt-get update
sudo apt-get install -y podman buildah

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: '${{ matrix.python-version }}'
cache: 'pip'

- name: Install pytest
run: |
python -m pip install pytest hatch
python -m pip install .


- name: Build the web image
run: |
buildah bud -t tmt-web:latest --build-arg PYTHON_VERSION=${{ matrix.python-version }} .

- name: Create Podman pod
run: |
podman pod create --name tmt-web-pod --infra-image=registry.k8s.io/pause:3.9 -p 8000:8000 -p 6379:6379
# Exposing redis port as well for test_api.py::TestCelery::test_basic_test_request

- name: Start Redis container
run: |
podman run -d --pod tmt-web-pod --name redis redis:latest
martinhoyer marked this conversation as resolved.
Show resolved Hide resolved

- name: Start Celery container
run: |
podman run -d --pod tmt-web-pod --name celery \
-e REDIS_URL=redis://localhost:6379 \
-e API_HOSTNAME=http://localhost:8000 \
tmt-web:latest celery --app=tmt_web.api.service worker --loglevel=INFO

- name: Start Web container
run: |
podman run -d --pod tmt-web-pod --name web \
-e REDIS_URL=redis://localhost:6379 \
-e API_HOSTNAME=http://localhost:8000 \
tmt-web:latest uvicorn tmt_web.api:app --reload --host 0.0.0.0 --port 8000

- name: Wait for services to be ready
run: |
for i in {1..30}; do
if curl -s http://localhost:8000/health; then
break
fi
sleep 4
done

- name: Run tests
run: |
python -m pytest

- name: Cleanup
if: always()
run: |
podman pod stop tmt-web-pod
podman pod rm tmt-web-pod
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
.pytest_cache
.tmp
.repos
venv
.venv
.idea
.vscode
__pycache__
dist
.ruff_cache
.mypy_cache
__pycache__
35 changes: 35 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: "v4.6.0"
hooks:
- id: check-merge-conflict
- id: check-symlinks
- id: check-toml
- id: destroyed-symlinks
- id: detect-private-key
- id: end-of-file-fixer
- id: mixed-line-ending
- id: no-commit-to-branch
args: [--branch, main]
- id: trailing-whitespace
args: [--markdown-linebreak-ext=md]


- repo: https://github.com/pre-commit/mirrors-mypy
rev: "v1.11.1"
hooks:
- id: mypy
language_version: "3.12"
additional_dependencies:
- 'tmt'
- 'pydantic'
- 'celery-types'

- repo: https://github.com/charliermarsh/ruff-pre-commit
rev: v0.6.1
hooks:
- id: ruff
args:
- '--fix'
- '--show-fixes'
13 changes: 13 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ARG PYTHON_VERSION=3.12
FROM python:${PYTHON_VERSION}

RUN mkdir /app
WORKDIR /app
COPY README.md LICENSE pyproject.toml src/ ./

RUN SETUPTOOLS_SCM_PRETEND_VERSION=0.1.0.dev0 pip install .

COPY /entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]
98 changes: 69 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,81 @@
# web
Web app for checking tmt tests and plans
# Run instructions
1. Create a virtual environment
2. Install the requirements
3. Use the `start_api.sh` script to start the api
# tmt web

Web application for checking tmt tests, plans and stories.

## Run instructions

To run the service locally for development purposes, use the following command:

```bash
podman-compose up --build
```

Add `-d` for the service to run in the background.

## Tests
To run the tests, use the pytest command
# API
API for checking tmt tests and plans metadata
## Version
The API version is defined by prefix in url, e.g.
`/v0.1/status`
## Endpoints
* `/` - returns ID of the created Celery task with additional metadata in JSON and callback url for `/status` endpoint,
returns the same in HTML format if `format` is set to `html`
* `test-url` - URL of the repo test is located in - accepts a `string`

* `test-ref` - Ref of the repository the test is located in - accepts a `string`,
defaults to default branch of the repo
To run the tests, use the `pytest` command (assuming the service is running).

Alternatively, if you have `hatch` installed, `hatch run test:run` command will
rebuild, start the service and run the tests.

## Environment variables

- `REDIS_URL` - *optional*, passed to Celery on initialization as a `broker` and
`backend` argument, default value is: `redis://localhost:6379`
- `CLONE_DIR_PATH` - *optional*, specifies the path where the repositories will
be cloned, default value is: `./.repos/`
- `USE_CELERY` - *optional*, specifies if the app should use Celery, set to
`false` for running without Celery
- `API_HOSTNAME` - *required*, specifies the hostname of the API, used for
creating the callback URL to the service

## API

The API version is defined by prefix in url, e.g. `/v0.1/status`.

If we want to display metadata for both tests and plans, we can combine
the `test-*` and `plan-*` options together, they are not mutually
exclusive.

`test-url` and `test-name`, or `plan-url` and `plan-name` are required.

### `/`

Returns ID of the created Celery task with additional metadata in JSON
and callback url for `/status` endpoint, returns the same in HTML format
if `format` is set to `html`.

* `test-url` - URL of the repo test is located in - accepts a `string`
* `test-ref` - Ref of the repository the test is located in - accepts
a `string`, defaults to default branch of the repo
* `test-path` - Points to directory where `fmf` tree is stored
* `test-name` - Name of the test - accepts a `string`

* `plan-url` - URL of the repo plan is located in - accepts a `string`

* `plan-ref` - Ref of the repository the plan is located in - accepts a `string`,
defaults to default branch of the repo
* `plan-ref` - Ref of the repository the plan is located in - accepts
a `string`, defaults to default branch of the repo
* `plan-path` - Points to directory where `fmf` tree is stored
* `plan-name` - Name of the plan - accepts a `string`
* `format` - Format of the output - accepts a `string`, default is `json`, other options are `xml`, `html`
(serves as a basic human-readable output format)

* `format` - Format of the output - accepts a `string`, default is
`json`, other options are `xml`, `html` (serves as a basic
human-readable output format)
* `id` - Unique ID of the tmt object
* `/status` - returns a status of the tmt object being processed by the backend

### `/status`

Returns a status of the tmt object being processed by the backend.

* `task_id` - ID of the task - accepts a `string`
* `/status/html` - returns a status of the tmt object being processed by the backend in a simple HTML formatting

### `/status/html`

Returns a status of the tmt object being processed by the backend in a
simple HTML formatting.

* `task_id` - ID of the task - accepts a `string`
* `/health` - returns a health status of the service

If we want to display metadata for both tests and plans, we can combine the `test-*`
and `plan-*` options together, they are not mutually exclusive.
### `/health`

`test-url` and `test-name`, or `plan-url` and `plan-name` are required.
Returns a health status of the service.
29 changes: 29 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
services:
web:
container_name: uvicorn
build:
context: .
dockerfile: ./Containerfile
command: uvicorn src.api:app --reload --host 0.0.0.0 --port 8000
environment:
- REDIS_URL=redis://redis:6379
- API_HOSTNAME=http://localhost:8000
ports:
- 8000:8000
redis:
container_name: redis
image: redis:latest
ports:
- 6379:6379

celery:
container_name: celery
build:
context: .
dockerfile: ./Containerfile
command: celery --app=src.api.service worker --loglevel=INFO
environment:
- REDIS_URL=redis://redis:6379
- API_HOSTNAME=http://localhost:8000
depends_on:
- redis
24 changes: 24 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/sh

# Name of container to start
APP=$1

[ -z "$APP" ] && { error "No api to run passed to entrypoint script"; exit 1; }

case $APP in
uvicorn)
COMMAND="uvicorn tmt_web.api:app --reload --host 0.0.0.0 --port 8000"
;;
celery)
COMMAND="celery --app=tmt_web.api.service worker --loglevel=INFO"
;;
*)
echo "Unknown app '$APP'"
exit 1
;;
esac

$COMMAND &
PID=$!

wait $PID
Loading