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
3 changes: 1 addition & 2 deletions .github/workflows/build-dev-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,7 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=raw,value=latest-dev,enable={{is_default_branch}}
type=sha,prefix={{branch}}-
type=raw,value=latest,enable={{is_default_branch}}

- name: Build and push Docker image
id: build
Expand Down
33 changes: 22 additions & 11 deletions .github/workflows/build-release-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ jobs:
# Update pom.xml version (without 'v' prefix)
./mvnw versions:set -DnewVersion=$POM_VERSION -DgenerateBackupPoms=false

# Update Helm values.yaml with full release tag (with 'v')
sed -i "s/tag: \".*\"/tag: \"$RELEASE_TAG\"/" deploy/sast-ai-chart/values.yaml
# Update Helm prod values.yaml with full release tag (with 'v')
sed -i "s/tag: \".*\"/tag: \"$RELEASE_TAG\"/" deploy/sast-ai-chart/values-prod.yaml

# Update Helm Chart.yaml versions (without 'v' prefix) - be specific to avoid updating dependency versions
sed -i "s/^version: .*/version: $POM_VERSION/" deploy/sast-ai-chart/Chart.yaml
Expand All @@ -95,16 +95,16 @@ jobs:
# Verify the changes
echo "Updated pom.xml version:"
./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout
echo "Updated values.yaml:"
grep -A 5 -B 5 "tag:" deploy/sast-ai-chart/values.yaml
echo "Updated prod values.yaml:"
grep -A 5 -B 5 "tag:" deploy/sast-ai-chart/values-prod.yaml
echo "Updated Chart.yaml:"
grep -E "(version|appVersion):" deploy/sast-ai-chart/Chart.yaml

- name: Commit version updates
run: |
git config --local user.email "[email protected]"
git config --local user.name "GitHub Action"
git add pom.xml deploy/sast-ai-chart/values.yaml deploy/sast-ai-chart/Chart.yaml
git add pom.xml deploy/sast-ai-chart/values-prod.yaml deploy/sast-ai-chart/Chart.yaml
if git diff --staged --quiet; then
echo "No changes to commit"
else
Expand All @@ -113,8 +113,8 @@ jobs:
git checkout $DEFAULT_BRANCH
git pull origin $DEFAULT_BRANCH
# Re-add and commit the changes
git add pom.xml deploy/sast-ai-chart/values.yaml deploy/sast-ai-chart/Chart.yaml
git commit -m "Update versions to ${{ github.event.release.tag_name }}"
git add pom.xml deploy/sast-ai-chart/values-prod.yaml deploy/sast-ai-chart/Chart.yaml
git commit -m "Update production versions to ${{ github.event.release.tag_name }}"
git push origin $DEFAULT_BRANCH
fi

Expand All @@ -134,23 +134,34 @@ jobs:

## 📦 Container Images

This release includes the following container images published to Quay.io:
This release includes the following container image published to Quay.io:

- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}\`
- \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest\`

### 🐳 Usage

\`\`\`bash
# Pull specific version
# Pull specific version for production
podman pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.event.release.tag_name }}

# Pull latest
# For development, use the latest tag
podman pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
\`\`\`

### 🔗 Registry
View all versions: [Quay.io Repository](https://quay.io/repository/ecosystem-appeng/sast-ai-orchestrator)

### 🚀 Deployment

**Production Deployment (sast-ai-prod namespace):**
\`\`\`bash
make deploy-prod
\`\`\`

**Development Deployment (sast-ai-dev namespace):**
\`\`\`bash
make deploy-dev
\`\`\`
`;

await github.rest.repos.updateRelease({
Expand Down
60 changes: 56 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -385,16 +385,68 @@ MLOps batch endpoints enable automated testing of multiple NVRs (Name-Version-Re

## Deployment

### Environment Strategy

The project supports two deployment environments:

- **Development** (`sast-ai-dev` namespace):
- Uses `latest` container images
- Updated automatically on every main branch push
- Debug logging and relaxed resource limits

- **Production** (`sast-ai-prod` namespace):
- Uses release-tagged container images (e.g., `v1.0.1`)
- Updated only on GitHub releases
- Production-grade resource allocation and logging

### Quick Deployment

```bash
# Development environment
cd deploy
make deploy-dev

# Production environment
cd deploy
make deploy-prod

# Check deployment status
make status
```

### Container Images

- **Development**: `quay.io/ecosystem-appeng/sast-ai-orchestrator:latest`
- **Production**: `quay.io/ecosystem-appeng/sast-ai-orchestrator:v1.0.x`

### Docker Deployment
```bash
# JVM Mode (Fast startup)
docker build -f src/main/docker/Dockerfile.jvm -t sast-ai-orchestrator:jvm .
# Development (latest)
docker run -p 8080:8080 quay.io/ecosystem-appeng/sast-ai-orchestrator:latest

# Production (specific version)
docker run -p 8080:8080 quay.io/ecosystem-appeng/sast-ai-orchestrator:v1.0.1
```

### Kubernetes Deployment
- **Helm Chart**: See `deploy/sast-ai-chart/` for Helm deployment
- **ArgoCD**: See `deploy/argocd/` for GitOps deployment
- **Documentation**: Refer to `deploy/README.md` for detailed instructions
- **ArgoCD**: See `deploy/argocd/` for GitOps deployment
- **Documentation**: Use `make help` in the `deploy/` directory for available commands

### Environment-Specific Access

After deployment, access the applications via OpenShift routes:

```bash
# Get the route URL for production
kubectl get route sast-ai-orchestrator-prod -n sast-ai-prod

# Get the route URL for development
kubectl get route sast-ai-orchestrator-dev -n sast-ai-dev

# Access the API directly via route
curl https://<route-hostname>/api/v1/health
```

## Configuration

Expand Down
141 changes: 90 additions & 51 deletions deploy/Makefile
Original file line number Diff line number Diff line change
@@ -1,89 +1,119 @@
# Detect OpenShift vs Kubernetes
KUBECTL_CMD := $(shell command -v oc 2>/dev/null || echo kubectl)

# Get current namespace from kubectl/oc, fallback to sast-ai-workflow
# Environment-specific settings
DEV_NAMESPACE := sast-ai-dev
PROD_NAMESPACE := sast-ai-prod

# Get current namespace from kubectl/oc, fallback to dev
CURRENT_NAMESPACE := $(shell $(KUBECTL_CMD) config view --minify --output 'jsonpath={..namespace}' 2>/dev/null)
NAMESPACE ?= $(if $(CURRENT_NAMESPACE),$(CURRENT_NAMESPACE),sast-ai-workflow)
NAMESPACE ?= $(if $(CURRENT_NAMESPACE),$(CURRENT_NAMESPACE),$(DEV_NAMESPACE))

RELEASE_NAME ?= sast-ai-orchestrator
CHART_PATH ?= ./sast-ai-chart
HELM_TIMEOUT ?= 300s

.DEFAULT_GOAL := help

.PHONY: deploy
deploy: ## Deploy SAST AI to the cluster
@echo "Deploying SAST AI..."
@echo "Namespace: $(NAMESPACE)"
@echo "Release: $(RELEASE_NAME)"
.PHONY: deploy-dev
deploy-dev: ## Deploy to development environment (sast-ai-dev namespace)
@echo "🚀 Deploying SAST AI to DEVELOPMENT environment..."
@echo "Namespace: $(DEV_NAMESPACE)"
@echo "Release: $(RELEASE_NAME)-dev"
@echo "Using: $(KUBECTL_CMD)"
@$(MAKE) _deploy NAMESPACE=$(DEV_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-dev VALUES_FILE=values-dev.yaml

.PHONY: deploy-prod
deploy-prod: ## Deploy to production environment (sast-ai-prod namespace)
@echo "🚀 Deploying SAST AI to PRODUCTION environment..."
@echo "Namespace: $(PROD_NAMESPACE)"
@echo "Release: $(RELEASE_NAME)-prod"
@echo "Using: $(KUBECTL_CMD)"
@$(MAKE) _deploy NAMESPACE=$(PROD_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-prod VALUES_FILE=values-prod.yaml

.PHONY: _deploy
_deploy: ## Internal deployment target
@helm repo add bitnami https://charts.bitnami.com/bitnami >/dev/null 2>&1 || true
@helm repo update >/dev/null 2>&1
@cd $(CHART_PATH) && helm dependency update
@helm install $(RELEASE_NAME) $(CHART_PATH) \
-f $(CHART_PATH)/values.yaml \
-f $(CHART_PATH)/$(VALUES_FILE) \
-n $(NAMESPACE) \
--create-namespace \
--timeout=$(HELM_TIMEOUT) \
--set app.env.SAST_AI_WORKFLOW_NAMESPACE=$(NAMESPACE)
@echo "Deployment completed!"
@$(MAKE) wait-pods
@echo "Checking for ArgoCD availability..."
@echo "Deployment completed!"
@$(MAKE) wait-pods NAMESPACE=$(NAMESPACE)
@echo "🔍 Checking for ArgoCD availability..."
@if $(KUBECTL_CMD) get crd applications.argoproj.io >/dev/null 2>&1; then \
echo "ArgoCD detected! Creating ArgoCD Application..."; \
$(MAKE) argocd; \
echo "📦 ArgoCD detected! Creating ArgoCD Application..."; \
$(MAKE) argocd NAMESPACE=$(NAMESPACE); \
else \
echo "ArgoCD not available in cluster, skipping ArgoCD Application creation."; \
echo "⚠️ ArgoCD not available in cluster, skipping ArgoCD Application creation."; \
fi
@$(MAKE) show-access
@$(MAKE) show-access NAMESPACE=$(NAMESPACE)

.PHONY: upgrade
upgrade: ## Upgrade existing deployment
@echo "Upgrading SAST AI..."
.PHONY: upgrade-dev
upgrade-dev: ## Upgrade development deployment
@echo "⬆️ Upgrading SAST AI DEVELOPMENT deployment..."
@$(MAKE) _upgrade NAMESPACE=$(DEV_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-dev VALUES_FILE=values-dev.yaml

.PHONY: upgrade-prod
upgrade-prod: ## Upgrade production deployment
@echo "⬆️ Upgrading SAST AI PRODUCTION deployment..."
@$(MAKE) _upgrade NAMESPACE=$(PROD_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-prod VALUES_FILE=values-prod.yaml

.PHONY: _upgrade
_upgrade: ## Internal upgrade target
@helm repo add bitnami https://charts.bitnami.com/bitnami >/dev/null 2>&1 || true
@helm repo update >/dev/null 2>&1
@cd $(CHART_PATH) && helm dependency update
@helm upgrade $(RELEASE_NAME) $(CHART_PATH) \
-f $(CHART_PATH)/values.yaml \
-f $(CHART_PATH)/$(VALUES_FILE) \
-n $(NAMESPACE) \
--timeout=$(HELM_TIMEOUT) \
--set app.env.SAST_AI_WORKFLOW_NAMESPACE=$(NAMESPACE)
@echo "Upgrade completed!"
@$(MAKE) wait
@echo "Upgrade completed!"
@$(MAKE) wait-pods NAMESPACE=$(NAMESPACE)

.PHONY: install
install: deploy ## Alias for deploy
.PHONY: clean-dev
clean-dev: ## Remove development deployment
@echo "🧹 Removing SAST AI DEVELOPMENT deployment..."
@$(MAKE) _clean NAMESPACE=$(DEV_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-dev

.PHONY: clean
clean: ## Remove the deployment
@echo "Removing SAST AI deployment..."
@echo "Checking for ArgoCD Application..."
@if $(KUBECTL_CMD) get crd applications.argoproj.io >/dev/null 2>&1; then \
if $(KUBECTL_CMD) get application $(RELEASE_NAME)-syncer -n $(NAMESPACE) >/dev/null 2>&1; then \
echo "Removing ArgoCD Application..."; \
echo "Removing finalizers to prevent hanging..."; \
$(KUBECTL_CMD) patch application $(RELEASE_NAME)-syncer -n $(NAMESPACE) --type='merge' -p='{"metadata":{"finalizers":[]}}' 2>/dev/null || true; \
$(KUBECTL_CMD) delete application $(RELEASE_NAME)-syncer -n $(NAMESPACE) --ignore-not-found=true; \
echo "ArgoCD Application removed!"; \
else \
echo "ArgoCD Application '$(RELEASE_NAME)-syncer' not found in namespace '$(NAMESPACE)'"; \
fi; \
else \
echo "ArgoCD not available in cluster, skipping ArgoCD Application removal."; \
fi
.PHONY: clean-prod
clean-prod: ## Remove production deployment
@echo "🧹 Removing SAST AI PRODUCTION deployment..."
@$(MAKE) _clean NAMESPACE=$(PROD_NAMESPACE) RELEASE_NAME=$(RELEASE_NAME)-prod

.PHONY: _clean
_clean: ## Internal clean target
@if helm list -n $(NAMESPACE) | grep -q "^$(RELEASE_NAME)"; then \
helm uninstall $(RELEASE_NAME) -n $(NAMESPACE) --timeout=$(HELM_TIMEOUT); \
echo "Deployment removed!"; \
@echo "Cleaning up remaining resources by label..."
@$(KUBECTL_CMD) delete all,pvc,secrets,configmaps,ingress,routes,networkpolicy,pdb,sa,role,rolebinding,job -n $(NAMESPACE) -l "app.kubernetes.io/instance=$(RELEASE_NAME)" --ignore-not-found=true 2>/dev/null || true
@echo "Force cleaning any remaining resources with release name prefix..."
@for resource_type in deployment replicaset pod service configmap secret pvc role rolebinding serviceaccount networkpolicy poddisruptionbudget job cronjob ingress route; do \
$(KUBECTL_CMD) get $$resource_type -n $(NAMESPACE) -o name 2>/dev/null | grep "$(RELEASE_NAME)" | xargs -r $(KUBECTL_CMD) delete -n $(NAMESPACE) --ignore-not-found=true 2>/dev/null || true; \
done
@echo "Cleanup completed!"
echo "✅ Deployment removed from $(NAMESPACE)"; \
else \
echo "Release '$(RELEASE_NAME)' not found in namespace '$(NAMESPACE)'"; \
fi
@echo "Cleaning up remaining resources by label..."
@$(KUBECTL_CMD) delete all,pvc,secrets,configmaps,ingress,routes,networkpolicy,pdb,sa,role,rolebinding,job -n $(NAMESPACE) -l "app.kubernetes.io/instance=$(RELEASE_NAME)" --ignore-not-found=true 2>/dev/null || true
@echo "Force cleaning any remaining resources with release name prefix..."
@for resource_type in deployment replicaset pod service configmap secret pvc role rolebinding serviceaccount networkpolicy poddisruptionbudget job cronjob ingress route; do \
$(KUBECTL_CMD) get $$resource_type -n $(NAMESPACE) -o name 2>/dev/null | grep "$(RELEASE_NAME)" | xargs -r $(KUBECTL_CMD) delete -n $(NAMESPACE) --ignore-not-found=true 2>/dev/null || true; \
done
@echo "Cleanup completed!"

.PHONY: status
status: ## Show deployment status
@echo "📊 SAST AI Deployment Status"
@echo "============================"
@echo ""
@echo "🔍 Development Environment ($(DEV_NAMESPACE)):"
@helm status $(RELEASE_NAME)-dev -n $(DEV_NAMESPACE) 2>/dev/null || echo " ❌ Not deployed"
@echo ""
@echo "🔍 Production Environment ($(PROD_NAMESPACE)):"
@helm status $(RELEASE_NAME)-prod -n $(PROD_NAMESPACE) 2>/dev/null || echo " ❌ Not deployed"

.PHONY: wait-pods
wait-pods: ## Wait for pods to be ready
Expand Down Expand Up @@ -150,10 +180,19 @@ argocd: ## Deploy ArgoCD Application to current namespace

.PHONY: help
help: ## Show this help message
@echo "SAST AI Deployment Helper"
@echo "SAST AI Deployment Commands"
@echo "============================"
@echo ""
@echo "Environment-specific deployments:"
@echo " deploy-dev Deploy to development environment (sast-ai-dev namespace)"
@echo " deploy-prod Deploy to production environment (sast-ai-prod namespace)"
@echo " upgrade-dev Upgrade development deployment"
@echo " upgrade-prod Upgrade production deployment"
@echo " clean-dev Remove development deployment"
@echo " clean-prod Remove production deployment"
@echo ""
@echo " make deploy # Deploy and wait until ready (sast-ai-workflow)"
@echo " make upgrade # Upgrade and wait until ready"
@echo " make clean # Remove deployment"
@echo " make argocd # Deploy ArgoCD Application"
@echo "Utility commands:"
@echo " status Show deployment status for both environments"
@echo " argocd Deploy ArgoCD Application"
@echo ""
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf " %-12s %s\n", $$1, $$2}' $(MAKEFILE_LIST)
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sast-ai-orchestrator-syncer
namespace: $NAMESPACE
name: sast-ai-orchestrator-dev
namespace: argocd
labels:
app.kubernetes.io/name: sast-ai-orchestrator-syncer
app.kubernetes.io/name: sast-ai-orchestrator-dev
app.kubernetes.io/part-of: sast-ai
environment: development
finalizers:
- resources-finalizer.argocd.argoproj.io/background
spec:
Expand All @@ -15,15 +16,16 @@ spec:
targetRevision: HEAD
path: deploy/sast-ai-chart
helm:
releaseName: sast-ai-orchestrator
releaseName: sast-ai-orchestrator-dev
valueFiles:
- values.yaml
- values-dev.yaml
parameters:
- name: app.env.SAST_AI_WORKFLOW_NAMESPACE
value: $NAMESPACE
value: sast-ai-dev
destination:
server: https://kubernetes.default.svc
namespace: $NAMESPACE
namespace: sast-ai-dev
syncPolicy:
automated:
prune: true
Expand All @@ -39,4 +41,4 @@ spec:
duration: 5s
factor: 2
maxDuration: 3m
revisionHistoryLimit: 10
revisionHistoryLimit: 10
Loading