Compare commits

..

No commits in common. "main" and "v39.2.2" have entirely different histories.

40 changed files with 9585 additions and 25556 deletions

View File

@ -197,63 +197,6 @@
"bug", "bug",
"code" "code"
] ]
},
{
"login": "rodrigorfk",
"name": "Rodrigo Fior Kuntzer",
"avatar_url": "https://avatars.githubusercontent.com/u/1995033?v=4",
"profile": "https://github.com/rodrigorfk",
"contributions": [
"code",
"test",
"bug"
]
},
{
"login": "levenleven",
"name": "Aleksey Levenstein",
"avatar_url": "https://avatars.githubusercontent.com/u/6463364?v=4",
"profile": "https://github.com/levenleven",
"contributions": [
"doc"
]
},
{
"login": "dan-hill2802",
"name": "Daniel Hill",
"avatar_url": "https://avatars.githubusercontent.com/u/5046322?v=4",
"profile": "https://github.com/dan-hill2802",
"contributions": [
"doc"
]
},
{
"login": "KeisukeYamashita",
"name": "KeisukeYamashita",
"avatar_url": "https://avatars.githubusercontent.com/u/23056537?v=4",
"profile": "https://keisukeyamashita.com",
"contributions": [
"doc"
]
},
{
"login": "codesculpture",
"name": "Aravind",
"avatar_url": "https://avatars.githubusercontent.com/u/63452117?v=4",
"profile": "https://github.com/codesculpture",
"contributions": [
"code",
"bug"
]
},
{
"login": "Whadup",
"name": "Lukas Pfahler",
"avatar_url": "https://avatars.githubusercontent.com/u/2308119?v=4",
"profile": "https://lukaspfahler.de",
"contributions": [
"code"
]
} }
], ],
"contributorsPerLine": 7, "contributorsPerLine": 7,

33
.github/workflows/auto-approve.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Auto approve
on:
pull_request_target
jobs:
auto-approve:
runs-on: ubuntu-latest
steps:
- uses: hmarr/auto-approve-action@v3
if: |
(
github.event.pull_request.user.login == 'dependabot[bot]' ||
github.event.pull_request.user.login == 'dependabot' ||
github.event.pull_request.user.login == 'dependabot-preview[bot]' ||
github.event.pull_request.user.login == 'dependabot-preview' ||
github.event.pull_request.user.login == 'renovate[bot]' ||
github.event.pull_request.user.login == 'renovate' ||
github.event.pull_request.user.login == 'github-actions[bot]'
)
&&
(
github.actor == 'dependabot[bot]' ||
github.actor == 'dependabot' ||
github.actor == 'dependabot-preview[bot]' ||
github.actor == 'dependabot-preview' ||
github.actor == 'renovate[bot]' ||
github.actor == 'renovate' ||
github.actor == 'github-actions[bot]'
)
with:
github-token: ${{ secrets.PAT_TOKEN }}

View File

@ -17,13 +17,13 @@ on:
schedule: schedule:
- cron: '15 16 * * 2' - cron: '15 16 * * 2'
permissions:
actions: read
contents: read
security-events: write
jobs: jobs:
codacy-security-scan: codacy-security-scan:
# Cancel other workflows that are running for the same branch
# https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
name: Codacy Security Scan name: Codacy Security Scan
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
@ -34,7 +34,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI - name: Run Codacy Analysis CLI
continue-on-error: true continue-on-error: true
uses: codacy/codacy-analysis-cli-action@v4.4.5 uses: codacy/codacy-analysis-cli-action@v4.3.0
with: with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations # You can also omit the token and run the tools that support default configurations
@ -51,6 +51,6 @@ jobs:
# Upload the SARIF file generated in the previous step # Upload the SARIF file generated in the previous step
- name: Upload SARIF results file - name: Upload SARIF results file
continue-on-error: true continue-on-error: true
uses: github/codeql-action/upload-sarif@v3 uses: github/codeql-action/upload-sarif@v2
with: with:
sarif_file: results.sarif sarif_file: results.sarif

View File

@ -20,11 +20,6 @@ on:
schedule: schedule:
- cron: '44 20 * * 0' - cron: '44 20 * * 0'
permissions:
actions: read
contents: read
security-events: write
jobs: jobs:
analyze: analyze:
name: Analyze name: Analyze
@ -47,7 +42,7 @@ jobs:
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@v3 uses: github/codeql-action/init@v2
with: with:
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file. # If you wish to specify custom queries, you can do so here or in a config file.
@ -61,7 +56,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@v3 uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell. # Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@ -74,6 +69,6 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh # ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3 uses: github/codeql-action/analyze@v2
with: with:
category: "/language:${{matrix.language}}" category: "/language:${{matrix.language}}"

View File

@ -2,17 +2,12 @@ name: Greetings
on: [pull_request_target, issues] on: [pull_request_target, issues]
permissions:
pull-requests: write
issues: write
jobs: jobs:
greeting: greeting:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/first-interaction@v1 - uses: actions/first-interaction@v1
continue-on-error: true
with: with:
repo-token: ${{ secrets.PAT_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Thanks for reporting this issue, don't forget to star this project if you haven't already to help us reach a wider audience." issue-message: "Thanks for reporting this issue, don't forget to star this project if you haven't already to help us reach a wider audience."
pr-message: "Thanks for implementing a fix, could you ensure that the test covers your changes if applicable." pr-message: "Thanks for implementing a fix, could you ensure that the test covers your changes if applicable."

View File

@ -1,8 +1,4 @@
name: Issue Comment Job Example name: Issue Comment Test
permissions:
contents: read
on: on:
issue_comment: issue_comment:

View File

@ -1,11 +1,9 @@
name: Manual Triggered Job Example name: Manual Test
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
jobs: jobs:
test: test:
name: Test changed-files name: Test changed-files

View File

@ -1,7 +1,4 @@
name: Matrix Example name: Matrix Test
permissions:
contents: read
on: on:
workflow_dispatch: workflow_dispatch:
@ -11,10 +8,10 @@ on:
jobs: jobs:
changed-files: changed-files:
name: Get changed files name: Get changes
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
matrix: ${{ steps.changed-files.outputs.all_changed_files }} matrix: ${{ steps.set-matrix.outputs.matrix }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -24,17 +21,19 @@ jobs:
id: changed-files id: changed-files
uses: ./ uses: ./
with: with:
matrix: true json: true
quotepath: false
- name: List all changed files - name: List all changed files
run: echo '${{ steps.changed-files.outputs.all_changed_files }}' run: echo '${{ steps.changed-files.outputs.all_changed_files }}'
- id: set-matrix
run: echo "matrix={\"files\":${{ steps.changed-files.outputs.all_changed_files }}}" >> "$GITHUB_OUTPUT"
matrix-job: matrix-job:
name: Run Matrix Job name: Run Matrix Job
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: [changed-files] needs: [changed-files]
strategy: strategy:
matrix: matrix: ${{ fromJSON(needs.changed-files.outputs.matrix) }}
files: ${{ fromJSON(needs.changed-files.outputs.matrix) }}
max-parallel: 4 max-parallel: 4
fail-fast: false fail-fast: false
steps: steps:

View File

@ -1,67 +0,0 @@
name: Multi Job Example
permissions:
contents: read
on:
push:
branches:
- "**"
pull_request:
branches:
- "**"
jobs:
changed-files:
name: Get changed files
runs-on: ubuntu-latest
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: ./
- name: List all changed files
run: echo '${{ steps.changed-files.outputs.all_changed_files }}'
view-changed-files:
name: View all changed files
runs-on: ubuntu-latest
needs: [changed-files]
steps:
- name: List all changed files
run: |
echo '${{ needs.changed-files.outputs.all_changed_files }}'
changed-files-rest-api:
name: Get changed files using REST API
runs-on: ubuntu-latest
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
continue-on-error: ${{ github.event_name == 'push' }}
uses: ./
with:
use_rest_api: true
- name: List all changed files
run: echo '${{ steps.changed-files.outputs.all_changed_files }}'
view-changed-files-rest-api:
name: View all changed files using REST API
runs-on: ubuntu-latest
needs: [changed-files-rest-api]
steps:
- name: List all changed files
run: |
echo '${{ needs.changed-files-rest-api.outputs.all_changed_files }}'

View File

@ -1,9 +1,4 @@
name: Update release version name: Update release version.
permissions:
contents: write
pull-requests: write
on: on:
release: release:
types: [published] types: [published]
@ -37,7 +32,7 @@ jobs:
- name: Run git-cliff - name: Run git-cliff
uses: tj-actions/git-cliff@v1 uses: tj-actions/git-cliff@v1
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v7.0.5 uses: peter-evans/create-pull-request@v5.0.2
with: with:
base: "main" base: "main"
labels: "merge when passing" labels: "merge when passing"

View File

@ -1,12 +1,12 @@
name: CI name: CI
permissions:
contents: read
on: on:
push: push:
branches: branches:
- "**" - "**"
pull_request_review:
types: [edited, dismissed, submitted]
pull_request_target:
pull_request: pull_request:
types: types:
- assigned - assigned
@ -27,16 +27,24 @@ on:
- auto_merge_enabled - auto_merge_enabled
- auto_merge_disabled - auto_merge_disabled
branches: branches:
- "**" - main
jobs: jobs:
shellcheck:
name: Run shellcheck
runs-on: ubuntu-latest
steps:
- name: Checkout branch
uses: actions/checkout@v4
- name: shellcheck
uses: reviewdog/action-shellcheck@v1.19
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
outputs: outputs:
files_changed: ${{ steps.changed_files.outputs.files_changed }} files_changed: ${{ steps.changed_files.outputs.files_changed }}
permissions:
contents: read
pull-requests: write
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -45,7 +53,7 @@ jobs:
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Use Node.js 20.x - name: Use Node.js 20.x
uses: actions/setup-node@v4.1.0 uses: actions/setup-node@v3.8.1
with: with:
cache: 'yarn' cache: 'yarn'
node-version: '20.x' node-version: '20.x'
@ -60,7 +68,7 @@ jobs:
yarn install yarn install
- name: Run eslint on changed files - name: Run eslint on changed files
uses: tj-actions/eslint-changed-files@v25 uses: tj-actions/eslint-changed-files@v21
if: github.event_name == 'pull_request' if: github.event_name == 'pull_request'
with: with:
token: ${{ secrets.PAT_TOKEN }} token: ${{ secrets.PAT_TOKEN }}
@ -70,12 +78,9 @@ jobs:
- name: Run build and test - name: Run build and test
run: | run: |
yarn all yarn all
env:
GITHUB_EVENT_PULL_REQUEST_HEAD_REPO_FORK: ${{ github.event.pull_request.head.repo.fork }}
- name: Verify Changed files - name: Verify Changed files
uses: tj-actions/verify-changed-files@v20 uses: tj-actions/verify-changed-files@v16
if: github.actor != 'dependabot[bot]'
id: changed_files id: changed_files
with: with:
files: | files: |
@ -99,7 +104,7 @@ jobs:
branch: ${{ github.head_ref }} branch: ${{ github.head_ref }}
- name: Upload build assets - name: Upload build assets
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v3
with: with:
name: build-assets name: build-assets
path: dist path: dist
@ -116,8 +121,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout into dir1 - name: Checkout into dir1
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -128,7 +131,7 @@ jobs:
path: dir1 path: dir1
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
path: dir1/dist path: dir1/dist
@ -154,7 +157,7 @@ jobs:
bash bash
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
path: dir2/dist path: dir2/dist
@ -192,8 +195,7 @@ jobs:
needs: build needs: build
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.event_name == 'push' && needs.build.outputs.files_changed != 'true' if: github.event_name == 'push' && needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -202,7 +204,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -251,8 +253,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
@ -262,7 +262,7 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -286,17 +286,11 @@ jobs:
shell: shell:
bash bash
test-using-branch-names-for-base-sha-and-sha-inputs: test-unset-github-output-env:
name: Test using branch names for base_sha and sha inputs name: Test unset GITHUB_OUTPUT env
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: | if: needs.build.outputs.files_changed != 'true'
(
github.event_name == 'push' ||
github.event_name == 'pull_request'
) && needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
@ -306,15 +300,16 @@ jobs:
fetch-depth: 0 fetch-depth: 0
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
- name: Run changed-files with main as the base_sha - name: Run changed-files with unset GITHUB_OUTPUT env
id: changed-files id: changed-files
continue-on-error: true
uses: ./ uses: ./
with: env:
base_sha: main GITHUB_OUTPUT: ""
- name: Show output - name: Show output
run: | run: |
@ -327,8 +322,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
@ -345,7 +338,7 @@ jobs:
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -368,8 +361,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: github.event_name != 'push' && needs.build.outputs.files_changed != 'true' if: github.event_name != 'push' && needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
@ -378,7 +369,7 @@ jobs:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -397,8 +388,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: github.event_name != 'push' && needs.build.outputs.files_changed != 'true' if: github.event_name != 'push' && needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -414,7 +403,7 @@ jobs:
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -433,14 +422,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -488,14 +476,13 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -555,7 +542,7 @@ jobs:
path: dir1 path: dir1
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
path: dir1/dist path: dir1/dist
@ -570,83 +557,11 @@ jobs:
shell: shell:
bash bash
test-dir-names-nested-folder:
name: Test changed-files with dir-names in a nested folder
runs-on: ubuntu-latest
needs: build
if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps:
- name: Checkout branch
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
submodules: true
fetch-depth: 0
- name: Download build assets
uses: actions/download-artifact@v4
with:
name: build-assets
path: dist
- name: Get changed files in the .github folder
id: changed-files
uses: ./
with:
path: .github
json: true
escape_json: false
dir_names: true
dir_names_exclude_current_dir: true
- name: Show output
run: |
echo "${{ toJSON(steps.changed-files.outputs) }}"
shell:
bash
test-non-existing-repository:
name: Test changed-files with non existing repository
runs-on: ubuntu-latest
needs: build
if: github.event_name == 'push' && needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps:
- name: Checkout into dir1
uses: actions/checkout@v4
with:
repository: ${{ github.event.pull_request.head.repo.full_name }}
submodules: true
fetch-depth: 0
path: dir1
- name: Download build assets
uses: actions/download-artifact@v4
with:
name: build-assets
path: dir1/dist
- name: Run changed-files with non existing repository
id: changed-files
continue-on-error: true
uses: ./dir1
- name: Verify failed
if: steps.changed-files.outcome != 'failure'
run: |
echo "Expected: (failure) got ${{ steps.changed-files.outcome }}"
exit 1
test-submodules: test-submodules:
name: Test changed-files with submodule name: Test changed-files with submodule
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -662,7 +577,7 @@ jobs:
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -685,34 +600,11 @@ jobs:
echo "${{ toJSON(steps.changed-files.outputs) }}" echo "${{ toJSON(steps.changed-files.outputs) }}"
shell: shell:
bash bash
- name: Run changed-files excluding submodule
id: changed-files-exclude-submodule
uses: ./
with:
base_sha: "85bd869"
sha: "adde7bb"
fetch_depth: 60000
exclude_submodules: true
- name: Verify no added files
if: steps.changed-files-exclude-submodule.outputs.added_files != ''
run: |
echo "Expected: ('') got ${{ steps.changed-files-exclude-submodule.outputs.added_files }}"
exit 1
- name: Show output
run: |
echo "${{ toJSON(steps.changed-files-exclude-submodule.outputs) }}"
shell:
bash
test-yaml: test-yaml:
name: Test changed-files with yaml name: Test changed-files with yaml
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -728,7 +620,7 @@ jobs:
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -760,54 +652,11 @@ jobs:
shell: shell:
bash bash
- name: Run changed-files with files_yaml, files_ignore_yaml
id: changed-files-ignore
uses: ./
with:
files_yaml: |
test:
- test/**.txt
- test/**.md
files_ignore_yaml: |
test:
- test/test.txt
- name: Show output
run: |
echo "${{ toJSON(steps.changed-files-ignore.outputs) }}"
shell:
bash
- name: Run changed-files with files_yaml, json and write_output_files
id: changed-files-json-write-output-files
uses: ./
with:
files_yaml: |
test:
- .github/workflows/test.yml
json: true
write_output_files: true
- name: Show all outputs
run: |
echo "${{ toJSON(steps.changed-files-json-write-output-files.outputs) }}"
shell:
bash
- name: Show all_changed_files output and list .github/outputs
run: |
echo '${{ toJSON(steps.changed-files-json-write-output-files.outputs.test_all_changed_files) }}'
cat .github/outputs/test_all_changed_files.json
shell:
bash
test-recover-deleted-file: test-recover-deleted-file:
name: Test changed-files recover deleted file name: Test changed-files recover deleted file
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -823,7 +672,7 @@ jobs:
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -865,7 +714,7 @@ jobs:
base_sha: "fcdeb5b3d797752d95f6dbe98552a95c29dad338" base_sha: "fcdeb5b3d797752d95f6dbe98552a95c29dad338"
sha: "432e0c810c60ef1332850a971c5ec39022034b4c" sha: "432e0c810c60ef1332850a971c5ec39022034b4c"
files: | files: |
test/** test
recover_deleted_files: true recover_deleted_files: true
fetch_depth: 60000 fetch_depth: 60000
@ -963,43 +812,11 @@ jobs:
cat "deleted_files/test/test deleted.txt" cat "deleted_files/test/test deleted.txt"
fi fi
- name: Run changed-files with recover_deleted_files for an expected git submodule file
id: changed-files-recover-deleted-files-within-submodule
uses: ./
with:
base_sha: "3be651e99d3d4eae395694f6c6f3b9d18457f6c8"
sha: "d90c240f2ad4ec04d8f0f48e5ac290ad96ebe850"
recover_deleted_files: true
fetch_depth: 60000
- name: Show output
run: |
echo "${{ toJSON(steps.changed-files-recover-deleted-files-within-submodule.outputs) }}"
shell:
bash
- name: Verify deleted files
if: steps.changed-files-recover-deleted-files-within-submodule.outputs.deleted_files != 'test/demo/.github/FUNDING.yml'
run: |
echo "Expected: (test/demo/.github/FUNDING.yml) got ${{ steps.changed-files-recover-deleted-files-within-submodule.outputs.deleted_files }}"
exit 1
- name: Verify that test/demo/.github/FUNDING.yml is restored
run: |
if [ ! -f "test/demo/.github/FUNDING.yml" ]; then
echo "Expected: (test/demo/.github/FUNDING.yml) to exist"
exit 1
else
cat "test/demo/.github/FUNDING.yml"
rm "test/demo/.github/FUNDING.yml"
fi
test-dir-names-deleted-files-include-only-deleted-dirs-single-file: test-dir-names-deleted-files-include-only-deleted-dirs-single-file:
name: Test dir names deleted files include only deleted dirs single file name: Test dir names deleted files include only deleted dirs single file
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
uses: actions/checkout@v4 uses: actions/checkout@v4
@ -1030,19 +847,14 @@ jobs:
bash bash
test-dir-names-deleted-files-include-only-deleted-dirs-directory: test-dir-names-deleted-files-include-only-deleted-dirs-directory:
name: Test dir names deleted files include only deleted dirs name: Test dir names deleted files include only deleted dirs
runs-on: ${{ matrix.platform }} runs-on: ubuntu-latest
needs: build needs: build
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
steps: steps:
- name: Checkout branch - name: Checkout branch
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: cd1e384723e4d1a184568182ac2b27c53ebf017f
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
submodules: true submodules: true
fetch-depth: 2 fetch-depth: 2
@ -1054,7 +866,6 @@ jobs:
sha: cd1e384723e4d1a184568182ac2b27c53ebf017f sha: cd1e384723e4d1a184568182ac2b27c53ebf017f
dir_names: true dir_names: true
dir_names_deleted_files_include_only_deleted_dirs: true dir_names_deleted_files_include_only_deleted_dirs: true
fetch_depth: 60000
- name: Show output - name: Show output
run: | run: |
echo '${{ toJSON(steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory.outputs) }}' echo '${{ toJSON(steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory.outputs) }}'
@ -1074,43 +885,12 @@ jobs:
exit 1 exit 1
shell: shell:
bash bash
- name: Run changed-files with dir_names and dir_names_deleted_files_include_only_deleted_dirs with the test directory deleted returns posix path separator
id: changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator
uses: ./
with:
base_sha: a52f8621d26d5d9f54b80f74bda2d9eedff94693
sha: cd1e384723e4d1a184568182ac2b27c53ebf017f
dir_names: true
dir_names_deleted_files_include_only_deleted_dirs: true
use_posix_path_separator: true
fetch_depth: 60000
- name: Show output
run: |
echo '${{ toJSON(steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator.outputs) }}'
shell:
bash
- name: Check deleted_files output on non windows platform
if: steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator.outputs.deleted_files != 'test/test3' && runner.os != 'Windows'
run: |
echo "Invalid output: Expected (test/test3) got (${{ steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator.outputs.deleted_files }})"
exit 1
shell:
bash
- name: Check deleted_files output on windows platform
if: "!contains(steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator.outputs.deleted_files, 'test/test3') && runner.os == 'Windows'"
run: |
echo "Invalid output: Expected (test/test3) got (${{ steps.changed-files-dir-names-deleted-files-include-only-deleted-dirs-directory-posix-path-separator.outputs.deleted_files }})"
exit 1
shell:
bash
test-since-last-remote-commit: test-since-last-remote-commit:
name: Test changed-files since last remote commit name: Test changed-files since last remote commit
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -1127,7 +907,7 @@ jobs:
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
@ -1138,10 +918,10 @@ jobs:
with: with:
since_last_remote_commit: true since_last_remote_commit: true
- name: Verify succeeded pull_request(closed) - name: Verify failed
if: steps.changed-files-since-last-remote-commit.outcome != 'success' && matrix.fetch-depth == 1 && github.event.action == 'closed' && github.event_name == 'pull_request' if: steps.changed-files-since-last-remote-commit.outcome != 'failure' && matrix.fetch-depth == 1 && github.event.action == 'closed' && github.event_name == 'pull_request'
run: | run: |
echo "Expected: (success) got ${{ steps.changed-files-since-last-remote-commit.outcome }}" echo "Expected: (failure) got ${{ steps.changed-files-since-last-remote-commit.outcome }}"
exit 1 exit 1
- name: Verify succeeded - name: Verify succeeded
@ -1161,8 +941,6 @@ jobs:
runs-on: ${{ matrix.platform }} runs-on: ${{ matrix.platform }}
needs: build needs: build
if: needs.build.outputs.files_changed != 'true' if: needs.build.outputs.files_changed != 'true'
permissions:
contents: read
strategy: strategy:
fail-fast: false fail-fast: false
max-parallel: 4 max-parallel: 4
@ -1178,7 +956,7 @@ jobs:
repository: ${{ github.event.pull_request.head.repo.full_name }} repository: ${{ github.event.pull_request.head.repo.full_name }}
fetch-depth: ${{ matrix.fetch-depth }} fetch-depth: ${{ matrix.fetch-depth }}
- name: Download build assets - name: Download build assets
uses: actions/download-artifact@v4 uses: actions/download-artifact@v3
with: with:
name: build-assets name: build-assets
- name: Dump GitHub context - name: Dump GitHub context
@ -1193,7 +971,7 @@ jobs:
echo '${{ toJSON(steps.changed-files.outputs) }}' echo '${{ toJSON(steps.changed-files.outputs) }}'
shell: shell:
bash bash
- name: Run changed-files with dir name pattern - name: Run changed-files with dir name
id: changed-files-dir-name id: changed-files-dir-name
uses: ./ uses: ./
with: with:
@ -2163,7 +1941,7 @@ jobs:
bash bash
- name: Get branch name - name: Get branch name
id: branch-name id: branch-name
uses: tj-actions/branch-names@v8 uses: tj-actions/branch-names@v7
if: github.event_name == 'pull_request' && matrix.fetch-depth == 0 if: github.event_name == 'pull_request' && matrix.fetch-depth == 0
- uses: nrwl/nx-set-shas@v4 - uses: nrwl/nx-set-shas@v4
id: last_successful_commit id: last_successful_commit

View File

@ -1,9 +1,5 @@
name: Format README.md name: Format README.md
permissions:
contents: read
pull-requests: write
on: on:
push: push:
branches: branches:
@ -19,15 +15,12 @@ jobs:
- name: Run auto-doc - name: Run auto-doc
uses: tj-actions/auto-doc@v3 uses: tj-actions/auto-doc@v3
with:
use_code_blocks: true
use_major_version: true
- name: Run remark - name: Run remark
uses: tj-actions/remark@v3 uses: tj-actions/remark@v3
- name: Verify Changed files - name: Verify Changed files
uses: tj-actions/verify-changed-files@v20 uses: tj-actions/verify-changed-files@v16
id: verify_changed_files id: verify_changed_files
with: with:
files: | files: |
@ -41,7 +34,7 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
if: failure() if: failure()
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@v5
with: with:
base: "main" base: "main"
labels: "merge when passing" labels: "merge when passing"

View File

@ -1,41 +0,0 @@
name: Workflow Run Example
on:
workflow_run:
workflows: [Matrix Example]
types: [completed]
permissions:
contents: read
jobs:
on-success:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: ./
- name: Echo list of changed files on success
run: |
echo "Changed files on success:"
echo "${{ steps.changed-files.outputs.all_changed_files }}"
on-failure:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Get changed files
id: changed-files
uses: ./
- name: Echo list of changed files on failure
run: |
echo "Changed files on failure:"
echo "${{ steps.changed-files.outputs.all_changed_files }}"

1984
HISTORY.md

File diff suppressed because it is too large Load Diff

772
README.md

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +0,0 @@
# Security Policy
## Proactive Security Measures
To proactively detect and address security vulnerabilities, we utilize several robust tools and processes:
- **Dependency Updates:** We use [Renovate](https://renovatebot.com) and [Dependabot](https://docs.github.com/en/code-security/dependabot/dependabot-security-updates/about-dependabot-security-updates) to keep our dependencies updated and promptly patch detected vulnerabilities through automated PRs.
- **[GitHub's Security Features](https://github.com/features/security):** Our repository and dependencies are continuously monitored via GitHub's security features, which include:
- **Code Scanning:** Using GitHub's CodeQL, all pull requests are scanned to identify potential vulnerabilities in our source code.
- **Automated Alerts:** Dependabot identifies vulnerabilities based on the GitHub Advisory Database and opens PRs with patches, while automated [secret scanning](https://docs.github.com/en/enterprise-cloud@latest/code-security/secret-scanning/about-secret-scanning#about-secret-scanning-for-partner-patterns) provides alerts for detected secrets.
- **[GitGuardian Security Checks](https://www.gitguardian.com/):** We employ GitGuardian to ensure security checks are performed on the codebase, enhancing the overall security of our project.
- **Code Analysis and Security Scanning:** With the help of [Codacy Static Code Analysis](https://www.codacy.com/) and [Codacy Security Scan](https://security.codacy.com/), we conduct thorough analyses and scans of our code for potential security risks.
## Reporting Security Vulnerabilities
Despite our best efforts to deliver secure software, we acknowledge the invaluable role of the community in identifying security breaches.
### Private Vulnerability Disclosures
We request all suspected vulnerabilities to be responsibly and privately disclosed by sending an email to [support@tj-actions.online](mailto:support@tj-actions.online).
### Public Vulnerability Disclosures
For publicly disclosed security vulnerabilities, please **IMMEDIATELY** email [support@tj-actions.online](mailto:support@tj-actions.online) with the details for prompt action.
Upon confirmation of a breach, reporters will receive full credit and recognition for their contribution. Please note, that we do not offer monetary compensation for reporting vulnerabilities.
## Communication of Security Breaches
We will utilize the [GitHub Security Advisory](https://github.com/tj-actions/changed-files/security/advisories) to communicate any security breaches. The advisory will be made public once a patch has been released to rectify the issue.
We appreciate your cooperation and contribution to maintaining the security of our software. Remember, a secure community is a strong community.

View File

@ -4,11 +4,11 @@ author: tj-actions
inputs: inputs:
separator: separator:
description: "Split character for output strings." description: "Split character for output strings"
required: false required: false
default: " " default: " "
include_all_old_new_renamed_files: include_all_old_new_renamed_files:
description: "Include `all_old_new_renamed_files` output. Note this can generate a large output See: #501." description: "Include `all_old_new_renamed_files` output. Note this can generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501)."
required: false required: false
default: "false" default: "false"
old_new_separator: old_new_separator:
@ -24,13 +24,11 @@ inputs:
required: false required: false
default: "" default: ""
files_from_source_file_separator: files_from_source_file_separator:
description: "Separator used to split the `files_from_source_file` input." description: 'Separator used to split the `files_from_source_file` input'
default: "\n" default: "\n"
required: false required: false
files: files:
description: | description: "File and directory patterns used to detect changes (Defaults to the entire repo if unset) **NOTE:** Multiline file/directory patterns should not include quotes."
File and directory patterns used to detect changes (Defaults to the entire repo if unset).
NOTE: Multiline file/directory patterns should not include quotes.
required: false required: false
default: "" default: ""
files_separator: files_separator:
@ -42,7 +40,7 @@ inputs:
required: false required: false
default: "" default: ""
files_yaml_from_source_file: files_yaml_from_source_file:
description: "Source file(s) used to populate the `files_yaml` input. Example: https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml" description: "Source file(s) used to populate the `files_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml)"
required: false required: false
default: "" default: ""
files_yaml_from_source_file_separator: files_yaml_from_source_file_separator:
@ -54,7 +52,7 @@ inputs:
required: false required: false
default: "" default: ""
files_ignore_yaml_from_source_file: files_ignore_yaml_from_source_file:
description: "Source file(s) used to populate the `files_ignore_yaml` input. Example: https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml" description: "Source file(s) used to populate the `files_ignore_yaml` input. [Example](https://github.com/tj-actions/changed-files/blob/main/test/changed-files.yml)"
required: false required: false
default: "" default: ""
files_ignore_yaml_from_source_file_separator: files_ignore_yaml_from_source_file_separator:
@ -62,7 +60,7 @@ inputs:
default: "\n" default: "\n"
required: false required: false
files_ignore: files_ignore:
description: "Ignore changes to these file(s). NOTE: Multiline file/directory patterns should not include quotes." description: "Ignore changes to these file(s) **NOTE:** Multiline file/directory patterns should not include quotes."
required: false required: false
default: "" default: ""
files_ignore_separator: files_ignore_separator:
@ -78,10 +76,10 @@ inputs:
default: "\n" default: "\n"
required: false required: false
sha: sha:
description: "Specify a different commit SHA or branch used for comparing changes" description: "Specify a different commit SHA used for comparing changes"
required: false required: false
base_sha: base_sha:
description: "Specify a different base commit SHA or branch used for comparing changes" description: "Specify a different base commit SHA used for comparing changes"
required: false required: false
since: since:
description: "Get changed files for commits whose timestamp is older than the given time." description: "Get changed files for commits whose timestamp is older than the given time."
@ -96,16 +94,16 @@ inputs:
required: false required: false
default: "." default: "."
quotepath: quotepath:
description: "Use non-ASCII characters to match files and output the filenames completely verbatim by setting this to `false`" description: "Use non-ascii characters to match files and output the filenames completely verbatim by setting this to `false`"
default: "true" default: "true"
required: false required: false
diff_relative: diff_relative:
description: "Exclude changes outside the current directory and show path names relative to it. NOTE: This requires you to specify the top-level directory via the `path` input." description: "Exclude changes outside the current directory and show path names relative to it. **NOTE:** This requires you to specify the top level directory via the `path` input."
required: false required: false
default: "true" default: "true"
dir_names: dir_names:
default: "false" default: "false"
description: "Output unique changed directories instead of filenames. NOTE: This returns `.` for changed files located in the current working directory which defaults to `$GITHUB_WORKSPACE`." description: "Output unique changed directories instead of filenames. **NOTE:** This returns `.` for changed files located in the current working directory which defaults to `$GITHUB_WORKSPACE`."
required: false required: false
dir_names_max_depth: dir_names_max_depth:
description: "Limit the directory output to a maximum depth e.g `test/test1/test2` with max depth of `2` returns `test/test1`." description: "Limit the directory output to a maximum depth e.g `test/test1/test2` with max depth of `2` returns `test/test1`."
@ -115,7 +113,7 @@ inputs:
required: false required: false
default: "false" default: "false"
dir_names_include_files: dir_names_include_files:
description: "File and directory patterns to include in the output when `dir_names` is set to `true`. NOTE: This returns only the matching files and also the directory names." description: "Include files in the output when `dir_names` is set to `true`. **NOTE:** This returns only the matching files and also the directory names."
required: false required: false
default: "" default: ""
dir_names_include_files_separator: dir_names_include_files_separator:
@ -127,25 +125,19 @@ inputs:
required: false required: false
default: "false" default: "false"
json: json:
description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs. Example: https://github.com/tj-actions/changed-files/blob/main/.github/workflows/matrix-example.yml" description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs. [Example](https://github.com/tj-actions/changed-files/blob/main/.github/workflows/matrix-test.yml)"
required: false required: false
default: "false" default: "false"
escape_json: escape_json:
description: "Escape JSON output." description: "Escape JSON output."
required: false required: false
default: "true" default: "true"
safe_output:
description: "Apply sanitization to output filenames before being set as output."
required: false
default: "true"
fetch_depth: fetch_depth:
description: "Depth of additional branch history fetched. NOTE: This can be adjusted to resolve errors with insufficient history." description: "Depth of additional branch history fetched. **NOTE**: This can be adjusted to resolve errors with insufficient history."
required: false required: false
default: "25" default: "50"
skip_initial_fetch: skip_initial_fetch:
description: | description: "Skip the initial fetch to improve performance for shallow repositories. **NOTE**: This could lead to errors with missing history and the intended use is limited to when you've fetched the history necessary to perform the diff."
Skip initially fetching additional history to improve performance for shallow repositories.
NOTE: This could lead to errors with missing history. It's intended to be used when you've fetched all necessary history to perform the diff.
required: false required: false
default: "false" default: "false"
fetch_additional_submodule_history: fetch_additional_submodule_history:
@ -157,7 +149,7 @@ inputs:
required: false required: false
default: "false" default: "false"
write_output_files: write_output_files:
description: "Write outputs to the `output_dir` defaults to `.github/outputs` folder. NOTE: This creates a `.txt` file by default and a `.json` file if `json` is set to `true`." description: "Write outputs to the `output_dir` defaults to `.github/outputs` folder. **NOTE:** This creates a `.txt` file by default and a `.json` file if `json` is set to `true`."
required: false required: false
default: "false" default: "false"
output_dir: output_dir:
@ -177,10 +169,7 @@ inputs:
required: false required: false
default: "" default: ""
recover_files: recover_files:
description: | description: "File and directory patterns used to recover deleted files, defaults to the patterns provided via the `files`, `files_from_source_file`, `files_ignore` and `files_ignore_from_source_file` inputs or all deleted files if no patterns are provided."
File and directory patterns used to recover deleted files,
defaults to the patterns provided via the `files`, `files_from_source_file`, `files_ignore` and `files_ignore_from_source_file` inputs
or all deleted files if no patterns are provided.
required: false required: false
default: "" default: ""
recover_files_separator: recover_files_separator:
@ -196,17 +185,13 @@ inputs:
default: "\n" default: "\n"
required: false required: false
token: token:
description: "GitHub token used to fetch changed files from Github's API." description: "Github token used to fetch changed files from Github's API."
required: false required: false
default: ${{ github.token }} default: ${{ github.token }}
api_url: api_url:
description: "Github API URL." description: "Github API URL."
required: false required: false
default: ${{ github.api_url }} default: ${{ github.api_url }}
use_rest_api:
description: "Force the use of Github's REST API even when a local copy of the repository exists"
required: false
default: "false"
fail_on_initial_diff_error: fail_on_initial_diff_error:
description: "Fail when the initial diff fails." description: "Fail when the initial diff fails."
required: false required: false
@ -215,35 +200,6 @@ inputs:
description: "Fail when the submodule diff fails." description: "Fail when the submodule diff fails."
required: false required: false
default: "false" default: "false"
negation_patterns_first:
description: "Apply the negation patterns first. NOTE: This affects how changed files are matched."
required: false
default: "false"
matrix:
description: "Output changed files in a format that can be used for matrix jobs. Alias for setting inputs `json` to `true` and `escape_json` to `false`."
required: false
default: "false"
exclude_submodules:
description: "Exclude changes to submodules."
required: false
default: "false"
fetch_missing_history_max_retries:
description: "Maximum number of retries to fetch missing history."
required: false
default: "20"
use_posix_path_separator:
description: "Use POSIX path separator `/` for output file paths on Windows."
required: false
default: "false"
tags_pattern:
description: "Tags pattern to include."
required: false
default: "*"
tags_ignore_pattern:
description: "Tags pattern to ignore."
required: false
default: ""
outputs: outputs:
added_files: added_files:
@ -283,45 +239,45 @@ outputs:
unknown_files_count: unknown_files_count:
description: "Returns the number of `unknown_files`" description: "Returns the number of `unknown_files`"
all_changed_and_modified_files: all_changed_and_modified_files:
description: "Returns all changed and modified files i.e. a combination of (ACMRDTUX)" description: "Returns all changed and modified files i.e. *a combination of (ACMRDTUX)*"
all_changed_and_modified_files_count: all_changed_and_modified_files_count:
description: "Returns the number of `all_changed_and_modified_files`" description: "Returns the number of `all_changed_and_modified_files`"
all_changed_files: all_changed_files:
description: "Returns all changed files i.e. a combination of all added, copied, modified and renamed files (ACMR)" description: "Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)*"
all_changed_files_count: all_changed_files_count:
description: "Returns the number of `all_changed_files`" description: "Returns the number of `all_changed_files`"
any_changed: any_changed:
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs have changed. This defaults to `true` when no patterns are specified. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*." description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
only_changed: only_changed:
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs have changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*." description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has changed. i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
other_changed_files: other_changed_files:
description: "Returns all other changed files not listed in the files input i.e. includes a combination of all added, copied, modified and renamed files (ACMR)." description: "Returns all other changed files not listed in the files input i.e. *includes a combination of all added, copied, modified and renamed files (ACMR)*."
other_changed_files_count: other_changed_files_count:
description: "Returns the number of `other_changed_files`" description: "Returns the number of `other_changed_files`"
all_modified_files: all_modified_files:
description: "Returns all changed files i.e. a combination of all added, copied, modified, renamed and deleted files (ACMRD)." description: "Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*."
all_modified_files_count: all_modified_files_count:
description: "Returns the number of `all_modified_files`" description: "Returns the number of `all_modified_files`"
any_modified: any_modified:
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs have been modified. This defaults to `true` when no patterns are specified. i.e. *includes a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*." description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has been modified. i.e. *includes a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*."
only_modified: only_modified:
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs have been modified. (ACMRD)." description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has been modified. (ACMRD)."
other_modified_files: other_modified_files:
description: "Returns all other modified files not listed in the files input i.e. a combination of all added, copied, modified, and deleted files (ACMRD)" description: "Returns all other modified files not listed in the files input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)*"
other_modified_files_count: other_modified_files_count:
description: "Returns the number of `other_modified_files`" description: "Returns the number of `other_modified_files`"
any_deleted: any_deleted:
description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs have been deleted. This defaults to `true` when no patterns are specified. (D)" description: "Returns `true` when any of the filenames provided using the `files*` or `files_ignore*` inputs has been deleted. (D)"
only_deleted: only_deleted:
description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs have been deleted. (D)" description: "Returns `true` when only files provided using the `files*` or `files_ignore*` inputs has been deleted. (D)"
other_deleted_files: other_deleted_files:
description: "Returns all other deleted files not listed in the files input i.e. a combination of all deleted files (D)" description: "Returns all other deleted files not listed in the files input i.e. *a combination of all deleted files (D)*"
other_deleted_files_count: other_deleted_files_count:
description: "Returns the number of `other_deleted_files`" description: "Returns the number of `other_deleted_files`"
modified_keys: modified_keys:
description: "Returns all modified YAML keys when the `files_yaml` input is used. i.e. key that contains any path that has either been added, copied, modified, and deleted (ACMRD)" description: "Returns all modified YAML keys when the `files_yaml` input is used. i.e. *key that contains any path that has either been added, copied, modified, and deleted (ACMRD)*"
changed_keys: changed_keys:
description: "Returns all changed YAML keys when the `files_yaml` input is used. i.e. key that contains any path that has either been added, copied, modified, and renamed (ACMR)" description: "Returns all changed YAML keys when the `files_yaml` input is used. i.e. *key that contains any path that has either been added, copied, modified, and renamed (ACMR)*"
runs: runs:
using: 'node20' using: 'node20'

21421
dist/index.js generated vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

5289
dist/licenses.txt generated vendored

File diff suppressed because it is too large Load Diff

2
dist/sourcemap-register.js generated vendored

File diff suppressed because one or more lines are too long

View File

@ -10,4 +10,4 @@ module.exports = {
setupFiles: [ setupFiles: [
"<rootDir>/jest/setupEnv.cjs" "<rootDir>/jest/setupEnv.cjs"
] ]
}; }

View File

@ -1,5 +1,6 @@
const path = require('path') const path = require('path')
process.env.TESTING = "1"
process.env.GITHUB_WORKSPACE = path.join( process.env.GITHUB_WORKSPACE = path.join(
path.resolve(__dirname, '..'), '.' path.resolve(__dirname, '..'), '.'
) )

View File

@ -1,6 +1,6 @@
{ {
"name": "@tj-actions/changed-files", "name": "@tj-actions/changed-files",
"version": "45.0.4", "version": "39.2.1",
"description": "Github action to retrieve all (added, copied, modified, deleted, renamed, type changed, unmerged, unknown) files and directories.", "description": "Github action to retrieve all (added, copied, modified, deleted, renamed, type changed, unmerged, unknown) files and directories.",
"main": "lib/main.js", "main": "lib/main.js",
"publishConfig": { "publishConfig": {
@ -8,13 +8,12 @@
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"format": "prettier --write src/*.ts src/**/*.ts", "format": "prettier --write **/*.ts",
"format-check": "prettier --check src/*.ts src/**/*.ts", "format-check": "prettier --check **/*.ts",
"lint": "eslint src/*.ts src/**/*.ts --max-warnings 0", "lint": "eslint **/*.ts --max-warnings 0",
"lint:fix": "eslint --fix src/*.ts src/**/*.ts", "lint:fix": "eslint --fix src/**/*.ts",
"package": "ncc build lib/main.js --source-map --license licenses.txt", "package": "ncc build lib/main.js --source-map --license licenses.txt",
"test": "jest --coverage", "test": "jest --coverage",
"update-snapshot": "jest -u",
"all": "yarn build && yarn format && yarn lint && yarn package && yarn test" "all": "yarn build && yarn format && yarn lint && yarn package && yarn test"
}, },
"repository": { "repository": {
@ -36,8 +35,7 @@
"@actions/core": "^1.10.0", "@actions/core": "^1.10.0",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/github": "^6.0.0", "@actions/github": "^6.0.0",
"@octokit/rest": "^21.0.0", "@octokit/rest": "^20.0.1",
"@stdlib/utils-convert-path": "^0.2.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"micromatch": "^4.0.5", "micromatch": "^4.0.5",
"yaml": "^2.3.1" "yaml": "^2.3.1"
@ -46,16 +44,16 @@
"@types/jest": "^29.5.2", "@types/jest": "^29.5.2",
"@types/lodash": "^4.14.195", "@types/lodash": "^4.14.195",
"@types/micromatch": "^4.0.2", "@types/micromatch": "^4.0.2",
"@types/node": "^22.0.0", "@types/node": "^20.3.2",
"@types/uuid": "^10.0.0", "@types/uuid": "^9.0.2",
"@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^7.0.0", "@typescript-eslint/parser": "^6.0.0",
"@vercel/ncc": "^0.38.0", "@vercel/ncc": "^0.38.0",
"eslint": "^8.43.0", "eslint": "^8.43.0",
"eslint-config-prettier": "^9.0.0", "eslint-plugin-github": "^4.8.0",
"eslint-plugin-github": "^5.0.0", "eslint-plugin-jest": "^27.2.2",
"eslint-plugin-jest": "^28.0.0",
"eslint-plugin-prettier": "^5.0.0-alpha.2", "eslint-plugin-prettier": "^5.0.0-alpha.2",
"eslint-config-prettier": "^9.0.0",
"jest": "^29.5.0", "jest": "^29.5.0",
"prettier": "^3.0.0", "prettier": "^3.0.0",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",

View File

@ -1,373 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`getInputs should correctly parse boolean inputs 1`] = `
{
"apiUrl": "",
"baseSha": "",
"diffRelative": "false",
"dirNames": "false",
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": "false",
"dirNamesExcludeCurrentDir": "false",
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"escapeJson": false,
"excludeSubmodules": "false",
"failOnInitialDiffError": "false",
"failOnSubmoduleDiffError": "false",
"fetchAdditionalSubmoduleHistory": "false",
"fetchMissingHistoryMaxRetries": 20,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": "false",
"json": true,
"negationPatternsFirst": "false",
"oldNewFilesSeparator": " ",
"oldNewSeparator": ",",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": "false",
"path": ".",
"quotepath": "false",
"recoverDeletedFiles": "false",
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "
",
"recoverFilesSeparator": "
",
"safeOutput": "false",
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": "false",
"skipInitialFetch": "true",
"tagsIgnorePattern": "",
"tagsPattern": "*",
"token": "",
"until": "",
"usePosixPathSeparator": "false",
"useRestApi": "false",
"writeOutputFiles": "false",
}
`;
exports[`getInputs should correctly parse numeric inputs 1`] = `
{
"apiUrl": "",
"baseSha": "",
"diffRelative": true,
"dirNames": false,
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": false,
"dirNamesExcludeCurrentDir": false,
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"dirNamesMaxDepth": 2,
"escapeJson": false,
"excludeSubmodules": false,
"failOnInitialDiffError": false,
"failOnSubmoduleDiffError": false,
"fetchAdditionalSubmoduleHistory": false,
"fetchDepth": 5,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": false,
"json": false,
"negationPatternsFirst": false,
"oldNewFilesSeparator": "",
"oldNewSeparator": "",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": false,
"path": "",
"quotepath": true,
"recoverDeletedFiles": false,
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "",
"recoverFilesSeparator": "",
"safeOutput": false,
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": false,
"skipInitialFetch": false,
"tagsIgnorePattern": "",
"tagsPattern": "",
"token": "",
"until": "",
"usePosixPathSeparator": false,
"useRestApi": false,
"writeOutputFiles": false,
}
`;
exports[`getInputs should correctly parse string inputs 1`] = `
{
"apiUrl": "https://api.github.com",
"baseSha": "",
"diffRelative": true,
"dirNames": false,
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": false,
"dirNamesExcludeCurrentDir": false,
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"escapeJson": false,
"excludeSubmodules": false,
"failOnInitialDiffError": false,
"failOnSubmoduleDiffError": false,
"fetchAdditionalSubmoduleHistory": false,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": false,
"json": false,
"negationPatternsFirst": false,
"oldNewFilesSeparator": "",
"oldNewSeparator": "",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": false,
"path": "",
"quotepath": true,
"recoverDeletedFiles": false,
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "",
"recoverFilesSeparator": "",
"safeOutput": false,
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": false,
"skipInitialFetch": false,
"tagsIgnorePattern": "",
"tagsPattern": "",
"token": "token",
"until": "",
"usePosixPathSeparator": false,
"useRestApi": false,
"writeOutputFiles": false,
}
`;
exports[`getInputs should handle invalid numeric inputs correctly 1`] = `
{
"apiUrl": "",
"baseSha": "",
"diffRelative": true,
"dirNames": false,
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": false,
"dirNamesExcludeCurrentDir": false,
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"dirNamesMaxDepth": 2,
"escapeJson": false,
"excludeSubmodules": false,
"failOnInitialDiffError": false,
"failOnSubmoduleDiffError": false,
"fetchAdditionalSubmoduleHistory": false,
"fetchDepth": NaN,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": false,
"json": false,
"negationPatternsFirst": false,
"oldNewFilesSeparator": "",
"oldNewSeparator": "",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": false,
"path": "",
"quotepath": true,
"recoverDeletedFiles": false,
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "",
"recoverFilesSeparator": "",
"safeOutput": false,
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": false,
"skipInitialFetch": false,
"tagsIgnorePattern": "",
"tagsPattern": "",
"token": "",
"until": "",
"usePosixPathSeparator": false,
"useRestApi": false,
"writeOutputFiles": false,
}
`;
exports[`getInputs should handle negative numeric inputs correctly 1`] = `
{
"apiUrl": "",
"baseSha": "",
"diffRelative": true,
"dirNames": false,
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": false,
"dirNamesExcludeCurrentDir": false,
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"dirNamesMaxDepth": -2,
"escapeJson": false,
"excludeSubmodules": false,
"failOnInitialDiffError": false,
"failOnSubmoduleDiffError": false,
"fetchAdditionalSubmoduleHistory": false,
"fetchDepth": 2,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": false,
"json": false,
"negationPatternsFirst": false,
"oldNewFilesSeparator": "",
"oldNewSeparator": "",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": false,
"path": "",
"quotepath": true,
"recoverDeletedFiles": false,
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "",
"recoverFilesSeparator": "",
"safeOutput": false,
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": false,
"skipInitialFetch": false,
"tagsIgnorePattern": "",
"tagsPattern": "",
"token": "",
"until": "",
"usePosixPathSeparator": false,
"useRestApi": false,
"writeOutputFiles": false,
}
`;
exports[`getInputs should return default values when no inputs are provided 1`] = `
{
"apiUrl": "",
"baseSha": "",
"diffRelative": true,
"dirNames": false,
"dirNamesDeletedFilesIncludeOnlyDeletedDirs": false,
"dirNamesExcludeCurrentDir": false,
"dirNamesIncludeFiles": "",
"dirNamesIncludeFilesSeparator": "",
"escapeJson": false,
"excludeSubmodules": false,
"failOnInitialDiffError": false,
"failOnSubmoduleDiffError": false,
"fetchAdditionalSubmoduleHistory": false,
"fetchMissingHistoryMaxRetries": 20,
"files": "",
"filesFromSourceFile": "",
"filesFromSourceFileSeparator": "",
"filesIgnore": "",
"filesIgnoreFromSourceFile": "",
"filesIgnoreFromSourceFileSeparator": "",
"filesIgnoreSeparator": "",
"filesIgnoreYaml": "",
"filesIgnoreYamlFromSourceFile": "",
"filesIgnoreYamlFromSourceFileSeparator": "",
"filesSeparator": "",
"filesYaml": "",
"filesYamlFromSourceFile": "",
"filesYamlFromSourceFileSeparator": "",
"includeAllOldNewRenamedFiles": false,
"json": false,
"negationPatternsFirst": false,
"oldNewFilesSeparator": " ",
"oldNewSeparator": ",",
"outputDir": "",
"outputRenamedFilesAsDeletedAndAdded": false,
"path": ".",
"quotepath": true,
"recoverDeletedFiles": false,
"recoverDeletedFilesToDestination": "",
"recoverFiles": "",
"recoverFilesIgnore": "",
"recoverFilesIgnoreSeparator": "
",
"recoverFilesSeparator": "
",
"safeOutput": false,
"separator": "",
"sha": "",
"since": "",
"sinceLastRemoteCommit": false,
"skipInitialFetch": false,
"tagsIgnorePattern": "",
"tagsPattern": "*",
"token": "",
"until": "",
"usePosixPathSeparator": false,
"useRestApi": false,
"writeOutputFiles": false,
}
`;

View File

@ -1,153 +0,0 @@
import * as core from '@actions/core'
import {getInputs, Inputs} from '../inputs'
import {DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS} from '../constant'
jest.mock('@actions/core')
describe('getInputs', () => {
afterEach(() => {
jest.clearAllMocks()
})
test('should return default values when no inputs are provided', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
'') as string
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
false) as boolean
})
expect(getInputs()).toMatchSnapshot()
})
test('should correctly parse boolean inputs', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
'') as string
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
switch (name) {
case 'matrix':
return 'true'
case 'skip_initial_fetch':
return 'true'
default:
return 'false'
}
})
expect(getInputs()).toMatchSnapshot()
})
test('should handle matrix alias correctly', () => {
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
return name === 'matrix' ? 'true' : 'false'
})
const inputs = getInputs()
expect(inputs).toHaveProperty('json', true)
expect(inputs).toHaveProperty('escapeJson', false)
})
test('should correctly parse string inputs', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
switch (name) {
case 'token':
return 'token'
case 'api_url':
return 'https://api.github.com'
default:
return ''
}
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
false) as boolean
})
expect(getInputs()).toMatchSnapshot()
})
test('should correctly parse numeric inputs', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
switch (name) {
case 'fetch_depth':
return '5'
case 'dir_names_max_depth':
return '2'
default:
return ''
}
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
false) as boolean
})
expect(getInputs()).toMatchSnapshot()
})
test('should handle invalid numeric inputs correctly', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
// TODO: Add validation for invalid numbers which should result in an error instead of NaN
switch (name) {
case 'fetch_depth':
return 'invalid'
case 'dir_names_max_depth':
return '2'
default:
return ''
}
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
false) as boolean
})
expect(getInputs()).toMatchSnapshot()
})
test('should handle negative numeric inputs correctly', () => {
;(core.getInput as jest.Mock).mockImplementation(name => {
// TODO: Add validation for negative numbers which should result in an error
switch (name) {
case 'fetch_depth':
return '-5'
case 'dir_names_max_depth':
return '-2'
default:
return ''
}
})
;(core.getBooleanInput as jest.Mock).mockImplementation(name => {
const camelCaseName = name.replace(/_([a-z])/g, (g: string[]) => {
return g[1].toUpperCase()
}) as keyof Inputs
return (DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[camelCaseName] ||
false) as boolean
})
expect(getInputs()).toMatchSnapshot()
})
})

View File

@ -0,0 +1,5 @@
describe('main test', () => {
it('adds two numbers', async () => {
expect(1 + 1).toEqual(2)
})
})

View File

@ -1,14 +1,9 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import {ChangeTypeEnum} from '../changedFiles' import {ChangeTypeEnum} from '../changedFiles'
import {Inputs} from '../inputs'
import { import {
getDirname, getDirname,
getDirnameMaxDepth, getDirnameMaxDepth,
getFilteredChangedFiles, getFilteredChangedFiles,
getPreviousGitTag, normalizeSeparators
normalizeSeparators,
warnUnsupportedRESTAPIInputs
} from '../utils' } from '../utils'
const originalPlatform = process.platform const originalPlatform = process.platform
@ -580,182 +575,4 @@ describe('utils test', () => {
expect(filteredFiles[ChangeTypeEnum.Modified]).toEqual([]) expect(filteredFiles[ChangeTypeEnum.Modified]).toEqual([])
}) })
}) })
describe('warnUnsupportedRESTAPIInputs', () => {
// Warns about unsupported inputs when using the REST API.
it('should warn about unsupported inputs when all inputs are supported', async () => {
const inputs: Inputs = {
files: '',
filesSeparator: '\n',
filesFromSourceFile: '',
filesFromSourceFileSeparator: '\n',
filesYaml: '',
filesYamlFromSourceFile: '',
filesYamlFromSourceFileSeparator: '\n',
filesIgnore: '',
filesIgnoreSeparator: '\n',
filesIgnoreFromSourceFile: '',
filesIgnoreFromSourceFileSeparator: '\n',
filesIgnoreYaml: '',
filesIgnoreYamlFromSourceFile: '',
filesIgnoreYamlFromSourceFileSeparator: '\n',
separator: ' ',
includeAllOldNewRenamedFiles: false,
oldNewSeparator: ',',
oldNewFilesSeparator: ' ',
sha: '1313123',
baseSha: '',
since: '',
until: '',
path: '.',
quotepath: true,
diffRelative: true,
dirNames: false,
dirNamesMaxDepth: undefined,
dirNamesExcludeCurrentDir: false,
dirNamesIncludeFiles: '',
dirNamesIncludeFilesSeparator: '\n',
dirNamesDeletedFilesIncludeOnlyDeletedDirs: false,
json: false,
escapeJson: true,
safeOutput: true,
fetchDepth: 50,
fetchAdditionalSubmoduleHistory: false,
sinceLastRemoteCommit: false,
writeOutputFiles: false,
outputDir: '.github/outputs',
outputRenamedFilesAsDeletedAndAdded: false,
recoverDeletedFiles: false,
recoverDeletedFilesToDestination: '',
recoverFiles: '',
recoverFilesSeparator: '\n',
recoverFilesIgnore: '',
recoverFilesIgnoreSeparator: '\n',
token: '${{ github.token }}',
apiUrl: '${{ github.api_url }}',
skipInitialFetch: false,
failOnInitialDiffError: false,
failOnSubmoduleDiffError: false,
negationPatternsFirst: false,
useRestApi: false,
excludeSubmodules: false,
fetchMissingHistoryMaxRetries: 20,
usePosixPathSeparator: false,
tagsPattern: '*',
tagsIgnorePattern: ''
}
const coreWarningSpy = jest.spyOn(core, 'warning')
await warnUnsupportedRESTAPIInputs({
inputs
})
expect(coreWarningSpy).toHaveBeenCalledWith(
'Input "sha" is not supported when using GitHub\'s REST API to get changed files'
)
expect(coreWarningSpy).toHaveBeenCalledTimes(1)
})
})
describe('getPreviousGitTag', () => {
// Check if the environment variable GITHUB_REPOSITORY_OWNER is 'tj-actions'
const shouldSkip = !!process.env.GITHUB_EVENT_PULL_REQUEST_HEAD_REPO_FORK
// Function returns the second-latest tag and its SHA
it('should return the second latest tag and its SHA when multiple tags are present', async () => {
if (shouldSkip) {
return
}
const result = await getPreviousGitTag({
cwd: '.',
tagsPattern: '*',
tagsIgnorePattern: '',
currentBranch: 'v1.0.1'
})
expect(result).toEqual({
tag: 'v1.0.0',
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
})
})
// Tags are filtered by a specified pattern when 'tagsPattern' is provided
it('should filter tags by the specified pattern', async () => {
if (shouldSkip) {
return
}
const result = await getPreviousGitTag({
cwd: '.',
tagsPattern: 'v1.*',
tagsIgnorePattern: '',
currentBranch: 'v1.0.1'
})
expect(result).toEqual({
tag: 'v1.0.0',
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
})
})
// Tags are excluded by a specified ignore pattern when 'tagsIgnorePattern' is provided
it('should exclude tags by the specified ignore pattern', async () => {
if (shouldSkip) {
return
}
const result = await getPreviousGitTag({
cwd: '.',
tagsPattern: '*',
tagsIgnorePattern: 'v0.*.*',
currentBranch: 'v1.0.1'
})
expect(result).toEqual({
tag: 'v1.0.0',
sha: 'f0751de6af436d4e79016e2041cf6400e0833653'
})
})
// No tags are available in the repository
it('should return empty values when no tags are available in the repository', async () => {
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
stdout: '',
stderr: '',
exitCode: 0
})
const result = await getPreviousGitTag({
cwd: '.',
tagsPattern: '*',
tagsIgnorePattern: '',
currentBranch: ''
})
expect(result).toEqual({tag: '', sha: ''})
})
// Only one tag is available, making it impossible to find a previous tag
it('should return empty values when only one tag is available', async () => {
jest.spyOn(exec, 'getExecOutput').mockResolvedValueOnce({
stdout:
'v1.0.1|f0751de6af436d4e79016e2041cf6400e0833653|2021-01-01T00:00:00Z',
stderr: '',
exitCode: 0
})
const result = await getPreviousGitTag({
cwd: '.',
tagsPattern: '*',
tagsIgnorePattern: '',
currentBranch: 'v1.0.1'
})
expect(result).toEqual({tag: '', sha: ''})
})
// Git commands fail and throw errors
it('should throw an error when git commands fail', async () => {
jest
.spyOn(exec, 'getExecOutput')
.mockRejectedValue(new Error('git command failed'))
await expect(
getPreviousGitTag({
cwd: '.',
tagsPattern: '*',
tagsIgnorePattern: '',
currentBranch: 'v1.0.1'
})
).rejects.toThrow('git command failed')
})
})
}) })

View File

@ -2,7 +2,6 @@ import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import type {RestEndpointMethodTypes} from '@octokit/rest' import type {RestEndpointMethodTypes} from '@octokit/rest'
import flatten from 'lodash/flatten' import flatten from 'lodash/flatten'
import convertPath from '@stdlib/utils-convert-path'
import mm from 'micromatch' import mm from 'micromatch'
import * as path from 'path' import * as path from 'path'
import {setOutputsAndGetModifiedAndChangedFilesStatus} from './changedFilesOutput' import {setOutputsAndGetModifiedAndChangedFilesStatus} from './changedFilesOutput'
@ -122,13 +121,13 @@ export const processChangedFiles = async ({
export const getRenamedFiles = async ({ export const getRenamedFiles = async ({
inputs, inputs,
workingDirectory, workingDirectory,
diffSubmodule, hasSubmodule,
diffResult, diffResult,
submodulePaths submodulePaths
}: { }: {
inputs: Inputs inputs: Inputs
workingDirectory: string workingDirectory: string
diffSubmodule: boolean hasSubmodule: boolean
diffResult: DiffResult diffResult: DiffResult
submodulePaths: string[] submodulePaths: string[]
}): Promise<{paths: string; count: string}> => { }): Promise<{paths: string; count: string}> => {
@ -140,7 +139,7 @@ export const getRenamedFiles = async ({
oldNewSeparator: inputs.oldNewSeparator oldNewSeparator: inputs.oldNewSeparator
}) })
if (diffSubmodule) { if (hasSubmodule) {
for (const submodulePath of submodulePaths) { for (const submodulePath of submodulePaths) {
const submoduleShaResult = await gitSubmoduleDiffSHA({ const submoduleShaResult = await gitSubmoduleDiffSHA({
cwd: workingDirectory, cwd: workingDirectory,
@ -167,7 +166,7 @@ export const getRenamedFiles = async ({
})) }))
) { ) {
let message = `Unable to use three dot diff for: ${submodulePath} submodule. Falling back to two dot diff. You can set 'fetch_additional_submodule_history: true' to fetch additional submodule history in order to use three dot diff` let message = `Unable to use three dot diff for: ${submodulePath} submodule. Falling back to two dot diff. You can set 'fetch_additional_submodule_history: true' to fetch additional submodule history in order to use three dot diff`
if (inputs.fetchAdditionalSubmoduleHistory) { if (inputs.fetchSubmoduleHistory) {
message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input` message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input`
} }
core.info(message) core.info(message)
@ -218,20 +217,20 @@ export type ChangedFiles = {
export const getAllDiffFiles = async ({ export const getAllDiffFiles = async ({
workingDirectory, workingDirectory,
diffSubmodule, hasSubmodule,
diffResult, diffResult,
submodulePaths, submodulePaths,
outputRenamedFilesAsDeletedAndAdded, outputRenamedFilesAsDeletedAndAdded,
fetchAdditionalSubmoduleHistory, fetchSubmoduleHistory,
failOnInitialDiffError, failOnInitialDiffError,
failOnSubmoduleDiffError failOnSubmoduleDiffError
}: { }: {
workingDirectory: string workingDirectory: string
diffSubmodule: boolean hasSubmodule: boolean
diffResult: DiffResult diffResult: DiffResult
submodulePaths: string[] submodulePaths: string[]
outputRenamedFilesAsDeletedAndAdded: boolean outputRenamedFilesAsDeletedAndAdded: boolean
fetchAdditionalSubmoduleHistory: boolean fetchSubmoduleHistory: boolean
failOnInitialDiffError: boolean failOnInitialDiffError: boolean
failOnSubmoduleDiffError: boolean failOnSubmoduleDiffError: boolean
}): Promise<ChangedFiles> => { }): Promise<ChangedFiles> => {
@ -244,7 +243,7 @@ export const getAllDiffFiles = async ({
failOnInitialDiffError failOnInitialDiffError
}) })
if (diffSubmodule) { if (hasSubmodule) {
for (const submodulePath of submodulePaths) { for (const submodulePath of submodulePaths) {
const submoduleShaResult = await gitSubmoduleDiffSHA({ const submoduleShaResult = await gitSubmoduleDiffSHA({
cwd: workingDirectory, cwd: workingDirectory,
@ -271,7 +270,7 @@ export const getAllDiffFiles = async ({
})) }))
) { ) {
let message = `Set 'fetch_additional_submodule_history: true' to fetch additional submodule history for: ${submodulePath}` let message = `Set 'fetch_additional_submodule_history: true' to fetch additional submodule history for: ${submodulePath}`
if (fetchAdditionalSubmoduleHistory) { if (fetchSubmoduleHistory) {
message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input` message = `To fetch additional submodule history for: ${submodulePath} you can increase history depth using 'fetch_depth' input`
} }
core.warning(message) core.warning(message)
@ -356,13 +355,9 @@ function* getChangeTypeFilesGenerator({
filePaths, filePaths,
dirNamesIncludeFilePatterns dirNamesIncludeFilePatterns
})) { })) {
if (isWindows() && inputs.usePosixPathSeparator) {
yield convertPath(filePath, 'mixed')
} else {
yield filePath yield filePath
} }
} }
}
} }
export const getChangeTypeFiles = async ({ export const getChangeTypeFiles = async ({
@ -407,12 +402,8 @@ function* getAllChangeTypeFilesGenerator({
filePaths, filePaths,
dirNamesIncludeFilePatterns dirNamesIncludeFilePatterns
})) { })) {
if (isWindows() && inputs.usePosixPathSeparator) {
yield convertPath(filePath, 'mixed')
} else {
yield filePath yield filePath
} }
}
} }
export const getAllChangeTypeFiles = async ({ export const getAllChangeTypeFiles = async ({
@ -484,7 +475,7 @@ export const getChangedFilesFromGithubAPI = async ({
if (changeType === ChangeTypeEnum.Renamed) { if (changeType === ChangeTypeEnum.Renamed) {
if (inputs.outputRenamedFilesAsDeletedAndAdded) { if (inputs.outputRenamedFilesAsDeletedAndAdded) {
changedFiles[ChangeTypeEnum.Deleted].push(item.previous_filename || '') changedFiles[ChangeTypeEnum.Deleted].push(item.filename)
changedFiles[ChangeTypeEnum.Added].push(item.filename) changedFiles[ChangeTypeEnum.Added].push(item.filename)
} else { } else {
changedFiles[ChangeTypeEnum.Renamed].push(item.filename) changedFiles[ChangeTypeEnum.Renamed].push(item.filename)

View File

@ -43,8 +43,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
key: getOutputKey('added_files_count', outputPrefix), key: getOutputKey('added_files_count', outputPrefix),
@ -65,8 +64,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -88,8 +86,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -111,8 +108,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -134,8 +130,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -157,8 +152,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -180,8 +174,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -206,8 +199,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -234,8 +226,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -247,7 +238,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
await setOutput({ await setOutput({
key: getOutputKey('any_changed', outputPrefix), key: getOutputKey('any_changed', outputPrefix),
value: allChangedFiles.paths.length > 0, value: allChangedFiles.paths.length > 0 && filePatterns.length > 0,
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json json: inputs.json
@ -323,8 +314,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -336,7 +326,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
await setOutput({ await setOutput({
key: getOutputKey('any_modified', outputPrefix), key: getOutputKey('any_modified', outputPrefix),
value: allModifiedFiles.paths.length > 0, value: allModifiedFiles.paths.length > 0 && filePatterns.length > 0,
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json json: inputs.json
@ -429,8 +419,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
@ -442,7 +431,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
await setOutput({ await setOutput({
key: getOutputKey('any_deleted', outputPrefix), key: getOutputKey('any_deleted', outputPrefix),
value: deletedFiles.paths.length > 0, value: deletedFiles.paths.length > 0 && filePatterns.length > 0,
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json json: inputs.json
@ -496,7 +485,7 @@ export const setOutputsAndGetModifiedAndChangedFilesStatus = async ({
}) })
return { return {
anyModified: allModifiedFiles.paths.length > 0, anyModified: allModifiedFiles.paths.length > 0 && filePatterns.length > 0,
anyChanged: allChangedFiles.paths.length > 0 anyChanged: allChangedFiles.paths.length > 0 && filePatterns.length > 0
} }
} }

View File

@ -5,7 +5,6 @@ import {Env} from './env'
import {Inputs} from './inputs' import {Inputs} from './inputs'
import { import {
canDiffCommits, canDiffCommits,
cleanShaInput,
getCurrentBranchName, getCurrentBranchName,
getHeadSha, getHeadSha,
getParentSha, getParentSha,
@ -24,11 +23,7 @@ const getCurrentSHA = async ({
inputs: Inputs inputs: Inputs
workingDirectory: string workingDirectory: string
}): Promise<string> => { }): Promise<string> => {
let currentSha = await cleanShaInput({ let currentSha = inputs.sha
sha: inputs.sha,
cwd: workingDirectory,
token: inputs.token
})
core.debug('Getting current SHA...') core.debug('Getting current SHA...')
if (inputs.until) { if (inputs.until) {
@ -86,27 +81,15 @@ export interface DiffResult {
initialCommit?: boolean initialCommit?: boolean
} }
interface SHAForNonPullRequestEvent { export const getSHAForNonPullRequestEvent = async (
inputs: Inputs inputs: Inputs,
env: Env env: Env,
workingDirectory: string workingDirectory: string,
isShallow: boolean isShallow: boolean,
diffSubmodule: boolean hasSubmodule: boolean,
gitFetchExtraArgs: string[] gitFetchExtraArgs: string[],
isTag: boolean isTag: boolean
remoteName: string ): Promise<DiffResult> => {
}
export const getSHAForNonPullRequestEvent = async ({
inputs,
env,
workingDirectory,
isShallow,
diffSubmodule,
gitFetchExtraArgs,
isTag,
remoteName
}: SHAForNonPullRequestEvent): Promise<DiffResult> => {
let targetBranch = env.GITHUB_REF_NAME let targetBranch = env.GITHUB_REF_NAME
let currentBranch = targetBranch let currentBranch = targetBranch
let initialCommit = false let initialCommit = false
@ -134,8 +117,8 @@ export const getSHAForNonPullRequestEvent = async ({
'-u', '-u',
'--progress', '--progress',
`--deepen=${inputs.fetchDepth}`, `--deepen=${inputs.fetchDepth}`,
remoteName, 'origin',
`+refs/heads/${sourceBranch}:refs/remotes/${remoteName}/${sourceBranch}` `+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}`
] ]
}) })
} else { } else {
@ -146,13 +129,13 @@ export const getSHAForNonPullRequestEvent = async ({
'-u', '-u',
'--progress', '--progress',
`--deepen=${inputs.fetchDepth}`, `--deepen=${inputs.fetchDepth}`,
remoteName, 'origin',
`+refs/heads/${targetBranch}:refs/remotes/${remoteName}/${targetBranch}` `+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
] ]
}) })
} }
if (diffSubmodule) { if (hasSubmodule) {
await gitFetchSubmodules({ await gitFetchSubmodules({
cwd: workingDirectory, cwd: workingDirectory,
args: [ args: [
@ -164,7 +147,7 @@ export const getSHAForNonPullRequestEvent = async ({
}) })
} }
} else { } else {
if (diffSubmodule && inputs.fetchAdditionalSubmoduleHistory) { if (hasSubmodule && inputs.fetchSubmoduleHistory) {
await gitFetchSubmodules({ await gitFetchSubmodules({
cwd: workingDirectory, cwd: workingDirectory,
args: [ args: [
@ -179,11 +162,7 @@ export const getSHAForNonPullRequestEvent = async ({
} }
const currentSha = await getCurrentSHA({inputs, workingDirectory}) const currentSha = await getCurrentSHA({inputs, workingDirectory})
let previousSha = await cleanShaInput({ let previousSha = inputs.baseSha
sha: inputs.baseSha,
cwd: workingDirectory,
token: inputs.token
})
const diff = '..' const diff = '..'
const currentBranchName = await getCurrentBranchName({cwd: workingDirectory}) const currentBranchName = await getCurrentBranchName({cwd: workingDirectory})
@ -196,7 +175,7 @@ export const getSHAForNonPullRequestEvent = async ({
currentBranch = currentBranchName currentBranch = currentBranchName
} }
if (inputs.baseSha && inputs.sha && currentBranch && targetBranch) { if (previousSha && currentSha && currentBranch && targetBranch) {
if (previousSha === currentSha) { if (previousSha === currentSha) {
core.error( core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.` `Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
@ -207,6 +186,7 @@ export const getSHAForNonPullRequestEvent = async ({
throw new Error('Similar commit hashes detected.') throw new Error('Similar commit hashes detected.')
} }
await verifyCommitSha({sha: previousSha, cwd: workingDirectory})
core.debug(`Previous SHA: ${previousSha}`) core.debug(`Previous SHA: ${previousSha}`)
return { return {
@ -218,7 +198,7 @@ export const getSHAForNonPullRequestEvent = async ({
} }
} }
if (!previousSha || previousSha === currentSha) { if (!previousSha) {
core.debug('Getting previous SHA...') core.debug('Getting previous SHA...')
if (inputs.since) { if (inputs.since) {
core.debug(`Getting base SHA for '${inputs.since}'...`) core.debug(`Getting base SHA for '${inputs.since}'...`)
@ -240,12 +220,7 @@ export const getSHAForNonPullRequestEvent = async ({
} }
} else if (isTag) { } else if (isTag) {
core.debug('Getting previous SHA for tag...') core.debug('Getting previous SHA for tag...')
const {sha, tag} = await getPreviousGitTag({ const {sha, tag} = await getPreviousGitTag({cwd: workingDirectory})
cwd: workingDirectory,
tagsPattern: inputs.tagsPattern,
tagsIgnorePattern: inputs.tagsIgnorePattern,
currentBranch
})
previousSha = sha previousSha = sha
targetBranch = tag targetBranch = tag
} else { } else {
@ -324,23 +299,14 @@ export const getSHAForNonPullRequestEvent = async ({
} }
} }
interface SHAForPullRequestEvent { export const getSHAForPullRequestEvent = async (
inputs: Inputs inputs: Inputs,
workingDirectory: string env: Env,
isShallow: boolean workingDirectory: string,
diffSubmodule: boolean isShallow: boolean,
hasSubmodule: boolean,
gitFetchExtraArgs: string[] gitFetchExtraArgs: string[]
remoteName: string ): Promise<DiffResult> => {
}
export const getSHAForPullRequestEvent = async ({
inputs,
workingDirectory,
isShallow,
diffSubmodule,
gitFetchExtraArgs,
remoteName
}: SHAForPullRequestEvent): Promise<DiffResult> => {
let targetBranch = github.context.payload.pull_request?.base?.ref let targetBranch = github.context.payload.pull_request?.base?.ref
const currentBranch = github.context.payload.pull_request?.head?.ref const currentBranch = github.context.payload.pull_request?.head?.ref
if (inputs.sinceLastRemoteCommit) { if (inputs.sinceLastRemoteCommit) {
@ -356,7 +322,7 @@ export const getSHAForPullRequestEvent = async ({
...gitFetchExtraArgs, ...gitFetchExtraArgs,
'-u', '-u',
'--progress', '--progress',
remoteName, 'origin',
`pull/${github.context.payload.pull_request?.number}/head:${currentBranch}` `pull/${github.context.payload.pull_request?.number}/head:${currentBranch}`
] ]
}) })
@ -369,8 +335,8 @@ export const getSHAForPullRequestEvent = async ({
'-u', '-u',
'--progress', '--progress',
`--deepen=${inputs.fetchDepth}`, `--deepen=${inputs.fetchDepth}`,
remoteName, 'origin',
`+refs/heads/${currentBranch}*:refs/remotes/${remoteName}/${currentBranch}*` `+refs/heads/${currentBranch}*:refs/remotes/origin/${currentBranch}*`
] ]
}) })
} }
@ -380,6 +346,8 @@ export const getSHAForPullRequestEvent = async ({
'Failed to fetch pull request branch. Please ensure "persist-credentials" is set to "true" when checking out the repository. See: https://github.com/actions/checkout#usage' 'Failed to fetch pull request branch. Please ensure "persist-credentials" is set to "true" when checking out the repository. See: https://github.com/actions/checkout#usage'
) )
} }
if (!inputs.sinceLastRemoteCommit) {
core.debug('Fetching target branch...') core.debug('Fetching target branch...')
await gitFetch({ await gitFetch({
cwd: workingDirectory, cwd: workingDirectory,
@ -388,12 +356,12 @@ export const getSHAForPullRequestEvent = async ({
'-u', '-u',
'--progress', '--progress',
`--deepen=${inputs.fetchDepth}`, `--deepen=${inputs.fetchDepth}`,
remoteName, 'origin',
`+refs/heads/${github.context.payload.pull_request?.base?.ref}:refs/remotes/${remoteName}/${github.context.payload.pull_request?.base?.ref}` `+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
] ]
}) })
if (diffSubmodule) { if (hasSubmodule) {
await gitFetchSubmodules({ await gitFetchSubmodules({
cwd: workingDirectory, cwd: workingDirectory,
args: [ args: [
@ -404,8 +372,9 @@ export const getSHAForPullRequestEvent = async ({
] ]
}) })
} }
}
} else { } else {
if (diffSubmodule && inputs.fetchAdditionalSubmoduleHistory) { if (hasSubmodule && inputs.fetchSubmoduleHistory) {
await gitFetchSubmodules({ await gitFetchSubmodules({
cwd: workingDirectory, cwd: workingDirectory,
args: [ args: [
@ -421,14 +390,10 @@ export const getSHAForPullRequestEvent = async ({
} }
const currentSha = await getCurrentSHA({inputs, workingDirectory}) const currentSha = await getCurrentSHA({inputs, workingDirectory})
let previousSha = await cleanShaInput({ let previousSha = inputs.baseSha
sha: inputs.baseSha,
cwd: workingDirectory,
token: inputs.token
})
let diff = '...' let diff = '...'
if (inputs.baseSha && inputs.sha && currentBranch && targetBranch) { if (previousSha && currentSha && currentBranch && targetBranch) {
if (previousSha === currentSha) { if (previousSha === currentSha) {
core.error( core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.` `Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
@ -439,6 +404,7 @@ export const getSHAForPullRequestEvent = async ({
throw new Error('Similar commit hashes detected.') throw new Error('Similar commit hashes detected.')
} }
await verifyCommitSha({sha: previousSha, cwd: workingDirectory})
core.debug(`Previous SHA: ${previousSha}`) core.debug(`Previous SHA: ${previousSha}`)
return { return {
@ -450,11 +416,14 @@ export const getSHAForPullRequestEvent = async ({
} }
} }
if (!github.context.payload.pull_request?.base?.ref) { if (
!github.context.payload.pull_request?.base?.ref ||
github.context.payload.head?.repo?.fork === 'true'
) {
diff = '..' diff = '..'
} }
if (!previousSha || previousSha === currentSha) { if (!previousSha) {
if (inputs.sinceLastRemoteCommit) { if (inputs.sinceLastRemoteCommit) {
previousSha = github.context.payload.before previousSha = github.context.payload.before
@ -507,14 +476,17 @@ export const getSHAForPullRequestEvent = async ({
} }
} }
} else { } else {
if (github.context.payload.action === 'closed') {
previousSha = github.context.payload.pull_request?.base?.sha previousSha = github.context.payload.pull_request?.base?.sha
} else {
if (!previousSha) {
previousSha = await getRemoteBranchHeadSha({ previousSha = await getRemoteBranchHeadSha({
cwd: workingDirectory, cwd: workingDirectory,
remoteName,
branch: targetBranch branch: targetBranch
}) })
if (!previousSha) {
previousSha = github.context.payload.pull_request?.base?.sha
}
} }
if (isShallow) { if (isShallow) {
@ -530,11 +502,7 @@ export const getSHAForPullRequestEvent = async ({
'Merge base is not in the local history, fetching remote target branch...' 'Merge base is not in the local history, fetching remote target branch...'
) )
for ( for (let i = 1; i <= 10; i++) {
let i = 1;
i <= (inputs.fetchMissingHistoryMaxRetries || 10);
i++
) {
await gitFetch({ await gitFetch({
cwd: workingDirectory, cwd: workingDirectory,
args: [ args: [
@ -542,8 +510,8 @@ export const getSHAForPullRequestEvent = async ({
'-u', '-u',
'--progress', '--progress',
`--deepen=${inputs.fetchDepth}`, `--deepen=${inputs.fetchDepth}`,
remoteName, 'origin',
`+refs/heads/${targetBranch}:refs/remotes/${remoteName}/${targetBranch}` `+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
] ]
}) })

View File

@ -1,29 +0,0 @@
import {Inputs} from './inputs'
export const DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS: Partial<Inputs> = {
sha: '',
baseSha: '',
since: '',
until: '',
path: '.',
quotepath: true,
diffRelative: true,
sinceLastRemoteCommit: false,
recoverDeletedFiles: false,
recoverDeletedFilesToDestination: '',
recoverFiles: '',
recoverFilesSeparator: '\n',
recoverFilesIgnore: '',
recoverFilesIgnoreSeparator: '\n',
includeAllOldNewRenamedFiles: false,
oldNewSeparator: ',',
oldNewFilesSeparator: ' ',
skipInitialFetch: false,
fetchAdditionalSubmoduleHistory: false,
dirNamesDeletedFilesIncludeOnlyDeletedDirs: false,
excludeSubmodules: false,
fetchMissingHistoryMaxRetries: 20,
usePosixPathSeparator: false,
tagsPattern: '*',
tagsIgnorePattern: ''
}

View File

@ -1,10 +1,13 @@
import * as core from '@actions/core'
export type Env = { export type Env = {
GITHUB_REF_NAME: string GITHUB_REF_NAME: string
GITHUB_REF: string GITHUB_REF: string
GITHUB_WORKSPACE: string GITHUB_WORKSPACE: string
} }
export const getEnv = async (): Promise<Env> => { export const getEnv = async (): Promise<Env> => {
core.debug(`Process Env: ${JSON.stringify(process.env, null, 2)}`)
return { return {
GITHUB_REF_NAME: process.env.GITHUB_REF_NAME || '', GITHUB_REF_NAME: process.env.GITHUB_REF_NAME || '',
GITHUB_REF: process.env.GITHUB_REF || '', GITHUB_REF: process.env.GITHUB_REF || '',

View File

@ -24,7 +24,7 @@ export type Inputs = {
since: string since: string
until: string until: string
path: string path: string
quotepath: boolean quotePath: boolean
diffRelative: boolean diffRelative: boolean
dirNames: boolean dirNames: boolean
dirNamesMaxDepth?: number dirNamesMaxDepth?: number
@ -34,9 +34,8 @@ export type Inputs = {
dirNamesDeletedFilesIncludeOnlyDeletedDirs: boolean dirNamesDeletedFilesIncludeOnlyDeletedDirs: boolean
json: boolean json: boolean
escapeJson: boolean escapeJson: boolean
safeOutput: boolean
fetchDepth?: number fetchDepth?: number
fetchAdditionalSubmoduleHistory: boolean fetchSubmoduleHistory: boolean
sinceLastRemoteCommit: boolean sinceLastRemoteCommit: boolean
writeOutputFiles: boolean writeOutputFiles: boolean
outputDir: string outputDir: string
@ -52,13 +51,6 @@ export type Inputs = {
skipInitialFetch: boolean skipInitialFetch: boolean
failOnInitialDiffError: boolean failOnInitialDiffError: boolean
failOnSubmoduleDiffError: boolean failOnSubmoduleDiffError: boolean
negationPatternsFirst: boolean
useRestApi: boolean
excludeSubmodules: boolean
fetchMissingHistoryMaxRetries?: number
usePosixPathSeparator: boolean
tagsPattern: string
tagsIgnorePattern?: string
} }
export const getInputs = (): Inputs => { export const getInputs = (): Inputs => {
@ -137,7 +129,7 @@ export const getInputs = (): Inputs => {
const since = core.getInput('since', {required: false}) const since = core.getInput('since', {required: false})
const until = core.getInput('until', {required: false}) const until = core.getInput('until', {required: false})
const path = core.getInput('path', {required: false}) const path = core.getInput('path', {required: false})
const quotepath = core.getBooleanInput('quotepath', {required: false}) const quotePath = core.getBooleanInput('quotepath', {required: false})
const diffRelative = core.getBooleanInput('diff_relative', {required: false}) const diffRelative = core.getBooleanInput('diff_relative', {required: false})
const dirNames = core.getBooleanInput('dir_names', {required: false}) const dirNames = core.getBooleanInput('dir_names', {required: false})
const dirNamesMaxDepth = core.getInput('dir_names_max_depth', { const dirNamesMaxDepth = core.getInput('dir_names_max_depth', {
@ -159,16 +151,8 @@ export const getInputs = (): Inputs => {
trimWhitespace: false trimWhitespace: false
} }
) )
let json = core.getBooleanInput('json', {required: false}) const json = core.getBooleanInput('json', {required: false})
let escapeJson = core.getBooleanInput('escape_json', {required: false}) const escapeJson = core.getBooleanInput('escape_json', {required: false})
const matrix = core.getBooleanInput('matrix', {required: false})
if (matrix) {
json = true
escapeJson = false
}
const safeOutput = core.getBooleanInput('safe_output', {required: false})
const fetchDepth = core.getInput('fetch_depth', {required: false}) const fetchDepth = core.getInput('fetch_depth', {required: false})
const sinceLastRemoteCommit = core.getBooleanInput( const sinceLastRemoteCommit = core.getBooleanInput(
'since_last_remote_commit', 'since_last_remote_commit',
@ -209,7 +193,7 @@ export const getInputs = (): Inputs => {
const skipInitialFetch = core.getBooleanInput('skip_initial_fetch', { const skipInitialFetch = core.getBooleanInput('skip_initial_fetch', {
required: false required: false
}) })
const fetchAdditionalSubmoduleHistory = core.getBooleanInput( const fetchSubmoduleHistory = core.getBooleanInput(
'fetch_additional_submodule_history', 'fetch_additional_submodule_history',
{ {
required: false required: false
@ -234,42 +218,6 @@ export const getInputs = (): Inputs => {
} }
) )
const negationPatternsFirst = core.getBooleanInput(
'negation_patterns_first',
{
required: false
}
)
const useRestApi = core.getBooleanInput('use_rest_api', {
required: false
})
const excludeSubmodules = core.getBooleanInput('exclude_submodules', {
required: false
})
const fetchMissingHistoryMaxRetries = core.getInput(
'fetch_missing_history_max_retries',
{required: false}
)
const usePosixPathSeparator = core.getBooleanInput(
'use_posix_path_separator',
{
required: false
}
)
const tagsPattern = core.getInput('tags_pattern', {
required: false,
trimWhitespace: false
})
const tagsIgnorePattern = core.getInput('tags_ignore_pattern', {
required: false,
trimWhitespace: false
})
const inputs: Inputs = { const inputs: Inputs = {
files, files,
filesSeparator, filesSeparator,
@ -294,7 +242,7 @@ export const getInputs = (): Inputs => {
since, since,
until, until,
path, path,
quotepath, quotePath,
diffRelative, diffRelative,
sinceLastRemoteCommit, sinceLastRemoteCommit,
recoverDeletedFiles, recoverDeletedFiles,
@ -307,12 +255,8 @@ export const getInputs = (): Inputs => {
oldNewSeparator, oldNewSeparator,
oldNewFilesSeparator, oldNewFilesSeparator,
skipInitialFetch, skipInitialFetch,
fetchAdditionalSubmoduleHistory, fetchSubmoduleHistory,
dirNamesDeletedFilesIncludeOnlyDeletedDirs, dirNamesDeletedFilesIncludeOnlyDeletedDirs,
excludeSubmodules,
usePosixPathSeparator,
tagsPattern,
tagsIgnorePattern,
// End Not Supported via REST API // End Not Supported via REST API
dirNames, dirNames,
dirNamesExcludeCurrentDir, dirNamesExcludeCurrentDir,
@ -320,18 +264,14 @@ export const getInputs = (): Inputs => {
dirNamesIncludeFilesSeparator, dirNamesIncludeFilesSeparator,
json, json,
escapeJson, escapeJson,
safeOutput,
writeOutputFiles, writeOutputFiles,
outputDir, outputDir,
outputRenamedFilesAsDeletedAndAdded, outputRenamedFilesAsDeletedAndAdded,
token, token,
apiUrl, apiUrl
negationPatternsFirst,
useRestApi
} }
if (fetchDepth) { if (fetchDepth) {
// Fallback to at least 2 if the fetch_depth is less than 2
inputs.fetchDepth = Math.max(parseInt(fetchDepth, 10), 2) inputs.fetchDepth = Math.max(parseInt(fetchDepth, 10), 2)
} }
@ -339,13 +279,5 @@ export const getInputs = (): Inputs => {
inputs.dirNamesMaxDepth = parseInt(dirNamesMaxDepth, 10) inputs.dirNamesMaxDepth = parseInt(dirNamesMaxDepth, 10)
} }
if (fetchMissingHistoryMaxRetries) {
// Fallback to at least 1 if the fetch_missing_history_max_retries is less than 1
inputs.fetchMissingHistoryMaxRetries = Math.max(
parseInt(fetchMissingHistoryMaxRetries, 10),
1
)
}
return inputs return inputs
} }

View File

@ -26,8 +26,7 @@ import {
setOutput, setOutput,
submoduleExists, submoduleExists,
updateGitGlobalConfig, updateGitGlobalConfig,
verifyMinimumGitVersion, verifyMinimumGitVersion
warnUnsupportedRESTAPIInputs
} from './utils' } from './utils'
const getChangedFilesFromLocalGitHistory = async ({ const getChangedFilesFromLocalGitHistory = async ({
@ -45,15 +44,15 @@ const getChangedFilesFromLocalGitHistory = async ({
}): Promise<void> => { }): Promise<void> => {
await verifyMinimumGitVersion() await verifyMinimumGitVersion()
let quotepathValue = 'on' let quotePathValue = 'on'
if (!inputs.quotepath) { if (!inputs.quotePath) {
quotepathValue = 'off' quotePathValue = 'off'
} }
await updateGitGlobalConfig({ await updateGitGlobalConfig({
name: 'core.quotepath', name: 'core.quotepath',
value: quotepathValue value: quotePathValue
}) })
if (inputs.diffRelative) { if (inputs.diffRelative) {
@ -64,26 +63,14 @@ const getChangedFilesFromLocalGitHistory = async ({
} }
const isShallow = await isRepoShallow({cwd: workingDirectory}) const isShallow = await isRepoShallow({cwd: workingDirectory})
let diffSubmodule = false const hasSubmodule = await submoduleExists({cwd: workingDirectory})
let gitFetchExtraArgs = ['--no-tags', '--prune'] let gitFetchExtraArgs = ['--no-tags', '--prune', '--recurse-submodules']
if (inputs.excludeSubmodules) {
core.info('Excluding submodules from the diff')
} else {
diffSubmodule = await submoduleExists({cwd: workingDirectory})
}
if (diffSubmodule) {
gitFetchExtraArgs.push('--recurse-submodules')
}
const isTag = env.GITHUB_REF?.startsWith('refs/tags/') const isTag = env.GITHUB_REF?.startsWith('refs/tags/')
const remoteName = 'origin'
const outputRenamedFilesAsDeletedAndAdded = const outputRenamedFilesAsDeletedAndAdded =
inputs.outputRenamedFilesAsDeletedAndAdded inputs.outputRenamedFilesAsDeletedAndAdded
let submodulePaths: string[] = [] let submodulePaths: string[] = []
if (diffSubmodule) { if (hasSubmodule) {
submodulePaths = await getSubmodulePath({cwd: workingDirectory}) submodulePaths = await getSubmodulePath({cwd: workingDirectory})
} }
@ -95,30 +82,29 @@ const getChangedFilesFromLocalGitHistory = async ({
if (!github.context.payload.pull_request?.base?.ref) { if (!github.context.payload.pull_request?.base?.ref) {
core.info(`Running on a ${github.context.eventName || 'push'} event...`) core.info(`Running on a ${github.context.eventName || 'push'} event...`)
diffResult = await getSHAForNonPullRequestEvent({ diffResult = await getSHAForNonPullRequestEvent(
inputs, inputs,
env, env,
workingDirectory, workingDirectory,
isShallow, isShallow,
diffSubmodule, hasSubmodule,
gitFetchExtraArgs, gitFetchExtraArgs,
isTag, isTag
remoteName )
})
} else { } else {
core.info( core.info(
`Running on a ${github.context.eventName || 'pull_request'} (${ `Running on a ${github.context.eventName || 'pull_request'} (${
github.context.payload.action github.context.payload.action
}) event...` }) event...`
) )
diffResult = await getSHAForPullRequestEvent({ diffResult = await getSHAForPullRequestEvent(
inputs, inputs,
env,
workingDirectory, workingDirectory,
isShallow, isShallow,
diffSubmodule, hasSubmodule,
gitFetchExtraArgs, gitFetchExtraArgs
remoteName )
})
} }
if (diffResult.initialCommit) { if (diffResult.initialCommit) {
@ -133,11 +119,11 @@ const getChangedFilesFromLocalGitHistory = async ({
const allDiffFiles = await getAllDiffFiles({ const allDiffFiles = await getAllDiffFiles({
workingDirectory, workingDirectory,
diffSubmodule, hasSubmodule,
diffResult, diffResult,
submodulePaths, submodulePaths,
outputRenamedFilesAsDeletedAndAdded, outputRenamedFilesAsDeletedAndAdded,
fetchAdditionalSubmoduleHistory: inputs.fetchAdditionalSubmoduleHistory, fetchSubmoduleHistory: inputs.fetchSubmoduleHistory,
failOnInitialDiffError: inputs.failOnInitialDiffError, failOnInitialDiffError: inputs.failOnInitialDiffError,
failOnSubmoduleDiffError: inputs.failOnSubmoduleDiffError failOnSubmoduleDiffError: inputs.failOnSubmoduleDiffError
}) })
@ -158,9 +144,7 @@ const getChangedFilesFromLocalGitHistory = async ({
workingDirectory, workingDirectory,
deletedFiles: allDiffFiles[ChangeTypeEnum.Deleted], deletedFiles: allDiffFiles[ChangeTypeEnum.Deleted],
recoverPatterns, recoverPatterns,
diffResult, sha: diffResult.previousSha
diffSubmodule,
submodulePaths
}) })
} }
@ -177,7 +161,7 @@ const getChangedFilesFromLocalGitHistory = async ({
const allOldNewRenamedFiles = await getRenamedFiles({ const allOldNewRenamedFiles = await getRenamedFiles({
inputs, inputs,
workingDirectory, workingDirectory,
diffSubmodule, hasSubmodule,
diffResult, diffResult,
submodulePaths submodulePaths
}) })
@ -187,8 +171,7 @@ const getChangedFilesFromLocalGitHistory = async ({
value: allOldNewRenamedFiles.paths, value: allOldNewRenamedFiles.paths,
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json
safeOutput: inputs.safeOutput
}) })
await setOutput({ await setOutput({
key: 'all_old_new_renamed_files_count', key: 'all_old_new_renamed_files_count',
@ -234,9 +217,11 @@ export async function run(): Promise<void> {
const inputs = getInputs() const inputs = getInputs()
core.debug(`Inputs: ${JSON.stringify(inputs, null, 2)}`) core.debug(`Inputs: ${JSON.stringify(inputs, null, 2)}`)
core.debug(`Github Context: ${JSON.stringify(github.context, null, 2)}`)
const workingDirectory = path.resolve( const workingDirectory = path.resolve(
env.GITHUB_WORKSPACE || process.cwd(), env.GITHUB_WORKSPACE || process.cwd(),
inputs.useRestApi ? '.' : inputs.path inputs.path
) )
core.debug(`Working directory: ${workingDirectory}`) core.debug(`Working directory: ${workingDirectory}`)
@ -255,19 +240,35 @@ export async function run(): Promise<void> {
}) })
core.debug(`Yaml file patterns: ${JSON.stringify(yamlFilePatterns)}`) core.debug(`Yaml file patterns: ${JSON.stringify(yamlFilePatterns)}`)
if (inputs.useRestApi && !github.context.payload.pull_request?.number) {
throw new Error(
"Only pull_request* events are supported when using GitHub's REST API."
)
}
if ( if (
inputs.token && inputs.token &&
github.context.payload.pull_request?.number && github.context.payload.pull_request?.number &&
(!hasGitDirectory || inputs.useRestApi) !hasGitDirectory
) { ) {
core.info("Using GitHub's REST API to get changed files") core.info("Using GitHub's REST API to get changed files")
await warnUnsupportedRESTAPIInputs({inputs}) const unsupportedInputs: (keyof Inputs)[] = [
'sha',
'baseSha',
'since',
'until',
'sinceLastRemoteCommit',
'recoverDeletedFiles',
'recoverDeletedFilesToDestination',
'recoverFiles',
'recoverFilesIgnore',
'includeAllOldNewRenamedFiles',
'skipInitialFetch',
'fetchSubmoduleHistory',
'dirNamesDeletedFilesIncludeOnlyDeletedDirs'
]
for (const input of unsupportedInputs) {
if (inputs[input]) {
core.warning(
`Input "${input}" is not supported when using GitHub's REST API to get changed files`
)
}
}
await getChangedFilesFromRESTAPI({ await getChangedFilesFromRESTAPI({
inputs, inputs,
filePatterns, filePatterns,
@ -275,9 +276,10 @@ export async function run(): Promise<void> {
}) })
} else { } else {
if (!hasGitDirectory) { if (!hasGitDirectory) {
throw new Error( core.setFailed(
`Unable to locate the git repository in the given path: ${workingDirectory}.\n Please run actions/checkout before this action (Make sure the 'path' input is correct).\n If you intend to use Github's REST API note that only pull_request* events are supported. Current event is "${github.context.eventName}".` "Can't find local .git directory. Please run actions/checkout before this action"
) )
return
} }
core.info('Using local .git directory') core.info('Using local .git directory')
@ -291,8 +293,10 @@ export async function run(): Promise<void> {
} }
} }
// eslint-disable-next-line github/no-then /* istanbul ignore if */
run().catch(e => { if (!process.env.TESTING) {
// eslint-disable-next-line github/no-then
run().catch(e => {
core.setFailed(e.message || e) core.setFailed(e.message || e)
process.exit(1) })
}) }

View File

@ -1,16 +1,14 @@
/*global AsyncIterableIterator*/ /*global AsyncIterableIterator*/
import * as core from '@actions/core' import * as core from '@actions/core'
import * as exec from '@actions/exec' import * as exec from '@actions/exec'
import * as github from '@actions/github'
import {createReadStream, promises as fs} from 'fs' import {createReadStream, promises as fs} from 'fs'
import {flattenDeep, snakeCase} from 'lodash' import {readFile} from 'fs/promises'
import {flattenDeep} from 'lodash'
import mm from 'micromatch' import mm from 'micromatch'
import * as path from 'path' import * as path from 'path'
import {createInterface} from 'readline' import {createInterface} from 'readline'
import {parseDocument} from 'yaml' import {parseDocument} from 'yaml'
import {ChangedFiles, ChangeTypeEnum} from './changedFiles' import {ChangedFiles, ChangeTypeEnum} from './changedFiles'
import {DiffResult} from './commitSha'
import {DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS} from './constant'
import {Inputs} from './inputs' import {Inputs} from './inputs'
const MINIMUM_GIT_VERSION = '2.18.0' const MINIMUM_GIT_VERSION = '2.18.0'
@ -32,13 +30,11 @@ export const normalizeSeparators = (p: string): string => {
// Remove redundant slashes // Remove redundant slashes
const isUnc = /^\\\\+[^\\]/.test(p) // e.g. \\hello const isUnc = /^\\\\+[^\\]/.test(p) // e.g. \\hello
p = (isUnc ? '\\' : '') + p.replace(/\\\\+/g, '\\') // preserve leading \\ for UNC return (isUnc ? '\\' : '') + p.replace(/\\\\+/g, '\\') // preserve leading \\ for UNC
} else {
// Remove redundant slashes on Linux/macOS
p = p.replace(/\/\/+/g, '/')
} }
return p // Remove redundant slashes
return p.replace(/\/\/+/g, '/')
} }
/** /**
@ -173,16 +169,15 @@ async function* lineOfFileGenerator({
input: fileStream, input: fileStream,
crlfDelay: Infinity crlfDelay: Infinity
}) })
for await (let line of rl) { for await (const line of rl) {
if (!line.startsWith('#') && line !== '') { if (!line.startsWith('#') && line !== '') {
if (excludedFiles) { if (excludedFiles) {
line = line.startsWith('!') ? line : `!${line}` if (line.startsWith('!')) {
if (line.endsWith(path.sep)) {
line = `${line}**`
}
yield line yield line
} else { } else {
line = line.endsWith(path.sep) ? `${line}**` : line yield `!${line}`
}
} else {
yield line yield line
} }
} }
@ -288,7 +283,6 @@ export const submoduleExists = async ({
* Fetches the git repository * Fetches the git repository
* @param args - arguments for fetch command * @param args - arguments for fetch command
* @param cwd - working directory * @param cwd - working directory
* @returns exit code
*/ */
export const gitFetch = async ({ export const gitFetch = async ({
args, args,
@ -337,7 +331,6 @@ export const gitFetchSubmodules = async ({
/** /**
* Retrieves all the submodule paths * Retrieves all the submodule paths
* @param cwd - working directory * @param cwd - working directory
* @returns submodule paths
*/ */
export const getSubmodulePath = async ({ export const getSubmodulePath = async ({
cwd cwd
@ -372,7 +365,6 @@ export const getSubmodulePath = async ({
* @param parentSha2 - parent commit sha * @param parentSha2 - parent commit sha
* @param submodulePath - path of submodule * @param submodulePath - path of submodule
* @param diff - diff type between parent commits (`..` or `...`) * @param diff - diff type between parent commits (`..` or `...`)
* @returns commit sha of submodule
*/ */
export const gitSubmoduleDiffSHA = async ({ export const gitSubmoduleDiffSHA = async ({
cwd, cwd,
@ -687,16 +679,14 @@ export const isInsideWorkTree = async ({
export const getRemoteBranchHeadSha = async ({ export const getRemoteBranchHeadSha = async ({
cwd, cwd,
branch, branch
remoteName
}: { }: {
cwd: string cwd: string
branch: string branch: string
remoteName: string
}): Promise<string> => { }): Promise<string> => {
const {stdout} = await exec.getExecOutput( const {stdout} = await exec.getExecOutput(
'git', 'git',
['rev-parse', `${remoteName}/${branch}`], ['rev-parse', `origin/${branch}`],
{ {
cwd, cwd,
silent: !core.isDebug() silent: !core.isDebug()
@ -781,130 +771,41 @@ export const verifyCommitSha = async ({
return exitCode return exitCode
} }
/**
* Clean the sha from the input which could be a branch name or a commit sha.
*
* If the input is a valid commit sha, return it as is.
*
* If the input is a branch name, get the HEAD sha of that branch and return it.
*
* @param sha The input string, which could be a branch name or a commit sha.
* @param cwd The working directory.
* @param token The GitHub token.
* @returns The cleaned SHA string.
*/
export const cleanShaInput = async ({
sha,
cwd,
token
}: {
sha: string
cwd: string
token: string
}): Promise<string> => {
// Check if the input is a valid commit sha
if (!sha) {
return sha
}
// Check if the input is a valid commit sha
const {stdout, exitCode} = await exec.getExecOutput(
'git',
['rev-parse', '--verify', `${sha}^{commit}`],
{
cwd,
ignoreReturnCode: true,
silent: !core.isDebug()
}
)
if (exitCode !== 0) {
const octokit = github.getOctokit(token)
// If it's not a valid commit sha, assume it's a branch name and get the HEAD sha
const {data: refData} = await octokit.rest.git.getRef({
owner: github.context.repo.owner,
repo: github.context.repo.repo,
ref: `heads/${sha}`
})
return refData.object.sha
}
return stdout.trim()
}
export const getPreviousGitTag = async ({ export const getPreviousGitTag = async ({
cwd, cwd
tagsPattern,
currentBranch,
tagsIgnorePattern
}: { }: {
cwd: string cwd: string
tagsPattern: string
currentBranch: string
tagsIgnorePattern?: string
}): Promise<{tag: string; sha: string}> => { }): Promise<{tag: string; sha: string}> => {
const ignorePatterns: string[] = []
let currentShaDate: Date | null = null
const {stdout} = await exec.getExecOutput( const {stdout} = await exec.getExecOutput(
'git', 'git',
[ ['tag', '--sort=-creatordate'],
'tag',
'--sort=-creatordate',
'--format=%(refname:short)|%(objectname)|%(creatordate:iso)'
],
{ {
cwd, cwd,
silent: !core.isDebug() silent: !core.isDebug()
} }
) )
if (tagsIgnorePattern) {
ignorePatterns.push(tagsIgnorePattern)
}
if (currentBranch) {
ignorePatterns.push(currentBranch)
try {
const {stdout: currentShaDateOutput} = await exec.getExecOutput(
'git',
['show', '-s', '--format=%ai', currentBranch],
{
cwd,
silent: !core.isDebug()
}
)
currentShaDate = new Date(currentShaDateOutput.trim())
} catch (error) {
// Handle the case where the current branch doesn't exist
// This might happen in detached head state
core.warning(`Failed to get date for current branch ${currentBranch}`)
}
}
const previousTag: {tag: string; sha: string} = {tag: '', sha: ''}
const tags = stdout.trim().split('\n') const tags = stdout.trim().split('\n')
for (const tagData of tags) {
const [tag, sha, dateString] = tagData.split('|')
if (!mm.isMatch(tag, tagsPattern) || mm.isMatch(tag, ignorePatterns)) {
continue
}
const date = new Date(dateString)
if (currentShaDate && date >= currentShaDate) {
continue
}
// Found a suitable tag, no need to continue
previousTag.tag = tag
previousTag.sha = sha
break
}
if (!previousTag.tag) { if (tags.length < 2) {
core.warning('No previous tag found') core.warning('No previous tag found')
return {tag: '', sha: ''}
} }
return previousTag const previousTag = tags[1]
const {stdout: stdout2} = await exec.getExecOutput(
'git',
['rev-parse', previousTag],
{
cwd,
silent: !core.isDebug()
}
)
const sha = stdout2.trim()
return {tag: previousTag, sha}
} }
export const canDiffCommits = async ({ export const canDiffCommits = async ({
@ -945,7 +846,7 @@ export const canDiffCommits = async ({
} else { } else {
const {exitCode, stderr} = await exec.getExecOutput( const {exitCode, stderr} = await exec.getExecOutput(
'git', 'git',
['diff', '--no-patch', sha1, sha2], ['diff', '--quiet', sha1, sha2],
{ {
cwd, cwd,
ignoreReturnCode: true, ignoreReturnCode: true,
@ -1037,101 +938,93 @@ export const getFilePatterns = async ({
inputs: Inputs inputs: Inputs
workingDirectory: string workingDirectory: string
}): Promise<string[]> => { }): Promise<string[]> => {
let cleanedFilePatterns: string[] = [] let filePatterns = inputs.files
if (inputs.files) {
const filesPatterns = inputs.files
.split(inputs.filesSeparator) .split(inputs.filesSeparator)
.map(p => (p.endsWith(path.sep) ? `${p}**` : p))
.filter(Boolean) .filter(Boolean)
.join('\n')
cleanedFilePatterns.push(...filesPatterns)
core.debug(`files patterns: ${filesPatterns.join('\n')}`)
}
if (inputs.filesFromSourceFile !== '') { if (inputs.filesFromSourceFile !== '') {
const inputFilesFromSourceFile = inputs.filesFromSourceFile const inputFilesFromSourceFile = inputs.filesFromSourceFile
.split(inputs.filesFromSourceFileSeparator) .split(inputs.filesFromSourceFileSeparator)
.filter(Boolean) .filter(p => p !== '')
.map(p => path.join(workingDirectory, p)) .map(p => path.join(workingDirectory, p))
core.debug(`files from source file: ${inputFilesFromSourceFile}`) core.debug(`files from source file: ${inputFilesFromSourceFile}`)
const filesFromSourceFiles = await getFilesFromSourceFile({ const filesFromSourceFiles = (
filePaths: inputFilesFromSourceFile await getFilesFromSourceFile({filePaths: inputFilesFromSourceFile})
}) ).join('\n')
core.debug( core.debug(`files from source files patterns: ${filesFromSourceFiles}`)
`files from source files patterns: ${filesFromSourceFiles.join('\n')}`
)
cleanedFilePatterns.push(...filesFromSourceFiles) filePatterns = filePatterns.concat('\n', filesFromSourceFiles)
} }
if (inputs.filesIgnore) { if (inputs.filesIgnore) {
const filesIgnorePatterns = inputs.filesIgnore const filesIgnorePatterns = inputs.filesIgnore
.split(inputs.filesIgnoreSeparator) .split(inputs.filesIgnoreSeparator)
.filter(Boolean) .filter(p => p !== '')
.map(p => { .map(p => {
p = p.startsWith('!') ? p : `!${p}` if (!p.startsWith('!')) {
if (p.endsWith(path.sep)) { p = `!${p}`
p = `${p}**`
} }
return p return p
}) })
.join('\n')
core.debug(`files ignore patterns: ${filesIgnorePatterns.join('\n')}`) core.debug(`files ignore patterns: ${filesIgnorePatterns}`)
cleanedFilePatterns.push(...filesIgnorePatterns) filePatterns = filePatterns.concat('\n', filesIgnorePatterns)
} }
if (inputs.filesIgnoreFromSourceFile) { if (inputs.filesIgnoreFromSourceFile) {
const inputFilesIgnoreFromSourceFile = inputs.filesIgnoreFromSourceFile const inputFilesIgnoreFromSourceFile = inputs.filesIgnoreFromSourceFile
.split(inputs.filesIgnoreFromSourceFileSeparator) .split(inputs.filesIgnoreFromSourceFileSeparator)
.filter(Boolean) .filter(p => p !== '')
.map(p => path.join(workingDirectory, p)) .map(p => path.join(workingDirectory, p))
core.debug( core.debug(
`files ignore from source file: ${inputFilesIgnoreFromSourceFile}` `files ignore from source file: ${inputFilesIgnoreFromSourceFile}`
) )
const filesIgnoreFromSourceFiles = await getFilesFromSourceFile({ const filesIgnoreFromSourceFiles = (
await getFilesFromSourceFile({
filePaths: inputFilesIgnoreFromSourceFile, filePaths: inputFilesIgnoreFromSourceFile,
excludedFiles: true excludedFiles: true
}) })
).join('\n')
core.debug( core.debug(
`files ignore from source files patterns: ${filesIgnoreFromSourceFiles.join( `files ignore from source files patterns: ${filesIgnoreFromSourceFiles}`
'\n'
)}`
) )
cleanedFilePatterns.push(...filesIgnoreFromSourceFiles) filePatterns = filePatterns.concat('\n', filesIgnoreFromSourceFiles)
}
if (inputs.negationPatternsFirst) {
cleanedFilePatterns.sort((a, b) => {
return a.startsWith('!') ? -1 : b.startsWith('!') ? 1 : 0
})
}
// Reorder file patterns '**' should come first
if (cleanedFilePatterns.includes('**')) {
cleanedFilePatterns.sort((a, b) => {
return a === '**' ? -1 : b === '**' ? 1 : 0
})
} }
if (isWindows()) { if (isWindows()) {
cleanedFilePatterns = cleanedFilePatterns.map(pattern => filePatterns = filePatterns.replace(/\r\n/g, '\n')
pattern.replace(/\r\n/g, '\n').replace(/\r/g, '\n') filePatterns = filePatterns.replace(/\r/g, '\n')
)
} }
core.debug(`Input file patterns: \n${cleanedFilePatterns.join('\n')}`) core.debug(`Input file patterns: ${filePatterns}`)
return cleanedFilePatterns return filePatterns
.trim()
.split('\n')
.filter(Boolean)
.map(pattern => {
if (pattern.endsWith('/')) {
return `${pattern}**`
} else {
const pathParts = pattern.split('/')
const lastPart = pathParts[pathParts.length - 1]
if (!lastPart.includes('.')) {
return `${pattern}/**`
} else {
return pattern
}
}
})
} }
// Example YAML input: // Example YAML input:
@ -1177,7 +1070,7 @@ const getYamlFilePatternsFromContents = async ({
throw new Error(`File does not exist: ${filePath}`) throw new Error(`File does not exist: ${filePath}`)
} }
source = await fs.readFile(filePath, 'utf8') source = await readFile(filePath, 'utf8')
} else { } else {
source = content source = content
} }
@ -1258,11 +1151,16 @@ export const getYamlFilePatterns = async ({
const newFilePatterns = await getYamlFilePatternsFromContents({filePath}) const newFilePatterns = await getYamlFilePatternsFromContents({filePath})
for (const key in newFilePatterns) { for (const key in newFilePatterns) {
if (key in filePatterns) { if (key in filePatterns) {
filePatterns[key] = [...filePatterns[key], ...newFilePatterns[key]] core.warning(
} else { `files_yaml_from_source_file: Duplicated key ${key} detected in ${filePath}, the ${filePatterns[key]} will be overwritten by ${newFilePatterns[key]}.`
filePatterns[key] = newFilePatterns[key] )
} }
} }
filePatterns = {
...filePatterns,
...newFilePatterns
}
} }
} }
@ -1274,12 +1172,9 @@ export const getYamlFilePatterns = async ({
for (const key in newIgnoreFilePatterns) { for (const key in newIgnoreFilePatterns) {
if (key in filePatterns) { if (key in filePatterns) {
filePatterns[key] = [ core.warning(
...filePatterns[key], `files_ignore_yaml: Duplicated key ${key} detected, the ${filePatterns[key]} will be overwritten by ${newIgnoreFilePatterns[key]}.`
...newIgnoreFilePatterns[key] )
]
} else {
filePatterns[key] = newIgnoreFilePatterns[key]
} }
} }
} }
@ -1303,14 +1198,16 @@ export const getYamlFilePatterns = async ({
for (const key in newIgnoreFilePatterns) { for (const key in newIgnoreFilePatterns) {
if (key in filePatterns) { if (key in filePatterns) {
filePatterns[key] = [ core.warning(
...filePatterns[key], `files_ignore_yaml_from_source_file: Duplicated key ${key} detected in ${filePath}, the ${filePatterns[key]} will be overwritten by ${newIgnoreFilePatterns[key]}.`
...newIgnoreFilePatterns[key] )
]
} else {
filePatterns[key] = newIgnoreFilePatterns[key]
} }
} }
filePatterns = {
...filePatterns,
...newIgnoreFilePatterns
}
} }
} }
@ -1369,8 +1266,7 @@ export const setArrayOutput = async ({
writeOutputFiles: inputs.writeOutputFiles, writeOutputFiles: inputs.writeOutputFiles,
outputDir: inputs.outputDir, outputDir: inputs.outputDir,
json: inputs.json, json: inputs.json,
shouldEscape: inputs.escapeJson, shouldEscape: inputs.escapeJson
safeOutput: inputs.safeOutput
}) })
} }
@ -1380,8 +1276,7 @@ export const setOutput = async ({
writeOutputFiles, writeOutputFiles,
outputDir, outputDir,
json = false, json = false,
shouldEscape = false, shouldEscape = false
safeOutput = false
}: { }: {
key: string key: string
value: string | string[] | boolean value: string | string[] | boolean
@ -1389,7 +1284,6 @@ export const setOutput = async ({
outputDir: string outputDir: string
json?: boolean json?: boolean
shouldEscape?: boolean shouldEscape?: boolean
safeOutput?: boolean
}): Promise<void> => { }): Promise<void> => {
let cleanedValue let cleanedValue
if (json) { if (json) {
@ -1398,11 +1292,6 @@ export const setOutput = async ({
cleanedValue = value.toString().trim() cleanedValue = value.toString().trim()
} }
// if safeOutput is true, escape special characters for bash shell
if (safeOutput) {
cleanedValue = cleanedValue.replace(/[^\x20-\x7E]|[:*?<>|;`$()&!]/g, '\\$&')
}
core.setOutput(key, cleanedValue) core.setOutput(key, cleanedValue)
if (writeOutputFiles) { if (writeOutputFiles) {
@ -1449,17 +1338,13 @@ export const recoverDeletedFiles = async ({
workingDirectory, workingDirectory,
deletedFiles, deletedFiles,
recoverPatterns, recoverPatterns,
diffResult, sha
diffSubmodule,
submodulePaths
}: { }: {
inputs: Inputs inputs: Inputs
workingDirectory: string workingDirectory: string
deletedFiles: string[] deletedFiles: string[]
recoverPatterns: string[] recoverPatterns: string[]
diffResult: DiffResult sha: string
diffSubmodule: boolean
submodulePaths: string[]
}): Promise<void> => { }): Promise<void> => {
let recoverableDeletedFiles = deletedFiles let recoverableDeletedFiles = deletedFiles
core.debug(`recoverable deleted files: ${recoverableDeletedFiles}`) core.debug(`recoverable deleted files: ${recoverableDeletedFiles}`)
@ -1484,64 +1369,19 @@ export const recoverDeletedFiles = async ({
) )
} }
let deletedFileContents: string const deletedFileContents = await getDeletedFileContents({
const submodulePath = submodulePaths.find(p => deletedFile.startsWith(p))
if (diffSubmodule && submodulePath) {
const submoduleShaResult = await gitSubmoduleDiffSHA({
cwd: workingDirectory,
parentSha1: diffResult.previousSha,
parentSha2: diffResult.currentSha,
submodulePath,
diff: diffResult.diff
})
if (submoduleShaResult.previousSha) {
core.debug(
`recovering deleted file "${deletedFile}" from submodule ${submodulePath} from ${submoduleShaResult.previousSha}`
)
deletedFileContents = await getDeletedFileContents({
cwd: path.join(workingDirectory, submodulePath),
// E.g. submodulePath = test/demo and deletedFile = test/demo/.github/README.md => filePath => .github/README.md
filePath: deletedFile.replace(submodulePath, '').substring(1),
sha: submoduleShaResult.previousSha
})
} else {
core.warning(
`Unable to recover deleted file "${deletedFile}" from submodule ${submodulePath} from ${submoduleShaResult.previousSha}`
)
continue
}
} else {
core.debug(
`recovering deleted file "${deletedFile}" from ${diffResult.previousSha}`
)
deletedFileContents = await getDeletedFileContents({
cwd: workingDirectory, cwd: workingDirectory,
filePath: deletedFile, filePath: deletedFile,
sha: diffResult.previousSha sha
}) })
}
core.debug(`recovered deleted file "${deletedFile}"`)
if (!(await exists(path.dirname(target)))) { if (!(await exists(path.dirname(target)))) {
core.debug(`creating directory "${path.dirname(target)}"`)
await fs.mkdir(path.dirname(target), {recursive: true}) await fs.mkdir(path.dirname(target), {recursive: true})
} }
core.debug(`writing file "${target}"`)
await fs.writeFile(target, deletedFileContents) await fs.writeFile(target, deletedFileContents)
core.debug(`wrote file "${target}"`)
} }
} }
/**
* Determines whether the specified working directory has a local Git directory.
*
* @param workingDirectory - The path of the working directory.
* @returns A boolean value indicating whether the working directory has a local Git directory.
*/
export const hasLocalGitDirectory = async ({ export const hasLocalGitDirectory = async ({
workingDirectory workingDirectory
}: { }: {
@ -1551,33 +1391,3 @@ export const hasLocalGitDirectory = async ({
cwd: workingDirectory cwd: workingDirectory
}) })
} }
/**
* Warns about unsupported inputs when using the REST API.
*
* @param inputs - The inputs object.
*/
export const warnUnsupportedRESTAPIInputs = async ({
inputs
}: {
inputs: Inputs
}): Promise<void> => {
for (const key of Object.keys(DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS)) {
const defaultValue = Object.hasOwnProperty.call(
DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS,
key
)
? DEFAULT_VALUES_OF_UNSUPPORTED_API_INPUTS[
key as keyof Inputs
]?.toString()
: ''
if (defaultValue !== inputs[key as keyof Inputs]?.toString()) {
core.warning(
`Input "${snakeCase(
key
)}" is not supported when using GitHub's REST API to get changed files`
)
}
}
}

View File

@ -1 +0,0 @@
This is a test markdown file

View File

@ -1 +1 @@
This is a test file... This is a test file.

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"outDir": "./lib", /* Redirect output structure to the directory. */ "outDir": "./lib", /* Redirect output structure to the directory. */
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */

3036
yarn.lock

File diff suppressed because it is too large Load Diff