Compare commits

..

1 Commits

Author SHA1 Message Date
Tonye Jack
fd2e9917c3 Updated separator 2022-02-16 22:59:19 -05:00
57 changed files with 1322 additions and 23854 deletions

View File

@@ -87,106 +87,6 @@
"contributions": [
"code"
]
},
{
"login": "fagai",
"name": "fagai",
"avatar_url": "https://avatars.githubusercontent.com/u/1772112?v=4",
"profile": "https://fagai.net",
"contributions": [
"doc"
]
},
{
"login": "pkit",
"name": "Constantine Peresypkin",
"avatar_url": "https://avatars.githubusercontent.com/u/805654?v=4",
"profile": "https://github.com/pkit",
"contributions": [
"code"
]
},
{
"login": "deronnax",
"name": "Mathieu Dupuy",
"avatar_url": "https://avatars.githubusercontent.com/u/439279?v=4",
"profile": "https://github.com/deronnax",
"contributions": [
"doc"
]
},
{
"login": "JoeOvo",
"name": "Joe Moggridge",
"avatar_url": "https://avatars.githubusercontent.com/u/100686542?v=4",
"profile": "https://github.com/JoeOvo",
"contributions": [
"doc"
]
},
{
"login": "thyarles",
"name": "Charles Santos",
"avatar_url": "https://avatars.githubusercontent.com/u/1340046?v=4",
"profile": "https://www.credly.com/users/thyarles/badges",
"contributions": [
"code"
]
},
{
"login": "kostiantyn-korniienko-aurea",
"name": "Kostiantyn Korniienko",
"avatar_url": "https://avatars.githubusercontent.com/u/37180625?v=4",
"profile": "https://github.com/kostiantyn-korniienko-aurea",
"contributions": [
"doc"
]
},
{
"login": "lpulley",
"name": "Logan Pulley",
"avatar_url": "https://avatars.githubusercontent.com/u/7193187?v=4",
"profile": "https://github.com/lpulley",
"contributions": [
"code"
]
},
{
"login": "kenji-miyake",
"name": "Kenji Miyake",
"avatar_url": "https://avatars.githubusercontent.com/u/31987104?v=4",
"profile": "https://www.linkedin.com/in/kenji-miyake/",
"contributions": [
"code"
]
},
{
"login": "adonisgarciac",
"name": "adonisgarciac",
"avatar_url": "https://avatars.githubusercontent.com/u/71078987?v=4",
"profile": "https://github.com/adonisgarciac",
"contributions": [
"code",
"doc"
]
},
{
"login": "cfernhout",
"name": "Chiel Fernhout",
"avatar_url": "https://avatars.githubusercontent.com/u/22294606?v=4",
"profile": "https://github.com/cfernhout",
"contributions": [
"doc"
]
},
{
"login": "albertoperdomo2",
"name": "Alberto Perdomo",
"avatar_url": "https://avatars.githubusercontent.com/u/62241095?v=4",
"profile": "https://github.com/albertoperdomo2",
"contributions": [
"doc"
]
}
],
"contributorsPerLine": 7,
@@ -194,6 +94,5 @@
"projectOwner": "tj-actions",
"repoType": "github",
"repoHost": "https://github.com",
"skipCi": true,
"commitConvention": "angular"
"skipCi": true
}

View File

@@ -1,4 +0,0 @@
dist/
lib/
node_modules/
jest.config.js

View File

@@ -1,81 +0,0 @@
{
"plugins": [
"jest",
"@typescript-eslint"
],
"extends": [
"plugin:github/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 9,
"sourceType": "module",
"project": "./tsconfig.json"
},
"rules": {
"i18n-text/no-en": "off",
"eslint-comments/no-use": "off",
"import/no-namespace": "off",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/explicit-member-accessibility": [
"error",
{
"accessibility": "no-public"
}
],
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/array-type": "error",
"@typescript-eslint/await-thenable": "error",
"@typescript-eslint/ban-ts-comment": "off",
"camelcase": "off",
"@typescript-eslint/consistent-type-assertions": "error",
"@typescript-eslint/explicit-function-return-type": [
"error",
{
"allowExpressions": true
}
],
"@typescript-eslint/func-call-spacing": [
"error",
"never"
],
"@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-namespace": "error",
"@typescript-eslint/no-non-null-assertion": "warn",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
"@typescript-eslint/no-useless-constructor": "error",
"@typescript-eslint/no-var-requires": "error",
"@typescript-eslint/prefer-for-of": "warn",
"@typescript-eslint/prefer-function-type": "warn",
"@typescript-eslint/prefer-includes": "error",
"@typescript-eslint/prefer-string-starts-ends-with": "error",
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-array-sort-compare": "error",
"@typescript-eslint/restrict-plus-operands": "error",
"semi": "off",
"filenames/match-regex": [
"error",
"^[a-zA-Z0-9\\-.]+$",
true
],
"@typescript-eslint/semi": [
"error",
"never"
],
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error"
},
"env": {
"node": true,
"es6": true,
"jest/globals": true
}
}

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
dist/** -diff linguist-generated=true

View File

@@ -69,14 +69,8 @@ body:
id: logs
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output which is obtained after enabling debug logging. This will be automatically formatted into code, so no need for backticks.
placeholder: |
1. Re-running the workflow with debug logging enabled.
2. Copy or download the log archive.
3. Paste the contents here or upload the file in a subsequent comment.
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: true
- type: textarea
attributes:
label: Anything else?

View File

@@ -53,7 +53,7 @@ body:
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](../blob/main/CODE_OF_CONDUCT.md)
description: By submitting this issue, you agree to follow our [Code of Conduct](./CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true

View File

@@ -3,12 +3,11 @@ name: Auto approve
on:
pull_request_target
jobs:
auto-approve:
runs-on: ubuntu-latest
steps:
- uses: hmarr/auto-approve-action@v3
- uses: hmarr/auto-approve-action@v2
if: |
(
github.event.pull_request.user.login == 'dependabot[bot]' ||

View File

@@ -16,7 +16,7 @@ jobs:
github.actor == 'renovate'
steps:
- name: automerge
uses: pascalgn/automerge-action@v0.15.6
uses: pascalgn/automerge-action@v0.14.3
env:
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
MERGE_METHOD: "rebase"

View File

@@ -19,22 +19,16 @@ on:
jobs:
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
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v2
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
continue-on-error: true
uses: codacy/codacy-analysis-cli-action@v4.3.0
uses: codacy/codacy-analysis-cli-action@4.0.0
with:
# 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
@@ -45,12 +39,11 @@ jobs:
# Adjust severity of non-security issues
gh-code-scanning-compat: true
# Force 0 exit code to allow SARIF file generation
# This will hand over control about PR rejection to the GitHub side
# This will handover control about PR rejection to the GitHub side
max-allowed-issues: 2147483647
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
continue-on-error: true
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif

View File

@@ -1,74 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '44 20 * * 0'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# 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)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# 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
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

View File

@@ -6,8 +6,8 @@ jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
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."
pr-message: "Thanks for implementing a fix, could you ensure that the test covers your changes if applicable."
- uses: actions/first-interaction@v1.1.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: "Thanks for reporting this issue, don't forget to star this project to help us reach a wider audience."
pr-message: "Thanks for implementing a fix. Could you ensure that the test covers your changes."

19
.github/workflows/label-conflict.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: "Maintenance"
on:
push:
branches:
- main
pull_request:
types: [synchronize]
jobs:
main:
runs-on: ubuntu-latest
steps:
- name: check if prs are dirty
uses: eps1lon/actions-label-merge-conflict@releases/2.x
with:
dirtyLabel: "PR: needs rebase"
repoToken: "${{ secrets.GITHUB_TOKEN }}"
commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request."
commentOnClean: "Conflicts have been resolved."

View File

@@ -1,53 +0,0 @@
name: Manual Test
on:
workflow_dispatch:
jobs:
test:
name: Test changed-files
runs-on: ${{ matrix.platform }}
strategy:
fail-fast: false
max-parallel: 7
matrix:
platform: [ubuntu-latest, ubuntu-22.04, windows-latest, macos-latest, macos-11, ubuntu-18.04, windows-2022]
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
- name: Run changed-files with defaults
id: changed-files
uses: ./
- name: Show output
run: |
echo '${{ toJSON(steps.changed-files.outputs) }}'
- name: Run changed-files with glob filtering
id: changed-files-glob
uses: ./
with:
files: |
test/*.txt
- name: Show output
run: |
echo '${{ toJSON(steps.changed-files-glob.outputs) }}'
- name: Run changed-files with glob filtering and all_old_new_renamed_files
id: changed-files-glob-all-old-new-renamed-files
uses: ./
with:
include_all_old_new_renamed_files: true
files: |
test/*.txt
- name: Show output
run: |
echo '${{ toJSON(steps.changed-files-glob-all-old-new-renamed-files.outputs) }}'

View File

@@ -1,44 +0,0 @@
name: Matrix Test
on:
workflow_dispatch:
pull_request:
branches:
- main
jobs:
changed-files:
name: Get changes
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: ./
with:
json: true
quotepath: false
- name: List all changed files
run: echo '${{ steps.changed-files.outputs.all_changed_files }}'
- id: set-matrix
run: echo "matrix={\"container\":${{ steps.changed-files.outputs.all_changed_files }}}" >> "$GITHUB_OUTPUT"
matrix-job:
name: Run Matrix Job
runs-on: ubuntu-latest
needs: [changed-files]
strategy:
matrix: ${{ fromJSON(needs.changed-files.outputs.matrix) }}
max-parallel: 4
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Test
run: |
echo ${{ matrix.container }}

18
.github/workflows/rebase.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: Automatic Rebase
on:
issue_comment:
types: [created]
jobs:
rebase:
name: Rebase
if: github.event.issue.pull_request != '' && contains(github.event.comment.body, '/rebase')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2.4.0
with:
token: ${{ secrets.PAT_TOKEN }}
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
- name: Automatic Rebase
uses: cirrus-actions/rebase@1.5
env:
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}

View File

@@ -1,29 +0,0 @@
on:
workflow_dispatch:
jobs:
sync:
name: Submodule Sync
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
submodules: recursive
- name: Git Sumbodule Update
run: |
git pull --recurse-submodules
git submodule update --remote --recursive
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.1
with:
title: "Updated submodule"
labels: "merge when passing"
branch: "chore/update-submodule"
commit-message: "Updated submodule"
body: "Updated submodule"
token: ${{ secrets.PAT_TOKEN }}

View File

@@ -8,26 +8,24 @@ jobs:
update-version:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2.4.0
with:
fetch-depth: 0
- name: Run release-tagger
uses: tj-actions/release-tagger@v3
- name: Sync release version.
uses: tj-actions/sync-release-version@v13
uses: tj-actions/sync-release-version@v9
id: sync-release-version
with:
pattern: '${{ github.repository }}@'
only_major: true
paths: |
README.md
- name: Run git-cliff
uses: tj-actions/git-cliff@v1
- name: Generate CHANGELOG
uses: tj-actions/github-changelog-generator@v1.11
with:
output: 'HISTORY.md'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.1
uses: peter-evans/create-pull-request@v3.12.1
with:
base: "main"
labels: "merge when passing"
title: "Upgraded to ${{ steps.sync-release-version.outputs.new_version }}"
branch: "upgrade-to-${{ steps.sync-release-version.outputs.new_version }}"
commit-message: "Upgraded from ${{ steps.sync-release-version.outputs.old_version }} -> ${{ steps.sync-release-version.outputs.new_version }}"

File diff suppressed because it is too large Load Diff

View File

@@ -9,18 +9,15 @@ jobs:
sync-assets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2.4.0
with:
fetch-depth: 0
- name: Run auto-doc
uses: tj-actions/auto-doc@v2
- name: Run remark
uses: tj-actions/remark@v3
- name: Run test
uses: tj-actions/remark@v2.3
- name: Verify Changed files
uses: tj-actions/verify-changed-files@v14
uses: tj-actions/verify-changed-files@v8
id: verify_changed_files
with:
files: |
@@ -29,15 +26,14 @@ jobs:
- name: README.md changed
if: steps.verify_changed_files.outputs.files_changed == 'true'
run: |
echo "README.md has uncommitted changes"
echo "README.md has uncommited changes"
exit 1
- name: Create Pull Request
if: failure()
uses: peter-evans/create-pull-request@v5
uses: peter-evans/create-pull-request@v3.12.1
with:
base: "main"
labels: "merge when passing"
title: "Updated README.md"
branch: "chore/update-readme"
commit-message: "Updated README.md"

109
.gitignore vendored
View File

@@ -1,107 +1,4 @@
# Dependency directory
node_modules
# Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
./.env
.env/../.env
./.env.local
./.env/../.env.local
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# next.js build output
.next
# nuxt.js build output
.nuxt
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# OS metadata
.DS_Store
Thumbs.db
# Ignore built ts files
__tests__/runner/*
lib/**/*
# IDEA
.idea/
.envrc
tag.sh
untag.sh

3
.gitmodules vendored
View File

@@ -1,3 +0,0 @@
[submodule "test/demo"]
path = test/demo
url = git@github.com:tj-actions/demo.git

1
.nvmrc
View File

@@ -1 +0,0 @@
16

View File

@@ -1,3 +0,0 @@
dist/
lib/
node_modules/

View File

@@ -1,10 +0,0 @@
{
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"bracketSpacing": false,
"arrowParens": "avoid"
}

6378
HISTORY.md

File diff suppressed because it is too large Load Diff

907
README.md

File diff suppressed because it is too large Load Diff

View File

@@ -1,165 +1,145 @@
name: Changed Files
description: Get all Added, Copied, Modified, Deleted, Renamed, Type changed, Unmerged, Unknown files.
name: Changed files
description: Get all changed files for push and pull request events.
author: tj-actions
inputs:
token:
description: 'Github token'
required: true
default: ${{ github.token }}
separator:
description: "Split character for output strings"
required: false
default: " "
include_all_old_new_renamed_files:
description: "Include `all_old_new_renamed_files` output. Note this can generate a large output See: [#501](https://github.com/tj-actions/changed-files/issues/501)."
required: false
default: "false"
old_new_separator:
description: "Split character for old and new filename pairs."
required: false
default: ","
old_new_files_separator:
description: "Split character for old and new renamed filename pairs."
required: false
description: 'Split character for array output'
required: true
default: " "
files_from_source_file:
description: "Source file(s) used to populate the `files` input."
description: 'Source file to populate the files input'
required: false
default: ""
files_from_source_file_separator:
description: 'Separator used to split the `files_from_source_file` input'
default: "\n"
required: false
files:
description: "File and directory patterns to detect changes using only these list of file(s) (Defaults to the entire repo) **NOTE:** Multiline file/directory patterns should not include quotes."
description: 'Check for changes using only this list of files (Defaults to the entire repo)'
required: false
default: ""
files_separator:
description: "Separator used to split the `files` input"
default: "\n"
required: false
files_ignore:
description: "Ignore changes to these file(s) **NOTE:** Multiline file/directory patterns should not include quotes."
required: false
default: ""
files_ignore_separator:
description: "Separator used to split the `files_ignore` input"
default: "\n"
required: false
files_ignore_from_source_file:
description: "Source file(s) used to populate the `files_ignore` input"
required: false
default: ""
files_ignore_from_source_file_separator:
description: 'Separator used to split the `files_ignore_from_source_file` input'
files-separator:
description: 'Separator used to split the files input'
default: "\n"
required: false
sha:
description: "Specify a different commit SHA used for comparing changes"
required: false
description: 'Specify a current commit SHA used for comparing changes'
required: true
default: ${{ github.sha }}
base_sha:
description: "Specify a different base commit SHA used for comparing changes"
description: 'Specify a base commit SHA on used for comparing changes'
required: false
since:
description: "Get changed files for commits whose timestamp is older than the given time."
required: false
default: ""
until:
description: "Get changed files for commits whose timestamp is earlier than the given time."
required: false
default: ""
path:
description: "Specify a relative path under `$GITHUB_WORKSPACE` to locate the repository."
required: false
default: "."
quotepath:
description: "Use non ascii characters to match files and output the filenames completely verbatim by setting this to `false`"
default: "true"
required: false
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."
required: false
default: "true"
dir_names:
default: "false"
description: "Output unique changed directories instead of filenames. **NOTE:** This returns `.` for changed files located in the root of the project."
required: false
dir_names_max_depth:
description: "Maximum depth of directories to output. e.g `test/test1/test2` with max depth of `2` returns `test/test1`."
required: false
dir_names_exclude_root:
description: "Exclude the root directory represented by `.` from the output when `dir_names`is set to `true`."
required: false
default: "false"
json:
description: "Output list of changed files in a JSON formatted string which can be used for matrix jobs."
required: false
default: "false"
escape_json:
description: "Escape JSON output."
required: false
default: "true"
fetch_depth:
description: "Depth of additional branch history fetched. **NOTE**: This can be adjusted to resolve errors with insufficient history."
required: false
default: "50"
since_last_remote_commit:
description: "Use the last commit on the remote branch as the `base_sha`. Defaults to the last non merge commit on the target branch for pull request events and the previous remote commit of the current branch for push events."
description: 'Use the last commit on the remote branch as the base_sha for push event.'
required: false
default: "false"
write_output_files:
description: "Write outputs to files in the `.github/outputs` folder by default."
default: 'false'
path:
description: 'Specify a relative path under $GITHUB_WORKSPACE to locate the repository'
required: false
default: "false"
output_dir:
description: "Directory to store output files."
required: false
default: ".github/outputs"
outputs:
added_files:
description: "Returns only files that are Added (A)."
description: List of added files.
value: ${{ steps.changed-files.outputs.added_files }}
copied_files:
description: "Returns only files that are Copied (C)."
description: List of copied files.
value: ${{ steps.changed-files.outputs.copied_files }}
deleted_files:
description: "Returns only files that are Deleted (D)."
description: List of deleted files.
value: ${{ steps.changed-files.outputs.deleted_files }}
modified_files:
description: "Returns only files that are Modified (M)."
description: List of modified files.
value: ${{ steps.changed-files.outputs.modified_files }}
renamed_files:
description: "Returns only files that are Renamed (R)."
all_old_new_renamed_files:
description: "Returns only files that are Renamed and list their old and new names. **NOTE:** This requires setting `include_all_old_new_renamed_files` to `true` (R)"
description: List of renamed files.
value: ${{ steps.changed-files.outputs.renamed_files }}
type_changed_files:
description: "Returns only files that have their file type changed (T)."
description: List of files that had type changes.
value: ${{ steps.changed-files.outputs.type_changed_files }}
unmerged_files:
description: "Returns only files that are Unmerged (U)."
description: List of unmerged files.
value: ${{ steps.changed-files.outputs.unmerged_files }}
unknown_files:
description: "Returns only files that are Unknown (X)."
description: List of unknown files.
value: ${{ steps.changed-files.outputs.unknown_files }}
all_changed_and_modified_files:
description: "Returns all changed and modified files i.e. *a combination of (ACMRDTUX)*"
description: List of all changed files.
value: ${{ steps.changed-files.outputs.all_changed_and_modified_files }}
all_changed_files:
description: "Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)*"
description: List of all copied, modified, and added files.
value: ${{ steps.changed-files.outputs.all_changed_files }}
any_changed:
description: "Returns `true` when any of the filenames provided using the `files` input has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
description: Return true only when any files provided using the files input have changed.
value: ${{ steps.changed-files.outputs.any_changed }}
only_changed:
description: "Returns `true` when only files provided using the `files` input has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
description: Return true when all files provided using the files input have changed.
value: ${{ steps.changed-files.outputs.only_changed }}
other_changed_files:
description: "Returns all other changed files not listed in the files input i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*."
description: Return list of changed files not listed in the files input.
value: ${{ steps.changed-files.outputs.other_changed_files }}
all_modified_files:
description: "Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*."
description: List of all copied, modified, added and deleted files.
value: ${{ steps.changed-files.outputs.all_modified_files }}
any_modified:
description: "Returns `true` when any of the filenames provided using the `files` input has been modified. i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*."
description: Return true only when any files provided using the files input have been modified.
value: ${{ steps.changed-files.outputs.any_modified }}
only_modified:
description: "Returns `true` when only files provided using the `files` input has been modified. (ACMRD)."
description: Return true when all files provided using the files input have been modified.
value: ${{ steps.changed-files.outputs.only_modified }}
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: Return list of modified files not listed in the files input.
value: ${{ steps.changed-files.outputs.other_modified_files }}
any_deleted:
description: "Returns `true` when any of the filenames provided using the `files` input has been deleted. (D)"
description: Return true only when any files provided using the files input have been deleted.
value: ${{ steps.changed-files.outputs.any_deleted }}
only_deleted:
description: "Returns `true` when only files provided using the `files` input has been deleted. (D)"
description: Return true when all files provided using the files input have been deleted.
value: ${{ steps.changed-files.outputs.only_deleted }}
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: Return list of deleted files not listed in the files input.
value: ${{ steps.changed-files.outputs.other_deleted_files }}
runs:
using: 'node16'
main: 'dist/index.js'
using: 'composite'
steps:
- run: |
# "Set base sha..."
if [[ -n "${{ inputs.base_sha }}" ]]; then
echo "::set-output name=base_sha::${{ inputs.base_sha }}"
elif [[ "${{ inputs.since_last_remote_commit }}" == "true" ]]; then
if [[ "${{ github.event.before }}" != "0000000000000000000000000000000000000000" ]]; then
echo "::set-output name=base_sha::${{ github.event.before }}"
else
echo "::set-output name=base_sha::${{ github.sha }}"
fi
fi
id: base-sha
shell: bash
- name: Glob match
uses: tj-actions/glob@v6
id: glob
with:
files: ${{ inputs.files }}
files-separator: ${{ inputs.files-separator }}
files-from-source-file: ${{ inputs.files_from_source_file }}
separator: "|"
- run: |
bash $GITHUB_ACTION_PATH/entrypoint.sh
id: changed-files
shell: bash
env:
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_BASE_REF: ${{ github.base_ref }}
# INPUT_<VARIABLE_NAME> is not available in Composite run steps
# https://github.community/t/input-variable-name-is-not-available-in-composite-run-steps/127611
INPUT_SHA: ${{ inputs.sha }}
INPUT_BASE_SHA: ${{ steps.base-sha.outputs.base_sha }}
INPUT_TOKEN: ${{ inputs.token }}
INPUT_FILES_PATTERN: ${{ steps.glob.outputs.paths }}
INPUT_SEPARATOR: ${{ inputs.separator }}
INPUT_PATH: ${{ inputs.path }}
branding:
icon: file-text

9872
dist/index.js vendored

File diff suppressed because it is too large Load Diff

1
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

247
dist/licenses.txt vendored
View File

@@ -1,247 +0,0 @@
@actions/core
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/exec
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/http-client
MIT
Actions Http Client for Node.js
Copyright (c) GitHub, Inc.
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@actions/io
MIT
The MIT License (MIT)
Copyright 2019 GitHub
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
braces
MIT
The MIT License (MIT)
Copyright (c) 2014-2018, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
fill-range
MIT
The MIT License (MIT)
Copyright (c) 2014-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
is-number
MIT
The MIT License (MIT)
Copyright (c) 2014-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
micromatch
MIT
The MIT License (MIT)
Copyright (c) 2014-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
picomatch
MIT
The MIT License (MIT)
Copyright (c) 2017-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
to-regex-range
MIT
The MIT License (MIT)
Copyright (c) 2015-present, Jon Schlinkert.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
tunnel
MIT
The MIT License (MIT)
Copyright (c) 2012 Koichi Kobayashi
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
uuid
MIT
The MIT License (MIT)
Copyright (c) 2010-2020 Robert Kieffer and other contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

File diff suppressed because one or more lines are too long

253
entrypoint.sh Executable file
View File

@@ -0,0 +1,253 @@
#!/usr/bin/env bash
set -eu
echo "::group::changed-files"
echo "Resolving repository path..."
if [[ -n $INPUT_PATH ]]; then
REPO_DIR="$GITHUB_WORKSPACE/$INPUT_PATH"
if [[ ! -d "$REPO_DIR" ]]; then
echo "::warning::Invalid repository path"
exit 1
fi
cd "$REPO_DIR"
fi
SERVER_URL=$(echo "$GITHUB_SERVER_URL" | awk -F/ '{print $3}')
echo "Setting up 'temp_changed_files' remote..."
git ls-remote --exit-code temp_changed_files 1>/dev/null 2>&1 && exit_status=$? || exit_status=$?
if [[ $exit_status -ne 0 ]]; then
echo "No 'temp_changed_files' remote found"
echo "Creating 'temp_changed_files' remote..."
git remote remove temp_changed_files 2>/dev/null || true
git remote add temp_changed_files "https://${INPUT_TOKEN}@${SERVER_URL}/${GITHUB_REPOSITORY}"
else
echo "Found 'temp_changed_files' remote"
fi
echo "Getting HEAD info..."
if [[ -z $INPUT_SHA ]]; then
CURRENT_SHA=$(git rev-parse HEAD 2>&1) && exit_status=$? || exit_status=$?
else
CURRENT_SHA=$INPUT_SHA && exit_status=$? || exit_status=$?
fi
git rev-parse --quiet --verify "$CURRENT_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$?
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to locate the current sha: $CURRENT_SHA"
echo "::warning::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage"
git remote remove temp_changed_files
exit 1
fi
if [[ -z $GITHUB_BASE_REF ]]; then
TARGET_BRANCH=${GITHUB_REF/refs\/heads\//}
CURRENT_BRANCH=$TARGET_BRANCH
if [[ -z $INPUT_BASE_SHA ]]; then
PREVIOUS_SHA=$(git rev-parse HEAD^1 2>&1) && exit_status=$? || exit_status=$?
else
PREVIOUS_SHA=$INPUT_BASE_SHA && exit_status=$? || exit_status=$?
TARGET_BRANCH=$(git name-rev --name-only "$PREVIOUS_SHA" 2>&1) && exit_status=$? || exit_status=$?
fi
git rev-parse --quiet --verify "$PREVIOUS_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$?
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to locate the previous sha: $PREVIOUS_SHA"
echo "::warning::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage"
git remote remove temp_changed_files
exit 1
fi
else
TARGET_BRANCH=$GITHUB_BASE_REF
CURRENT_BRANCH=$GITHUB_HEAD_REF
if [[ -z $INPUT_BASE_SHA ]]; then
git fetch --no-tags -u --progress --depth=1 temp_changed_files "${TARGET_BRANCH}":"${TARGET_BRANCH}" && exit_status=$? || exit_status=$?
PREVIOUS_SHA=$(git rev-parse "${TARGET_BRANCH}" 2>&1) && exit_status=$? || exit_status=$?
else
git fetch --no-tags -u --progress --depth=1 temp_changed_files "$INPUT_BASE_SHA" && exit_status=$? || exit_status=$?
PREVIOUS_SHA=$INPUT_BASE_SHA
TARGET_BRANCH=$(git name-rev --name-only "$PREVIOUS_SHA" 2>&1) && exit_status=$? || exit_status=$?
fi
git rev-parse --quiet --verify "$PREVIOUS_SHA^{commit}" 1>/dev/null 2>&1 && exit_status=$? || exit_status=$?
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to locate the previous sha: $PREVIOUS_SHA"
echo "::warning::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage"
git remote remove temp_changed_files
exit 1
fi
fi
echo "Retrieving changes between $PREVIOUS_SHA ($TARGET_BRANCH) → $CURRENT_SHA ($CURRENT_BRANCH)"
echo "Getting diff..."
if [[ -z "$INPUT_FILES_PATTERN" ]]; then
ADDED=$(git diff --submodule=diff --diff-filter=A --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
COPIED=$(git diff --submodule=diff --diff-filter=C --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
DELETED=$(git diff --submodule=diff --diff-filter=D --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
MODIFIED=$(git diff --submodule=diff --diff-filter=M --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
RENAMED=$(git diff --submodule=diff --diff-filter=R --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
TYPE_CHANGED=$(git diff --submodule=diff --diff-filter=T --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
UNMERGED=$(git diff --submodule=diff --diff-filter=U --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
UNKNOWN=$(git diff --submodule=diff --diff-filter=X --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED_AND_MODIFIED=$(git diff --submodule=diff --diff-filter="*ACDMRTUX" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED=$(git diff --submodule=diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_MODIFIED=$(git diff --submodule=diff --diff-filter="ACMRD" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
else
echo "Input files pattern: $INPUT_FILES_PATTERN"
FILES_PATTERN="^($INPUT_FILES_PATTERN)$"
ADDED=$(git diff --submodule=diff --diff-filter=A --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
COPIED=$(git diff --submodule=diff --diff-filter=C --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
DELETED=$(git diff --submodule=diff --diff-filter=D --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
MODIFIED=$(git diff --submodule=diff --diff-filter=M --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
RENAMED=$(git diff --submodule=diff --diff-filter=R --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
TYPE_CHANGED=$(git diff --submodule=diff --diff-filter=T --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
UNMERGED=$(git diff --submodule=diff --diff-filter=U --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
UNKNOWN=$(git diff --submodule=diff --diff-filter=X --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED_AND_MODIFIED=$(git diff --submodule=diff --diff-filter="*ACDMRTUX" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED=$(git diff --submodule=diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_MODIFIED=$(git diff --submodule=diff --diff-filter="ACMRD" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "$FILES_PATTERN" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_OTHER_CHANGED=$(git diff --submodule=diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
UNIQUE_ALL_CHANGED=$(echo "${ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${UNIQUE_ALL_CHANGED}" ]]; then
echo "Matching changed files: ${UNIQUE_ALL_CHANGED}"
echo "::set-output name=any_changed::true"
else
echo "::set-output name=any_changed::false"
fi
OTHER_CHANGED=""
if [[ -n $ALL_OTHER_CHANGED ]]; then
if [[ -n "$UNIQUE_ALL_CHANGED" ]]; then
OTHER_CHANGED=$(echo "${ALL_OTHER_CHANGED}|${UNIQUE_ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
else
OTHER_CHANGED=$ALL_OTHER_CHANGED
fi
fi
OTHER_CHANGED=$(echo "${OTHER_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${OTHER_CHANGED}" ]]; then
echo "Non Matching changed files: ${OTHER_CHANGED}"
echo "::set-output name=only_changed::false"
echo "::set-output name=other_changed_files::$OTHER_CHANGED"
elif [[ -n "${UNIQUE_ALL_CHANGED}" ]]; then
echo "::set-output name=only_changed::true"
fi
ALL_OTHER_MODIFIED=$(git diff --diff-filter="ACMRD" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
UNIQUE_ALL_MODIFIED=$(echo "${ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${UNIQUE_ALL_MODIFIED}" ]]; then
echo "Matching modified files: ${UNIQUE_ALL_MODIFIED}"
echo "::set-output name=any_modified::true"
else
echo "::set-output name=any_modified::false"
fi
OTHER_MODIFIED=""
if [[ -n $ALL_OTHER_MODIFIED ]]; then
if [[ -n "$UNIQUE_ALL_MODIFIED" ]]; then
OTHER_MODIFIED=$(echo "${ALL_OTHER_MODIFIED}|${UNIQUE_ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
else
OTHER_MODIFIED=$ALL_OTHER_MODIFIED
fi
fi
OTHER_MODIFIED=$(echo "${OTHER_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${OTHER_MODIFIED}" ]]; then
echo "Non Matching modified files: ${OTHER_MODIFIED}"
echo "::set-output name=only_modified::false"
echo "::set-output name=other_modified_files::$OTHER_MODIFIED"
elif [[ -n "${UNIQUE_ALL_MODIFIED}" ]]; then
echo "::set-output name=only_modified::true"
fi
ALL_OTHER_DELETED=$(git diff --diff-filter=D --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
UNIQUE_ALL_DELETED=$(echo "${DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk '!a[$0]++' | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${UNIQUE_ALL_DELETED}" ]]; then
echo "Matching deleted files: ${UNIQUE_ALL_DELETED}"
echo "::set-output name=any_deleted::true"
else
echo "::set-output name=any_deleted::false"
fi
OTHER_DELETED=""
if [[ -n $ALL_OTHER_DELETED ]]; then
if [[ -n "$UNIQUE_ALL_DELETED" ]]; then
OTHER_DELETED=$(echo "${ALL_OTHER_DELETED}|${UNIQUE_ALL_DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | sort | uniq -u | awk -v d="|" '{s=(NR==1?s:s d)$0}END{print s}')
else
OTHER_DELETED=$ALL_OTHER_DELETED
fi
fi
OTHER_DELETED=$(echo "${OTHER_DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
if [[ -n "${OTHER_DELETED}" ]]; then
echo "Non Matching deleted files: ${OTHER_DELETED}"
echo "::set-output name=only_deleted::false"
echo "::set-output name=other_deleted_files::$OTHER_DELETED"
elif [[ -n "${UNIQUE_ALL_DELETED}" ]]; then
echo "::set-output name=only_deleted::true"
fi
ADDED=$(echo "${ADDED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
COPIED=$(echo "${COPIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
DELETED=$(echo "${DELETED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
MODIFIED=$(echo "${MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
RENAMED=$(echo "${RENAMED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
TYPE_CHANGED=$(echo "${TYPE_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
UNMERGED=$(echo "${UNMERGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
UNKNOWN=$(echo "${UNKNOWN}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED_AND_MODIFIED=$(echo "${ALL_CHANGED_AND_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_CHANGED=$(echo "${ALL_CHANGED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
ALL_MODIFIED=$(echo "${ALL_MODIFIED}" | awk '{gsub(/\|/,"\n"); print $0;}' | awk -v d="$INPUT_SEPARATOR" '{s=(NR==1?s:s d)$0}END{print s}')
fi
echo "Added files: $ADDED"
echo "Copied files: $COPIED"
echo "Deleted files: $DELETED"
echo "Modified files: $MODIFIED"
echo "Renamed files: $RENAMED"
echo "Type Changed files: $TYPE_CHANGED"
echo "Unmerged files: $UNMERGED"
echo "Unknown files: $UNKNOWN"
echo "All changed and modified files: $ALL_CHANGED_AND_MODIFIED"
echo "All changed files: $ALL_CHANGED"
echo "All modified files: $ALL_MODIFIED"
git remote remove temp_changed_files
echo "::set-output name=added_files::$ADDED"
echo "::set-output name=copied_files::$COPIED"
echo "::set-output name=deleted_files::$DELETED"
echo "::set-output name=modified_files::$MODIFIED"
echo "::set-output name=renamed_files::$RENAMED"
echo "::set-output name=type_changed_files::$TYPE_CHANGED"
echo "::set-output name=unmerged_files::$UNMERGED"
echo "::set-output name=unknown_files::$UNKNOWN"
echo "::set-output name=all_changed_and_modified_files::$ALL_CHANGED_AND_MODIFIED"
echo "::set-output name=all_changed_files::$ALL_CHANGED"
echo "::set-output name=all_modified_files::$ALL_MODIFIED"
echo "::endgroup::"

View File

@@ -1,13 +0,0 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true,
testTimeout: 10000,
setupFiles: [
"<rootDir>/jest/setupEnv.cjs"
]
}

View File

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

View File

@@ -1,56 +0,0 @@
{
"name": "@tj-actions/glob",
"version": "17.2.5",
"description": "Glob pattern matching github action",
"main": "lib/main.js",
"publishConfig": {
"registry": "https://npm.pkg.github.com"
},
"scripts": {
"build": "tsc",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "eslint src/**/*.ts",
"lint:fix": "eslint --fix src/**/*.ts",
"package": "ncc build lib/main.js --source-map --license licenses.txt",
"test": "jest --coverage",
"all": "yarn build && yarn format && yarn lint && yarn package && yarn test"
},
"repository": {
"type": "git",
"url": "git+https://github.com/tj-actions/glob.git"
},
"keywords": [
"actions",
"glob",
"github-actions"
],
"author": "Tonye Jack",
"license": "MIT",
"bugs": {
"url": "https://github.com/tj-actions/glob/issues"
},
"homepage": "https://github.com/tj-actions/glob#readme",
"dependencies": {
"@actions/core": "1.10.0",
"@actions/exec": "1.1.1",
"micromatch": "^4.0.5"
},
"devDependencies": {
"@types/jest": "29.5.1",
"@types/micromatch": "^4.0.2",
"@types/node": "20.2.1",
"@types/uuid": "9.0.1",
"@typescript-eslint/eslint-plugin": "5.59.7",
"@typescript-eslint/parser": "5.59.7",
"@vercel/ncc": "0.36.1",
"eslint": "8.41.0",
"eslint-plugin-github": "4.7.0",
"eslint-plugin-jest": "27.2.1",
"eslint-plugin-prettier": "^4.2.1",
"jest": "29.5.0",
"prettier": "2.8.8",
"ts-jest": "29.1.0",
"typescript": "5.0.4"
}
}

View File

@@ -3,12 +3,11 @@
"config:base"
],
"enabled": true,
"prHourlyLimit": 30,
"prConcurrentLimit": 10,
"prHourlyLimit": 10,
"prConcurrentLimit": 5,
"rebaseWhen": "behind-base-branch",
"addLabels": [
"dependencies",
"merge when passing"
"dependencies"
],
"assignees": [
"jackton1"

View File

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

View File

@@ -1,143 +0,0 @@
import * as path from 'path'
import {DiffResult} from './commitSha'
import {Inputs} from './inputs'
import {
getDirnameMaxDepth,
gitDiff,
gitRenamedFiles,
gitSubmoduleDiffSHA,
jsonOutput
} from './utils'
export const getRenamedFiles = async ({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
submodulePaths
}: {
inputs: Inputs
workingDirectory: string
hasSubmodule: boolean
diffResult: DiffResult
submodulePaths: string[]
}): Promise<string> => {
const renamedFiles = await gitRenamedFiles({
cwd: workingDirectory,
sha1: diffResult.previousSha,
sha2: diffResult.currentSha,
diff: diffResult.diff,
oldNewSeparator: inputs.oldNewSeparator
})
if (hasSubmodule) {
for (const submodulePath of submodulePaths) {
const submoduleShaResult = await gitSubmoduleDiffSHA({
cwd: workingDirectory,
parentSha1: diffResult.previousSha,
parentSha2: diffResult.currentSha,
submodulePath,
diff: diffResult.diff
})
const submoduleWorkingDirectory = path.join(
workingDirectory,
submodulePath
)
if (submoduleShaResult.currentSha && submoduleShaResult.previousSha) {
const submoduleRenamedFiles = await gitRenamedFiles({
cwd: submoduleWorkingDirectory,
sha1: submoduleShaResult.previousSha,
sha2: submoduleShaResult.currentSha,
diff: diffResult.diff,
oldNewSeparator: inputs.oldNewSeparator,
isSubmodule: true,
parentDir: submodulePath
})
renamedFiles.push(...submoduleRenamedFiles)
}
}
}
if (inputs.json) {
return jsonOutput({value: renamedFiles, shouldEscape: inputs.escapeJson})
}
return renamedFiles.join(inputs.oldNewFilesSeparator)
}
export const getDiffFiles = async ({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter,
filePatterns = [],
submodulePaths
}: {
inputs: Inputs
workingDirectory: string
hasSubmodule: boolean
diffResult: DiffResult
diffFilter: string
filePatterns?: string[]
submodulePaths: string[]
}): Promise<string> => {
let files = await gitDiff({
cwd: workingDirectory,
sha1: diffResult.previousSha,
sha2: diffResult.currentSha,
diff: diffResult.diff,
diffFilter,
filePatterns
})
if (hasSubmodule) {
for (const submodulePath of submodulePaths) {
const submoduleShaResult = await gitSubmoduleDiffSHA({
cwd: workingDirectory,
parentSha1: diffResult.previousSha,
parentSha2: diffResult.currentSha,
submodulePath,
diff: diffResult.diff
})
const submoduleWorkingDirectory = path.join(
workingDirectory,
submodulePath
)
if (submoduleShaResult.currentSha && submoduleShaResult.previousSha) {
const submoduleFiles = await gitDiff({
cwd: submoduleWorkingDirectory,
sha1: submoduleShaResult.previousSha,
sha2: submoduleShaResult.currentSha,
diff: diffResult.diff,
diffFilter,
isSubmodule: true,
filePatterns,
parentDir: submodulePath
})
files.push(...submoduleFiles)
}
}
}
if (inputs.dirNames) {
files = files.map(file =>
getDirnameMaxDepth({
pathStr: file,
dirNamesMaxDepth: inputs.dirNamesMaxDepth,
excludeRoot: inputs.dirNamesExcludeRoot
})
)
}
if (inputs.json) {
return jsonOutput({value: files, shouldEscape: inputs.escapeJson})
}
return files.join(inputs.separator)
}

View File

@@ -1,468 +0,0 @@
import * as core from '@actions/core'
import {Env} from './env'
import {Inputs} from './inputs'
import {
canDiffCommits,
getHeadSha,
getParentSha,
getPreviousGitTag,
gitFetch,
gitFetchSubmodules,
gitLog,
gitLsRemote,
verifyCommitSha
} from './utils'
const getCurrentSHA = async ({
inputs,
workingDirectory
}: {
inputs: Inputs
workingDirectory: string
}): Promise<string> => {
let currentSha = inputs.sha
core.debug('Getting current SHA...')
if (inputs.until) {
core.debug(`Getting base SHA for '${inputs.until}'...`)
try {
currentSha = await gitLog({
cwd: workingDirectory,
args: [
'--format=%H',
'-n',
'1',
'--date',
'local',
'--until',
inputs.until
]
})
} catch (error) {
core.error(
`Invalid until date: ${inputs.until}. ${(error as Error).message}`
)
throw error
}
} else {
if (!currentSha) {
currentSha = await getHeadSha({cwd: workingDirectory})
}
}
await verifyCommitSha({sha: currentSha, cwd: workingDirectory})
core.debug(`Current SHA: ${currentSha}`)
return currentSha
}
export interface DiffResult {
previousSha: string
currentSha: string
currentBranch: string
targetBranch: string
diff: string
}
export const getSHAForPushEvent = async (
inputs: Inputs,
env: Env,
workingDirectory: string,
isShallow: boolean,
hasSubmodule: boolean,
gitExtraArgs: string[],
isTag: boolean
): Promise<DiffResult> => {
let targetBranch = env.GITHUB_REF_NAME
const currentBranch = targetBranch
let initialCommit = false
if (isShallow) {
core.info('Repository is shallow, fetching more history...')
if (isTag) {
const sourceBranch = env.GITHUB_EVENT_BASE_REF.replace('refs/heads/', '')
await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`,
'origin',
`+refs/tags/${sourceBranch}:refs/remotes/origin/${sourceBranch}`
]
})
} else {
await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`,
'origin',
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
]
})
}
if (hasSubmodule) {
await gitFetchSubmodules({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`
]
})
}
}
const currentSha = await getCurrentSHA({inputs, workingDirectory})
let previousSha = inputs.baseSha
const diff = '..'
if (previousSha && currentSha && currentBranch && targetBranch) {
if (previousSha === currentSha) {
core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
)
core.error(
`Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${inputs.fetchDepth}.`
)
throw new Error('Similar commit hashes detected.')
}
await verifyCommitSha({sha: previousSha, cwd: workingDirectory})
core.info(`Previous SHA: ${previousSha}`)
return {
previousSha,
currentSha,
currentBranch,
targetBranch,
diff
}
}
if (!previousSha) {
core.debug('Getting previous SHA...')
if (inputs.since) {
core.debug(`Getting base SHA for '${inputs.since}'...`)
try {
const allCommitsFrom = await gitLog({
cwd: workingDirectory,
args: ['--format=%H', '--date', 'local', '--since', inputs.since]
})
if (allCommitsFrom) {
const allCommitsFromArray = allCommitsFrom.split('\n')
previousSha = allCommitsFromArray[allCommitsFromArray.length - 1]
}
} catch (error) {
core.error(
`Invalid since date: ${inputs.since}. ${(error as Error).message}`
)
throw error
}
} else if (isTag) {
core.debug('Getting previous SHA for tag...')
const {sha, tag} = await getPreviousGitTag({cwd: workingDirectory})
previousSha = sha
targetBranch = tag
} else {
core.debug('Getting previous SHA for last remote commit...')
if (env.GITHUB_EVENT_FORCED === 'false' || !env.GITHUB_EVENT_FORCED) {
previousSha = env.GITHUB_EVENT_BEFORE
} else {
previousSha = await getParentSha({
cwd: workingDirectory
})
}
if (
!previousSha ||
previousSha === '0000000000000000000000000000000000000000'
) {
previousSha = await getParentSha({
cwd: workingDirectory
})
}
if (previousSha === currentSha) {
if (!(await getParentSha({cwd: workingDirectory}))) {
core.warning('Initial commit detected no previous commit found.')
initialCommit = true
previousSha = currentSha
} else {
previousSha = await getParentSha({
cwd: workingDirectory
})
}
} else {
if (!previousSha) {
core.error('Unable to locate a previous commit.')
throw new Error('Unable to locate a previous commit.')
}
}
}
}
await verifyCommitSha({sha: previousSha, cwd: workingDirectory})
core.debug(`Previous SHA: ${previousSha}`)
core.debug(`Target branch: ${targetBranch}`)
core.debug(`Current branch: ${currentBranch}`)
if (!initialCommit && previousSha === currentSha) {
core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
)
core.error(
`Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${inputs.fetchDepth}.`
)
throw new Error('Similar commit hashes detected.')
}
return {
previousSha,
currentSha,
currentBranch,
targetBranch,
diff
}
}
export const getSHAForPullRequestEvent = async (
inputs: Inputs,
env: Env,
workingDirectory: string,
isShallow: boolean,
hasSubmodule: boolean,
gitExtraArgs: string[]
): Promise<DiffResult> => {
let targetBranch = env.GITHUB_EVENT_PULL_REQUEST_BASE_REF
const currentBranch = env.GITHUB_EVENT_PULL_REQUEST_HEAD_REF
if (inputs.sinceLastRemoteCommit) {
targetBranch = currentBranch
}
if (isShallow) {
core.info('Repository is shallow, fetching more history...')
const prFetchExitCode = await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
'origin',
`pull/${env.GITHUB_EVENT_PULL_REQUEST_NUMBER}/head:${currentBranch}`
]
})
if (prFetchExitCode !== 0) {
await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`,
'origin',
`+refs/heads/${currentBranch}*:refs/remotes/origin/${currentBranch}*`
]
})
}
if (!inputs.sinceLastRemoteCommit) {
core.debug('Fetching target branch...')
await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`,
'origin',
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
]
})
if (hasSubmodule) {
await gitFetchSubmodules({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`
]
})
}
}
}
const currentSha = await getCurrentSHA({inputs, workingDirectory})
let previousSha = inputs.baseSha
let diff = '...'
if (previousSha && currentSha && currentBranch && targetBranch) {
if (previousSha === currentSha) {
core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
)
core.error(
`Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${inputs.fetchDepth}.`
)
throw new Error('Similar commit hashes detected.')
}
await verifyCommitSha({sha: currentSha, cwd: workingDirectory})
core.info(`Previous SHA: ${previousSha}`)
return {
previousSha,
currentSha,
currentBranch,
targetBranch,
diff
}
}
if (
!env.GITHUB_EVENT_PULL_REQUEST_BASE_REF ||
env.GITHUB_EVENT_HEAD_REPO_FORK === 'true'
) {
diff = '..'
}
if (!previousSha) {
if (inputs.sinceLastRemoteCommit) {
previousSha = env.GITHUB_EVENT_BEFORE
if (!previousSha) {
previousSha = await gitLsRemote({
cwd: workingDirectory,
args: [currentBranch]
})
}
if (
(await verifyCommitSha({
sha: previousSha,
cwd: workingDirectory,
showAsErrorMessage: false
})) !== 0
) {
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
}
} else {
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
if (!previousSha) {
previousSha = await gitLsRemote({
cwd: workingDirectory,
args: [targetBranch]
})
}
if (isShallow) {
if (
await canDiffCommits({
cwd: workingDirectory,
sha1: previousSha,
sha2: currentSha,
diff
})
) {
core.debug(
'Merge base is not in the local history, fetching remote target branch...'
)
for (let i = 1; i <= 10; i++) {
await gitFetch({
cwd: workingDirectory,
args: [
...gitExtraArgs,
'-u',
'--progress',
`--deepen=${inputs.fetchDepth}`,
'origin',
`+refs/heads/${targetBranch}:refs/remotes/origin/${targetBranch}`
]
})
if (
await canDiffCommits({
cwd: workingDirectory,
sha1: previousSha,
sha2: currentSha,
diff
})
) {
break
}
core.debug(
'Merge base is not in the local history, fetching remote target branch again...'
)
core.debug(`Attempt ${i}/10`)
}
}
}
}
if (!previousSha || previousSha === currentSha) {
previousSha = env.GITHUB_EVENT_PULL_REQUEST_BASE_SHA
}
}
if (
!(await canDiffCommits({
cwd: workingDirectory,
sha1: previousSha,
sha2: currentSha,
diff
}))
) {
diff = '..'
}
await verifyCommitSha({sha: previousSha, cwd: workingDirectory})
core.debug(`Previous SHA: ${previousSha}`)
if (
!(await canDiffCommits({
cwd: workingDirectory,
sha1: previousSha,
sha2: currentSha,
diff
}))
) {
throw new Error(
`Unable to determine a difference between ${previousSha}${diff}${currentSha}`
)
}
if (previousSha === currentSha) {
core.error(
`Similar commit hashes detected: previous sha: ${previousSha} is equivalent to the current sha: ${currentSha}.`
)
core.error(
`Please verify that both commits are valid, and increase the fetch_depth to a number higher than ${inputs.fetchDepth}.`
)
throw new Error('Similar commit hashes detected.')
}
return {
previousSha,
currentSha,
currentBranch,
targetBranch,
diff
}
}

View File

@@ -1,59 +0,0 @@
import {promises as fs} from 'fs'
import * as core from '@actions/core'
export type Env = {
GITHUB_EVENT_PULL_REQUEST_HEAD_REF: string
GITHUB_EVENT_PULL_REQUEST_BASE_REF: string
GITHUB_EVENT_BEFORE: string
GITHUB_REF_NAME: string
GITHUB_REF: string
GITHUB_EVENT_BASE_REF: string
GITHUB_EVENT_HEAD_REPO_FORK: string
GITHUB_WORKSPACE: string
GITHUB_EVENT_FORCED: string
GITHUB_EVENT_PULL_REQUEST_NUMBER: string
GITHUB_EVENT_PULL_REQUEST_BASE_SHA: string
}
type GithubEvent = {
forced?: string
pull_request?: {
head: {
ref: string
}
base: {
ref: string
sha: string
}
number: string
}
before?: string
base_ref?: string
head_repo?: {
fork: string
}
}
export const getEnv = async (): Promise<Env> => {
const eventPath = process.env.GITHUB_EVENT_PATH
let eventJson: GithubEvent = {}
if (eventPath) {
eventJson = JSON.parse(await fs.readFile(eventPath, {encoding: 'utf8'}))
}
core.debug(`Event: ${JSON.stringify(eventJson, null, 2)}`)
return {
GITHUB_EVENT_PULL_REQUEST_HEAD_REF: eventJson.pull_request?.head?.ref || '',
GITHUB_EVENT_PULL_REQUEST_BASE_REF: eventJson.pull_request?.base?.ref || '',
GITHUB_EVENT_BEFORE: eventJson.before || '',
GITHUB_EVENT_BASE_REF: eventJson.base_ref || '',
GITHUB_EVENT_HEAD_REPO_FORK: eventJson.head_repo?.fork || '',
GITHUB_EVENT_PULL_REQUEST_NUMBER: eventJson.pull_request?.number || '',
GITHUB_EVENT_PULL_REQUEST_BASE_SHA: eventJson.pull_request?.base?.sha || '',
GITHUB_EVENT_FORCED: eventJson.forced || '',
GITHUB_REF_NAME: process.env.GITHUB_REF_NAME || '',
GITHUB_REF: process.env.GITHUB_REF || '',
GITHUB_WORKSPACE: process.env.GITHUB_WORKSPACE || ''
}
}

View File

@@ -1,146 +0,0 @@
import * as core from '@actions/core'
export type Inputs = {
files: string
filesSeparator: string
filesFromSourceFile: string
filesFromSourceFileSeparator: string
filesIgnore: string
filesIgnoreSeparator: string
filesIgnoreFromSourceFile: string
filesIgnoreFromSourceFileSeparator: string
separator: string
includeAllOldNewRenamedFiles: boolean
oldNewSeparator: string
oldNewFilesSeparator: string
sha: string
baseSha: string
since: string
until: string
path: string
quotePath: boolean
diffRelative: boolean
dirNames: boolean
dirNamesMaxDepth?: number
dirNamesExcludeRoot: boolean
json: boolean
escapeJson: boolean
fetchDepth?: number
sinceLastRemoteCommit: boolean
writeOutputFiles: boolean
outputDir: string
}
export const getInputs = (): Inputs => {
const files = core.getInput('files', {required: false})
const filesSeparator = core.getInput('files_separator', {
required: false,
trimWhitespace: false
})
const filesIgnore = core.getInput('files_ignore', {required: false})
const filesIgnoreSeparator = core.getInput('files_ignore_separator', {
required: false,
trimWhitespace: false
})
const filesFromSourceFile = core.getInput('files_from_source_file', {
required: false
})
const filesFromSourceFileSeparator = core.getInput(
'files_from_source_file_separator',
{
required: false,
trimWhitespace: false
}
)
const filesIgnoreFromSourceFile = core.getInput(
'files_ignore_from_source_file',
{required: false}
)
const filesIgnoreFromSourceFileSeparator = core.getInput(
'files_ignore_from_source_file_separator',
{
required: false,
trimWhitespace: false
}
)
const separator = core.getInput('separator', {
required: true,
trimWhitespace: false
})
const includeAllOldNewRenamedFiles = core.getBooleanInput(
'include_all_old_new_renamed_files',
{required: false}
)
const oldNewSeparator = core.getInput('old_new_separator', {
required: true,
trimWhitespace: false
})
const oldNewFilesSeparator = core.getInput('old_new_files_separator', {
required: true,
trimWhitespace: false
})
const sha = core.getInput('sha', {required: false})
const baseSha = core.getInput('base_sha', {required: false})
const since = core.getInput('since', {required: false})
const until = core.getInput('until', {required: false})
const path = core.getInput('path', {required: false})
const quotePath = core.getBooleanInput('quotepath', {required: false})
const diffRelative = core.getBooleanInput('diff_relative', {required: false})
const dirNames = core.getBooleanInput('dir_names', {required: false})
const dirNamesMaxDepth = core.getInput('dir_names_max_depth', {
required: false
})
const dirNamesExcludeRoot = core.getBooleanInput('dir_names_exclude_root', {
required: false
})
const json = core.getBooleanInput('json', {required: false})
const escapeJson = core.getBooleanInput('escape_json', {required: false})
const fetchDepth = core.getInput('fetch_depth', {required: false})
const sinceLastRemoteCommit = core.getBooleanInput(
'since_last_remote_commit',
{required: false}
)
const writeOutputFiles = core.getBooleanInput('write_output_files', {
required: false
})
const outputDir = core.getInput('output_dir', {required: false})
const inputs: Inputs = {
files,
filesSeparator,
filesFromSourceFile,
filesFromSourceFileSeparator,
filesIgnore,
filesIgnoreSeparator,
filesIgnoreFromSourceFile,
filesIgnoreFromSourceFileSeparator,
separator,
includeAllOldNewRenamedFiles,
oldNewSeparator,
oldNewFilesSeparator,
sha,
baseSha,
since,
until,
path,
quotePath,
diffRelative,
dirNames,
dirNamesExcludeRoot,
json,
escapeJson,
sinceLastRemoteCommit,
writeOutputFiles,
outputDir
}
if (fetchDepth) {
inputs.fetchDepth = parseInt(fetchDepth, 10)
}
if (dirNamesMaxDepth) {
inputs.dirNamesMaxDepth = parseInt(dirNamesMaxDepth, 10)
}
return inputs
}

View File

@@ -1,413 +0,0 @@
import * as core from '@actions/core'
import path from 'path'
import {getDiffFiles, getRenamedFiles} from './changedFiles'
import {
getSHAForPullRequestEvent,
getSHAForPushEvent,
DiffResult
} from './commitSha'
import {getEnv} from './env'
import {getInputs} from './inputs'
import {
getFilePatterns,
getSubmodulePath,
isRepoShallow,
setOutput,
submoduleExists,
updateGitGlobalConfig,
verifyMinimumGitVersion
} from './utils'
export async function run(): Promise<void> {
core.startGroup('changed-files')
const env = await getEnv()
core.debug(`Env: ${JSON.stringify(env, null, 2)}`)
const inputs = getInputs()
core.debug(`Inputs: ${JSON.stringify(inputs, null, 2)}`)
await verifyMinimumGitVersion()
let quotePathValue = 'on'
if (!inputs.quotePath) {
quotePathValue = 'off'
}
await updateGitGlobalConfig({
name: 'core.quotepath',
value: quotePathValue
})
if (inputs.diffRelative) {
await updateGitGlobalConfig({
name: 'diff.relative',
value: 'true'
})
}
const workingDirectory = path.resolve(
env.GITHUB_WORKSPACE || process.cwd(),
inputs.path
)
const isShallow = await isRepoShallow({cwd: workingDirectory})
const hasSubmodule = await submoduleExists({cwd: workingDirectory})
let gitExtraArgs = ['--no-tags', '--prune', '--recurse-submodules']
const isTag = env.GITHUB_REF?.startsWith('refs/tags/')
let submodulePaths: string[] = []
if (hasSubmodule) {
submodulePaths = await getSubmodulePath({cwd: workingDirectory})
}
if (isTag) {
gitExtraArgs = ['--prune', '--no-recurse-submodules']
}
let diffResult: DiffResult
if (!env.GITHUB_EVENT_PULL_REQUEST_BASE_REF) {
core.info('Running on a push event...')
diffResult = await getSHAForPushEvent(
inputs,
env,
workingDirectory,
isShallow,
hasSubmodule,
gitExtraArgs,
isTag
)
} else {
core.info('Running on a pull request event...')
diffResult = await getSHAForPullRequestEvent(
inputs,
env,
workingDirectory,
isShallow,
hasSubmodule,
gitExtraArgs
)
}
core.info(
`Retrieving changes between ${diffResult.previousSha} (${diffResult.targetBranch}) → ${diffResult.currentSha} (${diffResult.currentBranch})`
)
const filePatterns = await getFilePatterns({
inputs
})
const addedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'A',
filePatterns,
submodulePaths
})
core.debug(`Added files: ${addedFiles}`)
await setOutput({
key: 'added_files',
value: addedFiles,
inputs
})
const copiedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'C',
filePatterns,
submodulePaths
})
core.debug(`Copied files: ${copiedFiles}`)
await setOutput({
key: 'copied_files',
value: copiedFiles,
inputs
})
const modifiedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'M',
filePatterns,
submodulePaths
})
core.debug(`Modified files: ${modifiedFiles}`)
await setOutput({
key: 'modified_files',
value: modifiedFiles,
inputs
})
const renamedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'R',
filePatterns,
submodulePaths
})
core.debug(`Renamed files: ${renamedFiles}`)
await setOutput({
key: 'renamed_files',
value: renamedFiles,
inputs
})
const typeChangedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'T',
filePatterns,
submodulePaths
})
core.debug(`Type changed files: ${typeChangedFiles}`)
await setOutput({
key: 'type_changed_files',
value: typeChangedFiles,
inputs
})
const unmergedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'U',
filePatterns,
submodulePaths
})
core.debug(`Unmerged files: ${unmergedFiles}`)
await setOutput({
key: 'unmerged_files',
value: unmergedFiles,
inputs
})
const unknownFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'X',
filePatterns,
submodulePaths
})
core.debug(`Unknown files: ${unknownFiles}`)
await setOutput({
key: 'unknown_files',
value: unknownFiles,
inputs
})
const allChangedAndModifiedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'ACDMRTUX',
filePatterns,
submodulePaths
})
core.debug(`All changed and modified files: ${allChangedAndModifiedFiles}`)
await setOutput({
key: 'all_changed_and_modified_files',
value: allChangedAndModifiedFiles,
inputs
})
const allChangedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'ACMR',
filePatterns,
submodulePaths
})
core.debug(`All changed files: ${allChangedFiles}`)
await setOutput({
key: 'all_changed_files',
value: allChangedFiles,
inputs
})
await setOutput({
key: 'any_changed',
value: allChangedFiles.length > 0 && filePatterns.length > 0,
inputs
})
const allOtherChangedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'ACMR',
submodulePaths
})
core.debug(`All other changed files: ${allOtherChangedFiles}`)
const otherChangedFiles = allOtherChangedFiles
.split(inputs.filesSeparator)
.filter(
filePath =>
!allChangedFiles.split(inputs.filesSeparator).includes(filePath)
)
const onlyChanged =
otherChangedFiles.length === 0 && allChangedFiles.length > 0
await setOutput({
key: 'only_changed',
value: onlyChanged,
inputs
})
await setOutput({
key: 'other_changed_files',
value: otherChangedFiles.join(inputs.filesSeparator),
inputs
})
const allModifiedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'ACMRD',
filePatterns,
submodulePaths
})
core.debug(`All modified files: ${allModifiedFiles}`)
await setOutput({
key: 'all_modified_files',
value: allModifiedFiles,
inputs
})
await setOutput({
key: 'any_modified',
value: allModifiedFiles.length > 0 && filePatterns.length > 0,
inputs
})
const allOtherModifiedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'ACMRD',
submodulePaths
})
const otherModifiedFiles = allOtherModifiedFiles
.split(inputs.filesSeparator)
.filter(
filePath =>
!allModifiedFiles.split(inputs.filesSeparator).includes(filePath)
)
const onlyModified =
otherModifiedFiles.length === 0 && allModifiedFiles.length > 0
await setOutput({
key: 'only_modified',
value: onlyModified,
inputs
})
await setOutput({
key: 'other_modified_files',
value: otherModifiedFiles.join(inputs.filesSeparator),
inputs
})
const deletedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'D',
filePatterns,
submodulePaths
})
core.debug(`Deleted files: ${deletedFiles}`)
await setOutput({
key: 'deleted_files',
value: deletedFiles,
inputs
})
await setOutput({
key: 'any_deleted',
value: deletedFiles.length > 0 && filePatterns.length > 0,
inputs
})
const allOtherDeletedFiles = await getDiffFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
diffFilter: 'D',
submodulePaths
})
const otherDeletedFiles = allOtherDeletedFiles
.split(inputs.filesSeparator)
.filter(
filePath => !deletedFiles.split(inputs.filesSeparator).includes(filePath)
)
const onlyDeleted = otherDeletedFiles.length === 0 && deletedFiles.length > 0
await setOutput({
key: 'only_deleted',
value: onlyDeleted,
inputs
})
await setOutput({
key: 'other_deleted_files',
value: otherDeletedFiles.join(inputs.filesSeparator),
inputs
})
if (inputs.includeAllOldNewRenamedFiles) {
const allOldNewRenamedFiles = await getRenamedFiles({
inputs,
workingDirectory,
hasSubmodule,
diffResult,
submodulePaths
})
core.debug(`All old new renamed files: ${allOldNewRenamedFiles}`)
await setOutput({
key: 'all_old_new_renamed_files',
value: allOldNewRenamedFiles,
inputs
})
}
core.info('All Done!')
core.endGroup()
}
/* istanbul ignore if */
if (!process.env.TESTING) {
// eslint-disable-next-line github/no-then
run().catch(e => {
core.setFailed(e.message || e)
})
}

View File

@@ -1,776 +0,0 @@
/*global AsyncIterableIterator*/
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import {createReadStream, promises as fs} from 'fs'
import mm from 'micromatch'
import * as path from 'path'
import {createInterface} from 'readline'
import {Inputs} from './inputs'
const IS_WINDOWS = process.platform === 'win32'
const MINIMUM_GIT_VERSION = '2.18.0'
/**
* Normalize file path separators to '/' on Windows and Linux/macOS
* @param p file path
* @returns file path with normalized separators
*/
const normalizeSeparators = (p: string): string => {
// Windows
if (IS_WINDOWS) {
// Convert slashes on Windows
p = p.replace(/\//g, '\\')
// Remove redundant slashes
const isUnc = /^\\\\+[^\\]/.test(p) // e.g. \\hello
return (isUnc ? '\\' : '') + p.replace(/\\\\+/g, '\\') // preserve leading \\ for UNC
}
// Remove redundant slashes
return p.replace(/\/\/+/g, '/')
}
/**
* Trims unnecessary trailing slash from file path
* @param p file path
* @returns file path without unnecessary trailing slash
*/
const safeTrimTrailingSeparator = (p: string): string => {
// Empty path
if (!p) {
return ''
}
// Normalize separators
p = normalizeSeparators(p)
// No trailing slash
if (!p.endsWith(path.sep)) {
return p
}
// Check '/' on Linux/macOS and '\' on Windows
if (p === path.sep) {
return p
}
// On Windows, avoid trimming the drive root, e.g. C:\ or \\hello
if (IS_WINDOWS && /^[A-Z]:\\$/i.test(p)) {
return p
}
// Trim trailing slash
return p.substring(0, p.length - 1)
}
const dirname = (p: string): string => {
// Normalize slashes and trim unnecessary trailing slash
p = safeTrimTrailingSeparator(p)
// Windows UNC root, e.g. \\hello or \\hello\world
if (IS_WINDOWS && /^\\\\[^\\]+(\\[^\\]+)?$/.test(p)) {
return p
}
// Get dirname
let result = path.dirname(p)
// Trim trailing slash for Windows UNC root, e.g. \\hello\world\
if (IS_WINDOWS && /^\\\\[^\\]+\\[^\\]+\\$/.test(result)) {
result = safeTrimTrailingSeparator(result)
}
return result
}
const versionToNumber = (version: string): number => {
const [major, minor, patch] = version.split('.').map(Number)
return major * 1000000 + minor * 1000 + patch
}
export const verifyMinimumGitVersion = async (): Promise<void> => {
const {exitCode, stdout, stderr} = await exec.getExecOutput(
'git',
['--version'],
{silent: process.env.ACTION_DEBUG === 'false'}
)
if (exitCode !== 0) {
throw new Error(stderr || 'An unexpected error occurred')
}
const gitVersion = stdout.trim()
if (versionToNumber(gitVersion) < versionToNumber(MINIMUM_GIT_VERSION)) {
throw new Error(
`Minimum required git version is ${MINIMUM_GIT_VERSION}, your version is ${gitVersion}`
)
}
}
const exists = async (filePath: string): Promise<boolean> => {
try {
await fs.access(filePath)
return true
} catch {
return false
}
}
async function* lineOfFileGenerator({
filePath,
excludedFiles
}: {
filePath: string
excludedFiles: boolean
}): AsyncIterableIterator<string> {
const fileStream = createReadStream(filePath)
/* istanbul ignore next */
fileStream.on('error', error => {
throw error
})
const rl = createInterface({
input: fileStream,
crlfDelay: Infinity
})
for await (const line of rl) {
if (!line.startsWith('#') && line !== '') {
if (excludedFiles) {
if (line.startsWith('!')) {
yield line
} else {
yield `!${line}`
}
} else {
yield line
}
}
}
}
const getFilesFromSourceFile = async ({
filePaths,
excludedFiles = false
}: {
filePaths: string[]
excludedFiles?: boolean
}): Promise<string[]> => {
const lines = []
for (const filePath of filePaths) {
for await (const line of lineOfFileGenerator({filePath, excludedFiles})) {
lines.push(line)
}
}
return lines
}
export const updateGitGlobalConfig = async ({
name,
value
}: {
name: string
value: string
}): Promise<void> => {
const {exitCode, stderr} = await exec.getExecOutput(
'git',
['config', '--global', name, value],
{
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
/* istanbul ignore if */
if (exitCode !== 0 || stderr) {
core.warning(stderr || `Couldn't update git global config ${name}`)
}
}
export const isRepoShallow = async ({cwd}: {cwd: string}): Promise<boolean> => {
const {stdout} = await exec.getExecOutput(
'git',
['rev-parse', '--is-shallow-repository'],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
return stdout.trim() === 'true'
}
export const submoduleExists = async ({
cwd
}: {
cwd: string
}): Promise<boolean> => {
const {stdout, exitCode} = await exec.getExecOutput(
'git',
['submodule', 'status'],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
return false
}
return stdout.trim() !== ''
}
export const gitFetch = async ({
args,
cwd
}: {
args: string[]
cwd: string
}): Promise<number> => {
const {exitCode} = await exec.getExecOutput('git', ['fetch', '-q', ...args], {
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
})
return exitCode
}
export const gitFetchSubmodules = async ({
args,
cwd
}: {
args: string[]
cwd: string
}): Promise<void> => {
const {exitCode, stderr} = await exec.getExecOutput(
'git',
['submodule', 'foreach', 'git', 'fetch', '-q', ...args],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
/* istanbul ignore if */
if (exitCode !== 0) {
core.warning(stderr || "Couldn't fetch submodules")
}
}
const normalizePath = (p: string): string => {
return p.replace(/\\/g, '/')
}
export const getSubmodulePath = async ({
cwd
}: {
cwd: string
}): Promise<string[]> => {
const {exitCode, stdout, stderr} = await exec.getExecOutput(
'git',
['submodule', 'status'],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
core.warning(stderr || "Couldn't get submodule names")
return []
}
return stdout
.trim()
.split('\n')
.map(line => normalizePath(line.split(' ')[1]))
}
export const gitSubmoduleDiffSHA = async ({
cwd,
parentSha1,
parentSha2,
submodulePath,
diff
}: {
cwd: string
parentSha1: string
parentSha2: string
submodulePath: string
diff: string
}): Promise<{previousSha?: string; currentSha?: string}> => {
const {stdout} = await exec.getExecOutput(
'git',
['diff', parentSha1, parentSha2, '--', submodulePath],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
const subprojectCommitPreRegex =
/^(?<preCommit>-)Subproject commit (?<commitHash>.+)$/m
const subprojectCommitCurRegex =
/^(?<curCommit>\+)Subproject commit (?<commitHash>.+)$/m
const previousSha =
subprojectCommitPreRegex.exec(stdout)?.groups?.commitHash ||
'4b825dc642cb6eb9a060e54bf8d69288fbee4904'
const currentSha = subprojectCommitCurRegex.exec(stdout)?.groups?.commitHash
if (currentSha) {
return {previousSha, currentSha}
}
core.debug(
`No submodule commit found for ${submodulePath} between ${parentSha1}${diff}${parentSha2}`
)
return {}
}
export const gitRenamedFiles = async ({
cwd,
sha1,
sha2,
diff,
oldNewSeparator,
isSubmodule = false,
parentDir = ''
}: {
cwd: string
sha1: string
sha2: string
diff: string
oldNewSeparator: string
isSubmodule?: boolean
parentDir?: string
}): Promise<string[]> => {
const {exitCode, stderr, stdout} = await exec.getExecOutput(
'git',
[
'diff',
'--name-status',
'--ignore-submodules=all',
'--diff-filter=R',
`${sha1}${diff}${sha2}`
],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
if (isSubmodule) {
core.warning(
stderr ||
`Failed to get renamed files for submodule between: ${sha1}${diff}${sha2}`
)
core.warning(
'Please ensure that submodules are initialized and up to date. See: https://github.com/actions/checkout#usage'
)
} else {
core.error(
stderr || `Failed to get renamed files between: ${sha1}${diff}${sha2}`
)
throw new Error('Unable to get renamed files')
}
return []
}
return stdout
.trim()
.split('\n')
.filter(Boolean)
.map(line => {
core.debug(`Renamed file: ${line}`)
const [, oldPath, newPath] = line.split('\t')
if (isSubmodule) {
return `${normalizePath(
path.join(parentDir, oldPath)
)}${oldNewSeparator}${normalizePath(path.join(parentDir, newPath))}`
}
return `${normalizePath(oldPath)}${oldNewSeparator}${normalizePath(
newPath
)}`
})
}
export const gitDiff = async ({
cwd,
sha1,
sha2,
diff,
diffFilter,
filePatterns = [],
isSubmodule = false,
parentDir = ''
}: {
cwd: string
sha1: string
sha2: string
diffFilter: string
diff: string
filePatterns?: string[]
isSubmodule?: boolean
parentDir?: string
}): Promise<string[]> => {
const {exitCode, stdout, stderr} = await exec.getExecOutput(
'git',
[
'diff',
'--name-only',
'--ignore-submodules=all',
`--diff-filter=${diffFilter}`,
`${sha1}${diff}${sha2}`
],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
if (isSubmodule) {
core.warning(
stderr ||
`Failed to get changed files for submodule between: ${sha1}${diff}${sha2}`
)
core.warning(
'Please ensure that submodules are initialized and up to date. See: https://github.com/actions/checkout#usage'
)
} else {
core.warning(
stderr || `Failed to get changed files between: ${sha1}${diff}${sha2}`
)
}
return []
}
const files = stdout
.split('\n')
.filter(Boolean)
.map(p => {
if (isSubmodule) {
return normalizePath(path.join(parentDir, p))
}
return normalizePath(p)
})
if (filePatterns.length === 0) {
return files
}
return mm(files, filePatterns, {
dot: true,
windows: IS_WINDOWS,
noext: true
})
}
export const gitLog = async ({
args,
cwd
}: {
args: string[]
cwd: string
}): Promise<string> => {
const {stdout} = await exec.getExecOutput('git', ['log', ...args], {
cwd,
silent: process.env.ACTION_DEBUG === 'false'
})
return stdout.trim()
}
export const getHeadSha = async ({cwd}: {cwd: string}): Promise<string> => {
const {stdout} = await exec.getExecOutput('git', ['rev-parse', 'HEAD'], {
cwd,
silent: process.env.ACTION_DEBUG === 'false'
})
return stdout.trim()
}
export const gitLsRemote = async ({
cwd,
args
}: {
cwd: string
args: string[]
}): Promise<string> => {
const {stdout} = await exec.getExecOutput(
'git',
['ls-remote', 'origin', ...args],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
const output = stdout.trim().split('\t')
if (output.length === 0) {
throw new Error('No output returned from git ls-remote')
}
return output[0]
}
export const getParentSha = async ({cwd}: {cwd: string}): Promise<string> => {
const {stdout} = await exec.getExecOutput(
'git',
['rev-list', '-n', '1', 'HEAD^'],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
return stdout.trim()
}
export const verifyCommitSha = async ({
sha,
cwd,
showAsErrorMessage = true
}: {
sha: string
cwd: string
showAsErrorMessage?: boolean
}): Promise<number> => {
const {exitCode, stderr} = await exec.getExecOutput(
'git',
['rev-parse', '--verify', `${sha}^{commit}`],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
if (showAsErrorMessage) {
core.error(`Unable to locate the commit sha: ${sha}`)
core.error(
"Please verify that the commit sha is correct, and increase the 'fetch_depth' input if needed"
)
core.debug(stderr)
} else {
core.warning(`Unable to locate the commit sha: ${sha}`)
core.debug(stderr)
}
}
return exitCode
}
export const getPreviousGitTag = async ({
cwd
}: {
cwd: string
}): Promise<{tag: string; sha: string}> => {
const {stdout} = await exec.getExecOutput(
'git',
['tag', '--sort=-version:refname'],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
const tags = stdout.trim().split('\n')
if (tags.length < 2) {
core.warning('No previous tag found')
return {tag: '', sha: ''}
}
const previousTag = tags[1]
const {stdout: stdout2} = await exec.getExecOutput(
'git',
['rev-parse', previousTag],
{
cwd,
silent: process.env.ACTION_DEBUG === 'false'
}
)
const sha = stdout2.trim()
return {tag: previousTag, sha}
}
export const canDiffCommits = async ({
cwd,
sha1,
sha2,
diff
}: {
cwd: string
sha1: string
sha2: string
diff: string
}): Promise<boolean> => {
const {exitCode, stderr} = await exec.getExecOutput(
'git',
['diff', '--name-only', '--ignore-submodules=all', `${sha1}${diff}${sha2}`],
{
cwd,
ignoreReturnCode: true,
silent: process.env.ACTION_DEBUG === 'false'
}
)
if (exitCode !== 0) {
core.warning(stderr || `Unable find merge base between ${sha1} and ${sha2}`)
return false
}
return true
}
export const getDirnameMaxDepth = ({
pathStr,
dirNamesMaxDepth,
excludeRoot
}: {
pathStr: string
dirNamesMaxDepth?: number
excludeRoot?: boolean
}): string => {
const pathArr = dirname(pathStr).split(path.sep)
const maxDepth = Math.min(dirNamesMaxDepth || pathArr.length, pathArr.length)
let output = pathArr[0]
for (let i = 1; i < maxDepth; i++) {
output = path.join(output, pathArr[i])
}
if (excludeRoot && output === '.') {
return ''
}
return normalizePath(output)
}
export const jsonOutput = ({
value,
shouldEscape
}: {
value: string | string[]
shouldEscape: boolean
}): string => {
const result = JSON.stringify(value)
return shouldEscape ? result.replace(/"/g, '\\"') : result
}
export const getFilePatterns = async ({
inputs
}: {
inputs: Inputs
}): Promise<string[]> => {
let filePatterns = inputs.files
.split(inputs.filesSeparator)
.filter(p => p !== '')
.join('\n')
if (inputs.filesFromSourceFile !== '') {
const inputFilesFromSourceFile = inputs.filesFromSourceFile
.split(inputs.filesFromSourceFileSeparator)
.filter(p => p !== '')
core.debug(`files from source file: ${inputFilesFromSourceFile}`)
const filesFromSourceFiles = (
await getFilesFromSourceFile({filePaths: inputFilesFromSourceFile})
).join('\n')
core.debug(`files from source files patterns: ${filesFromSourceFiles}`)
filePatterns = filePatterns.concat('\n', filesFromSourceFiles)
}
if (inputs.filesIgnore) {
const filesIgnorePatterns = inputs.filesIgnore
.split(inputs.filesIgnoreSeparator)
.filter(p => p !== '')
.map(p => {
if (!p.startsWith('!')) {
p = `!${p}`
}
return p
})
.join('\n')
core.debug(`files ignore patterns: ${filesIgnorePatterns}`)
filePatterns = filePatterns.concat('\n', filesIgnorePatterns)
}
if (inputs.filesIgnoreFromSourceFile) {
const inputFilesIgnoreFromSourceFile = inputs.filesIgnoreFromSourceFile
.split(inputs.filesIgnoreFromSourceFileSeparator)
.filter(p => p !== '')
core.debug(
`files ignore from source file: ${inputFilesIgnoreFromSourceFile}`
)
const filesIgnoreFromSourceFiles = (
await getFilesFromSourceFile({
filePaths: inputFilesIgnoreFromSourceFile,
excludedFiles: true
})
).join('\n')
core.debug(
`files ignore from source files patterns: ${filesIgnoreFromSourceFiles}`
)
filePatterns = filePatterns.concat('\n', filesIgnoreFromSourceFiles)
}
if (IS_WINDOWS) {
filePatterns = filePatterns.replace(/\r\n/g, '\n')
filePatterns = filePatterns.replace(/\r/g, '\n')
}
core.debug(`file patterns: ${filePatterns}`)
return filePatterns.trim().split('\n').filter(Boolean)
}
export const setOutput = async ({
key,
value,
inputs
}: {
key: string
value: string | boolean
inputs: Inputs
}): Promise<void> => {
const cleanedValue = value.toString().trim()
core.setOutput(key, cleanedValue)
if (inputs.writeOutputFiles) {
const outputDir = inputs.outputDir || '.github/outputs'
const extension = inputs.json ? 'json' : 'txt'
const outputFilePath = path.join(outputDir, `${key}.${extension}`)
if (!(await exists(outputDir))) {
await fs.mkdir(outputDir, {recursive: true})
}
await fs.writeFile(outputFilePath, cleanedValue.replace(/\\"/g, '"'))
}
}

View File

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

View File

@@ -4,4 +4,3 @@ action.yml
action.yml
**/test.txt
!test/test/test.txt
[test new].txt

Submodule test/demo deleted from 83ccca9b63

View File

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

View File

@@ -1 +0,0 @@
This is test file 2.

View File

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

View File

@@ -1 +0,0 @@
This is a test file with non ascii character in the filename.

View File

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

View File

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

View File

@@ -1 +0,0 @@
Lorem ipsum dolor sit amet, consectetur adipiscing elit et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

View File

@@ -1 +0,0 @@
Test file.

View File

@@ -1 +0,0 @@
Test file.

View File

@@ -1,12 +0,0 @@
{
"compilerOptions": {
"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'. */
"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. */
"strict": true, /* Enable all strict type-checking options. */
"noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"exclude": ["node_modules", "jest/setEnvVars.cjs"]
}

3798
yarn.lock

File diff suppressed because it is too large Load Diff