27 Commits

Author SHA1 Message Date
Mondo Diaz
06c9038858 Add post-deployment integration tests
Adds integration test jobs that run after deployment to verify the
deployed application is functioning correctly. Tests cover:
- Health endpoint
- Project creation
- Package creation
- Artifact upload
- Artifact download (with content verification)
- Artifact listing

Each test run creates isolated resources (using unique IDs) and
cleans up after itself. Tests run against the deployed URL for
both stage (main branch) and feature branch deployments.
2026-01-13 23:02:47 +00:00
Mondo Diaz
b90e478f4b Run only unit tests in CI test stage
Integration tests require Docker Compose services (PostgreSQL, MinIO, Redis)
which aren't available in the CI container. Unit tests run independently.
2026-01-13 23:01:08 +00:00
Mondo Diaz
b6e5a0fa4d Remove exists rule from frontend_tests for consistent behavior 2026-01-13 22:53:32 +00:00
Mondo Diaz
22c173ec37 Enhance test jobs with caching, coverage, and parallel execution
CI improvements:
- Add needs: [] to run tests parallel with build (faster pipeline)
- Add pip/npm caching (faster subsequent runs)
- Add 15m timeout to prevent hung jobs
- Add pytest coverage with cobertura report for GitLab
- Add pytest JUnit report for test tab in MR
- Add vitest coverage with cobertura report for GitLab
- Add coverage regex for badge display

Frontend:
- Add @vitest/coverage-v8 dependency
- Configure vitest coverage reporter (text, cobertura, html)
2026-01-13 22:50:50 +00:00
Mondo Diaz
acd31129e9 Use deps.global.bsf.tools registry for frontend_tests image 2026-01-13 22:45:12 +00:00
Mondo Diaz
b74276ba70 Fix frontend_tests to use correct container registry 2026-01-13 22:44:27 +00:00
Mondo Diaz
085ed898e2 Refactor CI pipeline with templates and add frontend tests
- Add frontend_tests job (npm run test with Vitest)
- Add verification checks to deploy_stage (health, API, frontend)
- Extract shared YAML anchors: deploy_template, helm_setup, verify_deployment
- Reduce code duplication across deploy jobs
2026-01-13 22:43:21 +00:00
Mondo Diaz
4ec91b46ed Fix security scan issues and harden docker-compose
Hadolint fixes:
- Use printf instead of echo for escape sequences
- Add hadolint ignore for apt pin version (DL3008)

KICS fixes (docker-compose):
- Add security_opt: no-new-privileges to all services
- Add mem_limit and cpus to prevent resource exhaustion
- Add healthcheck to orchard-server in docker-compose.yml

Gitleaks:
- Add .gitleaksignore for false positive (s3_key attribute name)
- Remove allow_failure from secrets job (now blocking)

Also:
- Remove || echo fallback from python_tests (tests should fail pipeline)
2026-01-13 22:40:51 +00:00
Mondo Diaz
d6644e9039 Add comprehensive deployment verification
- Health endpoint polling with retry loop
- API check (GET /api/v1/projects returns 200)
- Frontend check (HTML is served)
- Clear output with section headers
2026-01-13 22:28:48 +00:00
Mondo Diaz
f1b0c93f30 Add deployment verification with health check polling
- Add --wait --timeout 5m to helm upgrade
- Add kubectl rollout status check
- Poll health endpoint for up to 5 minutes (for cert provisioning)
2026-01-13 22:28:30 +00:00
Mondo Diaz
69180dd9eb Add PROSPER-NOTES.md to gitignore 2026-01-13 22:20:45 +00:00
Mondo Diaz
b07b6a8f8f Add build_image dependency to deploy jobs 2026-01-13 22:14:31 +00:00
Mondo Diaz
ace643bb2e Fix image tag format to match Prosper output (git.linux-amd64-SHA) 2026-01-13 22:06:02 +00:00
Mondo Diaz
f1aae057ed Clean up CI pipeline and remove unused values files
- Use branch name (CI_COMMIT_REF_SLUG) instead of commit SHA for feature IDs
- Remove commented-out code and unused deploy template
- Fix deploy_stage to use kubectl config use-context
- Remove values-production.yaml and values-external.yaml
2026-01-13 21:51:50 +00:00
Mondo Diaz
66515f24d4 Add kubectl context to cleanup_feature job 2026-01-13 21:49:28 +00:00
Mondo Diaz
892f63e685 Fix helm path by returning to project root before deploy 2026-01-13 21:37:37 +00:00
Mondo Diaz
cd7c930176 Use kubectl config use-context for agent authentication 2026-01-13 21:28:10 +00:00
Mondo Diaz
0bbfe38293 Test: hardcode agent path to rule out variable interpolation 2026-01-13 21:12:08 +00:00
Mondo Diaz
86567b4ae1 Add GitLab Agent configs with CI/CD access for deployments 2026-01-13 20:08:29 +00:00
Mondo Diaz
d3a47f6167 Fix GitLab Agent paths to use full project:agent format 2026-01-13 19:32:09 +00:00
Armando Diaz
089d4a50df update jobs to use correct image and agents. 2026-01-13 12:05:16 -06:00
Mondo Diaz
f6b79a7af0 Add feature branch deployment pipeline
- Add deploy_feature job for ephemeral dev environments
- Use unique identifier (feat-{short_sha}) for K8s resource isolation
- Dynamic hostnames for ingress (orchard-{sha}.common.global.bsf.tools)
- Add cleanup_feature job with on_stop for automatic cleanup on merge
- Add values-dev.yaml with lighter resources for ephemeral deployments
- Refactor deploy_stage to use dynamic image tag from CI
2026-01-13 16:45:48 +00:00
Dane Moss
deda96795b comment out rule block for now 2026-01-13 16:43:49 +00:00
Dane Moss
f555dd6bde try another rule 2026-01-13 16:43:49 +00:00
Dane Moss
36b79485ba update job name 2026-01-13 16:43:49 +00:00
Dane Moss
b58deb4a60 Update .gitlab-ci.yml file 2026-01-13 16:43:49 +00:00
Dane Moss
d3bacfe6b6 Update 2 files
- /helm/orchard/values-stage.yaml
- /.gitlab-ci.yml
2026-01-13 16:43:49 +00:00
15 changed files with 761 additions and 165 deletions

1
.gitignore vendored
View File

@@ -65,3 +65,4 @@ temp/
.claude/
CLAUDE.md
AGENTS.md
PROSPER-NOTES.md

View File

@@ -7,45 +7,351 @@ variables:
# renovate: datasource=gitlab-tags depName=esv/bsf/pypi/prosper versioning=semver registryUrl=https://gitlab.global.bsf.tools
PROSPER_VERSION: v0.64.1
stages:
- build
- test
- deploy
- integration # Post-deployment integration tests
kics:
allow_failure: true
hadolint:
allow_failure: true
secrets:
allow_failure: true
# secrets job is a blocking check
# Run Python tests
# Post-deployment integration tests template
.integration_test_template: &integration_test_template
stage: integration
image: deps.global.bsf.tools/docker/python:3.12-slim
timeout: 10m
before_script:
- pip install httpx
script:
- |
python - <<'PYTEST_SCRIPT'
import httpx
import os
import sys
import uuid
import hashlib
BASE_URL = os.environ.get("BASE_URL")
if not BASE_URL:
print("ERROR: BASE_URL not set")
sys.exit(1)
print(f"Running integration tests against {BASE_URL}")
client = httpx.Client(base_url=BASE_URL, timeout=30.0)
# Generate unique names for this test run
test_id = uuid.uuid4().hex[:8]
project_name = f"ci-test-{test_id}"
package_name = f"test-package-{test_id}"
test_content = f"Test content from CI pipeline {test_id}"
expected_hash = hashlib.sha256(test_content.encode()).hexdigest()
errors = []
try:
# Test 1: Health endpoint
print("\n=== Test 1: Health endpoint ===")
r = client.get("/health")
if r.status_code == 200:
print("PASS: Health check passed")
else:
errors.append(f"Health check failed: {r.status_code}")
# Test 2: Create project
print("\n=== Test 2: Create project ===")
r = client.post("/api/v1/projects", json={"name": project_name})
if r.status_code == 201:
print(f"PASS: Created project: {project_name}")
else:
errors.append(f"Failed to create project: {r.status_code} - {r.text}")
# Test 3: Create package
print("\n=== Test 3: Create package ===")
r = client.post(f"/api/v1/project/{project_name}/packages", json={"name": package_name})
if r.status_code == 201:
print(f"PASS: Created package: {package_name}")
else:
errors.append(f"Failed to create package: {r.status_code} - {r.text}")
# Test 4: Upload artifact
print("\n=== Test 4: Upload artifact ===")
files = {"file": ("test.txt", test_content.encode(), "text/plain")}
r = client.post(f"/api/v1/project/{project_name}/{package_name}/upload", files=files)
if r.status_code == 201:
upload_data = r.json()
print(f"PASS: Uploaded artifact: {upload_data.get('artifact_id', 'unknown')[:16]}...")
else:
errors.append(f"Failed to upload: {r.status_code} - {r.text}")
# Test 5: Download artifact by hash
print("\n=== Test 5: Download artifact ===")
r = client.get(f"/api/v1/project/{project_name}/{package_name}/+/artifact:{expected_hash}", follow_redirects=True)
if r.status_code == 200:
if r.content.decode() == test_content:
print("PASS: Downloaded content matches uploaded content")
else:
errors.append(f"Content mismatch: got '{r.content.decode()}'")
else:
errors.append(f"Failed to download: {r.status_code}")
# Test 6: List artifacts
print("\n=== Test 6: List artifacts ===")
r = client.get(f"/api/v1/project/{project_name}/{package_name}/artifacts")
if r.status_code == 200:
artifacts = r.json()
print(f"PASS: Found {len(artifacts)} artifact(s)")
else:
errors.append(f"Failed to list artifacts: {r.status_code}")
finally:
# Cleanup: Delete the test project
print("\n=== Cleanup ===")
r = client.delete(f"/api/v1/project/{project_name}")
if r.status_code in (200, 204):
print(f"PASS: Cleaned up project: {project_name}")
else:
print(f"Warning: Failed to cleanup project: {r.status_code}")
# Report results
print("\n" + "=" * 50)
if errors:
print(f"FAILED: {len(errors)} error(s)")
for e in errors:
print(f" FAIL: {e}")
sys.exit(1)
else:
print("SUCCESS: All integration tests passed!")
sys.exit(0)
PYTEST_SCRIPT
# Integration tests for stage deployment
integration_test_stage:
<<: *integration_test_template
needs: [deploy_stage]
variables:
BASE_URL: https://orchard-stage.common.global.bsf.tools
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# Integration tests for feature deployment
integration_test_feature:
<<: *integration_test_template
needs: [deploy_feature]
variables:
BASE_URL: https://orchard-$CI_COMMIT_REF_SLUG.common.global.bsf.tools
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: always
# Run Python backend tests
python_tests:
stage: test
needs: [] # Run in parallel with build
image: deps.global.bsf.tools/docker/python:3.12-slim
timeout: 15m
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
cache:
key: pip-$CI_COMMIT_REF_SLUG
paths:
- .pip-cache/
policy: pull-push
before_script:
- pip install -r backend/requirements.txt
- pip install pytest pytest-asyncio httpx
- pip install pytest pytest-asyncio pytest-cov httpx
script:
- cd backend
- python -m pytest -v || echo "No tests yet"
# Only run unit tests - integration tests require Docker Compose services
- python -m pytest tests/unit/ -v --cov=app --cov-report=term --cov-report=xml:coverage.xml --cov-report=html:coverage_html --junitxml=pytest-report.xml
artifacts:
when: always
expire_in: 1 week
paths:
- backend/coverage.xml
- backend/coverage_html/
- backend/pytest-report.xml
reports:
junit: backend/pytest-report.xml
coverage_report:
coverage_format: cobertura
path: backend/coverage.xml
coverage: '/TOTAL.*\s+(\d+%)/'
# deploy_helm_charts:
# stage: deploy
# image:
# name: deps.global.bsf.tools/registry-1.docker.io/alpine/k8s:1.29.12
# parallel:
# matrix:
# # - ENV: "prod"
# # VALUES_FILE: "helm/values-prod.yaml"
# # CONTEXT: "esv/bsf/bsf-services/gitlab-kaas-agent-config:services-prod-agent"
# # NAMESPACE: "bsf-services-namespace"
# # ONLY: "main"
# - ENV: "dev"
# VALUES_FILE: "helm/orchard/values.yaml"
# CONTEXT: "esv/bsf/bsf-services/gitlab-kaas-agent-config:services-prod-agent"
# NAMESPACE: "bsf-services-dev-namespace"
# # ONLY: ["branches", "!main"]
# script:
# - kubectl config use-context $CONTEXT
# - echo "Deploy - buildah push ${IMAGE_NAME}:latest"
# - |
# helm upgrade --install orchard-dev ./helm/orchard --namespace $NAMESPACE -f $VALUES_FILE
# Run frontend tests
frontend_tests:
stage: test
needs: [] # Run in parallel with build
image: deps.global.bsf.tools/docker/node:20-alpine
timeout: 15m
cache:
key: npm-$CI_COMMIT_REF_SLUG
paths:
- frontend/node_modules/
policy: pull-push
before_script:
- cd frontend
- npm ci
script:
- npm run test -- --run --reporter=verbose --coverage
artifacts:
when: always
expire_in: 1 week
paths:
- frontend/coverage/
reports:
coverage_report:
coverage_format: cobertura
path: frontend/coverage/cobertura-coverage.xml
coverage: '/All files[^|]*\|[^|]*\s+([\d\.]+)/'
# Shared deploy configuration
.deploy_template: &deploy_template
stage: deploy
needs: [build_image]
image: deps.global.bsf.tools/registry-1.docker.io/alpine/k8s:1.29.12
.helm_setup: &helm_setup
- helm version
- helm repo add stable https://charts.helm.sh/stable
- helm repo add bitnami https://charts.bitnami.com/bitnami
- cd helm/orchard
- helm dependency update
- helm repo update
.verify_deployment: &verify_deployment |
echo "=== Waiting for health endpoint (certs may take a few minutes) ==="
for i in $(seq 1 30); do
if curl -sf --max-time 10 "$BASE_URL/health" > /dev/null 2>&1; then
echo "Health check passed!"
break
fi
echo "Attempt $i/30 - waiting 10s..."
sleep 10
done
# Verify health endpoint
echo ""
echo "=== Health Check ==="
curl -sf "$BASE_URL/health" || { echo "Health check failed"; exit 1; }
echo ""
# Verify API is responding
echo ""
echo "=== API Check (GET /api/v1/projects) ==="
HTTP_CODE=$(curl -sf -o /dev/null -w "%{http_code}" "$BASE_URL/api/v1/projects")
if [ "$HTTP_CODE" = "200" ]; then
echo "API responding: HTTP $HTTP_CODE"
else
echo "API check failed: HTTP $HTTP_CODE"
exit 1
fi
# Verify frontend is served
echo ""
echo "=== Frontend Check ==="
if curl -sf "$BASE_URL/" | grep -q "</html>"; then
echo "Frontend is being served"
else
echo "Frontend check failed"
exit 1
fi
echo ""
echo "=== All checks passed! ==="
echo "Deployment URL: $BASE_URL"
# Deploy to stage (main branch)
deploy_stage:
<<: *deploy_template
variables:
NAMESPACE: orch-stage-namespace
VALUES_FILE: helm/orchard/values-stage.yaml
BASE_URL: https://orchard-stage.common.global.bsf.tools
before_script:
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
- *helm_setup
script:
- echo "Deploying to stage environment"
- cd $CI_PROJECT_DIR
- |
helm upgrade --install orchard-stage ./helm/orchard \
--namespace $NAMESPACE \
-f $VALUES_FILE \
--set image.tag=git.linux-amd64-$CI_COMMIT_SHA \
--wait \
--timeout 5m
- kubectl rollout status deployment/orchard-stage -n $NAMESPACE --timeout=5m
- *verify_deployment
environment:
name: stage
url: https://orchard-stage.common.global.bsf.tools
kubernetes:
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
# Deploy feature branch to dev namespace
deploy_feature:
<<: *deploy_template
variables:
NAMESPACE: orch-dev-namespace
VALUES_FILE: helm/orchard/values-dev.yaml
before_script:
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard
- *helm_setup
script:
- echo "Deploying feature branch $CI_COMMIT_REF_SLUG"
- cd $CI_PROJECT_DIR
- |
helm upgrade --install orchard-$CI_COMMIT_REF_SLUG ./helm/orchard \
--namespace $NAMESPACE \
-f $VALUES_FILE \
--set image.tag=git.linux-amd64-$CI_COMMIT_SHA \
--set ingress.hosts[0].host=orchard-$CI_COMMIT_REF_SLUG.common.global.bsf.tools \
--set ingress.tls[0].hosts[0]=orchard-$CI_COMMIT_REF_SLUG.common.global.bsf.tools \
--set ingress.tls[0].secretName=orchard-$CI_COMMIT_REF_SLUG-tls \
--set minioIngress.host=minio-$CI_COMMIT_REF_SLUG.common.global.bsf.tools \
--set minioIngress.tls.secretName=minio-$CI_COMMIT_REF_SLUG-tls \
--wait \
--timeout 5m
- kubectl rollout status deployment/orchard-$CI_COMMIT_REF_SLUG -n $NAMESPACE --timeout=5m
- export BASE_URL="https://orchard-$CI_COMMIT_REF_SLUG.common.global.bsf.tools"
- *verify_deployment
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://orchard-$CI_COMMIT_REF_SLUG.common.global.bsf.tools
on_stop: cleanup_feature
kubernetes:
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: always
# Cleanup feature branch deployment
cleanup_feature:
<<: *deploy_template
needs: []
variables:
NAMESPACE: orch-dev-namespace
before_script:
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard
script:
- echo "Cleaning up feature deployment orchard-$CI_COMMIT_REF_SLUG"
- helm uninstall orchard-$CI_COMMIT_REF_SLUG --namespace $NAMESPACE || true
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
kubernetes:
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: manual
allow_failure: true

View File

@@ -0,0 +1,4 @@
# GitLab Agent configuration for stage deployments
ci_access:
projects:
- id: esv/bsf/bsf-integration/orchard/orchard-mvp

View File

@@ -0,0 +1,4 @@
# GitLab Agent configuration for dev/feature deployments
ci_access:
projects:
- id: esv/bsf/bsf-integration/orchard/orchard-mvp

6
.gitleaksignore Normal file
View File

@@ -0,0 +1,6 @@
# Gitleaks ignore file
# https://github.com/gitleaks/gitleaks#gitleaksignore
# False positive: s3_key is an attribute name, not a secret
35fda65d381acc5ab59bc592ee3013f75906c197:backend/tests/unit/test_storage.py:generic-api-key:381
08dce6cbb836b687002751fed4159bfc2da61f8b:backend/tests/unit/test_storage.py:generic-api-key:381

View File

@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Added GitLab CI pipeline for feature branch deployments to dev namespace (#51)
- Added `deploy_feature` job with dynamic hostnames and unique release names (#51)
- Added `cleanup_feature` job with `on_stop` for automatic cleanup on merge (#51)
- Added `values-dev.yaml` Helm values for lightweight ephemeral environments (#51)
## [0.4.0] - 2026-01-12
### Added

View File

@@ -22,9 +22,10 @@ RUN npm run build
FROM containers.global.bsf.tools/python:3.12-slim
# Disable proxy cache
RUN echo 'Acquire::http::Pipeline-Depth 0;\nAcquire::http::No-Cache true;\nAcquire::BrokenProxy true;\n' > /etc/apt/apt.conf.d/99fixbadproxy
RUN printf 'Acquire::http::Pipeline-Depth 0;\nAcquire::http::No-Cache true;\nAcquire::BrokenProxy true;\n' > /etc/apt/apt.conf.d/99fixbadproxy
# Install system dependencies
# hadolint ignore=DL3008
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*

View File

@@ -42,6 +42,10 @@ services:
timeout: 3s
start_period: 10s
retries: 3
security_opt:
- no-new-privileges:true
mem_limit: 1g
cpus: 1.0
postgres:
image: postgres:16-alpine
@@ -62,6 +66,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 512m
cpus: 0.5
minio:
image: minio/minio:latest
@@ -82,6 +90,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 512m
cpus: 0.5
minio-init:
image: minio/mc:latest
@@ -97,6 +109,10 @@ services:
"
networks:
- orchard-network
security_opt:
- no-new-privileges:true
mem_limit: 128m
cpus: 0.25
redis:
image: redis:7-alpine
@@ -113,6 +129,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 256m
cpus: 0.25
volumes:
postgres-data-local:

View File

@@ -34,6 +34,16 @@ services:
networks:
- orchard-network
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 3s
start_period: 10s
retries: 3
security_opt:
- no-new-privileges:true
mem_limit: 1g
cpus: 1.0
postgres:
image: containers.global.bsf.tools/postgres:16-alpine
@@ -54,6 +64,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 512m
cpus: 0.5
minio:
image: containers.global.bsf.tools/minio/minio:latest
@@ -74,6 +88,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 512m
cpus: 0.5
minio-init:
image: containers.global.bsf.tools/minio/mc:latest
@@ -89,6 +107,10 @@ services:
"
networks:
- orchard-network
security_opt:
- no-new-privileges:true
mem_limit: 128m
cpus: 0.25
redis:
image: containers.global.bsf.tools/redis:7-alpine
@@ -105,6 +127,10 @@ services:
networks:
- orchard-network
restart: unless-stopped
security_opt:
- no-new-privileges:true
mem_limit: 256m
cpus: 0.25
volumes:
postgres-data:

View File

@@ -23,6 +23,7 @@
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"@vitejs/plugin-react": "^4.2.1",
"@vitest/coverage-v8": "^1.3.1",
"jsdom": "^24.0.0",
"typescript": "^5.3.3",
"vite": "^5.0.12",

View File

@@ -16,5 +16,10 @@ export default defineConfig({
environment: 'jsdom',
setupFiles: './src/test/setup.ts',
css: true,
coverage: {
provider: 'v8',
reporter: ['text', 'cobertura', 'html'],
reportsDirectory: './coverage',
},
}
})

View File

@@ -0,0 +1,165 @@
# Values for feature branch deployments (ephemeral dev environments)
# Hostnames are overridden by CI pipeline via --set flags
replicaCount: 1
image:
repository: registry.global.bsf.tools/esv/bsf/bsf-integration/orchard/orchard-mvp
pullPolicy: Always
tag: "latest" # Overridden by CI
imagePullSecrets:
- name: orchard-pull-secret
initContainer:
image:
repository: containers.global.bsf.tools/busybox
tag: "1.36"
pullPolicy: IfNotPresent
serviceAccount:
create: true
automount: true
annotations: {}
name: "" # Auto-generated based on release name
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
securityContext:
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 1000
service:
type: ClusterIP
port: 8080
# Ingress - hostnames overridden by CI pipeline
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
hosts:
- host: orchard-dev.common.global.bsf.tools # Overridden by CI
paths:
- path: /
pathType: Prefix
tls:
- secretName: orchard-tls # Overridden by CI
hosts:
- orchard-dev.common.global.bsf.tools # Overridden by CI
# Lighter resources for ephemeral environments
resources:
limits:
cpu: 250m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 5
autoscaling:
enabled: false
nodeSelector: {}
tolerations: []
affinity: {}
orchard:
server:
host: "0.0.0.0"
port: 8080
database:
host: ""
port: 5432
user: orchard
password: ""
dbname: orchard
sslmode: disable
existingSecret: ""
existingSecretPasswordKey: "password"
s3:
endpoint: ""
region: us-east-1
bucket: orchard-artifacts
accessKeyId: ""
secretAccessKey: ""
usePathStyle: true
existingSecret: ""
existingSecretAccessKeyKey: "access-key-id"
existingSecretSecretKeyKey: "secret-access-key"
download:
mode: "presigned"
presignedUrlExpiry: 3600
# PostgreSQL - ephemeral, no persistence
postgresql:
enabled: true
image:
registry: containers.global.bsf.tools
repository: bitnami/postgresql
tag: "15"
pullPolicy: IfNotPresent
auth:
username: orchard
password: orchard-password
database: orchard
primary:
persistence:
enabled: false
# MinIO - ephemeral, no persistence
minio:
enabled: true
image:
registry: containers.global.bsf.tools
repository: bitnami/minio
tag: "latest"
pullPolicy: IfNotPresent
auth:
rootUser: minioadmin
rootPassword: minioadmin
defaultBuckets: "orchard-artifacts"
persistence:
enabled: false
# MinIO ingress - hostname overridden by CI
minioIngress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
nginx.ingress.kubernetes.io/proxy-body-size: "0"
host: "minio-dev.common.global.bsf.tools" # Overridden by CI
tls:
enabled: true
secretName: minio-tls # Overridden by CI
redis:
enabled: false
waitForDatabase: true
global:
security:
allowInsecureImages: true

View File

@@ -1,58 +0,0 @@
# Values for using external PostgreSQL and S3 storage
# Use this when you have existing infrastructure
replicaCount: 2
image:
pullPolicy: Always
# Disable subcharts - use external services
postgresql:
enabled: false
minio:
enabled: false
redis:
enabled: false
orchard:
database:
host: "your-postgres-host.example.com"
port: 5432
user: orchard
dbname: orchard
sslmode: require
# Option 1: Use existing secret
existingSecret: "my-postgres-secret"
existingSecretPasswordKey: "password"
# Option 2: Set password directly (not recommended)
# password: "your-password"
s3:
endpoint: "https://s3.amazonaws.com"
region: us-east-1
bucket: orchard-artifacts
usePathStyle: false
# Option 1: Use existing secret
existingSecret: "my-s3-secret"
existingSecretAccessKeyKey: "access-key-id"
existingSecretSecretKeyKey: "secret-access-key"
# Option 2: Set credentials directly (not recommended)
# accessKeyId: "your-access-key"
# secretAccessKey: "your-secret-key"
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: orchard.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: orchard-tls
hosts:
- orchard.example.com

View File

@@ -1,80 +0,0 @@
# Production values for orchard
replicaCount: 3
image:
pullPolicy: Always
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 20
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/proxy-body-size: "500m"
hosts:
- host: orchard.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: orchard-tls
hosts:
- orchard.example.com
orchard:
database:
sslmode: require
postgresql:
enabled: true
auth:
password: "" # Set via --set or external secret
primary:
persistence:
enabled: true
size: 100Gi
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
minio:
enabled: true
auth:
rootPassword: "" # Set via --set or external secret
persistence:
enabled: true
size: 500Gi
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
redis:
enabled: true
auth:
password: "" # Set via --set or external secret
master:
persistence:
enabled: true
size: 10Gi

View File

@@ -0,0 +1,190 @@
# Default values for orchard
replicaCount: 1
image:
repository: registry.global.bsf.tools/esv/bsf/bsf-integration/orchard/orchard-mvp
pullPolicy: Always
tag: "latest" # Defaults to chart appVersion
imagePullSecrets:
- name: orchard-pull-secret
# Init container image (used for wait-for-db, wait-for-minio)
initContainer:
image:
repository: containers.global.bsf.tools/busybox
tag: "1.36"
pullPolicy: IfNotPresent
serviceAccount:
create: true
automount: true
annotations: {}
name: "orchard"
podAnnotations: {}
podLabels: {}
podSecurityContext: {}
securityContext:
readOnlyRootFilesystem: false # Python needs to write __pycache__
runAsNonRoot: true
runAsUser: 1000
service:
type: ClusterIP
port: 8080
ingress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
hosts:
- host: orchard-stage.common.global.bsf.tools
paths:
- path: /
pathType: Prefix
tls:
- secretName: orchard-tls
hosts:
- orchard-stage.common.global.bsf.tools
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 500m
memory: 512Mi
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 5
periodSeconds: 5
autoscaling:
enabled: false
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 80
targetMemoryUtilizationPercentage: 80
nodeSelector: {}
tolerations: []
affinity: {}
# Orchard server configuration
orchard:
server:
host: "0.0.0.0"
port: 8080
# Database configuration (used when postgresql.enabled is false)
database:
host: ""
port: 5432
user: orchard
password: ""
dbname: orchard
sslmode: disable
existingSecret: ""
existingSecretPasswordKey: "password"
# S3 configuration (used when minio.enabled is false)
s3:
endpoint: ""
region: us-east-1
bucket: orchard-artifacts
accessKeyId: ""
secretAccessKey: ""
usePathStyle: true
existingSecret: ""
existingSecretAccessKeyKey: "access-key-id"
existingSecretSecretKeyKey: "secret-access-key"
# Download configuration
download:
mode: "presigned" # presigned, redirect, or proxy
presignedUrlExpiry: 3600 # Presigned URL expiry in seconds
# PostgreSQL subchart configuration
postgresql:
enabled: true
image:
registry: containers.global.bsf.tools
repository: bitnami/postgresql
tag: "15"
pullPolicy: IfNotPresent
auth:
username: orchard
password: orchard-password
database: orchard
primary:
persistence:
enabled: false
size: 10Gi
# MinIO subchart configuration
minio:
enabled: true
image:
registry: containers.global.bsf.tools
repository: bitnami/minio
tag: "latest"
pullPolicy: IfNotPresent
auth:
rootUser: minioadmin
rootPassword: minioadmin
defaultBuckets: "orchard-artifacts"
persistence:
enabled: false
size: 50Gi
# MinIO external ingress for presigned URL access (separate from subchart ingress)
minioIngress:
enabled: true
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt"
nginx.ingress.kubernetes.io/proxy-body-size: "0" # Disable body size limit for uploads
host: "minio-orch-stage.common.global.bsf.tools"
tls:
enabled: true
secretName: minio-tls
# Redis subchart configuration (for future caching)
redis:
enabled: false
image:
registry: containers.global.bsf.tools
repository: bitnami/redis
tag: "7.2"
pullPolicy: IfNotPresent
auth:
enabled: true
password: redis-password
architecture: standalone
master:
persistence:
enabled: true
size: 1Gi
# Wait for database before starting (SQLAlchemy creates tables on startup)
waitForDatabase: true
global:
security:
allowInsecureImages: true