diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d4df3817..2031e1ad 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -211,12 +211,15 @@ jobs: max-parallel: 4 matrix: platform: [ubuntu-latest, ubuntu-22.04, windows-latest, macos-latest, macos-11, ubuntu-18.04, windows-2022] + fetch-depth: [1, 2] steps: - name: Checkout to branch uses: actions/checkout@v3 + with: + fetch-depth: ${{ matrix.fetch-depth }} - - name: Run changed-files with a single commit history + - name: Run changed-files id: changed-files uses: ./ @@ -358,6 +361,16 @@ jobs: echo '${{ toJSON(steps.changed-files.outputs) }}' shell: bash + - name: Run changed-files with include_all_old_new_renamed_files + id: changed-files-all-old-new-renamed-files + uses: ./ + with: + include_all_old_new_renamed_files: true + - name: Show output + run: | + echo '${{ toJSON(steps.changed-files-all-old-new-renamed-files.outputs) }}' + shell: + bash - name: List all modified files run: | for file in ${{ steps.changed-files.outputs.modified_files }}; do diff --git a/action.yml b/action.yml index 474c3328..e364216c 100644 --- a/action.yml +++ b/action.yml @@ -77,10 +77,10 @@ inputs: description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs." required: false default: "false" - max_fetch_depth: - description: "Max limit for fetching branch history. **NOTE**: This can be adjusted to resolve errors with insufficient history." + fetch_depth: + description: "Limit depth of target branch history fetched. **NOTE**: This can be adjusted to resolve errors with insufficient history." required: false - default: "300" + default: "30" outputs: added_files: @@ -171,7 +171,7 @@ runs: INPUT_SINCE: ${{ inputs.since }} INPUT_UNTIL: ${{ inputs.until }} INPUT_PATH: ${{ inputs.path }} - INPUT_MAX_FETCH_DEPTH: ${{ inputs.max_fetch_depth }} + INPUT_FETCH_DEPTH: ${{ inputs.fetch_depth }} - name: Glob match uses: tj-actions/glob@v15 id: glob diff --git a/diff-sha.sh b/diff-sha.sh index 8d9bade8..5b3661fa 100644 --- a/diff-sha.sh +++ b/diff-sha.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -eu +set -euo pipefail INITIAL_COMMIT="false" GITHUB_OUTPUT=${GITHUB_OUTPUT:-""} @@ -50,7 +50,7 @@ if [[ -n "$INPUT_UNTIL" ]]; then fi else if [[ -z $INPUT_SHA ]]; then - CURRENT_SHA=$(git rev-list -n 1 "HEAD" 2>&1) && exit_status=$? || exit_status=$? + CURRENT_SHA=$(git rev-list --no-merges -n 1 HEAD 2>&1) && exit_status=$? || exit_status=$? else CURRENT_SHA=$INPUT_SHA; exit_status=$? fi @@ -67,28 +67,6 @@ else echo "::debug::Current SHA: $CURRENT_SHA" fi -function deepenShallowCloneToFindCommit() { - local base_ref="$1" - local diff="$2" - local ref="$3" - local target_branch="$4" - local depth=20 - local max_depth=$INPUT_MAX_FETCH_DEPTH - - while ! git diff "$base_ref$diff$ref" &>/dev/null; do - echo "::debug::Unable to find merge-base in shallow clone. Increasing depth to $((depth * 2))..." - - depth=$((depth * 2)) - - if [[ $depth -gt $max_depth ]]; then - echo "::error::Unable to find merge-base in shallow clone. Please increase 'max_fetch_depth' to at least $((depth + 20))." - exit 1 - fi - - git fetch --no-tags -u --progress --deepen="$depth" origin "$target_branch":"$target_branch" - done -} - if [[ -z $GITHUB_BASE_REF ]]; then echo "Running on a push event..." TARGET_BRANCH=${GITHUB_REF/refs\/heads\//} && exit_status=$? || exit_status=$? @@ -104,10 +82,14 @@ if [[ -z $GITHUB_BASE_REF ]]; then exit 1 fi else - PREVIOUS_SHA="" + git fetch --no-tags -u --progress --depth="$INPUT_FETCH_DEPTH" origin "$TARGET_BRANCH":"$TARGET_BRANCH" - if [[ "$GITHUB_EVENT_FORCED" == "false" || -z "$GITHUB_EVENT_FORCED" ]]; then - PREVIOUS_SHA=$GITHUB_EVENT_BEFORE + PREVIOUS_SHA=$(git rev-list --no-merges -n 1 "$TARGET_BRANCH" 2>&1) && exit_status=$? || exit_status=$? + + if [[ -z "$PREVIOUS_SHA" ]]; then + if [[ "$GITHUB_EVENT_FORCED" == "false" || -z "$GITHUB_EVENT_FORCED" ]]; then + PREVIOUS_SHA=$GITHUB_EVENT_BEFORE + fi fi if [[ -z "$PREVIOUS_SHA" || "$PREVIOUS_SHA" == "0000000000000000000000000000000000000000" ]]; then @@ -138,15 +120,12 @@ if [[ -z $GITHUB_BASE_REF ]]; then echo "::debug::Target branch $TARGET_BRANCH..." echo "::debug::Current branch $CURRENT_BRANCH..." - echo "::debug::Fetching previous commit SHA: $PREVIOUS_SHA" - deepenShallowCloneToFindCommit "$PREVIOUS_SHA" ".." "$CURRENT_SHA" "$TARGET_BRANCH" - echo "::debug::Verifying the previous commit SHA: $PREVIOUS_SHA" git rev-parse --quiet --verify "$PREVIOUS_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Unable to locate the previous sha: $PREVIOUS_SHA" - echo "::error::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage" + echo "::error::Please verify that both commit are valid, and increase the fetch_depth to a number higher than $INPUT_INPUT_FETCH_DEPTH." exit 1 fi else @@ -155,33 +134,36 @@ else CURRENT_BRANCH=$GITHUB_HEAD_REF if [[ -z $INPUT_BASE_SHA ]]; then - git fetch --no-tags -u --progress --depth=10 origin "$TARGET_BRANCH":"$TARGET_BRANCH" - PREVIOUS_SHA=$GITHUB_EVENT_PULL_REQUEST_BASE_SHA && exit_status=$? || exit_status=$? + git fetch --no-tags -u --progress --depth="$INPUT_FETCH_DEPTH" origin "$TARGET_BRANCH":"$TARGET_BRANCH" + git fetch --no-tags -u --progress --deepen=40000 + + PREVIOUS_SHA=$(git rev-list --no-merges -n 1 "$TARGET_BRANCH" 2>&1) && exit_status=$? || exit_status=$? + if [[ -z "$PREVIOUS_SHA" ]]; then + PREVIOUS_SHA=$GITHUB_EVENT_PULL_REQUEST_BASE_SHA && exit_status=$? || exit_status=$? + fi echo "::debug::Previous SHA: $PREVIOUS_SHA" else - git fetch --no-tags -u --progress --depth=10 origin "$INPUT_BASE_SHA" && exit_status=$? || exit_status=$? + git fetch --no-tags -u --progress --depth="$INPUT_FETCH_DEPTH" origin "$INPUT_BASE_SHA" && exit_status=$? || exit_status=$? + git fetch --no-tags -u --progress --deepen=40000 PREVIOUS_SHA=$INPUT_BASE_SHA && exit_status=$? || exit_status=$? fi echo "::debug::Target branch: $TARGET_BRANCH" echo "::debug::Current branch: $CURRENT_BRANCH" - echo "::debug::Fetching previous commit SHA: $PREVIOUS_SHA" - deepenShallowCloneToFindCommit "$PREVIOUS_SHA" "..." "$CURRENT_SHA" "$TARGET_BRANCH" - echo "::debug::Verifying the previous commit SHA: $PREVIOUS_SHA" git rev-parse --quiet --verify "$PREVIOUS_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Unable to locate the previous sha: $PREVIOUS_SHA" - echo "::error::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage" + echo "::error::Please verify that both commit are valid, and increase the fetch_depth to a number higher than $INPUT_INPUT_FETCH_DEPTH." exit 1 fi fi -if [[ -n "$PREVIOUS_SHA" && -n "$CURRENT_SHA" && "$PREVIOUS_SHA" == "$CURRENT_SHA" && "$INITIAL_COMMIT" == "false" ]]; then - echo "::error::Similar commit hashes detected: previous sha: $PREVIOUS_SHA is equivalent to the current sha: $CURRENT_SHA" - echo "::error::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage" +if [[ "$PREVIOUS_SHA" == "$CURRENT_SHA" && "$INITIAL_COMMIT" == "false" ]]; then + echo "::error::Similar commit hashes detected: previous sha: $PREVIOUS_SHA is equivalent to the current sha: $CURRENT_SHA." + echo "::error::Please verify that both commit are valid, and increase the fetch_depth to a number higher than $INPUT_INPUT_FETCH_DEPTH." exit 1 fi diff --git a/get-changed-paths.sh b/get-changed-paths.sh index e2655a49..265ac711 100755 --- a/get-changed-paths.sh +++ b/get-changed-paths.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -set -eu +set -euo pipefail INPUT_SEPARATOR="${INPUT_SEPARATOR//'%'/'%25'}" INPUT_SEPARATOR="${INPUT_SEPARATOR//'.'/'%2E'}" @@ -30,13 +30,13 @@ function get_diff() { local filter="$3" while IFS='' read -r sub; do - sub_commit_pre="$(git diff "$base$DIFF$sha" -- "$sub" | grep '^[-]Subproject commit' | awk '{print $3}')" && exit_status=$? || exit_status=$? + sub_commit_pre="$(git diff "$base$DIFF$sha" -- "$sub" | { grep '^[-]Subproject commit' || true; } | awk '{print $3}')" && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get previous commit for submodule ($sub) between: $base$DIFF$sha" exit 1 fi - sub_commit_cur="$(git diff "$base$DIFF$sha" -- "$sub" | grep '^[+]Subproject commit' | awk '{print $3}')" && exit_status=$? || exit_status=$? + sub_commit_cur="$(git diff "$base$DIFF$sha" -- "$sub" | { grep '^[+]Subproject commit' || true; } | awk '{print $3}')" && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get current commit for submodule ($sub) between: $base$DIFF$sha" exit 1 @@ -74,13 +74,13 @@ function get_renames() { local sha="$2" while IFS='' read -r sub; do - sub_commit_pre="$(git diff "$base$DIFF$sha" -- "$sub" | grep '^[-]Subproject commit' | awk '{print $3}')" && exit_status=$? || exit_status=$? + sub_commit_pre="$(git diff "$base$DIFF$sha" -- "$sub" | { grep '^[-]Subproject commit' || true; } | awk '{print $3}')" && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get previous commit for submodule ($sub) between: $base$DIFF$sha" exit 1 fi - sub_commit_cur="$(git diff "$base$DIFF$sha" -- "$sub" | grep '^[+]Subproject commit' | awk '{print $3}')" && exit_status=$? || exit_status=$? + sub_commit_cur="$(git diff "$base$DIFF$sha" -- "$sub" | { grep '^[+]Subproject commit' || true; } | awk '{print $3}')" && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get current commit for submodule ($sub) between: $base$DIFF$sha" exit 1 @@ -97,14 +97,14 @@ function get_renames() { done < <(git submodule | awk '{print $2}') if [[ "$INPUT_DIR_NAMES" == "true" ]]; then - git log --name-status --ignore-submodules=all "$base" "$sha" | grep -E "^R" | awk -F '\t' -v d="$INPUT_OLD_NEW_SEPARATOR" '{print $2d$3}' | xargs -I {} dirname {} | uniq && exit_status=$? || exit_status=$? + git log --name-status --ignore-submodules=all "$base" "$sha" | { grep -E "^R" || true; } | awk -F '\t' -v d="$INPUT_OLD_NEW_SEPARATOR" '{print $2d$3}' | xargs -I {} dirname {} | uniq && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get renamed directories between: $base → $sha" exit 1 fi else - git log --name-status --ignore-submodules=all "$base" "$sha" | grep -E "^R" | awk -F '\t' -v d="$INPUT_OLD_NEW_SEPARATOR" '{print $2d$3}' && exit_status=$? || exit_status=$? + git log --name-status --ignore-submodules=all "$base" "$sha" | { grep -E "^R" || true; } | awk -F '\t' -v d="$INPUT_OLD_NEW_SEPARATOR" '{print $2d$3}' && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then echo "::error::Failed to get renamed files between: $base → $sha" @@ -161,19 +161,19 @@ if [[ "$INPUT_HAS_CUSTOM_PATTERNS" == "false" ]]; then fi fi else - ADDED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" A | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - COPIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" C | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - DELETED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" D | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" M | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - RENAMED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" R | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - TYPE_CHANGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" T | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - UNMERGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" U | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - UNKNOWN=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" X | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - ALL_CHANGED_AND_MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "*ACDMRTUX" | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - ALL_CHANGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMR" | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - ALL_MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMRD" | grep -x -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + ADDED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" A | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + COPIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" C | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + DELETED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" D | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" M | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + RENAMED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" R | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + TYPE_CHANGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" T | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + UNMERGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" U | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + UNKNOWN=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" X | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + ALL_CHANGED_AND_MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "*ACDMRTUX" | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + ALL_CHANGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMR" | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + ALL_MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMRD" | { grep -x -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') if [[ $INPUT_INCLUDE_ALL_OLD_NEW_RENAMED_FILES == "true" ]]; then - ALL_OLD_NEW_RENAMED=$(get_renames "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" | grep -w -E -f "$INPUT_FILES_PATTERN_FILE" | awk -v d="$INPUT_OLD_NEW_FILES_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}') + ALL_OLD_NEW_RENAMED=$(get_renames "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" | { grep -w -E -f "$INPUT_FILES_PATTERN_FILE" || true; } | awk -v d="$INPUT_OLD_NEW_FILES_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}') fi ALL_OTHER_CHANGED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMR" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')