From 0b33274468e37b3c664da9d2d112195002291c38 Mon Sep 17 00:00:00 2001 From: Tonye Jack Date: Thu, 17 Feb 2022 02:35:49 -0500 Subject: [PATCH] feat: Added support for using fork point to detect file changes. (#384) * feat: Added support for using fork point to detect file changes. * Updated README.md * Updated test.yml * Updated action.yml * Updated diff-sha.sh * Updated diff-sha.sh * Updated diff-sha.sh * Updated diff-sha.sh * Updated diff-sha.sh * Updated README.md * Updated test file * Updated test.yml * Updated test.yml * Removed unused code. * Removed unused code. * Test using head_ref * Test using head * Removed unused code. --- .github/workflows/test.yml | 28 ++++++++---- README.md | 91 +++++++++++++++++++------------------- action.yml | 12 ++--- diff-sha.sh | 11 ++++- test/test.txt | 2 +- 5 files changed, 82 insertions(+), 62 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9b729e00..74631d5d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,8 +20,8 @@ jobs: - name: shellcheck uses: reviewdog/action-shellcheck@v1.14 - test-pull-requests-diff: - name: Test changed-files diff on pull_requests + test-pull-requests-from-forks: + name: Test changed-files diff on pull_requests from forks runs-on: ${{ matrix.platform }} strategy: fail-fast: false @@ -40,6 +40,18 @@ jobs: shell: bash + - name: Get changed files use_fork_point + id: changed-files-fork-point + uses: ./ + with: + use_fork_point: "true" + + - name: Show output + run: | + echo '${{ toJSON(steps.changed-files-fork-point.outputs) }}' + shell: + bash + - name: Get changed files id: changed-files uses: ./ @@ -446,28 +458,28 @@ jobs: echo '${{ toJSON(steps.changed-files-specific-forward-slash.outputs) }}' shell: bash - - name: Verify any_changed files comma separator + - name: Verify any_changed files forward slash separator if: "!contains(steps.changed-files-specific-forward-slash.outputs.all_changed_files, 'action.yml') && !contains(steps.changed-files-specific-forward-slash.outputs.all_changed_files, '.github/workflows/test.yml')" run: | - if [[ "${{ steps.changed-files-specific.outputs.any_changed }}" != "false" ]]; then + if [[ "${{ steps.changed-files-specific-forward-slash.outputs.any_changed }}" != "false" ]]; then echo "Invalid output: Expected (false) got (${{ steps.changed-files-specific-forward-slash.outputs.any_changed }})" exit 1 fi shell: bash - - name: Verify any_modified files comma separator + - name: Verify any_modified files forward slash separator if: "!contains(steps.changed-files-specific-forward-slash.outputs.all_modified_files, 'action.yml') && !contains(steps.changed-files-specific-forward-slash.outputs.all_modified_files, '.github/workflows/test.yml')" run: | - if [[ "${{ steps.changed-files-specific.outputs.any_modified }}" != "false" ]]; then + if [[ "${{ steps.changed-files-specific-forward-slash.outputs.any_modified }}" != "false" ]]; then echo "Invalid output: Expected (false) got (${{ steps.changed-files-specific-forward-slash.outputs.any_modified }})" exit 1 fi shell: bash - - name: Verify any_deleted files comma separator + - name: Verify any_deleted files forward slash separator if: "!contains(steps.changed-files-specific-forward-slash.outputs.deleted_files, 'action.yml') && !contains(steps.changed-files-specific-forward-slash.outputs.deleted_files, '.github/workflows/test.yml')" run: | - if [[ "${{ steps.changed-files-specific.outputs.any_deleted }}" != "false" ]]; then + if [[ "${{ steps.changed-files-specific-forward-slash.outputs.any_deleted }}" != "false" ]]; then echo "Invalid output: Expected (false) got (${{ steps.changed-files-specific-forward-slash.outputs.any_deleted }})" exit 1 fi diff --git a/README.md b/README.md index 85a67189..97ba63b3 100644 --- a/README.md +++ b/README.md @@ -88,56 +88,57 @@ Support this project with a :star: ## Outputs -| Acronym | Meaning | +| Acronym | Meaning | |:---------:|:------------:| -| A | Added | -| C | Copied | -| M | Modified | -| D | Deleted | -| R | Renamed | -| T | Type changed | -| U | Unmerged | -| X | Unknown | +| A | Added | +| C | Copied | +| M | Modified | +| D | Deleted | +| R | Renamed | +| T | Type changed | +| U | Unmerged | +| X | Unknown | -| Output | type | example | description | -|:--------------------:|:------------:|:----------------------------------:|:----------------------------------------:| -| any\_changed | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has changed.
i.e. *using a combination of all added,
copied, modified and renamed files (ACMR)* | -| only\_changed | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has changed. (ACMR) | -| other\_changed\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other changed files
not listed in the files input
i.e. *a combination of all added,
copied and modified files (ACMR)* | -| any\_modified | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has been modified.
i.e. *using a combination of all added,
copied, modified, renamed, and deleted files (ACMRD)* | -| only\_modified | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has been modified. (ACMRD) | -| other\_modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other modified files
not listed in the files input
i.e. *a combination of all added,
copied, modified, and deleted files (ACMRD)* | -| any\_deleted | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has been deleted. (D) | -| only\_deleted | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has been deleted. (D) | -| other\_deleted\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other deleted files
not listed in the files input
i.e. *a combination of all deleted files (D)* | -| 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)* | -| 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) | -| modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Modified (M) | -| renamed\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Renamed (R) | -| type\_changed\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that have their file type changed (T) | -| unmerged\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unmerged (U) | -| unknown\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unknown (X) | +| Output | type | example | description | +|:----------------------------------:|:--------:|:--------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:| +| any\_changed | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has changed.
i.e. *using a combination of all added,
copied, modified and renamed files (ACMR)* | +| only\_changed | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has changed. (ACMR) | +| other\_changed\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other changed files
not listed in the files input
i.e. *a combination of all added,
copied and modified files (ACMR)* | +| any\_modified | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has been modified.
i.e. *using a combination of all added,
copied, modified, renamed, and deleted files (ACMRD)* | +| only\_modified | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has been modified. (ACMRD) | +| other\_modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other modified files
not listed in the files input
i.e. *a combination of all added,
copied, modified, and deleted files (ACMRD)* | +| any\_deleted | `string` | `true` OR `false` | Returns `true` when any
of the filenames provided using
the `files` input has been deleted. (D) | +| only\_deleted | `string` | `true` OR `false` | Returns `true` when only
files provided using
the `files` input has been deleted. (D) | +| other\_deleted\_files | `string` | `'new.txt path/to/file.png ...'` | Select all other deleted files
not listed in the files input
i.e. *a combination of all deleted files (D)* | +| 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)* | +| 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) | +| modified\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Modified (M) | +| renamed\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Renamed (R) | +| type\_changed\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that have their file type changed (T) | +| unmerged\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unmerged (U) | +| unknown\_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unknown (X) | ## 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` | `true` | `' '` | Output string separator | -| 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 | `string` | `false` | `false` | Use the last commit on the remote
branch as the `base_sha`
(Defaults to the previous commit).
NOTE: This requires
`fetch-depth: 0`
with `actions/checkout@v2` | +| 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` | `true` | `' '` | Output string separator | +| 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 | `string` | `false` | `false` | Use the last commit on the remote
branch as the `base_sha`
(Defaults to the previous commit).
NOTE: This requires
`fetch-depth: 0`
with `actions/checkout@v2` | +| use_fork_point | `string` | `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 | ## Example diff --git a/action.yml b/action.yml index 5ada6f96..636fe7a2 100644 --- a/action.yml +++ b/action.yml @@ -49,6 +49,10 @@ inputs: path: description: 'Specify a relative path under $GITHUB_WORKSPACE to locate the repository' required: false + use_fork_point: + description: 'Finds best common ancestor between two commits to use in a three-way merge as the base_sha' + default: 'false' + required: false outputs: added_files: @@ -136,6 +140,7 @@ runs: GITHUB_SERVER_URL: ${{ github.server_url }} GITHUB_REPOSITORY: ${{ github.repository }} GITHUB_BASE_REF: ${{ github.base_ref }} + GITHUB_HEAD_REF: ${{ github.head_ref }} GITHUB_ACTION_PATH: ${{ github.action_path }} # INPUT_ is not available in Composite run steps # https://github.community/t/input-variable-name-is-not-available-in-composite-run-steps/127611 @@ -143,6 +148,7 @@ runs: INPUT_BASE_SHA: ${{ steps.base-sha.outputs.base_sha }} INPUT_TOKEN: ${{ inputs.token }} INPUT_PATH: ${{ inputs.path }} + INPUT_USE_FORK_POINT: ${{ inputs.use_fork_point }} - name: Glob match uses: tj-actions/glob@v7 id: glob @@ -163,15 +169,9 @@ runs: id: changed-files shell: bash env: - GITHUB_SERVER_URL: ${{ github.server_url }} - GITHUB_REPOSITORY: ${{ github.repository }} - GITHUB_BASE_REF: ${{ github.base_ref }} GITHUB_ACTION_PATH: ${{ github.action_path }} # INPUT_ is not available in Composite run steps # https://github.community/t/input-variable-name-is-not-available-in-composite-run-steps/127611 - INPUT_SHA: ${{ inputs.sha }} - INPUT_BASE_SHA: ${{ steps.base-sha.outputs.base_sha }} - INPUT_TOKEN: ${{ inputs.token }} INPUT_FILES_PATTERN: ${{ steps.glob.outputs.paths }} INPUT_SEPARATOR: ${{ inputs.separator }} INPUT_PATH: ${{ inputs.path }} diff --git a/diff-sha.sh b/diff-sha.sh index 04a8afe4..685a59bf 100644 --- a/diff-sha.sh +++ b/diff-sha.sh @@ -71,14 +71,21 @@ else CURRENT_BRANCH=$GITHUB_HEAD_REF if [[ -z $INPUT_BASE_SHA ]]; then - git fetch --no-tags -u --progress --depth=1 temp_changed_files "${TARGET_BRANCH}":"${TARGET_BRANCH}" && exit_status=$? || exit_status=$? - PREVIOUS_SHA=$(git rev-list --no-merges -n 1 "${TARGET_BRANCH}" 2>&1) && exit_status=$? || exit_status=$? + if [[ "$INPUT_USE_FORK_POINT" == "true" ]]; then + echo "Getting fork point..." + git fetch --no-tags -u --progress temp_changed_files "${TARGET_BRANCH}":"${TARGET_BRANCH}" && exit_status=$? || exit_status=$? + PREVIOUS_SHA=$(git merge-base --fork-point "${TARGET_BRANCH}") && exit_status=$? || exit_status=$? + else + git fetch --no-tags -u --progress --depth=1 temp_changed_files "${TARGET_BRANCH}":"${TARGET_BRANCH}" && exit_status=$? || exit_status=$? + PREVIOUS_SHA=$(git rev-list --no-merges -n 1 "${TARGET_BRANCH}" 2>&1) && exit_status=$? || exit_status=$? + fi else git fetch --no-tags -u --progress --depth=1 temp_changed_files "$INPUT_BASE_SHA" && exit_status=$? || exit_status=$? PREVIOUS_SHA=$INPUT_BASE_SHA TARGET_BRANCH=$(git name-rev --name-only "$PREVIOUS_SHA" 2>&1) && exit_status=$? || exit_status=$? fi + echo "Verifying commit SHA..." git rev-parse --quiet --verify "$PREVIOUS_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$? if [[ $exit_status -ne 0 ]]; then diff --git a/test/test.txt b/test/test.txt index 9f4b6d8b..6de7b8c6 100644 --- a/test/test.txt +++ b/test/test.txt @@ -1 +1 @@ -This is a test file +This is a test file.