Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a89a9ff
feat(guardrails): scaffold guardrailed_agent directory (RHAIENG-6262)
tarun-etikala Jul 22, 2026
3c3bf96
feat(guardrails): add banking agent source with check_account_balance…
tarun-etikala Jul 22, 2026
c4cc1f7
feat(guardrails): add NeMo Guardrails safety config (RHAIENG-6262)
tarun-etikala Jul 22, 2026
d0914f1
feat(guardrails): add project config files (RHAIENG-6262)
tarun-etikala Jul 22, 2026
6013672
feat(guardrails): add Makefile and Dockerfile (RHAIENG-6262)
tarun-etikala Jul 22, 2026
5c581d5
test(guardrails): add config and packaging tests (RHAIENG-6262)
tarun-etikala Jul 22, 2026
eafa1ff
docs(guardrails): add README for guardrailed agent (RHAIENG-6262)
tarun-etikala Jul 23, 2026
7c57083
fix(guardrails): add missing dataclasses-json dep (RHAIENG-6262)
tarun-etikala Jul 23, 2026
8614e1e
fix(guardrails): fix nemo deps and clarify LLM setup (RHAIENG-6262)
tarun-etikala Jul 23, 2026
f056049
fix(guardrails): use OGX server as LLM backend (RHAIENG-6262)
tarun-etikala Jul 23, 2026
b7b5354
fix(guardrails): add missing ogx-server Makefile target (RHAIENG-6262)
tarun-etikala Jul 23, 2026
49539b4
fix(guardrails): use OGX-compatible model name (RHAIENG-6262)
tarun-etikala Jul 23, 2026
765b6fe
fix(guardrails): enable passthrough and fix api_key (RHAIENG-6262)
tarun-etikala Jul 23, 2026
08463c8
fix(guardrails): use Ollama direct, E2E verified (RHAIENG-6262)
tarun-etikala Jul 27, 2026
f555d20
fix(guardrails): fix ollama target next-steps message (RHAIENG-6262)
tarun-etikala Jul 27, 2026
949f959
fix(guardrails): remove ogx-server target from Makefile (RHAIENG-6262)
tarun-etikala Jul 27, 2026
08d8a6c
fix(guardrails): handle output rail block gracefully (RHAIENG-6262)
tarun-etikala Jul 27, 2026
05abe1a
fix(guardrails): handle output rail block in streaming (RHAIENG-6262)
tarun-etikala Jul 27, 2026
99f4583
fix(guardrails): address review findings (RHAIENG-6262)
tarun-etikala Jul 27, 2026
d284800
fix(guardrails): address remaining review findings (RHAIENG-6262)
tarun-etikala Jul 27, 2026
4f9dba0
docs(guardrails): replace FSI acronym with banking (RHAIENG-6262)
tarun-etikala Jul 27, 2026
ed9ee1c
fix(guardrails): remove unimplemented test targets (RHAIENG-6262)
tarun-etikala Jul 27, 2026
9b4dd10
fix(guardrails): address PR review findings (RHAIENG-6262)
tarun-etikala Jul 27, 2026
1b1dcc4
refactor(guardrails): generate config at startup, not as separate ste…
tarun-etikala Jul 27, 2026
847d8f2
docs(guardrails): add inline comments for pinned deps (RHAIENG-6262)
tarun-etikala Jul 27, 2026
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
18 changes: 18 additions & 0 deletions agents/langgraph/examples/guardrailed_agent/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.env
.env.*
!.env.example
.venv
__pycache__
*.pyc
*.pyo
.pytest_cache
.mypy_cache
.ruff_cache
.git
.gitignore
.helm-secrets.yaml
.DS_Store
tests/
examples/
docs/
*.md
26 changes: 26 additions & 0 deletions agents/langgraph/examples/guardrailed_agent/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Required — agent connects to NeMo Guardrails proxy, not directly to the LLM
API_KEY=not-needed-for-local-development
BASE_URL=http://localhost:8090/v1
MODEL_ID=llama3.1:8b

# NeMo Guardrails — the proxy server that sits between the agent and the LLM
# Start with: make guardrails-server (generates config.yaml from these values)
# GUARDRAILS_PORT=8090
# LLM_BASE_URL=http://localhost:11434/v1

# Deployment
#CONTAINER_IMAGE=

# Auth (local default off; comma-separate multiple allowlist entries)
# AUTH_ENABLED=false
# AUTH_AUDIENCE=langgraph-guardrailed-agent
# AUTH_ALLOWED_SERVICEACCOUNTS=ci-testing:langgraph-guardrailed-agent-caller

# Optional — MLflow Tracing
# Tracing is opt-in: if MLFLOW_TRACKING_URI is not set, the agent runs without MLflow.
# Note: MLflow traces show the overall request but not guardrails internals.
# NeMo Guardrails appears as a regular ChatOpenAI endpoint in MLflow.

# --- Local MLflow server (no auth, no TLS) ---
# MLFLOW_TRACKING_URI=http://localhost:5000
# MLFLOW_EXPERIMENT_NAME=langgraph-guardrailed-agent
6 changes: 6 additions & 0 deletions agents/langgraph/examples/guardrailed_agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Local environment (may contain API keys)
.env

# NeMo Guardrails config is generated at startup by `make guardrails-server`
# from .env values — may contain API_KEY, never commit.
guardrails/safety/config.yaml
47 changes: 47 additions & 0 deletions agents/langgraph/examples/guardrailed_agent/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Use Red Hat UBI9 Python 3.12 image (no Docker Hub rate limits on OpenShift)
# To update: docker pull registry.access.redhat.com/ubi9/python-312:latest
# docker inspect --format='{{index .RepoDigests 0}}' registry.access.redhat.com/ubi9/python-312:latest
FROM registry.access.redhat.com/ubi9/python-312@sha256:e95978812895b9abb2bdc109b501078da2a47c8dbb9fa23758af40ed50ab6023
WORKDIR /opt/app-root/src/agents/langgraph/examples/guardrailed_agent

# Switch to root for installing dependencies
USER 0

# Install uv for fast dependency management (v0.11.1)
# To update: docker pull ghcr.io/astral-sh/uv:latest
# docker inspect --format='{{index .RepoDigests 0}}' ghcr.io/astral-sh/uv:latest
COPY --from=ghcr.io/astral-sh/uv@sha256:fc93e9ecd7218e9ec8fba117af89348eef8fd2463c50c13347478769aaedd0ce /uv /usr/local/bin/uv

# Copy project files for dependency installation.
# Keep the repo-relative layout so ../../../../components/auth resolves.
COPY pyproject.toml .
COPY src/ ./src/
COPY components/auth/ /opt/app-root/src/components/auth/

# Install the project and its dependencies using uv
# NeMo Guardrails runs as a separate pod in production (managed by NemoGuardrails CRD),
# so the [guardrails] extra is intentionally omitted from the agent container image.
RUN uv pip install --no-cache ".[tracing,auth]"

# Copy the application entrypoint, playground UI, and images
COPY main.py .
COPY playground/ ./playground/
COPY images/ ./images/

# Make everything group-writable (GID 0) for OpenShift arbitrary UID support
RUN chown -R 1001:0 /opt/app-root/src \
&& chmod -R g=u /opt/app-root/src

# Switch back to default non-root user
USER 1001

# Expose port 8080 (OpenShift standard)
EXPOSE 8080

# Set environment variables
ENV PORT=8080
ENV HOME=/opt/app-root
ENV PYTHONPATH=/opt/app-root/src/agents/langgraph/examples/guardrailed_agent

# Run the application — reads PORT at runtime
CMD ["sh", "-c", "uvicorn main:app --host 0.0.0.0 --port ${PORT}"]
212 changes: 212 additions & 0 deletions agents/langgraph/examples/guardrailed_agent/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
SHELL := bash
AGENT_NAME := $(shell python3 -c "import re; print(re.search(r'^name:\s*(.+)', open('agent.yaml').read(), re.M).group(1).strip())")
CHART_DIR := ../../deployment
VALUES_FILE := values.yaml
CONTAINER_CLI := $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null)
MODEL ?= llama3.1:8b

.PHONY: init re-init env ollama run-app run-app-fresh build push build-openshift deploy undeploy test dry-run help guardrails-server

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Mark _check-env as phony.

deploy depends on _check-env, but this target is absent from .PHONY. If a file named _check-env exists, make can skip the required environment validation and continue with missing deployment settings. Add _check-env to the .PHONY list.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agents/langgraph/examples/guardrailed_agent/Makefile` at line 8, Update the
.PHONY declaration to include the _check-env target, ensuring deploy always
executes its environment validation even when a file named _check-env exists.


help: ## Show this help
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf " %-20s %s\n", $$1, $$2}'

re-init: ## Activate venv and reload .env variables
@source .venv/bin/activate && set -a && source .env && set +a && \
echo "Venv activated and .env variables loaded."

init: ## Copy .env.example to .env for configuration
@if [ ! -f .env ]; then cp .env.example .env && echo "Created .env from .env.example - edit it with your configuration"; else echo ".env already exists - skipping"; fi
Comment thread
tarun-etikala marked this conversation as resolved.
Resolved

env: ## Create venv, load .env, and install dependencies (including NeMo Guardrails)
@echo "==> Creating virtual environment and installing dependencies..." && \
rm -rf .venv && \
uv sync --python 3.12 --extra guardrails && \
echo "==> Load .env variables..." && \
source .venv/bin/activate && set -a && source .env && set +a && \
echo "" && \
echo "Done. Next steps:" && \
echo " make ollama # install Ollama and pull models" && \
echo " make guardrails-server # start NeMo Guardrails proxy" && \
echo " make run-app # start the agent"

ollama: ## Install Ollama, start it, and pull models
@source .venv/bin/activate && set -a && source .env && set +a && \
if command -v ollama >/dev/null 2>&1; then \
echo "==> Ollama already installed, skipping..."; \
else \
echo "==> Installing Ollama..." && \
curl -fsSL https://ollama.com/install.sh | sh; \
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
fi && \
echo "==> Starting Ollama service..." && \
ollama serve &>/dev/null & \
OLLAMA_PID=$$! && \
echo "Waiting for Ollama to be ready (max 30s)..." && \
OLLAMA_WAIT=0 && \
until ollama list >/dev/null 2>&1; do \
OLLAMA_WAIT=$$((OLLAMA_WAIT + 1)); \
if [ $$OLLAMA_WAIT -ge 30 ]; then \
echo "ERROR: Ollama failed to start within 30 seconds." && \
kill $$OLLAMA_PID 2>/dev/null; \
exit 1; \
fi; \
sleep 1; \
done && \
echo "==> Pulling $(MODEL)..." && \
ollama pull $(MODEL) && \
echo "" && \
echo "Done. Run 'make guardrails-server' to start NeMo Guardrails."

guardrails-server: ## Generate config from .env and start NeMo Guardrails proxy
@source .venv/bin/activate && set -a && source .env && set +a && \
cp guardrails/safety/config.yaml.example guardrails/safety/config.yaml && \
python3 -c "\
import yaml; \
f='guardrails/safety/config.yaml'; \
c=yaml.safe_load(open(f)); \
url='$${LLM_BASE_URL:-http://localhost:11434/v1}'; \
model='$${MODEL_ID:-llama3.1:8b}'; \
key='$${API_KEY:-not-needed}'; \
[m['parameters'].update(base_url=url, api_key=key) or m.update(model=model) for m in c['models']]; \
yaml.dump(c, open(f,'w'), default_flow_style=False, sort_keys=False); \
Comment thread
tarun-etikala marked this conversation as resolved.
Resolved
print(f'Config generated: LLM_BASE_URL={url} MODEL_ID={model}')" && \
echo "Starting NeMo Guardrails server on port $${GUARDRAILS_PORT:-8090}..." && \
nemoguardrails server --config guardrails --default-config-id safety --port $${GUARDRAILS_PORT:-8090} --disable-chat-ui

run-app: ## Run agent locally with hot-reload
@source .venv/bin/activate && set -a && source .env && set +a && \
if lsof -ti:$${PORT:-8000} >/dev/null 2>&1; then \
echo "ERROR: Port $${PORT:-8000} is already in use." && \
echo " Change PORT in .env or run: make run-app-fresh" && \
exit 1; \
fi && \
uv run $${MLFLOW_TRACKING_URI:+--extra tracing} uvicorn main:app --host 127.0.0.1 --port $${PORT:-8000} --reload --reload-exclude .venv

run-app-fresh: ## Kill existing process on port and run agent with hot-reload
@source .venv/bin/activate && set -a && source .env && set +a && \
echo "==> Killing existing process on port $${PORT:-8000}..." && \
lsof -ti:$${PORT:-8000} | xargs kill -9 2>/dev/null; true && \
uv run $${MLFLOW_TRACKING_URI:+--extra tracing} uvicorn main:app --host 127.0.0.1 --port $${PORT:-8000} --reload --reload-exclude .venv

build: ## Build container image locally (podman/docker)
@[ -n "$(CONTAINER_CLI)" ] || { echo "ERROR: neither podman nor docker found in PATH"; exit 1; } && \
source .env && \
[ -n "$${CONTAINER_IMAGE}" ] || { echo "ERROR: CONTAINER_IMAGE is not set in .env"; exit 1; } && \
cp -r ../../../../images ./images && \
mkdir -p ./components && cp -r ../../../../components/auth ./components/auth && \
trap 'rm -rf ./images ./components/auth; rmdir ./components 2>/dev/null || true' EXIT && \
$(CONTAINER_CLI) build --platform linux/amd64 -t "$${CONTAINER_IMAGE}" -f Dockerfile .

push: ## Push container image to registry
@[ -n "$(CONTAINER_CLI)" ] || { echo "ERROR: neither podman nor docker found in PATH"; exit 1; } && \
source .env && \
[ -n "$${CONTAINER_IMAGE}" ] || { echo "ERROR: CONTAINER_IMAGE is not set in .env"; exit 1; } && \
$(CONTAINER_CLI) push "$${CONTAINER_IMAGE}"

build-openshift: ## Build image in-cluster via OpenShift BuildConfig (no podman/docker needed)
@cp -r ../../../../images ./images && \
mkdir -p ./components && cp -r ../../../../components/auth ./components/auth && \
trap 'rm -rf ./images ./components/auth; rmdir ./components 2>/dev/null || true' EXIT && \
oc new-build --strategy=docker --binary --name=$(AGENT_NAME) --to=$(AGENT_NAME):latest 2>/dev/null || true && \
oc start-build $(AGENT_NAME) --from-dir=. --follow && \
NS=$$(oc project -q) && \
echo "" && \
echo "Image built. To deploy, set in .env:" && \
echo " CONTAINER_IMAGE=image-registry.openshift-image-registry.svc:5000/$$NS/$(AGENT_NAME):latest"

_check-env:
@set -a && source .env 2>/dev/null && set +a; \
missing=""; \
for var in $$(sed -n '/^ *required:/,/^ *[a-z]/{ /^ *- /s/^ *- *//p; }' agent.yaml); do \
eval val="\$$$$var"; \
[ -n "$$val" ] || missing="$$missing $$var"; \
done; \
[ -z "$$missing" ] || { echo "ERROR: Missing required env vars:$$missing"; exit 1; }

deploy: _check-env ## Deploy to OpenShift/K8s via Helm
@source .env && \
AUTH_ALLOWLIST="$${AUTH_ALLOWED_SERVICEACCOUNTS:-$${AUTH_ALLOWED_SERVICEACCOUNT}}" && \
AUTH_ALLOWLIST_ARGS="" && \
if [ -n "$$AUTH_ALLOWLIST" ]; then \
IFS=',' read -r -a AUTH_ALLOWLIST_ITEMS <<< "$$AUTH_ALLOWLIST"; \
for idx in "$${!AUTH_ALLOWLIST_ITEMS[@]}"; do \
account="$${AUTH_ALLOWLIST_ITEMS[$$idx]}"; \
account="$$(echo -n "$$account" | tr -d '[:space:]')"; \
[ -n "$$account" ] || continue; \
AUTH_ALLOWLIST_ARGS="$$AUTH_ALLOWLIST_ARGS --set-string auth.allowedServiceAccounts[$$idx]=$$account"; \
done; \
fi && \
[ -n "$${CONTAINER_IMAGE}" ] || { echo "ERROR: CONTAINER_IMAGE is not set in .env"; exit 1; } && \
LAST_SEG="$${CONTAINER_IMAGE##*/}" && if [[ "$$LAST_SEG" == *:* ]]; then IMAGE_REPO="$${CONTAINER_IMAGE%:*}"; IMAGE_TAG="$${LAST_SEG##*:}"; else IMAGE_REPO="$${CONTAINER_IMAGE}"; IMAGE_TAG="latest"; fi && \
trap 'rm -f .helm-secrets.yaml' EXIT && \
umask 077 && \
{ printf 'secrets:\n apiKey: "%s"\n' "$${API_KEY}"; \
[ -z "$${MLFLOW_TRACKING_TOKEN}" ] || printf ' mlflowTrackingToken: "%s"\n' "$${MLFLOW_TRACKING_TOKEN}"; \
} > .helm-secrets.yaml && \
Comment on lines +140 to +144

@coderabbitai coderabbitai Bot Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Serialize Helm secrets without manual YAML interpolation.

API keys and MLflow tokens may legally contain ", \, or newlines; printf inserts them unescaped into .helm-secrets.yaml, producing invalid or changed secret values. Use Helm --set-file with temporary secret files, or a real YAML serializer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agents/langgraph/examples/guardrailed_agent/Makefile` around lines 142 - 146,
Update the Helm secret generation flow near the Makefile recipe’s temporary
.helm-secrets.yaml creation to avoid manually interpolating API_KEY and
MLFLOW_TRACKING_TOKEN into YAML. Use Helm’s --set-file with securely created
temporary files, or an existing real YAML serializer, so quotes, backslashes,
and newlines are preserved exactly; retain cleanup and restrictive permissions
for all temporary secret files.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged — same pattern in all agents' Makefiles across the repo. Will track as a cross-agent improvement separately.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tarun-etikala, acknowledged. The finding remains valid but is reasonable to address as a cross-agent follow-up rather than in this PR. Would you like me to open a GitHub issue capturing the affected Makefile pattern and acceptance criteria?

Comment on lines +142 to +144

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Helm secrets still serialized via manual printf interpolation.

API_KEY/MLFLOW_TRACKING_TOKEN may contain ", \, or newlines, which printf won't escape, producing an invalid/corrupted .helm-secrets.yaml. Prefer --set-file with temp files or a real YAML serializer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agents/langgraph/examples/guardrailed_agent/Makefile` around lines 142 - 144,
The Makefile’s Helm secret generation block still interpolates API_KEY and
MLFLOW_TRACKING_TOKEN directly into YAML via printf. Replace the manual
serialization in the target recipe with Helm --set-file using securely created
temporary files (or an existing YAML serializer), preserving omission of
MLFLOW_TRACKING_TOKEN when unset and ensuring both values remain valid for
quotes, backslashes, and newlines.

helm upgrade --install $(AGENT_NAME) $(CHART_DIR) \
-f $(VALUES_FILE) \
-f .helm-secrets.yaml \
--set image.repository="$${IMAGE_REPO}" \
--set image.tag="$${IMAGE_TAG}" \
--set env.BASE_URL="$${BASE_URL}" \
--set env.MODEL_ID="$${MODEL_ID}" \
$${AUTH_ENABLED:+--set "auth.enabled=$${AUTH_ENABLED}"} \
$${AUTH_ENABLED:+--set "serviceAccount.create=$${AUTH_ENABLED}"} \
$${AUTH_AUDIENCE:+--set-string "auth.audience=$${AUTH_AUDIENCE}"} \
$${AUTH_ALLOWLIST_ARGS} \
$${MLFLOW_TRACKING_URI:+--set env.MLFLOW_TRACKING_URI="$${MLFLOW_TRACKING_URI}"} \
$${MLFLOW_EXPERIMENT_NAME:+--set env.MLFLOW_EXPERIMENT_NAME="$${MLFLOW_EXPERIMENT_NAME}"} \
$${MLFLOW_TRACKING_AUTH:+--set env.MLFLOW_TRACKING_AUTH="$${MLFLOW_TRACKING_AUTH}"} \
$${MLFLOW_TRACKING_INSECURE_TLS:+--set env.MLFLOW_TRACKING_INSECURE_TLS="$${MLFLOW_TRACKING_INSECURE_TLS}"} \
$${MLFLOW_TRACKING_SERVER_CERT_PATH:+--set env.MLFLOW_TRACKING_SERVER_CERT_PATH="$${MLFLOW_TRACKING_SERVER_CERT_PATH}"} \
$${MLFLOW_WORKSPACE:+--set env.MLFLOW_WORKSPACE="$${MLFLOW_WORKSPACE}"} && \
if command -v oc >/dev/null 2>&1; then \
echo "" && echo "Waiting for rollout to complete..." && \
if oc rollout status deployment/$(AGENT_NAME) --timeout=120s; then \
ROUTE=$$(oc get route $(AGENT_NAME) -o jsonpath='{.spec.host}' 2>/dev/null || true); \
if [ -n "$$ROUTE" ]; then echo "" && echo "Agent is available at: https://$$ROUTE"; fi; \
else \
echo "" && echo "WARNING: Rollout did not complete successfully. Check pod status with:" && \
echo " oc get pods -l app.kubernetes.io/name=$(AGENT_NAME)" && \
echo " oc logs deployment/$(AGENT_NAME)"; \
fi; \
fi

dry-run: _check-env ## Render Helm templates without deploying
@source .env && \
AUTH_ALLOWLIST="$${AUTH_ALLOWED_SERVICEACCOUNTS:-$${AUTH_ALLOWED_SERVICEACCOUNT}}" && \
AUTH_ALLOWLIST_ARGS="" && \
if [ -n "$$AUTH_ALLOWLIST" ]; then \
IFS=',' read -r -a AUTH_ALLOWLIST_ITEMS <<< "$$AUTH_ALLOWLIST"; \
for idx in "$${!AUTH_ALLOWLIST_ITEMS[@]}"; do \
account="$${AUTH_ALLOWLIST_ITEMS[$$idx]}"; \
account="$$(echo -n "$$account" | tr -d '[:space:]')"; \
[ -n "$$account" ] || continue; \
AUTH_ALLOWLIST_ARGS="$$AUTH_ALLOWLIST_ARGS --set-string auth.allowedServiceAccounts[$$idx]=$$account"; \
done; \
fi && \
[ -n "$${CONTAINER_IMAGE}" ] || { echo "ERROR: CONTAINER_IMAGE is not set in .env"; exit 1; } && \
LAST_SEG="$${CONTAINER_IMAGE##*/}" && if [[ "$$LAST_SEG" == *:* ]]; then IMAGE_REPO="$${CONTAINER_IMAGE%:*}"; IMAGE_TAG="$${LAST_SEG##*:}"; else IMAGE_REPO="$${CONTAINER_IMAGE}"; IMAGE_TAG="latest"; fi && \
helm template $(AGENT_NAME) $(CHART_DIR) \
-f $(VALUES_FILE) \
--set secrets.apiKey="REDACTED" \
--set image.repository="$${IMAGE_REPO}" \
--set image.tag="$${IMAGE_TAG}" \
--set env.BASE_URL="$${BASE_URL}" \
--set env.MODEL_ID="$${MODEL_ID}" \
$${AUTH_ENABLED:+--set "auth.enabled=$${AUTH_ENABLED}"} \
$${AUTH_ENABLED:+--set "serviceAccount.create=$${AUTH_ENABLED}"} \
$${AUTH_AUDIENCE:+--set-string "auth.audience=$${AUTH_AUDIENCE}"} \
$${AUTH_ALLOWLIST_ARGS} \
$${MLFLOW_TRACKING_URI:+--set env.MLFLOW_TRACKING_URI="$${MLFLOW_TRACKING_URI}"} \
$${MLFLOW_TRACKING_TOKEN:+--set secrets.mlflowTrackingToken="REDACTED"} \
$${MLFLOW_EXPERIMENT_NAME:+--set env.MLFLOW_EXPERIMENT_NAME="$${MLFLOW_EXPERIMENT_NAME}"} \
$${MLFLOW_TRACKING_AUTH:+--set env.MLFLOW_TRACKING_AUTH="$${MLFLOW_TRACKING_AUTH}"} \
$${MLFLOW_TRACKING_INSECURE_TLS:+--set env.MLFLOW_TRACKING_INSECURE_TLS="$${MLFLOW_TRACKING_INSECURE_TLS}"} \
$${MLFLOW_TRACKING_SERVER_CERT_PATH:+--set env.MLFLOW_TRACKING_SERVER_CERT_PATH="$${MLFLOW_TRACKING_SERVER_CERT_PATH}"} \
$${MLFLOW_WORKSPACE:+--set env.MLFLOW_WORKSPACE="$${MLFLOW_WORKSPACE}"}

undeploy: ## Remove deployment from cluster
helm uninstall $(AGENT_NAME)

test: ## Run unit tests
uv run --extra dev python -m pytest tests/ $(PYTEST_ARGS)
Loading
Loading