Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
33bcf83
feat(changed-paths): add shared_paths input to trigger full matrix on…
bedatty Mar 19, 2026
cc16a7d
fix(changed-paths): rename inputs to kebab-case to pass composite-sch…
bedatty Mar 19, 2026
7ea0c6f
fix(workflows): remove trailing spaces and quote GITHUB_OUTPUT redire…
bedatty Mar 19, 2026
7c9370a
fix(workflows): quote GITHUB_OUTPUT redirects and suppress inapplicab…
bedatty Mar 19, 2026
3d9c910
fix(workflows): quote GITHUB_OUTPUT, fix SC2188/SC2034/SC2193/SC2001 …
bedatty Mar 19, 2026
3b20c34
docs(changed-paths): update README input names to kebab-case and add …
bedatty Mar 19, 2026
ec5a27d
fix(changed-paths): add jq error handling for malformed filter-paths …
bedatty Mar 19, 2026
4a311b2
fix(gptchangelog): replace useless cat with input redirection (SC2002)
bedatty Mar 19, 2026
504a488
fix(gptchangelog): rename unused APP_NAME/VERSION to _ in changelog P…
bedatty Mar 19, 2026
f3ac96b
fix(changed-paths): align error message and README section to kebab-c…
bedatty Mar 19, 2026
32cd57b
docs(changed-paths): update remaining snake_case section headers and …
bedatty Mar 19, 2026
e3a1a27
docs(changed-paths): move path-level disabled annotation from default…
bedatty Mar 19, 2026
78582a1
feat(workflows): propagate shared_paths input to all reusable workflo…
bedatty Mar 20, 2026
30d667f
fix(workflows): point changed-paths to feat branch for self-consisten…
bedatty Mar 20, 2026
1709f28
fix(workflows): revert changed-paths ref back to develop pre-merge
bedatty Mar 20, 2026
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
12 changes: 6 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,18 +134,18 @@
- name: Get changed paths (monorepo)
if: inputs.filter_paths != ''
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop

Check warning on line 137 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
path_level: ${{ inputs.path_level }}
get_app_name: 'true'
app_name_prefix: ${{ inputs.app_name_prefix }}
app_name_overrides: ${{ inputs.app_name_overrides }}
normalize_to_filter: ${{ inputs.normalize_to_filter }}
filter-paths: ${{ inputs.filter_paths }}
path-level: ${{ inputs.path_level }}
get-app-name: 'true'
app-name-prefix: ${{ inputs.app_name_prefix }}
app-name-overrides: ${{ inputs.app_name_overrides }}
normalize-to-filter: ${{ inputs.normalize_to_filter }}

- name: Set matrix
id: set-matrix
run: |

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:9:25: Double quote to prevent globbing and word splitting

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:5:29: Double quote to prevent globbing and word splitting

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:4:74: Double quote to prevent globbing and word splitting

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:13:31: Double quote to prevent globbing and word splitting

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:12:30: Double quote to prevent globbing and word splitting

Check failure on line 148 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:10:32: Double quote to prevent globbing and word splitting
if [ -z "${{ inputs.filter_paths }}" ]; then
# Single app mode - build from root
APP_NAME="${{ github.event.repository.name }}"
Expand All @@ -164,7 +164,7 @@

- name: Set platforms based on tag type
id: set-platforms
run: |

Check failure on line 167 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:5:49: Double quote to prevent globbing and word splitting

Check failure on line 167 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:15:29: Double quote to prevent globbing and word splitting

Check failure on line 167 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:14:47: Double quote to prevent globbing and word splitting

Check failure on line 167 in .github/workflows/build.yml

View workflow job for this annotation

GitHub Actions / Action Lint

shellcheck reported issue in this script: SC2086:info:10:32: Double quote to prevent globbing and word splitting
TAG="${GITHUB_REF#refs/tags/}"

if [[ "$TAG" == *"-beta"* ]] || [[ "$TAG" == *"-rc"* ]]; then
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/gptchangelog.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: "GPT Changelog"

# This reusable workflow generates CHANGELOG.md files using GPTChangelog
Expand Down Expand Up @@ -141,11 +141,11 @@
- name: Get changed paths (monorepo)
if: (steps.check-tag.outputs.is_stable == 'true' || inputs.stable_releases_only == false) && inputs.filter_paths != ''
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop

Check warning on line 144 in .github/workflows/gptchangelog.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
path_level: ${{ inputs.path_level }}
get_app_name: 'true'
filter-paths: ${{ inputs.filter_paths }}
path-level: ${{ inputs.path_level }}
get-app-name: 'true'

- name: Set matrix
id: set-matrix
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/pr-security-scan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,20 +86,20 @@
# ----------------- Detect Changes & Build Matrix -----------------
- name: Get changed paths
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop

Check warning on line 89 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
get_app_name: true
path_level: ${{ inputs.path_level }}
app_name_prefix: ${{ inputs.app_name_prefix }}
app_name_overrides: ${{ inputs.app_name_overrides }}
normalize_to_filter: ${{ inputs.normalize_to_filter }}
ignore_dirs: |
filter-paths: ${{ inputs.filter_paths }}
get-app-name: true
path-level: ${{ inputs.path_level }}
app-name-prefix: ${{ inputs.app_name_prefix }}
app-name-overrides: ${{ inputs.app_name_overrides }}
normalize-to-filter: ${{ inputs.normalize_to_filter }}
ignore-dirs: |
.github
.githooks
fallback_app_name: ${{ github.event.repository.name }}
consolidate_to_root: ${{ inputs.monorepo_type == 'type2' }}
consolidate_keep_dirs: ${{ inputs.frontend_folder }}
fallback-app-name: ${{ github.event.repository.name }}
consolidate-to-root: ${{ inputs.monorepo_type == 'type2' }}
consolidate-keep-dirs: ${{ inputs.frontend_folder }}

security_scan:
needs: prepare_matrix
Expand Down Expand Up @@ -135,7 +135,7 @@
- name: Trivy Filesystem Scan
id: fs-scan
if: always()
uses: LerianStudio/github-actions-shared-workflows/src/security/trivy-fs-scan@develop

Check warning on line 138 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/security/trivy-fs-scan@develop
with:
scan-ref: ${{ matrix.working_dir }}
app-name: ${{ env.APP_NAME }}
Expand All @@ -159,7 +159,7 @@
- name: Trivy Image Scan
id: image-scan
if: always() && inputs.enable_docker_scan
uses: LerianStudio/github-actions-shared-workflows/src/security/trivy-image-scan@develop

Check warning on line 162 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/security/trivy-image-scan@develop
with:
image-ref: '${{ env.DOCKERHUB_ORG }}/${{ env.APP_NAME }}:pr-scan-${{ github.sha }}'
app-name: ${{ env.APP_NAME }}
Expand All @@ -169,7 +169,7 @@
- name: Dockerfile Compliance Checks
id: dockerfile-checks
if: always() && inputs.enable_docker_scan && inputs.enable_health_score
uses: LerianStudio/github-actions-shared-workflows/src/security/dockerfile-checks@develop

Check warning on line 172 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/security/dockerfile-checks@develop
with:
dockerfile-path: ${{ env.DOCKERFILE_PATH }}

Expand All @@ -177,7 +177,7 @@
- name: Post Security Scan Results to PR
id: post-results
if: always() && github.event_name == 'pull_request'
uses: LerianStudio/github-actions-shared-workflows/src/security/pr-security-reporter@develop

Check warning on line 180 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/security/pr-security-reporter@develop
with:
github-token: ${{ secrets.MANAGE_TOKEN || secrets.GITHUB_TOKEN }}
app-name: ${{ env.APP_NAME }}
Expand Down Expand Up @@ -209,7 +209,7 @@
runs-on: ${{ inputs.runner_type }}
steps:
- name: Slack Notification
uses: LerianStudio/github-actions-shared-workflows/src/notify/slack-notify@develop

Check warning on line 212 in .github/workflows/pr-security-scan.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/notify/slack-notify@develop
with:
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
status: ${{ needs.security_scan.result }}
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@
- name: Get changed paths (monorepo)
if: inputs.filter_paths != ''
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop

Check warning on line 58 in .github/workflows/release.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
path_level: ${{ inputs.path_level }}
get_app_name: 'true'
filter-paths: ${{ inputs.filter_paths }}
path-level: ${{ inputs.path_level }}
get-app-name: 'true'

- name: Set matrix
id: set-matrix
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/typescript-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,14 @@
- name: Get changed paths (monorepo)
if: inputs.components_json == '' && inputs.filter_paths != ''
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop

Check warning on line 156 in .github/workflows/typescript-build.yml

View workflow job for this annotation

GitHub Actions / Pinned Actions Check

Internal action not pinned to a final release version: uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
path_level: ${{ inputs.path_level }}
get_app_name: 'true'
app_name_prefix: ${{ inputs.app_name_prefix }}
app_name_overrides: ${{ inputs.app_name_overrides }}
normalize_to_filter: ${{ inputs.normalize_to_filter }}
filter-paths: ${{ inputs.filter_paths }}
path-level: ${{ inputs.path_level }}
get-app-name: 'true'
app-name-prefix: ${{ inputs.app_name_prefix }}
app-name-overrides: ${{ inputs.app_name_overrides }}
normalize-to-filter: ${{ inputs.normalize_to_filter }}

- name: Set matrix
id: set-matrix
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/typescript-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ jobs:
id: changed-paths
uses: LerianStudio/github-actions-shared-workflows/src/config/changed-paths@develop
with:
filter_paths: ${{ inputs.filter_paths }}
path_level: ${{ inputs.path_level }}
get_app_name: 'true'
filter-paths: ${{ inputs.filter_paths }}
path-level: ${{ inputs.path_level }}
get-app-name: 'true'

- name: Set matrix
id: set-matrix
Expand Down
21 changes: 21 additions & 0 deletions src/config/changed-paths/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Composite action that detects changed files between commits and outputs a matrix
| Input | Description | Required | Default |
|---|---|:---:|---|
| `filter_paths` | JSON array of path prefixes to filter results | No | `''` |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
| `shared_paths` | Newline-separated (or JSON array) path patterns that, when matched by any changed file, include ALL `filter_paths` components in the matrix (e.g., `go.mod`, `go.sum`, `libs/`) | No | `''` |
| `path_level` | Limits the path to the first N segments | No | `0` (disabled) |
| `get_app_name` | Output matrix with `name` and `working_dir` fields | No | `false` |
| `app_name_prefix` | Prefix to add to each app name | No | `''` |
Expand Down Expand Up @@ -143,6 +144,26 @@ If `components/api` and `frontend` both changed:
]
```

### With shared_paths (monorepo root-level files)

When root-level files like `go.mod` or `go.sum` change, all components should be rebuilt. Use `shared_paths` to trigger a full matrix whenever such files are touched:

```yaml
with:
filter_paths: |-
components/manager
components/worker
shared_paths: |-
go.mod
go.sum
libs/
path_level: 2
get_app_name: true
```

If only `go.mod` changes → both `components/manager` and `components/worker` are included in the matrix.
If only `components/worker/cmd/main.go` changes → only `components/worker` is included (normal behaviour).

### With normalize_to_filter

When `normalize_to_filter: true`, deeper changed paths are normalized back to the matching filter path.
Expand Down
166 changes: 104 additions & 62 deletions src/config/changed-paths/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,47 @@ name: Get Changed Paths
description: Detects changed files between commits and outputs a matrix of changed directories for monorepo CI/CD pipelines.

inputs:
filter_paths:
filter-paths:
description: 'Newline-separated list of path prefixes to filter results (e.g., "components/mdz\ncomponents/transaction"). Also accepts JSON array format.'
required: false
default: ''
path_level:
shared-paths:
description: 'Newline-separated list of path patterns (e.g., "go.mod\ngo.sum\nlibs/") that, when matched by any changed file, trigger a build for ALL components in filter_paths. Also accepts JSON array format.'
required: false
default: ''
path-level:
description: 'Limits the path to the first N segments (e.g., 2 -> "components/transactions")'
required: false
default: '0'
get_app_name:
get-app-name:
description: 'If true, outputs a matrix of objects with app name and working directory. Otherwise, outputs a list of changed directories'
required: false
default: 'false'
app_name_prefix:
app-name-prefix:
description: 'Prefix to add to each app name when get_app_name is true'
required: false
default: ''
app_name_overrides:
app-name-overrides:
description: 'Newline-separated list of explicit app name mappings in "path:name" format. Use "path:" for prefix-only. Overrides default segment extraction'
required: false
default: ''
normalize_to_filter:
normalize-to-filter:
description: 'If true, uses the filter path as working_dir instead of the actual trimmed directory path'
required: false
default: 'false'
ignore_dirs:
ignore-dirs:
description: 'Newline-separated list of directories to exclude from the output matrix (e.g., ".github\n.githooks"). Matched by exact name or prefix.'
required: false
default: ''
fallback_app_name:
fallback-app-name:
description: 'When filter_paths is empty, return a single-item matrix with this name and working_dir "." instead of detecting changes. Enables single-app mode.'
required: false
default: ''
consolidate_to_root:
consolidate-to-root:
description: 'When true, consolidate all entries (except those in consolidate_keep_dirs) to a single root entry using fallback_app_name. Requires get_app_name and fallback_app_name.'
required: false
default: 'false'
consolidate_keep_dirs:
consolidate-keep-dirs:
description: 'Newline-separated list of working_dirs to keep as-is during consolidation (e.g., "frontend"). Only used when consolidate_to_root is true.'
required: false
default: ''
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Expand Down Expand Up @@ -116,16 +120,17 @@ runs:
shell: bash
run: |
FILES="${{ steps.changed.outputs.files }}"
FILTER_PATHS='${{ inputs.filter_paths }}'
PATH_LEVEL="${{ inputs.path_level }}"
GET_APP_NAME="${{ inputs.get_app_name }}"
APP_NAME_PREFIX="${{ inputs.app_name_prefix }}"
APP_NAME_OVERRIDES="${{ inputs.app_name_overrides }}"
NORMALIZE_TO_FILTER="${{ inputs.normalize_to_filter }}"
IGNORE_DIRS='${{ inputs.ignore_dirs }}'
FALLBACK_APP_NAME="${{ inputs.fallback_app_name }}"
CONSOLIDATE_TO_ROOT="${{ inputs.consolidate_to_root }}"
CONSOLIDATE_KEEP_DIRS='${{ inputs.consolidate_keep_dirs }}'
FILTER_PATHS='${{ inputs.filter-paths }}'
SHARED_PATHS='${{ inputs.shared-paths }}'
PATH_LEVEL="${{ inputs.path-level }}"
GET_APP_NAME="${{ inputs.get-app-name }}"
APP_NAME_PREFIX="${{ inputs.app-name-prefix }}"
APP_NAME_OVERRIDES="${{ inputs.app-name-overrides }}"
NORMALIZE_TO_FILTER="${{ inputs.normalize-to-filter }}"
IGNORE_DIRS='${{ inputs.ignore-dirs }}'
FALLBACK_APP_NAME="${{ inputs.fallback-app-name }}"
CONSOLIDATE_TO_ROOT="${{ inputs.consolidate-to-root }}"
CONSOLIDATE_KEEP_DIRS='${{ inputs.consolidate-keep-dirs }}'

# Single app fallback: when filter_paths is empty and fallback_app_name is set,
# return a single-item matrix without detecting changes
Expand Down Expand Up @@ -154,58 +159,95 @@ runs:
exit 0
fi

# Get directory for each file
DIRS=$(echo "$FILES" | xargs -n1 dirname)

# Trim to first N path segments if specified
if [[ -n "$PATH_LEVEL" ]] && [[ "$PATH_LEVEL" -gt 0 ]]; then
echo "Trimming paths to first $PATH_LEVEL segments"
DIRS=$(echo "$DIRS" | cut -d'/' -f-"$PATH_LEVEL")
fi
DIRS_FROM_SHARED=false

# Filter paths if filter_paths is provided (supports both JSON array and newline-separated formats)
if [[ -n "$FILTER_PATHS" ]] && [[ "$FILTER_PATHS" != "[]" ]] && [[ "$FILTER_PATHS" != "" ]]; then
# Detect format and parse accordingly
if [[ "$FILTER_PATHS" == "["* ]]; then
# Input looks like JSON array — validate strictly
FILTER_LIST=$(echo "$FILTER_PATHS" | jq -er '.[]' 2>/dev/null)
# Check shared_paths: if any changed file matches, include ALL filter_paths entries
if [[ -n "$SHARED_PATHS" ]] && [[ "$SHARED_PATHS" != "[]" ]] && [[ -n "$FILTER_PATHS" ]] && [[ "$FILTER_PATHS" != "[]" ]]; then
if [[ "$SHARED_PATHS" == "["* ]]; then
SHARED_LIST=$(echo "$SHARED_PATHS" | jq -er '.[]' 2>/dev/null)
if [[ $? -ne 0 ]]; then
echo "::error::filter_paths looks like a JSON array but is malformed: $FILTER_PATHS"
echo "::error::shared_paths looks like a JSON array but is malformed: $SHARED_PATHS"
exit 1
fi
else
# Newline-separated input
FILTER_LIST="$FILTER_PATHS"
SHARED_LIST="$SHARED_PATHS"
fi

if [[ -n "$FILTER_LIST" ]]; then
FILTERED=""
while read -r DIR; do
while read -r FILTER; do
[[ -z "$FILTER" ]] && continue
while [[ "$FILTER" == */ && "$FILTER" != "/" ]]; do
FILTER="${FILTER%/}"
done
if [[ "$DIR" == "$FILTER" ]] || [[ "$DIR" == "$FILTER"/* ]]; then
if [[ "$NORMALIZE_TO_FILTER" == "true" ]]; then
FILTERED+="$FILTER"$'\n'
else
FILTERED+="$DIR"$'\n'
fi
break
fi
done <<< "$FILTER_LIST"
done <<< "$DIRS"
while IFS= read -r FILE; do
[[ -z "$FILE" ]] && continue
while IFS= read -r SHARED; do
[[ -z "$SHARED" ]] && continue
while [[ "$SHARED" == */ && "$SHARED" != "/" ]]; do SHARED="${SHARED%/}"; done
if [[ "$FILE" == "$SHARED" ]] || [[ "$FILE" == "$SHARED"/* ]]; then
echo "Shared path hit: '$FILE' matches '$SHARED' — including all filter_paths"
DIRS_FROM_SHARED=true
break 2
fi
done <<< "$SHARED_LIST"
done <<< "$FILES"
fi

# If nothing matched, exit
if [[ -z "$FILTERED" ]]; then
echo "No matching directories found after filtering."
printf "matrix=[]\n" >> "$GITHUB_OUTPUT"
printf "has_changes=false\n" >> "$GITHUB_OUTPUT"
exit 0
if [[ "$DIRS_FROM_SHARED" == "true" ]]; then
# Use all filter_paths as the build targets
if [[ "$FILTER_PATHS" == "["* ]]; then
DIRS=$(echo "$FILTER_PATHS" | jq -er '.[]')
else
DIRS="$FILTER_PATHS"
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.
else
# Get directory for each file
DIRS=$(echo "$FILES" | xargs -n1 dirname)

# Trim to first N path segments if specified
if [[ -n "$PATH_LEVEL" ]] && [[ "$PATH_LEVEL" -gt 0 ]]; then
echo "Trimming paths to first $PATH_LEVEL segments"
DIRS=$(echo "$DIRS" | cut -d'/' -f-"$PATH_LEVEL")
fi

# Filter paths if filter_paths is provided (supports both JSON array and newline-separated formats)
if [[ -n "$FILTER_PATHS" ]] && [[ "$FILTER_PATHS" != "[]" ]] && [[ "$FILTER_PATHS" != "" ]]; then
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# Detect format and parse accordingly
if [[ "$FILTER_PATHS" == "["* ]]; then
# Input looks like JSON array — validate strictly
FILTER_LIST=$(echo "$FILTER_PATHS" | jq -er '.[]' 2>/dev/null)
if [[ $? -ne 0 ]]; then
echo "::error::filter_paths looks like a JSON array but is malformed: $FILTER_PATHS"
exit 1
fi
Comment thread
coderabbitai[bot] marked this conversation as resolved.
else
# Newline-separated input
FILTER_LIST="$FILTER_PATHS"
fi

DIRS="$FILTERED"
if [[ -n "$FILTER_LIST" ]]; then
FILTERED=""
while read -r DIR; do
while read -r FILTER; do
[[ -z "$FILTER" ]] && continue
while [[ "$FILTER" == */ && "$FILTER" != "/" ]]; do
FILTER="${FILTER%/}"
done
if [[ "$DIR" == "$FILTER" ]] || [[ "$DIR" == "$FILTER"/* ]]; then
if [[ "$NORMALIZE_TO_FILTER" == "true" ]]; then
FILTERED+="$FILTER"$'\n'
else
FILTERED+="$DIR"$'\n'
fi
break
fi
done <<< "$FILTER_LIST"
done <<< "$DIRS"

# If nothing matched, exit
if [[ -z "$FILTERED" ]]; then
echo "No matching directories found after filtering."
printf "matrix=[]\n" >> "$GITHUB_OUTPUT"
printf "has_changes=false\n" >> "$GITHUB_OUTPUT"
exit 0
fi

DIRS="$FILTERED"
fi
fi
fi

Expand Down
Loading