Compare commits

..

1 Commits

Author SHA1 Message Date
Tonye Jack
f0751de6af Added version warning 2022-02-17 00:12:45 -05:00
58 changed files with 819 additions and 24609 deletions

View File

@@ -32,161 +32,6 @@
"code",
"doc"
]
},
{
"login": "IvanPizhenko",
"name": "Ivan Pizhenko",
"avatar_url": "https://avatars.githubusercontent.com/u/11859904?v=4",
"profile": "https://github.com/IvanPizhenko",
"contributions": [
"code",
"doc"
]
},
{
"login": "talva-tr",
"name": "talva-tr",
"avatar_url": "https://avatars.githubusercontent.com/u/82046981?v=4",
"profile": "https://github.com/talva-tr",
"contributions": [
"code"
]
},
{
"login": "eltociear",
"name": "Ikko Ashimine",
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
"profile": "https://bandism.net/",
"contributions": [
"doc"
]
},
{
"login": "Zamiell",
"name": "James",
"avatar_url": "https://avatars.githubusercontent.com/u/5511220?v=4",
"profile": "https://github.com/Zamiell",
"contributions": [
"doc"
]
},
{
"login": "wushujames",
"name": "James Cheng",
"avatar_url": "https://avatars.githubusercontent.com/u/677529?v=4",
"profile": "https://github.com/wushujames",
"contributions": [
"doc"
]
},
{
"login": "massongit",
"name": "Masaya Suzuki",
"avatar_url": "https://avatars.githubusercontent.com/u/15100604?v=4",
"profile": "https://qiita.com/SUZUKI_Masaya",
"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 +39,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

@@ -15,13 +15,6 @@ body:
options:
- label: I have searched the existing issues
required: true
- type: checkboxes
attributes:
label: Does this issue exist in the latest version?
description: Please view all releases to confirm that this issue hasn't already been fixed.
options:
- label: I'm using the latest release
required: true
- type: textarea
id: what-happened
attributes:
@@ -69,14 +62,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

@@ -8,13 +8,6 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this feature request!
- type: checkboxes
attributes:
label: Is this feature missing in the latest version?
description: Please upgrade to the latest version to verify that this feature is still missing.
options:
- label: I'm using the latest release
required: true
- type: textarea
id: what-happened
attributes:
@@ -53,7 +46,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

@@ -2,6 +2,7 @@ name: automerge
on:
check_suite:
types:
- rerequested
- completed
jobs:
@@ -16,11 +17,11 @@ jobs:
github.actor == 'renovate'
steps:
- name: automerge
uses: pascalgn/automerge-action@v0.15.6
uses: pascalgn/automerge-action@v0.14.2
env:
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN }}
GITHUB_TOKEN: ${{ secrets.PAT_TOKEN || github.token }}
MERGE_METHOD: "rebase"
UPDATE_METHOD: "rebase"
MERGE_RETRIES: "6"
MERGE_RETRY_SLEEP: "100000"
MERGE_LABELS: ""
MERGE_LABELS: ""

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.'
pr-message: 'Thanks for implementing a fix. Could you include a test that 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.3.4
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.3.4
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@v8.7
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.8
with:
output: 'HISTORY.md'
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5.0.1
uses: peter-evans/create-pull-request@v3.10.0
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,35 +9,29 @@ jobs:
sync-assets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2.3.4
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@v1.5
- name: Verify Changed files
uses: tj-actions/verify-changed-files@v14
uses: tj-actions/verify-changed-files@v7
id: verify_changed_files
with:
files: |
README.md
- 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
with:
base: "main"
labels: "merge when passing"
title: "Updated README.md"
branch: "chore/update-readme"
commit-message: "Updated README.md"

107
.gitignore vendored
View File

@@ -1,107 +1,2 @@
# 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

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"
}

6344
HISTORY.md

File diff suppressed because it is too large Load Diff

902
README.md
View File

@@ -1,75 +1,38 @@
[![Ubuntu](https://img.shields.io/badge/Ubuntu-E95420?style=for-the-badge\&logo=ubuntu\&logoColor=white)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
[![Mac OS](https://img.shields.io/badge/mac%20os-000000?style=for-the-badge\&logo=macos\&logoColor=F0F0F0)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
[![Windows](https://img.shields.io/badge/Windows-0078D6?style=for-the-badge\&logo=windows\&logoColor=white)](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
[![Public workflows that use this action.](https://img.shields.io/endpoint?style=for-the-badge\&url=https%3A%2F%2Fused-by.vercel.app%2Fapi%2Fgithub-actions%2Fused-by%3Faction%3Dtj-actions%2Fchanged-files%26badge%3Dtrue)](https://github.com/search?o=desc\&q=tj-actions+changed-files+language%3AYAML\&s=\&type=Code)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4a625e9b62794b5b98e169c15c0e673c)](https://www.codacy.com/gh/tj-actions/changed-files/dashboard?utm_source=github.com\&utm_medium=referral\&utm_content=tj-actions/changed-files\&utm_campaign=Badge_Grade)
[![CI](https://github.com/tj-actions/changed-files/actions/workflows/test.yml/badge.svg)](https://github.com/tj-actions/changed-files/actions/workflows/test.yml)
[![Update release version.](https://github.com/tj-actions/changed-files/actions/workflows/sync-release-version.yml/badge.svg)](https://github.com/tj-actions/changed-files/actions/workflows/sync-release-version.yml)
[![CI](https://github.com/tj-actions/changed-files/actions/workflows/test.yml/badge.svg)](https://github.com/tj-actions/changed-files/actions/workflows/test.yml) [![Update release version.](https://github.com/tj-actions/changed-files/actions/workflows/sync-release-version.yml/badge.svg)](https://github.com/tj-actions/changed-files/actions/workflows/sync-release-version.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/a3822d6c37f644bc99a5faa0bfb9c2c1)](https://www.codacy.com/gh/tj-actions/changed-files/dashboard?utm_source=github.com\&utm_medium=referral\&utm_content=tj-actions/changed-files\&utm_campaign=Badge_Grade) [![Public workflows that use this action.](https://img.shields.io/endpoint?url=https%3A%2F%2Fapi-tj-actions1.vercel.app%2Fapi%2Fgithub-actions%2Fused-by%3Faction%3Dtj-actions%2Fchanged-files%26badge%3Dtrue)](https://github.com/search?o=desc\&q=tj-actions+changed-files+language%3AYAML\&s=\&type=Code)
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-20-orange.svg?style=flat-square)](#contributors-)
[![All Contributors](https://img.shields.io/badge/all_contributors-3-orange.svg?style=flat-square)](#contributors-)
<!-- ALL-CONTRIBUTORS-BADGE:END -->
<div align="center">
<img width="auto" alt="Screen Shot 2021-11-19 at 4 59 21 PM" src="https://user-images.githubusercontent.com/17484350/229027815-eee0bf22-f3e5-444d-9d90-6409c68a0dc9.png">
</div>
## changed-files
Retrieve all changed files and directories relative to a target branch, preceeding commit or the last remote commit returning a **relative path** from the project root.
## Table of contents
* [Features](#features)
* [Usage](#usage)
* [Useful Acronyms](#useful-acronyms)
* [Outputs](#outputs)
* [Inputs](#inputs)
* [Versioning](#versioning)
* [Examples](#examples)
* [Real world usage](#real-world-usage)
* [Known Limitation](#known-limitation)
* [Migration guide](#migration-guide)
* [Credits](#credits)
* [Report Bugs](#report-bugs)
* [Contributors ✨](#contributors-)
Retrieve all changed files relative to the default branch (`pull_request*` based events) or a previous commit (`push` based event) returning the **absolute path** to all changed files from the project root.
## Features
* Fast execution (0-10 seconds on average).
* Easy to debug.
* Scales to large repositories.
* Supports Git submodules.
* Escaped JSON output which can be used to run matrix jobs based on changed files.
* List changed directories.
* Restrict the max depth of matching changed directories.
* Write outputs to a `.txt` or `.json` file at a specified location for further processing.
* Monorepos (Fetches a fixed number of commits).
* Supports all platforms (Linux, MacOS, Windows).
* [GitHub-hosted runners](https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners) support
* [GitHub Enterprise Server](https://docs.github.com/en/enterprise-server@3.3/admin/github-actions/getting-started-with-github-actions-for-your-enterprise/getting-started-with-github-actions-for-github-enterprise-server) support.
* [self-hosted runners](https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners) support.
* List all files and directories that have changed:
* Between the current pull request branch and the last commit on the target branch.
* Boolean output indicating that certain files have been modified.
* List all files that have changed.
* Between the current pull request branch and the default branch.
* Between the last commit and the current pushed change.
* Between the last remote branch commit and the current HEAD.
* Restrict change detection to a subset of files and directories:
* Boolean output indicating that certain files have been changed.
* Using [Glob pattern](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet) matching.
* Brace expansion.
* Restrict change detection to a subset of files.
* Report on files that have at least one change.
* [Regex pattern](https://www.gnu.org/software/grep/manual/grep.html#Regular-Expressions) matching on a subset of files.
## Supported Platforms
* [`ubuntu-*`](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
* [`macos-*`](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
* [`windows-*`](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
## Usage
> **Warning**:
> NOTE: :warning:
>
> * **IMPORTANT:** For `push` events when configuring [`actions/checkout`](https://github.com/actions/checkout#usage) the `fetch-depth` should be set to either `fetch-depth: 0` **OR** `fetch-depth: 2` depending on your use case.
> * For monorepos where pulling all the branch history might not be desired, you can omit [`actions/checkout`](https://github.com/actions/checkout#usage) - `fetch-depth` for `pull_request` events.
> * For files located in a sub-directory ensure that the pattern specified contains `**/` (globstar) to match any preceding directories or explicitly pass the full path relative to the project root. See: [Pattern Gotcha](https://github.com/tj-actions/glob#pattern-gotcha).
> * All multiline inputs should not use double or single quotes since the value is already a string seperated by a newline character. See [Examples](#examples) for more information.
> * Ensure that `persist-credentials` is set to `true` when configuring [`actions/checkout`](https://github.com/actions/checkout#usage) if `fetch-depth` isn't set to `0`.
> * **IMPORTANT:** For `push` events you need to include `fetch-depth: 0` **OR** `fetch-depth: 2` depending on your use case.
> * When using `persist-credentials: false` with `actions/checkout@v2` you'll need to specify a `token` using the `token` input.
```yaml
name: CI
@@ -82,698 +45,188 @@ on:
branches:
- main
# -------------------------------------------------------------------------------------------------------------------------
# Event `push`: Compare the preceeding commit -> to the current commit of the main branch.
# Event `pull_request`: Compare the last commit of main -> to the current commit of a Pull Request branch.
# -------------------------------------------------------------------------------------------------------------------------
jobs:
build:
runs-on: ubuntu-latest # windows-latest | macos-latest
name: Test changed-files
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v2
with:
fetch-depth: 0 # OR "2" -> To retrieve the preceding commit.
# Example 1
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
# To compare changes between the current commit and the last pushed remote commit set `since_last_remote_commit: true`. e.g
# with:
# since_last_remote_commit: true
- name: List all changed files
run: |
for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
echo "$file was changed"
done
# Example 2
- name: Get changed files in the docs folder
id: changed-files-specific
uses: tj-actions/changed-files@v36
with:
files: docs/*.{js,html} # Alternatively using: `docs/**` or `docs`
- name: Run step if any file(s) in the docs folder change
if: steps.changed-files-specific.outputs.any_changed == 'true'
run: |
echo "One or more files in the docs folder has changed."
echo "List all the files that have changed: ${{ steps.changed-files-specific.outputs.all_changed_files }}"
uses: tj-actions/changed-files@v9.3
# Example 3
- name: Get all changed *.js file(s) or any file in the static folder excluding the docs folder
id: changed-files-excluded
uses: tj-actions/changed-files@v36
with:
files: |
**/*.js
static
files_ignore: docs
- name: Run step if any *.js file(s) or any file in the static folder change
if: steps.changed-files-excluded.outputs.any_changed == 'true'
- name: List all modified files
run: |
echo "One or more *.js file(s) or any file in the static folder but not in the doc folder has changed."
echo "List all the files that have changed: ${{ steps.changed-files-excluded.outputs.all_changed_files }}"
for file in "${{ steps.changed-files.outputs.all_modified_files }}"; do
echo "$file was modified"
done
```
To access more examples, navigate to the [Examples](#examples) section.
If you feel generous and want to show some extra appreciation:
Support this project with a :star:
[![Buy me a coffee][buymeacoffee-shield]][buymeacoffee]
[buymeacoffee]: https://www.buymeacoffee.com/jackton1
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png
## Useful Acronyms
| Acronym | Meaning |
|:---------:|:------------:|
| A | Added |
| C | Copied |
| M | Modified |
| D | Deleted |
| R | Renamed |
| T | Type changed |
| U | Unmerged |
| X | Unknown |
## Outputs
<!-- AUTO-DOC-OUTPUT:START - Do not remove or modify this section -->
| Acronym | Meaning |
|:---------:|:------------:|
| A | Added |
| C | Copied |
| M | Modified |
| D | Deleted |
| R | Renamed |
| T | Type changed |
| U | Unmerged |
| X | Unknown |
| OUTPUT | TYPE | DESCRIPTION |
|--------------------------------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| added\_files | string | Returns only files that are <br>Added (A). |
| all\_changed\_and\_modified\_files | string | Returns all changed and modified <br>files i.e. *a combination of (ACMRDTUX)* |
| all\_changed\_files | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified and renamed files (ACMR)* |
| all\_modified\_files | string | Returns all changed files i.e. <br>*a combination of all added, copied, modified, renamed and deleted files (ACMRD)*. |
| all\_old\_new\_renamed\_files | string | Returns only files that are <br>Renamed and list their old <br>and new names. **NOTE:** This <br>requires setting `include_all_old_new_renamed_files` to `true` <br>(R) |
| any\_changed | string | Returns `true` when any of <br>the filenames provided using the <br>`files` input has changed. i.e. <br>*using a combination of all added, copied, modified and renamed files (ACMR)*. |
| any\_deleted | string | Returns `true` when any of <br>the filenames provided using the <br>`files` input has been deleted. <br>(D) |
| any\_modified | string | Returns `true` when any of <br>the filenames provided using the <br>`files` input has been modified. <br>i.e. *using a combination of all added, copied, modified, renamed, and deleted files (ACMRD)*. |
| copied\_files | string | Returns only files that are <br>Copied (C). |
| deleted\_files | string | Returns only files that are <br>Deleted (D). |
| modified\_files | string | Returns only files that are <br>Modified (M). |
| only\_changed | string | Returns `true` when only files <br>provided using the `files` input <br>has changed. i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. |
| only\_deleted | string | Returns `true` when only files <br>provided using the `files` input <br>has been deleted. (D) |
| only\_modified | string | Returns `true` when only files <br>provided using the `files` input <br>has been modified. (ACMRD). |
| other\_changed\_files | string | Returns all other changed files <br>not listed in the files <br>input i.e. *using a combination of all added, copied, modified and renamed files (ACMR)*. |
| other\_deleted\_files | string | Returns all other deleted files <br>not listed in the files <br>input i.e. *a combination of all deleted files (D)* |
| other\_modified\_files | string | Returns all other modified files <br>not listed in the files <br>input i.e. *a combination of all added, copied, modified, and deleted files (ACMRD)* |
| renamed\_files | string | Returns only files that are <br>Renamed (R). |
| type\_changed\_files | string | Returns only files that have <br>their file type changed (T). |
| unknown\_files | string | Returns only files that are <br>Unknown (X). |
| unmerged\_files | string | Returns only files that are <br>Unmerged (U). |
<!-- AUTO-DOC-OUTPUT:END -->
| Output | type | example | description |
|:--------------------:|:------------:|:----------------------------------:|:----------------------------------------:|
| any_changed | `string` | `true` OR `false` | Returns `true` when any <br /> of the filenames provided using <br /> the `files` input has changed (ACMDR) |
| only_changed | `string` | `true` OR `false` | Returns `true` when only <br /> files provided using <br /> the `files` input have changed. |
| other_changed_files | `string` | `'new.txt path/to/file.png ...'` | Select all modified files <br/> not listed in the files input <br /> i.e. *a combination of all added, <br /> copied and modified files (ACM).* |
| all_modified_files | `string` | `'new.txt path/to/file.png ...'` | Select all modified files <br /> i.e. *a combination of all added, <br />copied, modified and renamed files (ACMR).* |
| all_changed_files | `string` | `'new.txt path/to/file.png ...'` | Select all paths (\*) <br /> i.e. *a combination of all options below.* |
| added_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Added (A) |
| copied_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Copied (C) |
| deleted_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Deleted (D) |
| modified_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Modified (M) |
| renamed_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Renamed (R) |
| type_changed_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that have their file type changed (T) |
| unmerged_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unmerged (U) |
| unknown_files | `string` | `'new.txt path/to/file.png ...'` | Select only files that are Unknown (X) |
## Inputs
<!-- AUTO-DOC-INPUT:START - Do not remove or modify this section -->
| Input | type | required | default | description |
|:-------------:|:-----------:|:-------------:|:-----------------------------:|:-------------:|
| token | `string` | `false` | `${{ github.token }}` | [GITHUB_TOKEN](https://docs.github.com/en/free-pro-team@latest/actions/reference/authentication-in-a-workflow#using-the-github_token-in-a-workflow) <br /> or a repo scoped <br /> [Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) |
| separator | `string` | `true` | `' '` | Output string separator |
| files | `string` OR `string[]` | `false` | | Check for changes <br> using only these <br> list of file(s) <br> (Defaults to the <br> entire repo) |
| base_sha | `string` | `false` | | Specify a different <br> base commit SHA <br> used for <br> comparing changes |
| sha | `string` | `true` | `${{ github.sha }}` | Specify a different <br> commit SHA <br> used for <br> comparing changes |
| files_from_source_file | `string` | `false` | | Source file <br> used to populate <br> the files input |
| INPUT | TYPE | REQUIRED | DEFAULT | DESCRIPTION |
|-----------------------------------------|--------|----------|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| base\_sha | string | false | | Specify a different base commit <br>SHA used for comparing changes |
| diff\_relative | string | false | `"true"` | Exclude changes outside the current <br>directory and show path names <br>relative to it. **NOTE:** This <br>requires you to specify the <br>top level directory via the <br>`path` input. |
| dir\_names | string | false | `"false"` | Output unique changed directories instead <br>of filenames. **NOTE:** This returns <br>`.` for changed files located <br>in the root of the <br>project. |
| dir\_names\_exclude\_root | string | false | `"false"` | Exclude the root directory represented <br>by `.` from the output <br>when `dir_names`is set to `true`. |
| dir\_names\_max\_depth | string | false | | Maximum depth of directories to <br>output. e.g `test/test1/test2` with max <br>depth of `2` returns `test/test1`. |
| escape\_json | string | false | `"true"` | Escape JSON output. |
| fetch\_depth | string | false | `"50"` | Depth of additional branch history <br>fetched. **NOTE**: This can be <br>adjusted to resolve errors with <br>insufficient history. |
| files | string | false | | File and directory patterns to <br>detect changes using only these <br>list of file(s) (Defaults to the entire repo) **NOTE:** <br>Multiline file/directory patterns should not <br>include quotes. |
| files\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files` input. |
| files\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_from_source_file` input |
| files\_ignore | string | false | | Ignore changes to these file(s) <br>**NOTE:** Multiline file/directory patterns should <br>not include quotes. |
| files\_ignore\_from\_source\_file | string | false | | Source file(s) used to populate <br>the `files_ignore` input |
| files\_ignore\_from\_source\_file\_separator | string | false | `"\n"` | Separator used to split the <br>`files_ignore_from_source_file` input |
| files\_ignore\_separator | string | false | `"\n"` | Separator used to split the <br>`files_ignore` input |
| files\_separator | string | false | `"\n"` | Separator used to split the <br>`files` input |
| include\_all\_old\_new\_renamed\_files | string | false | `"false"` | Include `all_old_new_renamed_files` output. Note this <br>can generate a large output <br>See: [#501](https://github.com/tj-actions/changed-files/issues/501). |
| json | string | false | `"false"` | Output list of changed files <br>in a JSON formatted string <br>which can be used for <br>matrix jobs. |
| old\_new\_files\_separator | string | false | `" "` | Split character for old and <br>new renamed filename pairs. |
| old\_new\_separator | string | false | `","` | Split character for old and <br>new filename pairs. |
| output\_dir | string | false | `".github/outputs"` | Directory to store output files. |
| path | string | false | `"."` | Specify a relative path under <br>`$GITHUB_WORKSPACE` to locate the repository. |
| quotepath | string | false | `"true"` | Use non ascii characters to <br>match files and output the <br>filenames completely verbatim by setting <br>this to `false` |
| separator | string | false | `" "` | Split character for output strings |
| sha | string | false | | Specify a different commit SHA <br>used for comparing changes |
| since | string | false | | Get changed files for commits <br>whose timestamp is older than <br>the given time. |
| since\_last\_remote\_commit | string | false | `"false"` | Use the last commit on <br>the remote branch as the <br>`base_sha`. Defaults to the last <br>non merge commit on the <br>target branch for pull request <br>events and the previous remote <br>commit of the current branch <br>for push events. |
| until | string | false | | Get changed files for commits <br>whose timestamp is earlier than <br>the given time. |
| write\_output\_files | string | false | `"false"` | Write outputs to files in <br>the `.github/outputs` folder by default. |
<!-- AUTO-DOC-INPUT:END -->
## Versioning
This GitHub Action follows the principles of [Semantic Versioning](https://semver.org) for versioning releases.
The format of the version string is as follows:
major: is a major release number that indicates significant changes or new features that may not be backward compatible.
minor: is a minor release number that indicates minor changes or new features that are backward compatible.
patch : is a patch release number that indicates bug fixes or other small changes that are backward compatible.
## Examples
<details>
<summary>Get all changed files in the current branch</summary>
## Example
```yaml
...
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
...
```
</details>
<details>
<summary>Get all changed files and using a comma separator</summary>
```yaml
...
- name: Get all changed files and use a comma separator in the output
id: changed-files
uses: tj-actions/changed-files@v36
with:
separator: ","
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary> Get all changed files and list all added files</summary>
```yaml
...
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
- name: List all added files
run: |
for file in ${{ steps.changed-files.outputs.added_files }}; do
echo "$file was added"
done
...
```
See [outputs](#outputs) for a list of all available outputs.
</details>
<details>
<summary>Get all changed files and optionally run a step if a file was modified</summary>
```yaml
...
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
- name: Run a step if my-file.txt was modified
if: contains(steps.changed-files.outputs.modified_files, 'my-file.txt')
run: |
echo "my-file.txt file has been modified."
...
```
See [outputs](#outputs) for a list of all available outputs.
</details>
<details>
<summary>Get all changed files and write the outputs to a txt file</summary>
```yaml
...
- name: Get changed files and write the outputs to a txt file
id: changed-files-write-output-files-txt
uses: ./
with:
write_output_files: true
- name: Verify the contents of the .github/outputs/added_files.txt file
run: |
cat .github/outputs/added_files.txt
...
```
</details>
<details>
<summary>Get all changed files and write the outputs to a json file</summary>
```yaml
...
- name: Get changed files and write the outputs to a json file
id: changed-files-write-output-files-json
uses: ./
with:
json: true
write_output_files: true
- name: Verify the contents of the .github/outputs/added_files.json file
run: |
cat .github/outputs/added_files.json
...
```
</details>
<details>
<summary>Get all changed files using a list of files</summary>
```yaml
...
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v36
with:
files: |
my-file.txt
*.sh
*.png
!*.md
test_directory
**/*.sql
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files using a list of files and take action based on the changes</summary>
```yaml
...
- name: Get changed files
id: changed-files-specific
uses: tj-actions/changed-files@v36
with:
files: |
my-file.txt
*.sh
*.png
!*.md
test_directory
**/*.sql
- name: Run step if any of the listed files above change
if: steps.changed-files-specific.outputs.any_changed == 'true'
run: |
echo "One or more files listed above has changed."
- name: Run step if only the files listed above change
if: steps.changed-files-specific.outputs.only_changed == 'true'
run: |
echo "Only files listed above have changed."
- name: Run step if any of the listed files above is deleted
if: steps.changed-files-specific.outputs.any_deleted == 'true'
run: |
for file in ${{ steps.changed-files-specific.outputs.deleted_files }}; do
echo "$file was deleted"
done
- name: Run step if all listed files above have been deleted
if: steps.changed-files-specific.outputs.only_deleted == 'true'
run: |
for file in ${{ steps.changed-files-specific.outputs.deleted_files }}; do
echo "$file was deleted"
done
...
```
See [outputs](#outputs) for a list of all available outputs.
</details>
<details>
<summary>Get all changed files using a source file or list of file(s) to populate to files input</summary>
```yaml
...
- name: Get changed files using a source file or list of file(s) to populate to files input.
id: changed-files-specific-source-file
uses: tj-actions/changed-files@v36
with:
files_from_source_file: test/changed-files-list.txt
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get changed files using a source file or list of file(s) to populate to files input and optionally specify more files</summary>
```yaml
...
- name: Get changed files using a source file or list of file(s) to populate to files input and optionally specify more files.
id: changed-files-specific-source-file-and-specify-files
uses: tj-actions/changed-files@v36
with:
files_from_source_file: |
test/changed-files-list.txt
files: |
test.txt
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files using a different SHA</summary>
```yaml
...
- name: Get changed files using a different SHA
id: changed-files
uses: tj-actions/changed-files@v36
with:
sha: ${{ github.event.pull_request.head.sha }}
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files using a different base SHA</summary>
```yaml
...
- name: Get changed files using a different base SHA
id: changed-files
uses: tj-actions/changed-files@v36
with:
base_sha: ${{ github.event.pull_request.base.sha }}
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files between the previous tag and the current tag</summary>
```yaml
...
on:
push:
tags:
- 'v*'
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- uses: actions/checkout@v2
- name: Get changed files
- name: Get changed files using defaults
id: changed-files
uses: tj-actions/changed-files@v36
- name: Get changed files in the .github folder
id: changed-files-specific
uses: tj-actions/changed-files@v36
uses: tj-actions/changed-files@v9.3
- name: Get changed files using a comma separator
id: changed-files-comma
uses: tj-actions/changed-files@v9.3
with:
base_sha: ${{ steps.get-base-sha.outputs.base_sha }}
files: .github/**
separator: ","
- name: Run step if any file(s) in the .github folder change
if: steps.changed-files-specific.outputs.any_changed == 'true'
- name: List all added files
run: |
echo "One or more files in the .github folder has changed."
echo "List all the files that have changed: ${{ steps.changed-files-specific.outputs.all_changed_files }}"
...
```
for file in "${{ steps.changed-files.outputs.added_files }}"; do
echo "$file was added"
done
See [inputs](#inputs) for more information.
- name: Run step when a file changes
if: contains(steps.changed-files.outputs.modified_files, 'my-file.txt')
run: |
echo "Your file my-file.txt has been modified."
</details>
- name: Run step when a file has been deleted
if: contains(steps.changed-files.outputs.deleted_files, 'test.txt')
run: |
echo "Your test.txt has been deleted."
<details>
<summary>Get all changed files for a repository located in a different path</summary>
```yaml
...
- name: Checkout into dir1
uses: actions/checkout@v3
with:
fetch-depth: 0
path: dir1
- name: Run changed-files with defaults in dir1
id: changed-files-for-dir1
uses: tj-actions/changed-files@v36
with:
path: dir1
- name: List all added files in dir1
run: |
for file in ${{ steps.changed-files-for-dir1.outputs.added_files }}; do
echo "$file was added"
done
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files with non äšćįí characters i.e (Filename in other languages)</summary>
```yaml
...
- name: Run changed-files with quotepath disabled
id: changed-files-quotepath
uses: tj-actions/changed-files@v36
with:
quotepath: "false"
- name: Run changed-files with quotepath disabled for a specified list of file(s)
id: changed-files-quotepath-specific
uses: ./
with:
files: test/test-è.txt
quotepath: "false"
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files using the last successful commit of the base branch</summary>
<ul>
<li>
<details>
<summary>Push event</summary>
```yaml
...
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v6
- uses: nrwl/nx-set-shas@v3
id: last_successful_commit_push
with:
main-branch-name: ${{ steps.branch-name.outputs.current_branch }} # Get the last successful commit for the current branch.
workflow-id: 'test.yml'
- name: Run changed-files with the commit of the last successful test workflow run
id: changed-files-base-sha-push
uses: tj-actions/changed-files@v36
with:
base_sha: ${{ steps.last_successful_commit_push.outputs.base }}
...
```
</details>
</li>
<li>
<details>
<summary>Pull request events </summary>
```yaml
...
- name: Get branch name
id: branch-name
uses: tj-actions/branch-names@v5
- uses: nrwl/nx-set-shas@v3
id: last_successful_commit_pull_request
with:
main-branch-name: ${{ steps.branch-name.outputs.base_ref_branch }} # Get the last successful commit on master or main branch
workflow_id: 'test.yml'
- name: Run changed-files with the commit of the last successful test workflow run on main
id: changed-files-base-sha-pull-request
uses: tj-actions/changed-files@v36
with:
base_sha: ${{ steps.last_successful_commit_pull_request.outputs.base }}
...
```
</details>
</li>
</ul>
> **Warning**: This setting overrides the commit sha used by setting `since_last_remote_commit` to true.
> It is recommended to use either solution that works for your use case.
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files but only return the directory names</summary>
```yaml
...
- name: Run changed-files with dir_names
id: changed-files-dir-names
uses: tj-actions/changed-files@v36
with:
dir_names: "true"
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files and return JSON formatted outputs</summary>
```yaml
...
- name: Run changed-files with json output
id: changed-files-json
uses: tj-actions/changed-files@v36
with:
json: "true"
...
```
See [inputs](#inputs) for more information.
</details>
<details>
<summary>Get all changed files by commits pushed in the past</summary>
```yaml
...
- name: Get changed-files since 2022-08-19
id: changed-files-since
uses: tj-actions/changed-files@v36
with:
since: "2022-08-19"
- name: Get changed-files until 2022-08-20
id: changed-files-until
uses: tj-actions/changed-files@v36
with:
until: "2022-08-20"
...
```
See [inputs](#inputs) for more information.
</details>
## Real world usage
* [vitejs/vite: uses tj-actions/changed-files to automate testing](https://github.com/vitejs/vite/blob/8da04227d6f818a8ad9efc0056101968037c2e36/.github/workflows/ci.yml#L61)
* [qgis/QGIS: uses tj-actions/changed-files to automate spell checking](https://github.com/qgis/QGIS/blob/a5333497e90ac9de4ca70463d8e0b64c3f294d63/.github/workflows/code_layout.yml#L147)
* [coder/code-server: uses tj-actions/changed-files to automate detecting changes and run steps based on the outcome](https://github.com/coder/code-server/blob/c32a31d802f679846876b8ad9aacff6cf7b5361d/.github/workflows/build.yaml#L48)
* [tldr-pages/tldr: uses tj-actions/changed-files to automate detecting spelling errors](https://github.com/tldr-pages/tldr/blob/main/.github/workflows/codespell.yml#L14)
* [nodejs/docker-node: uses tj-actions/changed-files to generate matrix jobs based on changes detected](https://github.com/nodejs/docker-node/blob/3c4fa6daf06a4786d202f2f610351837806a0380/.github/workflows/build-test.yml#L29)
And many more...
## Known Limitation
> **Warning**:
>
> * Spaces in file names can introduce bugs when using bash loops. See: [#216](https://github.com/tj-actions/changed-files/issues/216)
> However, this action will handle spaces in file names, with a recommendation of using a separator to prevent hidden issues.
>
> ![Screen Shot 2021-10-23 at 9 37 34 AM](https://user-images.githubusercontent.com/17484350/138558767-b13c90bf-a1ae-4e86-9520-70a6a4624f41.png)
## Migration guide
With the switch from using grep's Extended regex to match files to the natively supported workflow glob pattern matching syntax introduced in [v13](https://github.com/tj-actions/changed-files/releases/tag/v13) you'll need to modify patterns used to match `files`.
```diff
...
- name: Get specific changed files
id: changed-files-specific
uses: tj-actions/changed-files@v24
uses: tj-actions/changed-files@v9.3
with:
files: |
- \.sh$
- .(sql|py)$
- ^(dir1|dir2)
+ *.{sh,sql,py}
+ dir1
+ dir2
my-file.txt
test.txt
new.txt
test_directory
*.sh
.(png|jpeg)$
.(sql)$
^(mynewfile|custom)
- name: Run step if any of the listed files above change
if: steps.changed-files-specific.outputs.any_changed == 'true'
run: |
echo "One or more files listed above has changed."
- name: Run step if only the files listed above change
if: steps.changed-files-specific.outputs.only_changed == 'true'
run: |
echo "Only files listed above have changed."
- name: Use a source file or list of file(s) to populate to files input.
id: changed-files-specific-source-file
uses: tj-actions/changed-files@v9.3
with:
files_from_source_file: |
test/changed-files-list.txt
- name: Use a source file or list of file(s) to populate to files input and optionally specify more files.
id: changed-files-specific-source-file-and-specify-files
uses: tj-actions/changed-files@v9.3
with:
files_from_source_file: |
test/changed-files-list.txt
files: |
.github/workflows/rebase.yml
- name: Use a different commit SHA
id: changed-files-custom-sha
uses: tj-actions/changed-files@v9.3
with:
sha: ${{ github.event.pull_request.head.sha }}
- name: Use a different base SHA
id: changed-files-custom-base-sha
uses: tj-actions/changed-files@v9.3
with:
base_sha: "2096ed0"
```
### Running [pre-commit](https://pre-commit.com/) on all modified files
```yaml
...
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v9.3
- name: Pre-commit
uses: pre-commit/action@v2.0.0
with:
extra_args: -v --hook-stage push --files ${{ steps.changed-files.outputs.all_modified_files }}
token: ${{ secrets.github_token }}
```
![Screen Shot 2021-07-06 at 2 50 23 PM](https://user-images.githubusercontent.com/17484350/124651978-96ed5280-de69-11eb-86d5-396a4c1a980f.png)
![Screen Shot 2021-07-17 at 10 52 48 AM](https://user-images.githubusercontent.com/17484350/126040772-30b65afb-a6b5-4150-b312-ac2017ba7b98.png)
* Free software: [MIT license](LICENSE)
If you feel generous and want to show some extra appreciation:
Support me with a :star:
[![Buy me a coffee][buymeacoffee-shield]][buymeacoffee]
## Credits
This package was created with [cookiecutter-action](https://github.com/tj-actions/cookiecutter-action).
* [tj-actions/glob](https://github.com/tj-actions/glob)
* [tj-actions/auto-doc](https://github.com/tj-actions/auto-doc)
* [tj-actions/verify-changed-files](https://github.com/tj-actions/verify-changed-files)
* [tj-actions/demo](https://github.com/tj-actions/demo)
* [tj-actions/demo2](https://github.com/tj-actions/demo2)
* [tj-actions/demo3](https://github.com/tj-actions/demo3)
* [tj-actions/release-tagger](https://github.com/tj-actions/release-tagger)
This package was created with [Cookiecutter](https://github.com/cookiecutter/cookiecutter).
## Report Bugs
@@ -782,7 +235,7 @@ Report bugs at https://github.com/tj-actions/changed-files/issues.
If you are reporting a bug, please include:
* Your operating system name and version.
* Any details about your workflow that might be helpful in troubleshooting. (**NOTE**: Ensure that you include full log outputs with debugging enabled)
* Any details about your workflow that might be helpful in troubleshooting.
* Detailed steps to reproduce the bug.
## Contributors ✨
@@ -796,34 +249,11 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/jsoref"><img src="https://avatars.githubusercontent.com/u/2119212?v=4?s=100" width="100px;" alt="Josh Soref"/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=jsoref" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/monoxgas"><img src="https://avatars.githubusercontent.com/u/1223016?v=4?s=100" width="100px;" alt="Nick Landers"/><br /><sub><b>Nick Landers</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=monoxgas" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Kras4ooo"><img src="https://avatars.githubusercontent.com/u/1948054?v=4?s=100" width="100px;" alt="Krasimir Nikolov"/><br /><sub><b>Krasimir Nikolov</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=Kras4ooo" title="Code">💻</a> <a href="https://github.com/tj-actions/changed-files/commits?author=Kras4ooo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/IvanPizhenko"><img src="https://avatars.githubusercontent.com/u/11859904?v=4?s=100" width="100px;" alt="Ivan Pizhenko"/><br /><sub><b>Ivan Pizhenko</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=IvanPizhenko" title="Code">💻</a> <a href="https://github.com/tj-actions/changed-files/commits?author=IvanPizhenko" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/talva-tr"><img src="https://avatars.githubusercontent.com/u/82046981?v=4?s=100" width="100px;" alt="talva-tr"/><br /><sub><b>talva-tr</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=talva-tr" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=100" width="100px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=eltociear" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zamiell"><img src="https://avatars.githubusercontent.com/u/5511220?v=4?s=100" width="100px;" alt="James"/><br /><sub><b>James</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=Zamiell" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/wushujames"><img src="https://avatars.githubusercontent.com/u/677529?v=4?s=100" width="100px;" alt="James Cheng"/><br /><sub><b>James Cheng</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=wushujames" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://qiita.com/SUZUKI_Masaya"><img src="https://avatars.githubusercontent.com/u/15100604?v=4?s=100" width="100px;" alt="Masaya Suzuki"/><br /><sub><b>Masaya Suzuki</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=massongit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://fagai.net"><img src="https://avatars.githubusercontent.com/u/1772112?v=4?s=100" width="100px;" alt="fagai"/><br /><sub><b>fagai</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=fagai" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/pkit"><img src="https://avatars.githubusercontent.com/u/805654?v=4?s=100" width="100px;" alt="Constantine Peresypkin"/><br /><sub><b>Constantine Peresypkin</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=pkit" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/deronnax"><img src="https://avatars.githubusercontent.com/u/439279?v=4?s=100" width="100px;" alt="Mathieu Dupuy"/><br /><sub><b>Mathieu Dupuy</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=deronnax" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/JoeOvo"><img src="https://avatars.githubusercontent.com/u/100686542?v=4?s=100" width="100px;" alt="Joe Moggridge"/><br /><sub><b>Joe Moggridge</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=JoeOvo" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.credly.com/users/thyarles/badges"><img src="https://avatars.githubusercontent.com/u/1340046?v=4?s=100" width="100px;" alt="Charles Santos"/><br /><sub><b>Charles Santos</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=thyarles" title="Code">💻</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/kostiantyn-korniienko-aurea"><img src="https://avatars.githubusercontent.com/u/37180625?v=4?s=100" width="100px;" alt="Kostiantyn Korniienko"/><br /><sub><b>Kostiantyn Korniienko</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=kostiantyn-korniienko-aurea" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lpulley"><img src="https://avatars.githubusercontent.com/u/7193187?v=4?s=100" width="100px;" alt="Logan Pulley"/><br /><sub><b>Logan Pulley</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=lpulley" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/kenji-miyake/"><img src="https://avatars.githubusercontent.com/u/31987104?v=4?s=100" width="100px;" alt="Kenji Miyake"/><br /><sub><b>Kenji Miyake</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=kenji-miyake" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/adonisgarciac"><img src="https://avatars.githubusercontent.com/u/71078987?v=4?s=100" width="100px;" alt="adonisgarciac"/><br /><sub><b>adonisgarciac</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=adonisgarciac" title="Code">💻</a> <a href="https://github.com/tj-actions/changed-files/commits?author=adonisgarciac" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/cfernhout"><img src="https://avatars.githubusercontent.com/u/22294606?v=4?s=100" width="100px;" alt="Chiel Fernhout"/><br /><sub><b>Chiel Fernhout</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=cfernhout" title="Documentation">📖</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/albertoperdomo2"><img src="https://avatars.githubusercontent.com/u/62241095?v=4?s=100" width="100px;" alt="Alberto Perdomo"/><br /><sub><b>Alberto Perdomo</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=albertoperdomo2" title="Documentation">📖</a></td>
</tr>
</tbody>
<tr>
<td align="center"><a href="https://github.com/jsoref"><img src="https://avatars.githubusercontent.com/u/2119212?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Josh Soref</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=jsoref" title="Documentation">📖</a></td>
<td align="center"><a href="https://github.com/monoxgas"><img src="https://avatars.githubusercontent.com/u/1223016?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Nick Landers</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=monoxgas" title="Code">💻</a></td>
<td align="center"><a href="https://github.com/Kras4ooo"><img src="https://avatars.githubusercontent.com/u/1948054?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Krasimir Nikolov</b></sub></a><br /><a href="https://github.com/tj-actions/changed-files/commits?author=Kras4ooo" title="Code">💻</a> <a href="https://github.com/tj-actions/changed-files/commits?author=Kras4ooo" title="Documentation">📖</a></td>
</tr>
</table>
<!-- markdownlint-restore -->
@@ -833,3 +263,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
[buymeacoffee]: https://www.buymeacoffee.com/jackton1
[buymeacoffee-shield]: https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png

View File

@@ -1,165 +1,105 @@
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'
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."
required: false
default: "false"
write_output_files:
description: "Write outputs to files in the `.github/outputs` folder by default."
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)."
all_changed_and_modified_files:
description: "Returns all changed and modified files i.e. *a combination of (ACMRDTUX)*"
description: List of unknown files.
value: ${{ steps.changed-files.outputs.unknown_files }}
all_changed_files:
description: "Returns all changed files i.e. *a combination of all added, copied, modified and renamed files (ACMR)*"
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)*."
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)*."
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: List of all changed files.
value: ${{ steps.changed-files.outputs.all_changed_files }}
all_modified_files:
description: "Returns all changed files i.e. *a combination of all added, copied, modified, renamed and deleted files (ACMRD)*."
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)*."
only_modified:
description: "Returns `true` when only files provided using the `files` input has been modified. (ACMRD)."
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)*"
any_deleted:
description: "Returns `true` when any of the filenames provided using the `files` input has been deleted. (D)"
only_deleted:
description: "Returns `true` when only files provided using the `files` input has been deleted. (D)"
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: List of all copied modified and added files.
value: ${{ steps.changed-files.outputs.all_modified_files }}
any_changed:
description: Return true only when any files provided using the files input have changed.
value: ${{ steps.changed-files.outputs.any_changed }}
only_changed:
description: Return true only when only files provided using the files input have changed.
value: ${{ steps.changed-files.outputs.only_changed }}
other_changed_files:
description: Return list of changed files not listed in the files input.
value: ${{ steps.changed-files.outputs.other_changed_files }}
runs:
using: 'node16'
main: 'dist/index.js'
using: 'composite'
steps:
- run: |
FILES=()
if [[ -n $INPUT_FILES_FROM_SOURCE_FILE ]]; then
for file in $INPUT_FILES_FROM_SOURCE_FILE
do
FILES+=$(cat $file | sort -u | tr "\n" " " )
done
fi
echo "::set-output name=files::$FILES"
id: source-input-files
shell: bash
env:
INPUT_FILES: ${{ inputs.files }}
INPUT_FILES_FROM_SOURCE_FILE: ${{ inputs.files_from_source_file }}
- run: |
bash $GITHUB_ACTION_PATH/entrypoint.sh
id: changed-files
shell: bash
env:
GITHUB_BASE_REF: ${{ github.base_ref }}
GITHUB_REPOSITORY: ${{ github.repository }}
# 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: ${{ inputs.base_sha }}
INPUT_TOKEN: ${{ inputs.token }}
INPUT_FILES: ${{ join(format('{0} {1}', inputs.files, steps.source-input-files.outputs.files), ' ') }}
INPUT_SEPARATOR: ${{ inputs.separator }}
branding:
icon: file-text

9884
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

180
entrypoint.sh Executable file
View File

@@ -0,0 +1,180 @@
#!/usr/bin/env bash
set -e
echo "::warning::Legacy version detected, please switch to the recommended v10.x. See https://github.com/tj-actions/changed-files#versioning for more information"
echo "::group::changed-files"
git remote add temp_changed_files "https://${INPUT_TOKEN}@github.com/${GITHUB_REPOSITORY}"
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
fi
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to determine the current head sha"
exit 1
fi
if [[ -z $GITHUB_BASE_REF ]]; then
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
fi
TARGET_BRANCH=${GITHUB_REF/refs\/heads\//}
CURRENT_BRANCH=$TARGET_BRANCH
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to determine the previous commit sha"
echo "::warning::You seem to be missing 'fetch-depth: 0' or 'fetch-depth: 2'. See https://github.com/tj-actions/changed-files#usage"
exit 1
fi
else
TARGET_BRANCH=$GITHUB_BASE_REF
CURRENT_BRANCH=$GITHUB_HEAD_REF
git fetch temp_changed_files "${TARGET_BRANCH}":"${TARGET_BRANCH}"
if [[ -z $INPUT_BASE_SHA ]]; then
PREVIOUS_SHA=$(git rev-parse "${TARGET_BRANCH}" 2>&1) && exit_status=$? || exit_status=$?
else
PREVIOUS_SHA=$INPUT_BASE_SHA
fi
if [[ $exit_status -ne 0 ]]; then
echo "::warning::Unable to determine the base ref sha for ${TARGET_BRANCH}"
exit 1
fi
fi
echo "Retrieving changes between $PREVIOUS_SHA ($TARGET_BRANCH) → $CURRENT_SHA ($CURRENT_BRANCH)"
UNIQUE_FILES=$(echo "$INPUT_FILES" | tr ' ' '\n' | sort -u | xargs)
if [[ -z "$UNIQUE_FILES" ]]; then
echo "Getting diff..."
ADDED=$(git diff --diff-filter=A --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
COPIED=$(git diff --diff-filter=C --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
DELETED=$(git diff --diff-filter=D --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
MODIFIED=$(git diff --diff-filter=M --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
RENAMED=$(git diff --diff-filter=R --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
TYPE_CHANGED=$(git diff --diff-filter=T --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
UNMERGED=$(git diff --diff-filter=U --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
UNKNOWN=$(git diff --diff-filter=X --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
ALL_CHANGED=$(git diff --diff-filter="*ACDMRTUX" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
ALL_MODIFIED_FILES=$(git diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | tr "\n" "$INPUT_SEPARATOR" | sed -E "s/($INPUT_SEPARATOR)$//")
else
ADDED_ARRAY=()
COPIED_ARRAY=()
DELETED_ARRAY=()
MODIFIED_ARRAY=()
RENAMED_ARRAY=()
TYPE_CHANGED_ARRAY=()
UNMERGED_ARRAY=()
UNKNOWN_ARRAY=()
ALL_CHANGED_ARRAY=()
ALL_MODIFIED_FILES_ARRAY=()
for path in ${UNIQUE_FILES}
do
echo "Checking for file changes: \"${path}\"..."
IFS=" "
# shellcheck disable=SC2207
ADDED_ARRAY+=($(git diff --diff-filter=A --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
COPIED_ARRAY+=($(git diff --diff-filter=C --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
DELETED_ARRAY+=($(git diff --diff-filter=D --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
MODIFIED_ARRAY+=($(git diff --diff-filter=M --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
RENAMED_ARRAY+=($(git diff --diff-filter=R --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
TYPE_CHANGED_ARRAY+=($(git diff --diff-filter=T --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
UNMERGED_ARRAY+=($(git diff --diff-filter=U --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
UNKNOWN_ARRAY+=($(git diff --diff-filter=X --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
ALL_CHANGED_ARRAY+=($(git diff --diff-filter="*ACDMRTUX" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
# shellcheck disable=SC2207
ALL_MODIFIED_FILES_ARRAY+=($(git diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA" | grep -E "(${path})" | xargs || true))
done
# shellcheck disable=SC2001
ADDED=$(echo "${ADDED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
COPIED=$(echo "${COPIED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
DELETED=$(echo "${DELETED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
MODIFIED=$(echo "${MODIFIED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
RENAMED=$(echo "${RENAMED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
TYPE_CHANGED=$(echo "${TYPE_CHANGED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
UNMERGED=$(echo "${UNMERGED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
UNKNOWN=$(echo "${UNKNOWN_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
ALL_CHANGED=$(echo "${ALL_CHANGED_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
# shellcheck disable=SC2001
ALL_MODIFIED_FILES=$(echo "${ALL_MODIFIED_FILES_ARRAY[*]}" | sed 's/ */'"$INPUT_SEPARATOR"'/g' | tr ' ' '\n' | sort -u | xargs)
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 files: $ALL_CHANGED"
echo "All modified files: $ALL_MODIFIED_FILES"
if [[ -n "$UNIQUE_FILES" ]]; then
# shellcheck disable=SC2001
ALL_INPUT_FILES=$(echo "$UNIQUE_FILES" | tr "\n" " " | xargs)
ALL_OTHER_CHANGED_FILES=$(git diff --diff-filter="ACMR" --name-only "$PREVIOUS_SHA" "$CURRENT_SHA")
OTHER_CHANGED_FILES=$(echo "${ALL_OTHER_CHANGED_FILES[@]}" "${ALL_MODIFIED_FILES[@]}" | tr ' ' '\n' | sort | uniq -u | tr "\n" " " | xargs)
echo "Input files: ${ALL_INPUT_FILES[*]}"
echo "Matching modified files: ${ALL_MODIFIED_FILES[*]}"
if [[ -n "$ALL_MODIFIED_FILES" ]]; then
echo "::set-output name=any_changed::true"
else
echo "::set-output name=any_changed::false"
fi
if [[ -n "$OTHER_CHANGED_FILES" ]]; then
echo "Non Matching modified files: ${OTHER_CHANGED_FILES[*]}"
echo "::set-output name=only_changed::false"
echo "::set-output name=other_changed_files::$OTHER_CHANGED_FILES"
else
echo "::set-output name=only_changed::true"
fi
fi
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_files::$ALL_CHANGED"
echo "::set-output name=all_modified_files::$ALL_MODIFIED_FILES"
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"
@@ -22,7 +21,7 @@
},
"packageRules": [
{
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"matchUpdateTypes": ["major", "minor", "patch", "pin", "digest"],
"automerge": true,
"rebaseWhen": "behind-base-branch",
"addLabels": [
@@ -34,7 +33,7 @@
"matchLanguages": [
"docker"
],
"matchUpdateTypes": ["minor", "patch", "pin", "digest"],
"matchUpdateTypes": ["major", "minor", "patch", "pin", "digest"],
"rebaseWhen": "behind-base-branch",
"addLabels": [
"automerge"

View File

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

View File

@@ -1,144 +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
})
)
files = [...new Set(files)]
}
if (inputs.json) {
return jsonOutput({value: files, shouldEscape: inputs.escapeJson})
}
return files.join(inputs.separator)
}

View File

@@ -1,474 +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
initialCommit?: boolean
}
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/heads/${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.debug(`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
}
if (
!previousSha ||
previousSha === '0000000000000000000000000000000000000000'
) {
previousSha = await getParentSha({
cwd: workingDirectory
})
} else if (
(await verifyCommitSha({
sha: previousSha,
cwd: workingDirectory,
showAsErrorMessage: false
})) !== 0
) {
core.warning(
`Previous commit ${previousSha} is not valid. Using parent commit.`
)
previousSha = await getParentSha({
cwd: workingDirectory
})
}
if (!previousSha || previousSha === currentSha) {
previousSha = await getParentSha({
cwd: workingDirectory
})
if (!previousSha) {
core.warning('Initial commit detected no previous commit found.')
initialCommit = true
previousSha = currentSha
}
}
}
}
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,
initialCommit
}
}
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.debug(`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,60 +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(`Env: ${JSON.stringify(process.env, null, 2)}`)
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 = Math.max(parseInt(fetchDepth, 10), 2)
}
if (dirNamesMaxDepth) {
inputs.dirNamesMaxDepth = parseInt(dirNamesMaxDepth, 10)
}
return inputs
}

View File

@@ -1,420 +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
)
}
if (diffResult.initialCommit) {
core.info('This is the first commit for this repository; exiting...')
core.endGroup()
return
}
core.info(
`Retrieving changes between ${diffResult.previousSha} (${diffResult.targetBranch}) → ${diffResult.currentSha} (${diffResult.currentBranch})`
)
const filePatterns = await getFilePatterns({
inputs,
workingDirectory
})
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,785 +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.RUNNER_DEBUG !== '1'}
)
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.RUNNER_DEBUG !== '1'
}
)
/* 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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
})
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.RUNNER_DEBUG !== '1'
}
)
/* 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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
})
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.RUNNER_DEBUG !== '1'
})
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.RUNNER_DEBUG !== '1'
}
)
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, exitCode} = await exec.getExecOutput(
'git',
['rev-list', '-n', '1', 'HEAD^'],
{
cwd,
ignoreReturnCode: true,
silent: process.env.RUNNER_DEBUG !== '1'
}
)
if (exitCode !== 0) {
return ''
}
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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.RUNNER_DEBUG !== '1'
}
)
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,
workingDirectory
}: {
inputs: Inputs
workingDirectory: string
}): 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 !== '')
.map(p => path.join(workingDirectory, 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 !== '')
.map(p => path.join(workingDirectory, 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

@@ -1,7 +1,4 @@
.github/workflows/test.yml
action.yml
action.yml
action.yml
**/test.txt
!test/test/test.txt
[test new].txt
test/changed-files-list.txt

Submodule test/demo deleted from 83ccca9b63

View File

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

View File

@@ -1 +0,0 @@
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 +0,0 @@
This is a test file.

View File

@@ -1 +0,0 @@
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"]
}

3714
yarn.lock

File diff suppressed because it is too large Load Diff