Improve CI pipeline consistency and efficiency
- Rename integration_test_prod to smoke_test_prod for clarity - Share pip cache between unit and integration tests - Add interruptible: true to test jobs (cancel on new pipeline) - Add retry: 1 to integration tests (handle network flakiness) - Simplify verify_deployment to health check only (integration tests do full checks) - Make cleanup_feature standalone (doesn't need deploy dependencies) - Extract environment URLs (STAGE_URL, PROD_URL) to global variables - Add timeout: 5m to cleanup_feature - Remove -x flag from integration tests (show all failures)
This commit is contained in:
@@ -8,6 +8,11 @@ variables:
|
|||||||
PROSPER_VERSION: v0.64.1
|
PROSPER_VERSION: v0.64.1
|
||||||
# Use internal PyPI proxy instead of public internet
|
# Use internal PyPI proxy instead of public internet
|
||||||
PIP_INDEX_URL: https://deps.global.bsf.tools/artifactory/api/pypi/pypi.org/simple
|
PIP_INDEX_URL: https://deps.global.bsf.tools/artifactory/api/pypi/pypi.org/simple
|
||||||
|
# Environment URLs (used by deploy and test jobs)
|
||||||
|
STAGE_URL: https://orchard-stage.common.global.bsf.tools
|
||||||
|
PROD_URL: https://orchard.common.global.bsf.tools
|
||||||
|
# Shared pip cache directory
|
||||||
|
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
|
||||||
|
|
||||||
# Prevent duplicate pipelines for MRs
|
# Prevent duplicate pipelines for MRs
|
||||||
workflow:
|
workflow:
|
||||||
@@ -35,10 +40,10 @@ kics:
|
|||||||
stage: deploy # Runs in deploy stage, but after deployment due to 'needs'
|
stage: deploy # Runs in deploy stage, but after deployment due to 'needs'
|
||||||
image: deps.global.bsf.tools/docker/python:3.12-slim
|
image: deps.global.bsf.tools/docker/python:3.12-slim
|
||||||
timeout: 20m # Full suite takes longer than smoke tests
|
timeout: 20m # Full suite takes longer than smoke tests
|
||||||
variables:
|
interruptible: true # Cancel if new pipeline starts
|
||||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
|
retry: 1 # Retry once on failure (network flakiness)
|
||||||
cache:
|
cache:
|
||||||
key: pip-integration-$CI_COMMIT_REF_SLUG
|
key: pip-$CI_COMMIT_REF_SLUG
|
||||||
paths:
|
paths:
|
||||||
- .pip-cache/
|
- .pip-cache/
|
||||||
policy: pull-push
|
policy: pull-push
|
||||||
@@ -53,8 +58,7 @@ kics:
|
|||||||
python -m pytest tests/integration/ -v \
|
python -m pytest tests/integration/ -v \
|
||||||
--junitxml=integration-report.xml \
|
--junitxml=integration-report.xml \
|
||||||
-m "not large and not slow" \
|
-m "not large and not slow" \
|
||||||
--tb=short \
|
--tb=short
|
||||||
-x # Stop on first failure for faster feedback
|
|
||||||
artifacts:
|
artifacts:
|
||||||
when: always
|
when: always
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
@@ -129,7 +133,7 @@ integration_test_stage:
|
|||||||
<<: *integration_test_template
|
<<: *integration_test_template
|
||||||
needs: [deploy_stage]
|
needs: [deploy_stage]
|
||||||
variables:
|
variables:
|
||||||
ORCHARD_TEST_URL: https://orchard-stage.common.global.bsf.tools
|
ORCHARD_TEST_URL: $STAGE_URL
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_BRANCH == "main"'
|
- if: '$CI_COMMIT_BRANCH == "main"'
|
||||||
when: on_success
|
when: on_success
|
||||||
@@ -150,8 +154,7 @@ python_unit_tests:
|
|||||||
needs: [] # Run in parallel with build
|
needs: [] # Run in parallel with build
|
||||||
image: deps.global.bsf.tools/docker/python:3.12-slim
|
image: deps.global.bsf.tools/docker/python:3.12-slim
|
||||||
timeout: 15m
|
timeout: 15m
|
||||||
variables:
|
interruptible: true # Cancel if new pipeline starts
|
||||||
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
|
|
||||||
cache:
|
cache:
|
||||||
key: pip-$CI_COMMIT_REF_SLUG
|
key: pip-$CI_COMMIT_REF_SLUG
|
||||||
paths:
|
paths:
|
||||||
@@ -184,6 +187,7 @@ frontend_tests:
|
|||||||
needs: [] # Run in parallel with build
|
needs: [] # Run in parallel with build
|
||||||
image: deps.global.bsf.tools/docker/node:20-alpine
|
image: deps.global.bsf.tools/docker/node:20-alpine
|
||||||
timeout: 15m
|
timeout: 15m
|
||||||
|
interruptible: true # Cancel if new pipeline starts
|
||||||
cache:
|
cache:
|
||||||
key: npm-$CI_COMMIT_REF_SLUG
|
key: npm-$CI_COMMIT_REF_SLUG
|
||||||
paths:
|
paths:
|
||||||
@@ -218,47 +222,21 @@ frontend_tests:
|
|||||||
# OCI-based charts from internal registry - no repo add needed
|
# OCI-based charts from internal registry - no repo add needed
|
||||||
- helm dependency update
|
- helm dependency update
|
||||||
|
|
||||||
|
# Simplified deployment verification - just health check
|
||||||
|
# Full API/frontend checks are done by integration tests post-deployment
|
||||||
.verify_deployment: &verify_deployment |
|
.verify_deployment: &verify_deployment |
|
||||||
echo "=== Waiting for health endpoint (certs may take a few minutes) ==="
|
echo "=== Waiting for health endpoint (certs may take a few minutes) ==="
|
||||||
for i in $(seq 1 30); do
|
for i in $(seq 1 30); do
|
||||||
if curl -sf --max-time 10 "$BASE_URL/health" > /dev/null 2>&1; then
|
if curl -sf --max-time 10 "$BASE_URL/health" > /dev/null 2>&1; then
|
||||||
echo "Health check passed!"
|
echo "Health check passed!"
|
||||||
break
|
echo "Deployment URL: $BASE_URL"
|
||||||
|
exit 0
|
||||||
fi
|
fi
|
||||||
echo "Attempt $i/30 - waiting 10s..."
|
echo "Attempt $i/30 - waiting 10s..."
|
||||||
sleep 10
|
sleep 10
|
||||||
done
|
done
|
||||||
|
echo "Health check failed after 30 attempts"
|
||||||
# Verify health endpoint
|
exit 1
|
||||||
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 to stage (main branch)
|
||||||
deploy_stage:
|
deploy_stage:
|
||||||
@@ -266,7 +244,7 @@ deploy_stage:
|
|||||||
variables:
|
variables:
|
||||||
NAMESPACE: orch-stage-namespace
|
NAMESPACE: orch-stage-namespace
|
||||||
VALUES_FILE: helm/orchard/values-stage.yaml
|
VALUES_FILE: helm/orchard/values-stage.yaml
|
||||||
BASE_URL: https://orchard-stage.common.global.bsf.tools
|
BASE_URL: $STAGE_URL
|
||||||
before_script:
|
before_script:
|
||||||
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
|
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
|
||||||
- *helm_setup
|
- *helm_setup
|
||||||
@@ -285,7 +263,7 @@ deploy_stage:
|
|||||||
- *verify_deployment
|
- *verify_deployment
|
||||||
environment:
|
environment:
|
||||||
name: stage
|
name: stage
|
||||||
url: https://orchard-stage.common.global.bsf.tools
|
url: $STAGE_URL
|
||||||
kubernetes:
|
kubernetes:
|
||||||
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
|
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-stage
|
||||||
rules:
|
rules:
|
||||||
@@ -331,10 +309,12 @@ deploy_feature:
|
|||||||
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
|
- if: '$CI_COMMIT_BRANCH && $CI_COMMIT_BRANCH != "main"'
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|
||||||
# Cleanup feature branch deployment
|
# Cleanup feature branch deployment (standalone - doesn't need deploy dependencies)
|
||||||
cleanup_feature:
|
cleanup_feature:
|
||||||
<<: *deploy_template
|
stage: deploy
|
||||||
needs: []
|
needs: []
|
||||||
|
image: deps.global.bsf.tools/registry-1.docker.io/alpine/k8s:1.29.12
|
||||||
|
timeout: 5m
|
||||||
variables:
|
variables:
|
||||||
NAMESPACE: orch-dev-namespace
|
NAMESPACE: orch-dev-namespace
|
||||||
GIT_STRATEGY: none # No source needed, branch may be deleted
|
GIT_STRATEGY: none # No source needed, branch may be deleted
|
||||||
@@ -363,7 +343,7 @@ deploy_prod:
|
|||||||
variables:
|
variables:
|
||||||
NAMESPACE: orch-prod-namespace
|
NAMESPACE: orch-prod-namespace
|
||||||
VALUES_FILE: helm/orchard/values-prod.yaml
|
VALUES_FILE: helm/orchard/values-prod.yaml
|
||||||
BASE_URL: https://orchard.common.global.bsf.tools
|
BASE_URL: $PROD_URL
|
||||||
before_script:
|
before_script:
|
||||||
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-prod
|
- kubectl config use-context esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-prod
|
||||||
- *helm_setup
|
- *helm_setup
|
||||||
@@ -382,7 +362,7 @@ deploy_prod:
|
|||||||
- *verify_deployment
|
- *verify_deployment
|
||||||
environment:
|
environment:
|
||||||
name: production
|
name: production
|
||||||
url: https://orchard.common.global.bsf.tools
|
url: $PROD_URL
|
||||||
kubernetes:
|
kubernetes:
|
||||||
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-prod
|
agent: esv/bsf/bsf-integration/orchard/orchard-mvp:orchard-prod
|
||||||
rules:
|
rules:
|
||||||
@@ -392,11 +372,11 @@ deploy_prod:
|
|||||||
allow_failure: false
|
allow_failure: false
|
||||||
|
|
||||||
# Smoke tests for production deployment (read-only, no test data creation)
|
# Smoke tests for production deployment (read-only, no test data creation)
|
||||||
integration_test_prod:
|
smoke_test_prod:
|
||||||
<<: *smoke_test_template
|
<<: *smoke_test_template
|
||||||
needs: [deploy_prod]
|
needs: [deploy_prod]
|
||||||
variables:
|
variables:
|
||||||
ORCHARD_TEST_URL: https://orchard.common.global.bsf.tools
|
ORCHARD_TEST_URL: $PROD_URL
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|||||||
@@ -63,6 +63,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Changed
|
### Changed
|
||||||
- CI integration tests now run full pytest suite (~350 tests) against deployed environment instead of 3 smoke tests
|
- CI integration tests now run full pytest suite (~350 tests) against deployed environment instead of 3 smoke tests
|
||||||
- CI production deployment uses lightweight smoke tests only (no test data creation in prod)
|
- CI production deployment uses lightweight smoke tests only (no test data creation in prod)
|
||||||
|
- CI pipeline improvements: shared pip cache, `interruptible` flag on test jobs, retry on integration tests
|
||||||
|
- Simplified deploy verification to health check only (full checks done by integration tests)
|
||||||
|
- Extracted environment URLs to global variables for maintainability
|
||||||
|
- Made `cleanup_feature` job standalone (no longer inherits deploy template dependencies)
|
||||||
|
- Renamed `integration_test_prod` to `smoke_test_prod` for clarity
|
||||||
- Updated download ref resolution to check versions before tags (version → tag → artifact ID) (#56)
|
- Updated download ref resolution to check versions before tags (version → tag → artifact ID) (#56)
|
||||||
- Deploy jobs now require all security scans to pass before deployment (added test_image, app_deps_scan, cve_scan, cve_sbom_analysis, app_sbom_analysis to dependencies) (#63)
|
- Deploy jobs now require all security scans to pass before deployment (added test_image, app_deps_scan, cve_scan, cve_sbom_analysis, app_sbom_analysis to dependencies) (#63)
|
||||||
- Increased deploy job timeout from 5m to 10m (#63)
|
- Increased deploy job timeout from 5m to 10m (#63)
|
||||||
|
|||||||
Reference in New Issue
Block a user