77 branches : [main]
88
99jobs :
10- # Discover all projects in the repository
10+ # Discover all projects in the repository and filter by changed files
1111 discover :
1212 runs-on : ubuntu-latest
1313 outputs :
14- node-projects : ${{ steps.find -projects.outputs.node-projects }}
15- poetry-projects : ${{ steps.find -projects.outputs.poetry-projects }}
16- uv-projects : ${{ steps.find -projects.outputs.uv-projects }}
17- pip-projects : ${{ steps.find -projects.outputs.pip-projects }}
14+ node-projects : ${{ steps.filter -projects.outputs.node-projects }}
15+ poetry-projects : ${{ steps.filter -projects.outputs.poetry-projects }}
16+ uv-projects : ${{ steps.filter -projects.outputs.uv-projects }}
17+ pip-projects : ${{ steps.filter -projects.outputs.pip-projects }}
1818 steps :
1919 - uses : actions/checkout@v4
20+ with :
21+ fetch-depth : 0
22+
23+ - name : Get changed files
24+ id : changed-files
25+ run : |
26+ if [ "${{ github.event_name }}" == "pull_request" ]; then
27+ # For PRs, compare against the base branch
28+ CHANGED_FILES=$(git diff --name-only origin/${{ github.base_ref }}...HEAD | tr '\n' ' ')
29+ else
30+ # For pushes, compare against the previous commit
31+ CHANGED_FILES=$(git diff --name-only HEAD~1...HEAD 2>/dev/null | tr '\n' ' ' || echo "")
32+ fi
33+ echo "Changed files: $CHANGED_FILES"
34+ echo "files=$CHANGED_FILES" >> $GITHUB_OUTPUT
2035
2136 - name : Find all projects
2237 id : find-projects
@@ -41,11 +56,78 @@ jobs:
4156 done | sort -u | jq -R -s -c 'split("\n") | map(select(length > 0))')
4257 echo "pip-projects=$PIP_PROJECTS" >> $GITHUB_OUTPUT
4358
59+ - name : Filter projects by changed files
60+ id : filter-projects
61+ run : |
62+ CHANGED_FILES="${{ steps.changed-files.outputs.files }}"
63+
64+ # If no changed files detected (e.g., first commit), run all projects
65+ if [ -z "$CHANGED_FILES" ]; then
66+ echo "No changed files detected, running all projects"
67+ echo "node-projects=${{ steps.find-projects.outputs.node-projects }}" >> $GITHUB_OUTPUT
68+ echo "poetry-projects=${{ steps.find-projects.outputs.poetry-projects }}" >> $GITHUB_OUTPUT
69+ echo "uv-projects=${{ steps.find-projects.outputs.uv-projects }}" >> $GITHUB_OUTPUT
70+ echo "pip-projects=${{ steps.find-projects.outputs.pip-projects }}" >> $GITHUB_OUTPUT
71+ exit 0
72+ fi
73+
74+ # Check if CI workflow itself changed - if so, run all projects
75+ if echo "$CHANGED_FILES" | grep -q ".github/workflows/ci.yml"; then
76+ echo "CI workflow changed, running all projects"
77+ echo "node-projects=${{ steps.find-projects.outputs.node-projects }}" >> $GITHUB_OUTPUT
78+ echo "poetry-projects=${{ steps.find-projects.outputs.poetry-projects }}" >> $GITHUB_OUTPUT
79+ echo "uv-projects=${{ steps.find-projects.outputs.uv-projects }}" >> $GITHUB_OUTPUT
80+ echo "pip-projects=${{ steps.find-projects.outputs.pip-projects }}" >> $GITHUB_OUTPUT
81+ exit 0
82+ fi
83+
84+ # Function to filter projects based on changed files
85+ filter_projects() {
86+ local projects_json="$1"
87+ local result=""
88+
89+ # Parse JSON array and check each project
90+ for project in $(echo "$projects_json" | jq -r '.[]'); do
91+ # Remove leading ./ for comparison
92+ project_path="${project#./}"
93+
94+ # Check if any changed file starts with this project path
95+ for changed_file in $CHANGED_FILES; do
96+ if [[ "$changed_file" == "$project_path"* ]] || [[ "./$changed_file" == "$project"* ]]; then
97+ if [ -z "$result" ]; then
98+ result="$project"
99+ else
100+ result="$result"$'\n'"$project"
101+ fi
102+ break
103+ fi
104+ done
105+ done
106+
107+ # Convert to JSON array
108+ if [ -z "$result" ]; then
109+ echo "[]"
110+ else
111+ echo "$result" | jq -R -s -c 'split("\n") | map(select(length > 0))'
112+ fi
113+ }
114+
115+ # Filter each project type
116+ NODE_FILTERED=$(filter_projects '${{ steps.find-projects.outputs.node-projects }}')
117+ POETRY_FILTERED=$(filter_projects '${{ steps.find-projects.outputs.poetry-projects }}')
118+ UV_FILTERED=$(filter_projects '${{ steps.find-projects.outputs.uv-projects }}')
119+ PIP_FILTERED=$(filter_projects '${{ steps.find-projects.outputs.pip-projects }}')
120+
121+ echo "node-projects=$NODE_FILTERED" >> $GITHUB_OUTPUT
122+ echo "poetry-projects=$POETRY_FILTERED" >> $GITHUB_OUTPUT
123+ echo "uv-projects=$UV_FILTERED" >> $GITHUB_OUTPUT
124+ echo "pip-projects=$PIP_FILTERED" >> $GITHUB_OUTPUT
125+
44126 # Debug output
45- echo "Node.js projects: $NODE_PROJECTS "
46- echo "Poetry projects: $POETRY_PROJECTS "
47- echo "uv projects: $UV_PROJECTS "
48- echo "pip projects: $PIP_PROJECTS "
127+ echo "Filtered Node.js projects: $NODE_FILTERED "
128+ echo "Filtered Poetry projects: $POETRY_FILTERED "
129+ echo "Filtered uv projects: $UV_FILTERED "
130+ echo "Filtered pip projects: $PIP_FILTERED "
49131
50132 # Build and lint Node.js projects
51133 node :
@@ -266,10 +348,22 @@ jobs:
266348 steps :
267349 - name : Check all jobs passed
268350 run : |
269- if [ "${{ needs.node.result }}" == "failure" ] || \
270- [ "${{ needs.poetry.result }}" == "failure" ] || \
271- [ "${{ needs.uv.result }}" == "failure" ] || \
272- [ "${{ needs.pip.result }}" == "failure" ]; then
351+ # Check each job result - 'skipped' is OK (no projects to build)
352+ # 'success' is OK, 'failure' is not OK
353+ NODE_RESULT="${{ needs.node.result }}"
354+ POETRY_RESULT="${{ needs.poetry.result }}"
355+ UV_RESULT="${{ needs.uv.result }}"
356+ PIP_RESULT="${{ needs.pip.result }}"
357+
358+ echo "Node job result: $NODE_RESULT"
359+ echo "Poetry job result: $POETRY_RESULT"
360+ echo "uv job result: $UV_RESULT"
361+ echo "pip job result: $PIP_RESULT"
362+
363+ if [ "$NODE_RESULT" == "failure" ] || \
364+ [ "$POETRY_RESULT" == "failure" ] || \
365+ [ "$UV_RESULT" == "failure" ] || \
366+ [ "$PIP_RESULT" == "failure" ]; then
273367 echo "One or more jobs failed"
274368 exit 1
275369 fi
0 commit comments