From e7a50e0a41a1b150d8dd0e92e63e7d8ad7cd9663 Mon Sep 17 00:00:00 2001 From: Alexandr Yepishev Date: Mon, 9 Dec 2024 20:30:08 +0000 Subject: [PATCH] Map affected files to modules --- .../scripts/map-affected-files-to-modules.sh | 41 +++++++++++++++++++ .github/workflows/ci-core.yml | 27 ++++++++++-- 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100755 .github/scripts/map-affected-files-to-modules.sh diff --git a/.github/scripts/map-affected-files-to-modules.sh b/.github/scripts/map-affected-files-to-modules.sh new file mode 100755 index 00000000000..38204c2bbb4 --- /dev/null +++ b/.github/scripts/map-affected-files-to-modules.sh @@ -0,0 +1,41 @@ +#!/bin/bash +set -e + +# Get the list of changed files from the JSON payload +changed_files=$(echo "$1" | jq -r '.[]') +echo "Changed files: ${changed_files[@]}" + +# Find all modules in the repository, strip the leading './' and remove duplicates +modules=$(find . -name 'go.mod' -exec dirname {} \; | sed 's|^./||' | uniq) +echo "Found modules: ${modules[@]}" + +# An associative array to track unique modules (since bash v4) +declare -A unique_modules + +# Loop through each changed file and determine its module +for path_to_file in $changed_files; do + echo "Resolving a module affected by a file: '$path_to_file'" + for module in $modules; do + echo "Checking against module: '$module'" + if [[ ! $path_to_file =~ \/ ]]; then # if no slash in the path it is the root (i.e. main.go vs .gitignore) + echo "File '$path_to_file' is a file in the root." + unique_modules["."]="." + break + # skip adding a dot to the affected_modules + # if the path to a file matches the path to a module, + # add it to affected_modules + elif [[ $module != "." && $path_to_file =~ ^$module* ]]; then + echo "File '$path_to_file' is in the module '$module'" + unique_modules["$module"]="$module" + break + fi + done +done + +# Convert associative array keys to an indexed array +affected_modules=("${!unique_modules[@]}") +echo "Affected modules: ${affected_modules[@]}" + +# Convert the array to a JSON array +json_array=$(printf '%s\n' "${affected_modules[@]}" | jq -R . | jq -s . | jq -c) +echo "module_names=$json_array" >> $GITHUB_OUTPUT diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 6ce992240da..1ba20be1ebe 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -33,7 +33,7 @@ jobs: permissions: pull-requests: read outputs: - affected-packages: ${{ steps.match-every.outputs.non-ignored_files }} + affected-packages: ${{ toJson(steps.resolved-modules.outputs.module_names) }} deployment-changes: ${{ steps.match-some.outputs.deployment == 'true' }} should-run-ci-core: ${{ steps.match-some.outputs.core-ci == 'true' || steps.match-every.outputs.non-ignored == 'true' || github.event_name == 'workflow_dispatch' || github.event_name == 'schedule' }} should-run-golangci: ${{ steps.match-some.outputs.golang-ci == 'true' || steps.match-every.outputs.non-ignored == 'true' || github.event_name == 'workflow_dispatch' }} @@ -96,14 +96,33 @@ jobs: - '!nix-darwin-shell-hook.sh' - '!LICENSE' - '!.github/**' - - name: TEST - run: echo "${{ steps.match-every.outputs.non-ignored_files }}" + + - name: Resolve affected files to modules + if: ${{ steps.match-every.outputs.non-ignored == 'true' }} + id: resolved-modules + shell: bash + run: | + bash ./.github/scripts/map-affected-files-to-modules.sh '${{ steps.match-every.outputs.non-ignored_files }}' + test-filter: + name: Test Filter + needs: [filter] + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4.2.1 + - name: Test Filter 1 + shell: bash + run: echo "${{ needs.filter.outputs.affected-packages }}" + - name: Test Filter 2 + shell: bash + run: echo "${{ fromJson(needs.filter.outputs.affected-packages) }}" + golangci: name: lint + needs: [filter, run-frequency] # We don't directly merge dependabot PRs, so let's not waste the resources. if: ${{ (github.event_name == 'pull_request' || github.event_name == 'schedule') && github.actor != 'dependabot[bot]' && needs.filter.outputs.should-run-golangci == 'true' }} - needs: [filter, run-frequency] permissions: # To annotate code in the PR. checks: write