Skip to content
Merged
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
187 changes: 187 additions & 0 deletions .github/workflows/ci-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
name: CI Pipeline

on:
push:
branches:
- "**"
pull_request:
branches:
- "main"
Comment on lines +6 to +9

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This workflow triggers on all pushes (branches: '**') and on every PR targeting main without any paths filter. Given the repo already has many module-specific *-ci.yaml workflows with path filters, this new pipeline will run in addition to them for the same PRs/commits, increasing CI load and duplicate signal. Consider narrowing triggers (add paths/paths-ignore, limit branches, or disable/replace the per-module workflows) so checks remain intentional and predictable.

Suggested change
- "**"
pull_request:
branches:
- "main"
- "main"
paths:
- "pom.xml"
- "**/pom.xml"
- "**/src/**"
pull_request:
branches:
- "main"
paths:
- "pom.xml"
- "**/pom.xml"
- "**/src/**"

Copilot uses AI. Check for mistakes.
workflow_dispatch:

permissions:
contents: read
actions: write

Copilot AI Apr 29, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workflow requests actions: write at the workflow level, which grants a broader token scope to every job than necessary. To follow least-privilege, restrict elevated permissions to only the job/step that needs it (e.g., artifact upload) and keep other jobs at contents: read (or omit permissions to use the default minimal set).

Suggested change
actions: write

Copilot uses AI. Check for mistakes.

jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.collect.outputs.matrix }}
has_services: ${{ steps.collect.outputs.has_services }}
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Detect changed Maven modules
id: collect
shell: bash
run: |
set -euo pipefail

mapfile -t reactor_modules < <(
sed -n 's:.*<module>\(.*\)</module>.*:\1:p' pom.xml |
sed 's/^\s*//; s/\s*$//' |
grep -v '^$'
)

if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then
base_sha="${{ github.event.pull_request.base.sha }}"
head_sha="${{ github.event.pull_request.head.sha }}"
else
base_sha="${{ github.event.before }}"
head_sha="${{ github.sha }}"
fi

if [[ -z "$base_sha" || "$base_sha" == "0000000000000000000000000000000000000000" ]]; then
base_sha="$(git rev-list --max-parents=0 HEAD | tail -n 1)"
fi

changed_files="$(git diff --name-only "$base_sha" "$head_sha" || true)"
build_all=false

if [[ -z "$changed_files" ]]; then
echo 'matrix={"include":[]}' >> "$GITHUB_OUTPUT"
echo 'has_services=false' >> "$GITHUB_OUTPUT"
exit 0
fi

if printf '%s\n' "$changed_files" | grep -qx 'pom.xml'; then
build_all=true
fi

# If shared build config changes, run CI for all modules.
# This keeps CI behavior predictable and is a good base for later tasks.
if printf '%s\n' "$changed_files" | grep -Eq '^(\.github/|checkstyle/)'; then
build_all=true
fi

mapfile -t top_level_dirs < <(
printf '%s\n' "$changed_files" |
awk -F/ 'NF > 1 {print $1}' |
sort -u
)

declare -a services=()

for top_level_dir in "${top_level_dirs[@]}"; do
if [[ "$top_level_dir" == "common-library" ]]; then
build_all=true
elif [[ -f "$top_level_dir/pom.xml" ]]; then
if printf '%s\n' "${reactor_modules[@]}" | grep -qx "$top_level_dir"; then
services+=("$top_level_dir")
fi
fi
done

if [[ "$build_all" == "true" ]]; then
services=("${reactor_modules[@]}")
fi

if [[ ${#services[@]} -eq 0 ]]; then
echo 'matrix={"include":[]}' >> "$GITHUB_OUTPUT"
echo 'has_services=false' >> "$GITHUB_OUTPUT"
exit 0
fi

matrix_json='{"include":['
for index in "${!services[@]}"; do
if [[ "$index" -gt 0 ]]; then
matrix_json+=','
fi
matrix_json+='{"service":"'"${services[$index]}"'"}'
done
matrix_json+=']}'

echo "matrix=$matrix_json" >> "$GITHUB_OUTPUT"
echo 'has_services=true' >> "$GITHUB_OUTPUT"

test:
needs: detect-changes
if: needs.detect-changes.outputs.has_services == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Java 25
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '25'
cache: maven

- name: Run tests for ${{ matrix.service }}
run: mvn -B -pl ${{ matrix.service }} -am test

- name: Upload test results for ${{ matrix.service }}
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.service }}
path: |
${{ matrix.service }}/target/surefire-reports/*.xml
${{ matrix.service }}/target/failsafe-reports/*.xml
if-no-files-found: ignore

build:
needs: [detect-changes, test]
if: needs.detect-changes.outputs.has_services == 'true'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix: ${{ fromJson(needs.detect-changes.outputs.matrix) }}
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Java 25
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '25'
cache: maven

- name: Build ${{ matrix.service }}
run: mvn -B -pl ${{ matrix.service }} -am -DskipTests package

ci-gate:
name: CI Gate
runs-on: ubuntu-latest
needs: [detect-changes, test, build]
if: always()
steps:
- name: Evaluate results
shell: bash
run: |
set -euo pipefail

if [[ "${{ needs.detect-changes.outputs.has_services }}" != "true" ]]; then
echo "No Maven module changes detected; passing."
exit 0
fi

echo "test result: ${{ needs.test.result }}"
echo "build result: ${{ needs.build.result }}"

if [[ "${{ needs.test.result }}" != "success" || "${{ needs.build.result }}" != "success" ]]; then
echo "CI failed."
exit 1
fi

echo "CI passed."
Loading