commit 6fcc591428baddb58df73eab14fc5851ffbf5eaf Author: burnettk Date: Fri Mar 15 17:08:28 2024 -0400 compose setup with postgres diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f32ecab --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.idea/ +.aider* +default.py diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..4da0077 --- /dev/null +++ b/Makefile @@ -0,0 +1,37 @@ +include configs/spiffworkflow-backend.env +include configs/spiffworkflow-frontend.env + +# if the directory is called something other than the repo name, let's still call +# the docker project by something we can refer to later. +docker_prefix = "bpmn" + +# credit: helper code to implement the help target originally from https://stackoverflow.com/a/64996042/6090676 +help: ## Show this help message + @grep -Eh '\s##\s' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m %-30s\033[0m %s\n", $$1, $$2}' + +start: ## Start SpiffWorkflow for local development + @docker compose -p $(docker_prefix) up + +up: ## Alias for start +up: start + +pull: ## Pull latest container images + @docker compose -p $(docker_prefix) pull + +build: ## Build or rebuild connector proxy image from source + @docker compose -p $(docker_prefix) build + +destroy-db: ## Delete the database docker volume + @if docker volume inspect "$(docker_prefix)_spiffworkflow_backend_db" >/dev/null; then \ + mountpoint=$$(docker volume inspect bpmn_spiffworkflow_backend_db --format="{{.Mountpoint}}"); \ + sudo rm "$$mountpoint/db.sqlite3"; \ + fi + +down: ## Shut down containers, but leave images and database data around + @docker compose -p $(docker_prefix) down + +destroy-all: ## Delete all docker images, containers, and volumes. Leave no trace. + @docker compose -p $(docker_prefix) down --volumes --rmi all + +update-docker-tags: ## Update docker tags for backend, frontend, and connector + @./bin/update_docker_tags diff --git a/README.md b/README.md new file mode 100644 index 0000000..465030a --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +## arena-compose-postgres + +This application consists of a frontend and a backend service, a PostgreSQL database, and a connector proxy, all orchestrated with Docker Compose. + +### Services and Default Ports: + +- `spiffworkflow-frontend`: The frontend user interface for the workflow application. +- `spiffworkflow-backend`: The backend service providing API endpoints for the frontend. +- `spiffdb`: A PostgreSQL database service used by the backend to store workflow data. +- `spiffworkflow-connector`: A connector proxy service for external integrations. + +### Getting Started: + +1. Ensure Docker and Docker Compose are installed on your system. +2. Clone the repository and navigate to the directory containing the `docker-compose.yml` file. The default ports are set in this file, but you can change them if needed. +3. Run `make up` to start all services. The services will be available on the following default ports: +4. Access the frontend at `http://localhost:8001`, where `8001` is the default port for the frontend service. +5. Access the backend API at `http://localhost:8000/v1.0`, where `8000` is the default port for the backend service. +6. Run `make down` to stop all services. + +### Database Access: + +To access the PostgreSQL database from within the `spiffdb` container, use the following command: + +```sh +psql -U spiffuser -d spiffworkflow +``` + +The default username is `spiffuser` and the password is `spiffpass`, as configured in the `docker-compose.yml` file. + +### Health Checks: + +Health checks are configured for the `spiffworkflow-backend` and `spiffdb` services to ensure they are ready before dependent services start. + +### Troubleshooting: + +If you encounter any issues with the services, check the logs using `docker-compose logs`. diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 0000000..ffeb29f --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,6 @@ +ARG SPIFFWORKFLOW_BACKEND_TAG=${SPIFFWORKFLOW_BACKEND_TAG} +FROM ghcr.io/sartography/spiffworkflow-backend:${SPIFFWORKFLOW_BACKEND_TAG} + +RUN apt-get update \ + && apt-get install -y -q libpq-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* diff --git a/bin/update_docker_tags b/bin/update_docker_tags new file mode 100755 index 0000000..4752fca --- /dev/null +++ b/bin/update_docker_tags @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +function error_handler() { + >&2 echo "Exited with BAD EXIT CODE '${2}' in ${0} script at line: ${1}." + exit "$2" +} +trap 'error_handler ${LINENO} $?' ERR +set -o errtrace -o errexit -o nounset -o pipefail + +if ! command -v jq > /dev/null; then + >&2 echo "ERROR: this command requires jq to be installed." + exit 1 +fi + +branch=main + +docker_image_repos=( + "spiffworkflow-backend" + "spiffworkflow-frontend" +) + +spiff_arena_directory="${HOME}/spiff-arena" +if [[ ! -d "$spiff_arena_directory" ]]; then + git clone https://github.com/sartography/spiff-arena.git "$spiff_arena_directory" +else + git -C "$spiff_arena_directory" pull +fi + +current_year="$(date +%Y)" +current_month="$(date +%m)" + +for docker_image_repo in "${docker_image_repos[@]}" ; do + normalized_repo_name=$(tr '-' '_' <<<"$docker_image_repo") + config_file="configs/${docker_image_repo}.env" + if [[ ! -f "$config_file" ]]; then + >&2 echo "ERROR: Could not find config file: ${config_file}" + exit 1 + fi + + tags=$("${spiff_arena_directory}/bin/list_ghcr_tags" "$docker_image_repo" "${branch}-${current_year}-${current_month}") + latest_tag="$(echo "${tags}" | jq -r '. | last')" + config_to_update="$(tr "[:lower:]" "[:upper:]" <<<"$normalized_repo_name")_TAG" + perl -pi -e "s/(${config_to_update}=).*/\1${latest_tag}/" "$config_file" +done diff --git a/configs/permissions/local_development.yml b/configs/permissions/local_development.yml new file mode 100644 index 0000000..12c7cdd --- /dev/null +++ b/configs/permissions/local_development.yml @@ -0,0 +1,50 @@ +users: + admin: + service: local_open_id + email: admin@spiffworkflow.org + password: admin + preferred_username: Admin + patrick: + service: local_open_id + email: patrick@example.com + password: patrick + preferred_username: Patrick + test_user: + service: local_open_id + email: testing@example.com + password: testing + preferred_username: Test User + +groups: + admin: + users: [admin@spiffworkflow.org, patrick@example.com] + testing: + users: [testing@example.com] + +permissions: + # Admins have access to everything. + admin: + groups: [admin] + allowed_permissions: [all] + uri: /* + + # Everybody can participate in tasks assigned to them. + # BASIC, PG, PM, are documented at https://spiff-arena.readthedocs.io/en/latest/DevOps_installation_integration/permission_url.html + basic: + groups: [everybody, testing] + allowed_permissions: [all] + uri: BASIC + + # Everyone can see everything (all groups, and processes are visible) + read-all-process-groups: + groups: [everybody, testing] + allowed_permissions: [read] + uri: PG:ALL + read-all-process-models: + groups: [everybody, testing] + allowed_permissions: [read] + uri: PM:ALL + run-all-process-models: + groups: [everybody, testing] + allowed_permissions: [start] + uri: PM:ALL diff --git a/configs/spiffworkflow-backend.env b/configs/spiffworkflow-backend.env new file mode 100644 index 0000000..1aabc32 --- /dev/null +++ b/configs/spiffworkflow-backend.env @@ -0,0 +1,2 @@ +export SPIFFWORKFLOW_BACKEND_TAG=main-2024-03-14_19-55-58-9acd295 +export SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH=/app/permissions/local_development.yml diff --git a/configs/spiffworkflow-frontend.env b/configs/spiffworkflow-frontend.env new file mode 100644 index 0000000..6875fa9 --- /dev/null +++ b/configs/spiffworkflow-frontend.env @@ -0,0 +1 @@ +export SPIFFWORKFLOW_FRONTEND_TAG=main-2024-03-14_19-55-55-9acd295 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cfb16b4 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,93 @@ +version: "3.8" + +services: + spiffworkflow-frontend: + container_name: spiffworkflow-frontend + image: ghcr.io/sartography/spiffworkflow-frontend:${SPIFFWORKFLOW_FRONTEND_TAG:-latest} + depends_on: + spiffworkflow-backend: + condition: service_healthy + environment: + APPLICATION_ROOT: "/" + PORT0: "${SPIFFWORKFLOW_FRONTEND_PORT:-8001}" + ports: + - "${SPIFFWORKFLOW_FRONTEND_PORT:-8001}:${SPIFFWORKFLOW_FRONTEND_PORT:-8001}/tcp" + + spiffworkflow-backend: + depends_on: + spiffdb: + condition: service_healthy + container_name: spiffworkflow-backend + # image: ghcr.io/sartography/spiffworkflow-backend:${SPIFFWORKFLOW_BACKEND_TAG:-latest} + build: + context: backend + args: + SPIFFWORKFLOW_BACKEND_TAG: "${SPIFFWORKFLOW_BACKEND_TAG}" # Replace "value" with the value you want to pass + environment: + SPIFFWORKFLOW_BACKEND_APPLICATION_ROOT: "/" + SPIFFWORKFLOW_BACKEND_ENV: "local_docker" + FLASK_DEBUG: "0" + FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}" + # WARNING: Frontend is a static site which assumes backend is frontend port - 1 on localhost. + SPIFFWORKFLOW_BACKEND_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}" + + SPIFFWORKFLOW_BACKEND_BPMN_SPEC_ABSOLUTE_DIR: "/app/process_models" + SPIFFWORKFLOW_BACKEND_CONNECTOR_PROXY_URL: "http://spiffworkflow-connector:8004" + SPIFFWORKFLOW_BACKEND_DATABASE_TYPE: "postgres" + SPIFFWORKFLOW_BACKEND_DATABASE_URI: "postgresql://spiffuser:spiffpass@spiffdb:5432/spiffworkflow" + SPIFFWORKFLOW_BACKEND_LOAD_FIXTURE_DATA: "false" + SPIFFWORKFLOW_BACKEND_LOG_LEVEL: "DEBUG" + SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_ID: "spiffworkflow-backend" + SPIFFWORKFLOW_BACKEND_OPEN_ID_CLIENT_SECRET_KEY: "my_open_id_secret_key" + SPIFFWORKFLOW_BACKEND_OPEN_ID_SERVER_URL: "http://localhost:${SPIFF_BACKEND_PORT:-8000}/openid" + SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH: "${SPIFFWORKFLOW_BACKEND_PERMISSIONS_FILE_ABSOLUTE_PATH}" + SPIFFWORKFLOW_BACKEND_PORT: "${SPIFF_BACKEND_PORT:-8000}" + SPIFFWORKFLOW_BACKEND_RUN_BACKGROUND_SCHEDULER_IN_CREATE_APP: "true" + SPIFFWORKFLOW_BACKEND_UPGRADE_DB: "true" + SPIFFWORKFLOW_BACKEND_URL_FOR_FRONTEND: "http://localhost:${SPIFFWORKFLOW_FRONTEND_PORT:-8001}" + ports: + - "${SPIFF_BACKEND_PORT:-8000}:${SPIFF_BACKEND_PORT:-8000}/tcp" + volumes: + - ./process_models:/app/process_models + - ./configs/permissions:/app/permissions + healthcheck: + test: "curl localhost:${SPIFF_BACKEND_PORT:-8000}/v1.0/status --fail" + interval: 10s + timeout: 5s + retries: 20 + + spiffdb: + image: postgres:latest + environment: + POSTGRES_USER: spiffuser + POSTGRES_PASSWORD: spiffpass + POSTGRES_DB: spiffworkflow + ports: + - "8005:5432" + volumes: + - spiffworkflow_backend_db:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U spiffuser -d spiffworkflow"] + interval: 10s + timeout: 5s + retries: 5 + + spiffworkflow-connector: + container_name: spiffworkflow-connector + image: ghcr.io/sartography/connector-proxy-demo:latest + environment: + FLASK_ENV: "${FLASK_ENV:-development}" + FLASK_DEBUG: "0" + FLASK_SESSION_SECRET_KEY: "${FLASK_SESSION_SECRET_KEY:-super_secret_key}" + CONNECTOR_PROXY_PORT: "${SPIFF_CONNECTOR_PORT:-8004}" + ports: + - "${SPIFF_CONNECTOR_PORT:-8004}:${SPIFF_CONNECTOR_PORT:-8004}/tcp" + healthcheck: + test: "curl localhost:${SPIFF_CONNECTOR_PORT:-8004}/liveness --fail" + interval: 10s + timeout: 5s + retries: 20 + +volumes: + spiffworkflow_backend_db: + driver: local diff --git a/process_models/.keep b/process_models/.keep new file mode 100644 index 0000000..e69de29 diff --git a/process_models/aviation/check-part/check-part.bpmn b/process_models/aviation/check-part/check-part.bpmn new file mode 100644 index 0000000..161be9b --- /dev/null +++ b/process_models/aviation/check-part/check-part.bpmn @@ -0,0 +1,51 @@ + + + + + Flow_17db3yp + + + + + The process instance completed successfully. + + Flow_12pkbxb + + + + + This is an example **Manual Task**. A **Manual Task** is designed to allow someone to complete a task outside of the system and then report back that it is complete. You can click the *Continue* button to proceed. When you are done running this process, you can edit the **Process Model** to include a: + + * **Script Task** - write a short snippet of python code to update some data + * **User Task** - generate a form that collects information from a user + * **Service Task** - communicate with an external API to fetch or update some data. + +You can also change the text you are reading here by updating the *Instructions* on this example manual task. + + Flow_17db3yp + Flow_12pkbxb + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/process_models/aviation/check-part/process_model.json b/process_models/aviation/check-part/process_model.json new file mode 100644 index 0000000..801b140 --- /dev/null +++ b/process_models/aviation/check-part/process_model.json @@ -0,0 +1,9 @@ +{ + "description": "Process to check on aviation part", + "display_name": "Check part", + "exception_notification_addresses": [], + "fault_or_suspend_on_exception": "fault", + "metadata_extraction_paths": null, + "primary_file_name": "check-part.bpmn", + "primary_process_id": "Process_check_part_qcpfm3t" +} \ No newline at end of file diff --git a/process_models/aviation/process_group.json b/process_models/aviation/process_group.json new file mode 100644 index 0000000..e7c4a67 --- /dev/null +++ b/process_models/aviation/process_group.json @@ -0,0 +1,5 @@ +{ + "data_store_specifications": {}, + "description": "Group for aviation-related process models", + "display_name": "Aviation" +} \ No newline at end of file