diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 25364eb4..60097e9e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -40,3 +40,24 @@ jobs: - name: Show output run: | echo "${{ toJSON(steps.changed-files-comma.outputs) }}" + - name: Run changed-files with specific files + id: changed-files-specific + uses: ./ + with: + files: | + action.yml + .github/workflows/test.yml + - name: Show output + run: | + echo "${{ toJSON(steps.changed-files-specific.outputs) }}" + - name: Run changed-files with specific files comma separator + id: changed-files-specific-comma + uses: ./ + with: + files: | + action.yml + .github/workflows/test.yml + separator: "," + - name: Show output + run: | + echo "${{ toJSON(steps.changed-files-specific-comma.outputs) }}" diff --git a/README.md b/README.md index 887ddfd4..d030d053 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Using the default separator. | Output | type | example | description | |:-------------------:|:------------:|:------------------------------:|:----------------------------------------:| | all_modified_files | `string` | 'new.txt other.png ...' | Select all modified files
*i.e a combination of all added,
copied and modified files (ACM).* | +| has_changed | `string` | `true OR false` | Returns `true` only when the filenames provided using `files` input have all changed | | all_changed_files | `string` | 'new.txt other.png ...' | Select all paths (*)
*i.e a combination of all options below.* | | added_files | `string` | 'new.txt other.png ...' | Select only files that are Added (A) | | copied_files | `string` | 'new.txt other.png ...' | Select only files that are Copied (C) | @@ -41,6 +42,7 @@ Using the default separator. | Input | type | required | default | description | |:-------------:|:-----------:|:-------------:|:----------------------------:|:-------------:| | separator | `string` | `true` | `' '` | Separator to return outputs | +| files | `string OR string[]` | `false` | | Restricted list of specific files to watch for changes | ## Usage diff --git a/action.yml b/action.yml index 8b18a3ba..f3e0d22f 100644 --- a/action.yml +++ b/action.yml @@ -6,6 +6,10 @@ inputs: description: 'Split character for array output' required: true default: " " + files: + description: 'Check for file changes for all files listed (Defaults to the entire repo)' + required: false + default: "" outputs: added_files: @@ -38,6 +42,9 @@ outputs: all_modified_files: description: List of all copied modified and added files value: ${{ steps.changed_files.outputs.all_modified_files }} + has_changed: + description: Return true only when all files provided using the files input have all changed. + value: ${{ steps.changed_files.outputs.has_changed }} runs: using: 'composite' @@ -53,30 +60,96 @@ runs: git fetch --depth=1 origin ${TARGET_BRANCH}:${TARGET_BRANCH} HEAD_SHA=$(git rev-parse ${TARGET_BRANCH} || true) fi - - echo "Getting diff..." - ADDED=$(git diff --diff-filter=A --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - COPIED=$(git diff --diff-filter=C --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - DELETED=$(git diff --diff-filter=D --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - MODIFIED=$(git diff --diff-filter=M --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - RENAMED=$(git diff --diff-filter=R --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - CHANGED=$(git diff --diff-filter=T --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - UNMERGED=$(git diff --diff-filter=U --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - UNKNOWN=$(git diff --diff-filter=X --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - ALL_CHANGED=$(git diff --diff-filter='*ACDMRTUX' --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - ALL_MODIFIED_FILES=$(git diff --diff-filter='ACM' --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') - - echo "::set-output name=added_files::$ADDED" - echo "::set-output name=copied_files::$COPIED" - echo "::set-output name=deleted_files::$DELETED" - echo "::set-output name=modified_files::$MODIFIED" - echo "::set-output name=renamed_files::$RENAMED" - echo "::set-output name=changed_files::$CHANGED" - echo "::set-output name=unmerged_files::$UNMERGED" - echo "::set-output name=unknown_files::$UNKNOWN" - echo "::set-output name=all_changed_files::$ALL_CHANGED" - echo "::set-output name=all_modified_files::$ALL_MODIFIED_FILES" + INPUT_FILES="${{ inputs.files }}" + + if [[ -z "$INPUT_FILES" ]]; then + + echo "Getting diff..." + + ADDED=$(git diff --diff-filter=A --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + COPIED=$(git diff --diff-filter=C --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + DELETED=$(git diff --diff-filter=D --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + MODIFIED=$(git diff --diff-filter=M --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + RENAMED=$(git diff --diff-filter=R --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + CHANGED=$(git diff --diff-filter=T --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + UNMERGED=$(git diff --diff-filter=U --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + UNKNOWN=$(git diff --diff-filter=X --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + ALL_CHANGED=$(git diff --diff-filter='*ACDMRTUX' --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + ALL_MODIFIED_FILES=$(git diff --diff-filter='ACM' --name-only "$HEAD_SHA" | tr "\n" "${{ inputs.separator }}" | sed -E 's/(${{ inputs.separator }})$//') + + echo "::set-output name=added_files::$ADDED" + echo "::set-output name=copied_files::$COPIED" + echo "::set-output name=deleted_files::$DELETED" + echo "::set-output name=modified_files::$MODIFIED" + echo "::set-output name=renamed_files::$RENAMED" + echo "::set-output name=changed_files::$CHANGED" + echo "::set-output name=unmerged_files::$UNMERGED" + echo "::set-output name=unknown_files::$UNKNOWN" + echo "::set-output name=all_changed_files::$ALL_CHANGED" + echo "::set-output name=all_modified_files::$ALL_MODIFIED_FILES" + + else + ADDED=() + COPIED=() + DELETED=() + MODIFIED=() + RENAMED=() + CHANGED=() + UNMERGED=() + UNKNOWN=() + ALL_CHANGED=() + ALL_MODIFIED_FILES=() + + for path in ${INPUT_FILES} + do + echo "Checking for file changes: \"${path}\"..." + ADDED+=$(git diff --diff-filter=A --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + COPIED+=$(git diff --diff-filter=C --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + DELETED+=$(git diff --diff-filter=D --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + MODIFIED+=$(git diff --diff-filter=M --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + RENAMED+=$(git diff --diff-filter=R --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + CHANGED+=$(git diff --diff-filter=T --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + UNMERGED+=$(git diff --diff-filter=U --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + UNKNOWN+=$(git diff --diff-filter=X --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + ALL_CHANGED+=$(git diff --diff-filter='*ACDMRTUX' --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + ALL_MODIFIED_FILES+=$(git diff --diff-filter='ACM' --name-only "$HEAD_SHA" | grep -E "(${path})" | xargs printf "%s${{ inputs.separator }}" || true) + done + + ADDED=$(echo "$ADDED" | sed -E 's/(${{ inputs.separator }})$//') + COPIED=$(echo $COPIED | sed -E 's/(${{ inputs.separator }})$//') + DELETED=$(echo "$DELETED" | sed -E 's/(${{ inputs.separator }})$//') + MODIFIED=$(echo "$MODIFIED" | sed -E 's/(${{ inputs.separator }})$//') + RENAMED=$(echo "$RENAMED" | sed -E 's/(${{ inputs.separator }})$//') + CHANGED=$(echo "$CHANGED" | sed -E 's/(${{ inputs.separator }})$//') + UNMERGED=$(echo "$UNMERGED" | sed -E 's/(${{ inputs.separator }})$//') + UNKNOWN=$(echo "$UNKNOWN" | sed -E 's/(${{ inputs.separator }})$//') + ALL_CHANGED=$(echo "$ALL_CHANGED" | sed -E 's/(${{ inputs.separator }})$//') + ALL_MODIFIED_FILES=$(echo "$ALL_MODIFIED_FILES" | sed -E 's/(${{ inputs.separator }})$//') + + OUTPUT_ALL_MODIFIED_FILES=$(echo $ALL_MODIFIED_FILES | sed "s/${{ inputs.separator }}/ /g") + ALL_INPUT_FILES=$(echo $INPUT_FILES | sed "s/\n/ /g") + + IFS=$'\n' SORTED_INPUT_FILES=($(sort <<<"${ALL_INPUT_FILES[*]}")) + IFS=$'\n' SORTED_OUTPUT_ALL_MODIFIED_FILES=($(sort <<<"${OUTPUT_ALL_MODIFIED_FILES[*]}")) + + if [[ "${SORTED_INPUT_FILES[*]}" == "${SORTED_OUTPUT_ALL_MODIFIED_FILES[*]}" ]]; then + echo "::set-output name=has_changed::true" + else + echo "::set-output name=has_changed::false" + fi + + echo "::set-output name=added_files::$ADDED" + echo "::set-output name=copied_files::$COPIED" + echo "::set-output name=deleted_files::$DELETED" + echo "::set-output name=modified_files::$MODIFIED" + echo "::set-output name=renamed_files::$RENAMED" + echo "::set-output name=changed_files::$CHANGED" + echo "::set-output name=unmerged_files::$UNMERGED" + echo "::set-output name=unknown_files::$UNKNOWN" + echo "::set-output name=all_changed_files::$ALL_CHANGED" + echo "::set-output name=all_modified_files::$ALL_MODIFIED_FILES" + fi shell: bash branding: