{"id":29917919,"url":"https://github.com/tchupp/actions-detect-directory-changes","last_synced_at":"2026-03-15T19:06:08.331Z","repository":{"id":42365157,"uuid":"470748807","full_name":"tchupp/actions-detect-directory-changes","owner":"tchupp","description":null,"archived":false,"fork":false,"pushed_at":"2024-08-22T13:54:19.000Z","size":116,"stargazers_count":5,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-08-02T06:24:59.030Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tchupp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-03-16T20:55:41.000Z","updated_at":"2025-07-23T13:36:19.000Z","dependencies_parsed_at":"2024-08-22T15:29:43.148Z","dependency_job_id":"84e5bd8e-4850-4cb7-b32d-6ed5c260795d","html_url":"https://github.com/tchupp/actions-detect-directory-changes","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"purl":"pkg:github/tchupp/actions-detect-directory-changes","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchupp%2Factions-detect-directory-changes","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchupp%2Factions-detect-directory-changes/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchupp%2Factions-detect-directory-changes/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchupp%2Factions-detect-directory-changes/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tchupp","download_url":"https://codeload.github.com/tchupp/actions-detect-directory-changes/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tchupp%2Factions-detect-directory-changes/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273322158,"owners_count":25085035,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-02T02:00:09.530Z","response_time":77,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-02T05:19:03.638Z","updated_at":"2026-03-15T19:06:03.276Z","avatar_url":"https://github.com/tchupp.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GitHub Actions: Detect Directory Changes\n\nGitHub Action for gathering directories with changed files.\n\n## Usage\n\nThis action can be used as follows:\n\n```yaml\n      - uses: tchupp/actions-detect-directory-changes@v1\n        with:\n          included-paths: \"\"\n          included-extensions: \"\"\n          if-these-paths-change-return-all-included-paths: \"\"\n```\n\n## Background\n\n### [Shut up and show me the copy/paste](#examples)\n\nThere are many existing GitHub Actions that allow you to detect the files that have changed:\n\n- https://github.com/tj-actions/changed-files\n- https://github.com/trilom/file-changes-action\n- https://github.com/UnicornGlobal/has-changes-action\n\nHowever, none of the existing solutions will group these changes files by the directory that changed.\n\nSome projects have multiple sub-projects with separate builds in one git repository.  \nLet's say your repo looked like this:\n\n```bash\n$ tree\n.\n├── my-awesome-nodejs-app\n│   ├── index.ts\n│   └── package.json\n└── a-neat-rust-project\n    ├── Cargo.toml\n    └── main.rs\n\n2 directories, 4 files\n```\n\nIt would be fairly reasonable to configure a GitHub Actions workflow that ran the build for each of your sub-projects:\n\n```yaml\non:\n  push:\n    branches:\n      - main\n  pull_request:\n    branches:\n      - main\n    paths:\n      - '.github/workflows/build.yml'\n\njobs:\n  build:\n    name: \"Build sub-projects\"\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        project:\n          - my-awesome-nodejs-app\n          - a-neat-rust-project\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Build ${{ matrix.project }}\n        working-directory: ./${{ matrix.project }}\n        run: ./build.sh\n```\n\nWith this type of setup, you end up waiting for all your sub-projects to build every push; causing you to spend a huge\namount on CI time for sub-projects that didn't even change!\n\n### That's where this action comes into play.\n\nUsing this action, you can detect the paths of files that have changed since your last push!  \nYou can use the output of this action to determine which sub-projects need to build.\n\n```yaml\non: \u003comitted for brevity, same as above\u003e\n\njobs:\n  detect-directory-changes:\n    name: \"Detect Directory Changes\"\n    runs-on: ubuntu-latest\n    outputs:\n      changed: ${{ steps.detect.outputs.changed }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Detect Directory Changes\n        id: detect\n        uses: tchupp/actions-detect-directory-changes@v1\n\n  build:\n    name: \"Build sub-projects\"\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        project: ${{ fromJSON(needs.detect-directory-changes.outputs.changed) }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Build ${{ matrix.project }}\n        working-directory: ./${{ matrix.project }}\n        run: ./build.sh\n```\n\nGiven our original repo layout, let's say a commit gets pushed where only `my-awesome-nodejs-app` is changed.  \nWhen the example workflow runs, this action would output a JSON array containing a list of the changed paths:\n\n```json\n[\n  \"my-awesome-nodejs-app\"\n]\n```\n\nThis is then used to build the `matrix` for the job that runs the build.  \nBy using this action, we have saved tons of CI time by skipping the build for configuration sets that didn't change!\n\n## Full Usage\n\nThis action can be used as follows:\n\n```yaml\n      - uses: tchupp/actions-detect-directory-changes@v1\n        with:\n          included-paths: \"\"\n          included-extensions: \"\" // ex. \"md,txt\" OR \"java,kotlin\" etc.\n```\n\n### Assumptions\n\nThe most common cause for issues involves a mismatch in expectations.  \nPlease read below to make sure your setup aligns with the assumptions made by this action.\n\n#### Setup\n\nThis action expects that the repo has been checked out.  \nThe following snippet from an example job, [which can be found below](#simple-setup).\n\n```yaml\n...\nsteps:\n  - name: Checkout\n    uses: actions/checkout@v2\n...\n```\n\n#### Repo Layout\n\nThis action is only really useful when you have multiple projects in a single repo.  \nFor instance if your repo only had a project set, this action might be overkill:\n\n```bash\n$ tree\n.\n└── my-awesome-nodejs-app\n    ├── index.ts\n    └── package.json\n\n1 directories, 2 files\n```\n\nWith a simple repo layout like this, it's sufficient to use `path` filters with GitHub Actions.\n\n### Inputs\n\nGiven the number of possible combinations of inputs, some possible use-cases may not be explicitly covered below.\n\n#### included-paths\n\n**Optional**. Comma-separated paths to narrow down the search for changes.  \nRespects \"unix style\" path globbing.  \nDefaults to all if not specified.\n\nThere are a lot of interesting use-cases for this input.\n\n#### included-extensions\n\n**Optional**. Comma-separated file extensions to narrow down the search for changes. Defaults to all if not specified.\n\nThere are a lot of interesting use-cases for this input.\n\n#### if-these-paths-change-return-all-included-paths\n\n**Note: I know the name is long and a little clunky, but it somewhat accurately describes how it works. Naming is hard.**\n\n**Optional**. Comma-separated paths to act as an override for the \"changed\" paths.  \nFor example you may want to rebuild everything if a change is detected in your CI configuration, \nor you may want to rebuild everything if a change is detected in a shared library.  \nThe possibilities are endless!\n\n\nRespects \"unix style\" path globbing.  \nDefaults to all if not specified.\n\nThere are a lot of interesting use-cases for this input.\n\n## Examples\n\n### Simple Setup\n\nThis is a simplified example based on the setup at the beginning. If your repo has multiple sub-projects sets and\ndoesn't have any top-level build:\n\n```bash\n$ tree\n.\n├── my-awesome-nodejs-app\n│   ├── index.ts\n│   └── package.json\n└── a-neat-rust-project\n    ├── Cargo.toml\n    └── main.rs\n\n2 directories, 4 files\n```\n\nThen your `.github/workflows/build.yml` file could use this:\n\n```yaml\non: \u003comitted for brevity, same as above\u003e\n\njobs:\n  detect-directory-changes:\n    name: \"Detect Directory Changes\"\n    runs-on: ubuntu-latest\n    outputs:\n      changed: ${{ steps.detect.outputs.changed }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Detect Directory Changes\n        id: detect\n        uses: tchupp/actions-detect-directory-changes@v1\n\n  build:\n    name: \"Build sub-projects\"\n    runs-on: ubuntu-latest\n    strategy:\n      matrix:\n        project: ${{ fromJSON(needs.detect-directory-changes.outputs.changed) }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Build ${{ matrix.project }}\n        working-directory: ./${{ matrix.project }}\n        run: ./build.sh\n```\n\n### Simple Setup with CI Configuration\n\nThis is a slightly more complete use-case.\nIf you were to include this action in your repo, you would likely have a `.github` directory that wouldn't contain a `./build.sh` script.\n\n```bash\n$ tree\n.\n├── .github\n│   └── workflows\n│       └── build.yml\n├── my-awesome-nodejs-app\n│   ├── index.ts\n│   └── package.json\n└── a-neat-rust-project\n    ├── Cargo.toml\n    └── main.rs\n\n4 directories, 5 files\n```\n\nThere are a few possible ways to handle this situation:\n\n#### Option 1: Use `included-extensions`\n\nYou could use `included-extensions` to ignore changes to `.yml` files, however this might prevent detection of changes in project-level `.yml` files:\n\n```yaml\non: \u003comitted for brevity, same as above\u003e\n\njobs:\n  detect-directory-changes:\n    name: \"Detect Directory Changes\"\n    runs-on: ubuntu-latest\n    outputs:\n      changed: ${{ steps.detect.outputs.changed }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Detect Directory Changes\n        id: detect\n        uses: tchupp/actions-detect-directory-changes@v1\n        with:\n          included-extensions: \"!*.yml\"\n\n  build: \u003comitted for brevity, same as above\u003e\n```\n\n#### Option 2: Use `included-paths`\n\nYou could use `included-paths` to only detect changes in the sub-projects, however this would require you to change some sub-project files anytime you wanted to trigger a rebuild:\n\n```yaml\non: \u003comitted for brevity, same as above\u003e\n\njobs:\n  detect-directory-changes:\n    name: \"Detect Directory Changes\"\n    runs-on: ubuntu-latest\n    outputs:\n      changed: ${{ steps.detect.outputs.changed }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Detect Directory Changes\n        id: detect\n        uses: tchupp/actions-detect-directory-changes@v1\n        with:\n          included-paths: \"!./.github/**\"\n\n  build: \u003comitted for brevity, same as above\u003e\n```\n\n\n#### Option 3: Use `if-these-paths-change-return-all-included-paths`\n\nWith this configuration, the action would still correctly detect changes in the sub-projects,\nbut would also trigger a rebuild on **all** sub-projects if any changes were detected in the `.github` directory:\n\n```yaml\non: \u003comitted for brevity, same as above\u003e\n\njobs:\n  detect-directory-changes:\n    name: \"Detect Directory Changes\"\n    runs-on: ubuntu-latest\n    outputs:\n      changed: ${{ steps.detect.outputs.changed }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n\n      - name: Detect Directory Changes\n        id: detect\n        uses: tchupp/actions-detect-directory-changes@v1\n        with:\n          included-paths: \"!./.github/**\"\n          if-these-paths-change-return-all-included-paths: \"./.github/**\"\n\n  build: \u003comitted for brevity, same as above\u003e\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftchupp%2Factions-detect-directory-changes","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftchupp%2Factions-detect-directory-changes","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftchupp%2Factions-detect-directory-changes/lists"}