Enhance deployment workflow with change detection

Added a job to detect changed services and conditionally deploy based on changes. Updated deployment strategy to handle service-specific environment files.
This commit is contained in:
Yonas Tewabe
2026-06-16 10:18:32 +03:00
committed by GitHub
parent f3d892f68e
commit c267d4f641

View File

@@ -1,5 +1,4 @@
name: Deploy Stacks name: Deploy Stacks
on: on:
push: push:
branches: branches:
@@ -9,52 +8,182 @@ on:
workflow_dispatch: workflow_dispatch:
permissions: permissions:
contents: read contents: read
concurrency: concurrency:
group: deploy-${{ github.ref_name }} group: deploy-${{ github.ref_name }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
detect-changes:
name: Detect changed services
runs-on: self-hosted
outputs:
matrix: ${{ steps.filter.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Determine changed services
id: filter
run: |
set -euo pipefail
ALL_SERVICES=(
"freight-api"
# "freight-portal"
# "freight-backoffice"
"passenger-api"
"passenger-portal"
"passenger-backoffice"
"payment-api"
)
# workflow_dispatch: deploy everything
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
JSON=$(printf '%s\n' "${ALL_SERVICES[@]}" | jq -R . | jq -sc .)
echo "matrix=${JSON}" >> "$GITHUB_OUTPUT"
exit 0
fi
CHANGED=$(git diff --name-only HEAD~1 HEAD)
echo "=== Changed files ==="
echo "$CHANGED"
echo "====================="
SERVICES=()
# -------------------------------------------------------
# Tier 1: Non-deployable files — skip if ONLY these changed
# -------------------------------------------------------
NON_DEPLOYABLE_PATTERN="^docs/\
|^README\.md$\
|^DEPLOYMENT\.md$\
|^CLAUDE\.md$\
|^checkpoint\.md$\
|^orgstructure\.md$\
|^ITMLS_DB_Design\.md$\
|.*\.md$\
|^\.eslintrc\
|^\.prettierrc\
|^\.editorconfig\
|^\.gitignore\
|^\.gitattributes\
|^commitlint\.config\.js$"
ALL_NON_DEPLOYABLE=true
while IFS= read -r file; do
if ! echo "$file" | grep -qE "$NON_DEPLOYABLE_PATTERN"; then
ALL_NON_DEPLOYABLE=false
break
fi
done <<< "$CHANGED"
if [ "$ALL_NON_DEPLOYABLE" = "true" ]; then
echo "Only non-deployable files changed. Skipping deploy."
echo "matrix=[]" >> "$GITHUB_OUTPUT"
exit 0
fi
# -------------------------------------------------------
# Tier 2: Global files — deploy all services
# -------------------------------------------------------
GLOBAL_PATTERN="^\.github/\
|^docker-compose\.yaml$\
|^turbo\.json$\
|^tsconfig\.json$\
|^tsconfig\.base\.json$\
|^pnpm-workspace\.yaml$\
|^pnpm-lock\.yaml$\
|^package\.json$\
|^\.env(\.[a-z]+)?$\
|^packages/\
|^infrastructure/\
|^scripts/deploy/\
|^wagon.*\.ts$\
|^cargo.*\.ts$\
|^container.*\.ts$\
|^use-.*\.ts$\
|^.*\.service\.ts$\
|^.*\.entity\.ts$\
|^.*-types\.ts$"
if echo "$CHANGED" | grep -qE "$GLOBAL_PATTERN"; then
echo "Global file(s) changed — deploying all services."
JSON=$(printf '%s\n' "${ALL_SERVICES[@]}" | jq -R . | jq -sc .)
echo "matrix=${JSON}" >> "$GITHUB_OUTPUT"
exit 0
fi
# -------------------------------------------------------
# Tier 3: Per-service app paths (exact structure)
# -------------------------------------------------------
# Freight
echo "$CHANGED" | grep -q "^apps/edr-freight-api/" && SERVICES+=("freight-api")
# echo "$CHANGED" | grep -q "^apps/edr-freight-web/portal/" && SERVICES+=("freight-portal")
# echo "$CHANGED" | grep -q "^apps/edr-freight-web/backoffice/" && SERVICES+=("freight-backoffice")
# Passenger
echo "$CHANGED" | grep -q "^apps/edr-passenger-api/" && SERVICES+=("passenger-api")
echo "$CHANGED" | grep -q "^apps/edr-passenger-web/portal/" && SERVICES+=("passenger-portal")
echo "$CHANGED" | grep -q "^apps/edr-passenger-web/backoffice/" && SERVICES+=("passenger-backoffice")
# Payment
echo "$CHANGED" | grep -q "^apps/edr-payment-api/" && SERVICES+=("payment-api")
# Deduplicate while preserving consistent order
SERVICES=($(printf '%s\n' "${SERVICES[@]}" | sort -u))
if [ ${#SERVICES[@]} -eq 0 ]; then
echo "No deployable service changes detected."
echo "matrix=[]" >> "$GITHUB_OUTPUT"
else
echo "Services to deploy: ${SERVICES[*]}"
JSON=$(printf '%s\n' "${SERVICES[@]}" | jq -R . | jq -sc .)
echo "matrix=${JSON}" >> "$GITHUB_OUTPUT"
fi
deploy: deploy:
name: Deploy ${{ matrix.service }} name: Deploy ${{ matrix.service }}
needs: detect-changes
if: ${{ needs.detect-changes.outputs.matrix != '[]' }}
runs-on: self-hosted runs-on: self-hosted
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
include: service: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
- project: edr-freight
build_env_file: freight-web.build.env
service: freight-api
# - project: edr-freight
# build_env_file: freight-web.build.env
# service: freight-portal
# - project: edr-freight
# build_env_file: freight-web.build.env
# service: freight-backoffice
- project: edr-passenger
build_env_file: passenger-web.build.env
service: passenger-api
- project: edr-passenger
build_env_file: passenger-web.build.env
service: passenger-portal
- project: edr-passenger
build_env_file: passenger-web.build.env
service: passenger-backoffice
- project: edr-payment
build_env_file: payment-web.build.env
service: payment-api
env: env:
PROJECT: ${{ matrix.project }}
BRANCH: ${{ github.ref_name }} BRANCH: ${{ github.ref_name }}
DEPLOY_USER: tria DEPLOY_USER: tria
BUILD_ENV_FILE: ${{ matrix.build_env_file }}
DOCKER_BUILDKIT: "1" DOCKER_BUILDKIT: "1"
COMPOSE_DOCKER_CLI_BUILD: "1" COMPOSE_DOCKER_CLI_BUILD: "1"
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Resolve project and build env file
run: |
case "${{ matrix.service }}" in
freight-api|freight-portal|freight-backoffice)
echo "PROJECT=edr-freight" >> "$GITHUB_ENV"
echo "BUILD_ENV_FILE=freight-web.build.env" >> "$GITHUB_ENV"
;;
passenger-api|passenger-portal|passenger-backoffice)
echo "PROJECT=edr-passenger" >> "$GITHUB_ENV"
echo "BUILD_ENV_FILE=passenger-web.build.env" >> "$GITHUB_ENV"
;;
payment-api)
echo "PROJECT=edr-payment" >> "$GITHUB_ENV"
echo "BUILD_ENV_FILE=payment-web.build.env" >> "$GITHUB_ENV"
;;
*)
echo "Unknown service: ${{ matrix.service }}" && exit 1
;;
esac
- name: Sync environment from server - name: Sync environment from server
run: | run: |
chmod +x scripts/deploy/*.sh chmod +x scripts/deploy/*.sh