Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 15 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# ignore all
*

# unignore image-related
!src/
!tests/
!alembic.ini
!SHA.txt
!LICENSE
!pytest.ini
!pyproject.toml
!README.md
!uv.lock
!uvicorn_disable_logging.json
!VERSION
11 changes: 11 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[flake8]
ignore = E203, E266, W503
exclude =
docs
k8s
max-line-length = 88
max-complexity = 18
select = B,C,E,F,W,T4,B9
per-file-ignores =
tests/**.py: E501, F401
src/alembic/env.py: F401, E402
52 changes: 52 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: "Python tests"

on:
pull_request:
branches: ["main"]

env:
SEGMENT: loc00
DB_HOST: localhost
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: postgres
DB_NAME: test_licensing

jobs:
pytest:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:17
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: test_licensing
ports: ["5432:5432"]
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
# Install a specific version of uv.
version: "0.6.3"

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version-file: ".python-version"

- run: uv sync --dev --frozen
- run: uv run pytest --cov bm.ucm

- uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: htmlcov
58 changes: 58 additions & 0 deletions .github/workflows/test-k8s.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: Tests k8s

on:
pull_request:
paths:
- k8s/**
- Tiltfile
branches: [master]
push:
paths:
- k8s/**
- Tiltfile
branches: [master]

jobs:
cdk8s-tests:
runs-on: buildjet-4vcpu-ubuntu-2204
defaults:
run:
working-directory: ./k8s
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: k8s/.nvmrc
- name: Install dependencies
run: npm ci
# Build command also run synth, tests to ensure that stack can be build
- name: Run build
run: npm run build

tilt-check:
runs-on: buildjet-4vcpu-ubuntu-2204
needs:
- cdk8s-tests
steps:
- name: Checkout Code
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Setup node
uses: actions/setup-node@v4
with:
node-version-file: k8s/.nvmrc
- name: Install tilt
shell: bash
run: |
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
- name: Create k8s cluster
uses: helm/kind-action@v1
- name: Check Tilt
shell: bash
run: |
tilt ci
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,6 @@ target/
profile_default/
ipython_config.py

# pyenv
.python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
Expand Down
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.12.9
61 changes: 10 additions & 51 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,62 +1,21 @@
SHELL := /bin/bash

.PHONY: k8s_synth
k8s_synth:
.PHONY: synth
synth:
(cd k8s && source ${HOME}/.nvm/nvm.sh && nvm use && npm run synth)

.PHONY: k8s_install
k8s_install:
.PHONY: cdk_install
cdk_install:
(cd k8s && source ${HOME}/.nvm/nvm.sh && nvm use && npm ci)

.PHONY: k8s_test
k8s_test:
.PHONY: cdk_test
cdk_test:
(cd k8s && source ${HOME}/.nvm/nvm.sh && nvm use && npm run test)

.PHONY: k8s_test_update
k8s_test_update:
.PHONY: update_snapshots
update_snapshots:
(cd k8s && source ${HOME}/.nvm/nvm.sh && nvm use && npm run test -- -u)

.PHONY: k8s_pretty
k8s_pretty:
.PHONY: cdk_pretty
cdk_pretty:
(cd k8s && source ${HOME}/.nvm/nvm.sh && nvm use && npm run prettier)

.PHONY: init
init:
kubectl create namespace licensing || true
skaffold run --cleanup=false --profile init

.PHONY: run-api
run-api:
skaffold dev --profile run-api

.PHONY: create-db
create-db:
skaffold run --cleanup=false --profile create-db

.PHONY: pg-port-forward
pg-port-forward:
kubectl port-forward service/licensing-db 5433:5432 -n licensing

.PHONY: run-migration
run-migration:
skaffold run --cleanup=false --profile run-migration

.PHONY: run-event-export
run-event-export:
skaffold run --cleanup=false --profile run-event-export

.PHONY: start
start:
make init
make create-db
make run-migration
kubectl wait --for=condition=complete --timeout=120s --namespace=licensing job/licensing-migration
make run-event-export
make run-api

.PHONY: delete
delete:
skaffold delete -p init
skaffold delete -p run-api
skaffold delete -p create-db
skaffold delete -p run-event-export
35 changes: 27 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,20 @@ We build a licensing service which combines the need of licensing on different l

## K8S
Best practice is to run the application in a local k8s cluster. Please see <a href="k8s/README.md">k8s/README.md</a>:
### Initialization

#### Using Tilt
##### Installation
https://docs.tilt.dev/install
```bash
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
```
##### Starting
```bash
make k8s_install
make k8s_synth
make init
tilt up
```
#### Starting
##### Stopping
```bash
make start
tilt down
```

## Manually
Expand All @@ -143,10 +148,24 @@ on your local postgreSQL database using the SQL query
CREATE DATABASE licm;
```

## Run uvicorn
### Install dependencies

We rely on <https://github.com/astral-sh/uv> to manage the project and its dependencies:

#### Create env
```shell
uv venv
source .venv/bin/activate
```

#### Sync your env
```shell
uv sync --extra export
```

### Run uvicorn
You can start the application using the following commands:
```sh
cd <licensing>
export PYTHONPATH=$PWD/src
uvicorn services.licensing.main:app --reload --workers 1 --host 0.0.0.0 --port 8000
```
Expand Down
54 changes: 54 additions & 0 deletions Tiltfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
local("make dist", dir="k8s")

# Create namespace if it doesn't exist
local(
"kubectl get namespace integration --no-headers || kubectl create namespace integration"
)
k8s_yaml(listdir(os.path.join("k8s", "dist")))

k8s_resource(
objects=[
"licensing:namespace",
"licensing:serviceaccount:licensing",
"licensing:role:licensing",
"licensing:rolebinding:licensing",
"licensing-config:configmap:licensing",
"licensing-db-init-db-script:configmap:licensing",
"licensing:secret:licensing",
"event-export:secret:licensing",
"licensing-ingress:ingress:licensing",
],
new_name="licensing:k8s",
labels="licensing",
)
k8s_resource(
"licensing-db",
labels="licensing",
resource_deps=["licensing:k8s"],
port_forwards=["15432:5432"],
)
k8s_resource("licensing-migration", labels="licensing", resource_deps=["licensing-db"])
# k8s_resource("licensing-api", labels="licensing", resource_deps=["licensing-migration"], port_forwards=['8000:8000'])
k8s_resource("licensing-api", labels="licensing", resource_deps=["licensing-migration"])
k8s_resource(
"licensing-event-export",
labels="licensing",
resource_deps=["licensing-migration"],
auto_init=False,
trigger_mode=TRIGGER_MODE_MANUAL,
)


def build_local():
python_version = str(read_file(".python-version")).strip("\n")
docker_build(
"licensing",
".",
dockerfile=os.path.join("k8s", "Dockerfile"),
build_args={"python_version": python_version},
)


SEGMENT = os.getenv("OPAL_SEGMENT", "loc00")

build_local()
File renamed without changes.
2 changes: 1 addition & 1 deletion k8s/.nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18.20.4
v20
8 changes: 8 additions & 0 deletions k8s/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
dist
imports
loc00
node_modules
tests/__snapshots__
jest.config.js
*.yaml
*.json
37 changes: 31 additions & 6 deletions k8s/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
FROM python:3.12.6-slim
ARG python_version 3.12.9

# INFO: we just install project dependencies in this layer
FROM python:${python_version}-slim-bookworm AS dependencies

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV UV_PROJECT_ENVIRONMENT=/venv
COPY --from=ghcr.io/astral-sh/uv:0.6.10 /uv /uvx /bin/

WORKDIR /code
COPY ./pyproject.toml .
COPY ./uv.lock .

RUN uv venv && uv sync --frozen --no-dev --no-install-project

# INFO: we take the virtual env and add the project itself
FROM python:${python_version}-slim-bookworm AS build
ENV UV_PROJECT_ENVIRONMENT=/venv
COPY --from=ghcr.io/astral-sh/uv:0.6.10 /uv /uvx /bin/
COPY --from=dependencies /venv /venv

WORKDIR /code
COPY ./requirements* /code/
COPY ./src .
COPY ./pyproject.toml .
COPY ./uv.lock .

RUN python3 -m pip install --no-cache-dir -IU pip
RUN uv sync --extra export --frozen --no-editable --no-dev

COPY . /code/
RUN python3 -m pip install --no-cache-dir .[export]
# INFO: final image only with virtual env
FROM python:${python_version}-slim-bookworm
ENV PYTHONUNBUFFERED 1
ENV PATH="/venv/bin:$PATH"
COPY --from=build /venv /venv
COPY ./alembic.ini .
COPY ./uvicorn_disable_logging.json .
COPY ./src/services/licensing/data/sqlalchemy/migrations ./src/services/licensing/data/sqlalchemy/migrations

CMD ["uvicorn", "services.licensing.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1", "--timeout-keep-alive", "0"]
CMD ["uvicorn", "services.licensing.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1", "--log-config", "uvicorn_disable_logging.json", "--timeout-keep-alive", "0"]
Loading
Loading