diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 4fdabc09..35af0262 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -69,8 +69,8 @@ body: id: logs attributes: label: Relevant log output - description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. - render: shell + description: Please copy and paste any relevant log outputs after enabling debug logging using ACTIONS_STEP_DEBUG=true See https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging. This will be automatically formatted into code, so no need for backticks. + render: bash - type: textarea attributes: label: Anything else? diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 41192bd0..d508be25 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -242,6 +242,16 @@ jobs: echo '${{ toJSON(steps.changed-files-quotepath.outputs) }}' shell: bash + - name: Run changed-files with dir_names + id: changed-files-only-dir-names + uses: ./ + with: + dir_names: "true" + - name: Show output + run: | + echo '${{ toJSON(steps.changed-files-only-dir-names.outputs) }}' + shell: + bash - name: Run changed-files with forward slash separator id: changed-files-forward-slash uses: ./ diff --git a/README.md b/README.md index b6945568..0446b6e2 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ Support this project with a :star: | all\_changed\_files | `string` | `'new.txt path/to/file.png ...'` | Select all changed files
i.e. *a combination of all added,
copied, modified and renamed files (ACMR)* | | all\_modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select all changed files
i.e. *a combination of all added,
copied, modified, renamed and deleted files (ACMRD)* | | all\_changed\_and\_modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select all changed
and modified files
i.e. *a combination of (ACMRDTUX)* | -| all\_old\_new\_renamed\_files | `string` | `'old name.txt,new name.txt old name 2.txt,new name 2.txt...'` | Select only files that are Renamed and list their old and new names (R) | +| all\_old\_new\_renamed\_files | `string` | `'old name.txt,new name.txt old name 2.txt,new name 2.txt...'` | Select only files that are Renamed and list their old and new names (R) | | added\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Added (A) | | copied\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Copied (C) | | deleted\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Deleted (D) | @@ -126,26 +126,27 @@ Support this project with a :star: ## Inputs -| Input | type | required | default | description | -|:---------------------------------:|:----------------------:|:--------:|:---------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| -| token | `string` | `false` | `${{ github.token }}` | [GITHUB\_TOKEN](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow)
or a repo scoped
[Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) | -| separator | `string` | `false` | `' '` | Split character for output strings | -| include\_all\_old\_new\_renamed\_files | `boolean` | `false` | `false` | Include `all_old_new_renamed_files` output. Note this can generate a large debug output See: [#501](https://github.com/tj-actions/changed-files/issues/501). | -| old\_new\_separator | `string` | `false` | `','` | Split character for old and new filename pairs | -| old\_new\_files\_separator | `string` | `false` | `' '` | Split character for multiple old and new filename pairs | -| files | `string` OR `string[]` | `false` | | Check for changes
using only these
list of file(s)
(Defaults to the
entire repo) | -| files\_separator | string | `false` | `'\n'` | Separator used to split the
`files` input | -| files\_from\_source\_file | `string` | `false` | | Source file(s)
used to populate
the `files` input | -| files\_ignore | string | `false` | | Ignore changes to these file(s) | -| files\_ignore\_separator | string | `false` | `'\n'` | Separator used to split the
`files-ignore` input | -| files\_ignore\_from\_source\_file | `string` | `false` | | Source file(s)
used to populate
the `files_ignore` input | -| sha | `string` | `true` | `${{ github.sha }}` | Specify a different
commit SHA
used for
comparing changes | -| base\_sha | `string` | `false` | | Specify a different
base commit SHA
used for
comparing changes | -| path | `string` | `false` | `'.'` | Relative path under
`GITHUB_WORKSPACE`
to the repository | -| since\_last\_remote\_commit | `boolean` | `false` | `false` | Use the last commit on the remote
branch as the `base_sha`
(Defaults to the last commit
on the target branch for Pull requests
or the previous commit
on the current branch
for push events).
NOTE: This requires
`fetch-depth: 0`
with `actions/checkout@v2` | -| use\_fork\_point | `boolean` | `false` | `false` | Finds best common ancestor
between two commits
to use in a three-way merge
as the `base_sha`
See: [git merge-base](https://git-scm.com/docs/git-merge-base#Documentation/git-merge-base.txt---fork-point).
NOTE: This pulls the entire commit history of the base branch | -| quotepath | `boolean` | `false` | `true` | Output filenames completely verbatim by setting this to `false` | -| diff\_relative | `boolean` | `false` | | Exclude changes outside the current directory and show pathnames relative to it. | +| Input | type | required | default | description | +|:--------------------------------------:|:----------------------:|:--------:|:---------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| token | `string` | `false` | `${{ github.token }}` | [GITHUB\_TOKEN](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow)
or a repo scoped
[Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) | +| separator | `string` | `false` | `' '` | Split character for output strings | +| include\_all\_old\_new\_renamed\_files | `boolean` | `false` | `false` | Include `all_old_new_renamed_files` output. Note this can generate a large debug output See: [#501](https://github.com/tj-actions/changed-files/issues/501). | +| old\_new\_separator | `string` | `false` | `','` | Split character for old and new filename pairs | +| old\_new\_files\_separator | `string` | `false` | `' '` | Split character for multiple old and new filename pairs | +| files | `string` OR `string[]` | `false` | | Check for changes
using only these
list of file(s)
(Defaults to the
entire repo) | +| files\_separator | `string` | `false` | `'\n'` | Separator used to split the
`files` input | +| files\_from\_source\_file | `string` | `false` | | Source file(s)
used to populate
the `files` input | +| files\_ignore | `string` | `false` | | Ignore changes to these file(s) | +| files\_ignore\_separator | `string` | `false` | `'\n'` | Separator used to split the
`files-ignore` input | +| files\_ignore\_from\_source\_file | `string` | `false` | | Source file(s)
used to populate
the `files_ignore` input | +| sha | `string` | `true` | `${{ github.sha }}` | Specify a different
commit SHA
used for
comparing changes | +| base\_sha | `string` | `false` | | Specify a different
base commit SHA
used for
comparing changes | +| path | `string` | `false` | `'.'` | Relative path under
`GITHUB_WORKSPACE`
to the repository | +| since\_last\_remote\_commit | `boolean` | `false` | `false` | Use the last commit on the remote
branch as the `base_sha`
(Defaults to the last commit
on the target branch for Pull requests
or the previous commit
on the current branch
for push events).
NOTE: This requires
`fetch-depth: 0`
with `actions/checkout@v2` | +| use\_fork\_point | `boolean` | `false` | `false` | Finds best common ancestor
between two commits
to use in a three-way merge
as the `base_sha`
See: [git merge-base](https://git-scm.com/docs/git-merge-base#Documentation/git-merge-base.txt---fork-point).
NOTE: This pulls the entire commit history of the base branch | +| quotepath | `boolean` | `false` | `true` | Output filenames completely verbatim by setting this to `false` | +| diff\_relative | `boolean` | `false` | | Exclude changes outside the current directory and show pathnames relative to it. | +| dir\_names | `boolean` | `false` | `false` | Output unique changed directories instead of the filenames.
NOTE: This returns `.` for
changed files located in the root of the project. | ## Examples @@ -341,7 +342,7 @@ Support this project with a :star: > NOTE: :warning: > -> * Using characters like `\n`, `%` and `\r` as separators would be [URL encoded](https://www.w3schools.com/tags/ref_urlencode.asp) +> * Using characters like `\n`, `%`, `.` and `\r` as separators would be [URL encoded](https://www.w3schools.com/tags/ref_urlencode.asp) > * Spaces in file names can introduce bugs when using bash loops. See: [#216](https://github.com/tj-actions/changed-files/issues/216) > However, this action will handle spaces in file names, with a recommendation of using a separator to prevent hidden issues. > ![Screen Shot 2021-10-23 at 9 37 34 AM](https://user-images.githubusercontent.com/17484350/138558767-b13c90bf-a1ae-4e86-9520-70a6a4624f41.png) diff --git a/action.yml b/action.yml index 768f2112..f79cb1a3 100644 --- a/action.yml +++ b/action.yml @@ -4,74 +4,78 @@ author: tj-actions inputs: token: - description: 'Github token' + description: "Github token" required: false default: ${{ github.token }} separator: - description: 'Split character for output strings' + description: "Split character for output strings" required: false default: " " include_all_old_new_renamed_files: - description: 'Include all_old_new_renamed_files output. Note this can generate a large debug output See: #501.' + description: "Include all_old_new_renamed_files output. Note this can generate a large debug output See: #501." required: false - default: false + default: "false" old_new_separator: - description: 'Split character for old and new filename pairs' + description: "Split character for old and new filename pairs" required: false default: "," old_new_files_separator: - description: 'Split character for multiple old and new filename pairs' + description: "Split character for multiple old and new filename pairs" required: false default: " " files_from_source_file: - description: 'Source file(s) to populate the files input' + description: "Source file(s) to populate the files input" required: false default: "" files: - description: 'Check for changes using only this list of files (Defaults to the entire repo)' + description: "Check for changes using only this list of files (Defaults to the entire repo)" required: false default: "" files_separator: - description: 'Separator used to split the files input' + description: "Separator used to split the files input" default: "\n" required: false files_ignore: - description: 'Ignore changes to this list of files' + description: "Ignore changes to this list of files" required: false default: "" files_ignore_separator: - description: 'Separator used to split the files-ignore input' + description: "Separator used to split the files-ignore input" default: "\n" required: false files_ignore_from_source_file: - description: 'Source file(s) to populate the files-ignore input' + description: "Source file(s) to populate the files-ignore input" required: false default: "" sha: - description: 'Specify a current commit SHA used for comparing changes' + description: "Specify a current commit SHA used for comparing changes" required: true default: ${{ github.sha }} base_sha: - description: 'Specify a base commit SHA on used for comparing changes' + description: "Specify a base commit SHA on used for comparing changes" required: false since_last_remote_commit: - description: 'Use the last commit on the remote branch as the base_sha for push event.' + description: "Use the last commit on the remote branch as the base_sha for push event." required: false - default: 'false' + default: "false" path: - description: 'Specify a relative path under $GITHUB_WORKSPACE to locate the repository' + description: "Specify a relative path under $GITHUB_WORKSPACE to locate the repository" required: false - default: '.' + default: "." use_fork_point: - description: 'Finds best common ancestor between two commits to use in a three-way merge as the base_sha' - default: 'false' + description: "Finds best common ancestor between two commits to use in a three-way merge as the base_sha" + default: "false" required: false quotepath: - description: 'Output filenames completely verbatim by setting this to false' - default: 'true' + description: "Output filenames completely verbatim by setting this to false" + default: "true" required: false diff_relative: - description: 'Exclude changes outside the current directory and show pathnames relative to it' + description: "Exclude changes outside the current directory and show pathnames relative to it" + required: false + dir_names: + default: "false" + description: "Output the absolute path to the changed directories instead of the filenames" required: false outputs: @@ -140,7 +144,7 @@ outputs: value: ${{ steps.changed-files.outputs.other_deleted_files }} runs: - using: 'composite' + using: "composite" steps: - run: | # "Set base sha..." @@ -207,6 +211,7 @@ runs: INPUT_OLD_NEW_SEPARATOR: ${{ inputs.old_new_separator }} INPUT_OLD_NEW_FILES_SEPARATOR: ${{ inputs.old_new_files_separator }} INPUT_DIFF_RELATIVE: ${{ inputs.diff_relative }} + INPUT_DIR_NAMES: ${{ inputs.dir_names }} branding: icon: file-text diff --git a/entrypoint.sh b/entrypoint.sh index a8cd92b2..716cb88b 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -3,6 +3,7 @@ set -eu INPUT_SEPARATOR="${INPUT_SEPARATOR//'%'/'%25'}" +INPUT_SEPARATOR="${INPUT_SEPARATOR//'.'/'%2E'}" INPUT_SEPARATOR="${INPUT_SEPARATOR//$'\n'/'%0A'}" INPUT_SEPARATOR="${INPUT_SEPARATOR//$'\r'/'%0D'}" @@ -32,7 +33,12 @@ function get_diff() { ) fi done < <(git submodule | awk '{print $2}') - git diff --diff-filter="$filter" --name-only --ignore-submodules=all "$base" "$sha" + + if [[ "$INPUT_DIR_NAMES" == "true" ]]; then + git diff --diff-filter="$filter" --name-only --ignore-submodules=all "$base" "$sha" | xargs -I {} dirname {} | uniq + else + git diff --diff-filter="$filter" --name-only --ignore-submodules=all "$base" "$sha" + fi } function get_renames() { @@ -51,7 +57,11 @@ function get_renames() { fi done < <(git submodule | awk '{print $2}') - git log --name-status --ignore-submodules=all "$base".."$sha" | grep -E "^R" | awk -F '\t' -v d="$INPUT_OLD_NEW_SEPARATOR" '{print $2d$3}' + 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 + 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}' + fi } echo "::group::changed-files" @@ -103,10 +113,9 @@ else 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}') - UNIQUE_ALL_CHANGED=$(echo "${ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - if [[ -n "${UNIQUE_ALL_CHANGED}" ]]; then - echo "::debug::Matching changed files: ${UNIQUE_ALL_CHANGED}" + if [[ -n "${ALL_CHANGED}" ]]; then + echo "::debug::Matching changed files: ${ALL_CHANGED}" echo "::set-output name=any_changed::true" else echo "::set-output name=any_changed::false" @@ -115,8 +124,8 @@ else OTHER_CHANGED="" if [[ -n $ALL_OTHER_CHANGED ]]; then - if [[ -n "$UNIQUE_ALL_CHANGED" ]]; then - OTHER_CHANGED=$(echo "${ALL_OTHER_CHANGED}|${UNIQUE_ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + if [[ -n "$ALL_CHANGED" ]]; then + OTHER_CHANGED=$(echo "${ALL_OTHER_CHANGED}|${ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') else OTHER_CHANGED=$ALL_OTHER_CHANGED fi @@ -128,15 +137,14 @@ else echo "::debug::Non Matching changed files: ${OTHER_CHANGED}" echo "::set-output name=only_changed::false" echo "::set-output name=other_changed_files::$OTHER_CHANGED" - elif [[ -n "${UNIQUE_ALL_CHANGED}" ]]; then + elif [[ -n "${ALL_CHANGED}" ]]; then echo "::set-output name=only_changed::true" fi ALL_OTHER_MODIFIED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" "ACMRD" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - UNIQUE_ALL_MODIFIED=$(echo "${ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - if [[ -n "${UNIQUE_ALL_MODIFIED}" ]]; then - echo "::debug::Matching modified files: ${UNIQUE_ALL_MODIFIED}" + if [[ -n "${ALL_MODIFIED}" ]]; then + echo "::debug::Matching modified files: ${ALL_MODIFIED}" echo "::set-output name=any_modified::true" else echo "::set-output name=any_modified::false" @@ -145,8 +153,8 @@ else OTHER_MODIFIED="" if [[ -n $ALL_OTHER_MODIFIED ]]; then - if [[ -n "$UNIQUE_ALL_MODIFIED" ]]; then - OTHER_MODIFIED=$(echo "${ALL_OTHER_MODIFIED}|${UNIQUE_ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + if [[ -n "$ALL_MODIFIED" ]]; then + OTHER_MODIFIED=$(echo "${ALL_OTHER_MODIFIED}|${ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') else OTHER_MODIFIED=$ALL_OTHER_MODIFIED fi @@ -158,15 +166,14 @@ else echo "::debug::Non Matching modified files: ${OTHER_MODIFIED}" echo "::set-output name=only_modified::false" echo "::set-output name=other_modified_files::$OTHER_MODIFIED" - elif [[ -n "${UNIQUE_ALL_MODIFIED}" ]]; then + elif [[ -n "${ALL_MODIFIED}" ]]; then echo "::set-output name=only_modified::true" fi ALL_OTHER_DELETED=$(get_diff "$INPUT_PREVIOUS_SHA" "$INPUT_CURRENT_SHA" D | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - UNIQUE_ALL_DELETED=$(echo "${DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') - if [[ -n "${UNIQUE_ALL_DELETED}" ]]; then - echo "::debug::Matching deleted files: ${UNIQUE_ALL_DELETED}" + if [[ -n "${DELETED}" ]]; then + echo "::debug::Matching deleted files: ${DELETED}" echo "::set-output name=any_deleted::true" else echo "::set-output name=any_deleted::false" @@ -175,8 +182,8 @@ else OTHER_DELETED="" if [[ -n $ALL_OTHER_DELETED ]]; then - if [[ -n "$UNIQUE_ALL_DELETED" ]]; then - OTHER_DELETED=$(echo "${ALL_OTHER_DELETED}|${UNIQUE_ALL_DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') + if [[ -n "$DELETED" ]]; then + OTHER_DELETED=$(echo "${ALL_OTHER_DELETED}|${DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}') else OTHER_DELETED=$ALL_OTHER_DELETED fi @@ -188,7 +195,7 @@ else echo "::debug::Non Matching deleted files: ${OTHER_DELETED}" echo "::set-output name=only_deleted::false" echo "::set-output name=other_deleted_files::$OTHER_DELETED" - elif [[ -n "${UNIQUE_ALL_DELETED}" ]]; then + elif [[ -n "${DELETED}" ]]; then echo "::set-output name=only_deleted::true" fi