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
This commit is contained in:
Mondo Diaz
2026-01-13 16:18:08 +00:00
parent d8352fde7c
commit 96477db51f
3 changed files with 243 additions and 20 deletions

View File

@@ -66,25 +66,78 @@ python_tests:
kubernetes:
agent: $AGENT
deploy_helm_chart:
# Deploy to stage (main branch)
deploy_stage:
stage: deploy
parallel:
matrix:
# - ENV: dev
# NAMESPACE: dev
# CHART: ./charts/chart-a
# AGENT: dev-agent
- ENV: stage
variables:
ENV: stage
NAMESPACE: orch-stage-namespace
VALUES_FILE: "helm/orchard/values-stage.yaml"
AGENT: orchard-stage
IMAGE: git.linux-amd64-81458b3bcb5ace97109ba4c16f4afa6e55b1b8bd
# rules:
# # - if: '$CI_COMMIT_TAG && $CI_JOB_NAME == "deploy (production)"'
# # when: always
# # - if: '$CI_COMMIT_BRANCH == "main" && $CI_JOB_NAME == "deploy (stage)" && $CI_COMMIT_TAG == null'
# # when: always
# - if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main" && $ENV == "dev" && $CI_COMMIT_TAG == null'
# when: always
# - when: never
IMAGE: $CI_COMMIT_SHA
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
when: always
<<: *deploy_template
# Deploy feature branch to dev namespace
deploy_feature:
stage: deploy
variables:
FEATURE_ID: feat-$CI_COMMIT_SHORT_SHA
ENV: feat-$CI_COMMIT_SHORT_SHA
NAMESPACE: orch-dev-namespace
VALUES_FILE: "helm/orchard/values-dev.yaml"
AGENT: orchard-dev
IMAGE: $CI_COMMIT_SHA
FEATURE_HOST: orchard-$CI_COMMIT_SHORT_SHA.common.global.bsf.tools
MINIO_HOST: minio-$CI_COMMIT_SHORT_SHA.common.global.bsf.tools
before_script:
- 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
script:
- echo "Deploying feature branch to $ENV environment"
- |
helm upgrade --install orchard-$FEATURE_ID ./helm/orchard \
--namespace $NAMESPACE \
-f $VALUES_FILE \
--set image.tag=$IMAGE \
--set ingress.hosts[0].host=$FEATURE_HOST \
--set ingress.tls[0].hosts[0]=$FEATURE_HOST \
--set ingress.tls[0].secretName=orchard-$FEATURE_ID-tls \
--set minioIngress.host=$MINIO_HOST \
--set minioIngress.tls.secretName=minio-$FEATURE_ID-tls
environment:
name: review/$CI_COMMIT_REF_SLUG
url: https://orchard-$CI_COMMIT_SHORT_SHA.common.global.bsf.tools
on_stop: cleanup_feature
kubernetes:
agent: $AGENT
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: always
# Cleanup feature branch deployment
cleanup_feature:
stage: deploy
variables:
FEATURE_ID: feat-$CI_COMMIT_SHORT_SHA
NAMESPACE: orch-dev-namespace
AGENT: orchard-dev
image: deps.global.bsf.tools/registry-1.docker.io/alpine/k8s:1.29.12
script:
- echo "Cleaning up feature deployment orchard-$FEATURE_ID"
- helm uninstall orchard-$FEATURE_ID --namespace $NAMESPACE || true
environment:
name: review/$CI_COMMIT_REF_SLUG
action: stop
kubernetes:
agent: $AGENT
rules:
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
when: manual
allow_failure: true

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

@@ -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