{"id":40993403,"url":"https://github.com/hellofresh/action-changed-files","last_synced_at":"2026-01-22T08:04:22.857Z","repository":{"id":38845453,"uuid":"444865177","full_name":"hellofresh/action-changed-files","owner":"hellofresh","description":"GitHub Action for matrix generation based on changed files matched against regular expressions","archived":false,"fork":false,"pushed_at":"2025-10-07T05:12:12.000Z","size":107,"stargazers_count":38,"open_issues_count":6,"forks_count":9,"subscribers_count":120,"default_branch":"master","last_synced_at":"2025-12-01T06:49:40.147Z","etag":null,"topics":["github-actions","open-source","wiz-reliability-platform-cloud-runtime"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hellofresh.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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2022-01-05T16:02:56.000Z","updated_at":"2025-10-13T02:55:03.000Z","dependencies_parsed_at":"2025-10-07T07:06:54.962Z","dependency_job_id":"d9f6d534-ce78-4d1b-8bef-5af57005b3a3","html_url":"https://github.com/hellofresh/action-changed-files","commit_stats":{"total_commits":83,"total_committers":8,"mean_commits":10.375,"dds":0.4819277108433735,"last_synced_commit":"c5338e4409bc8a710c4b6b339aef615589787bda"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/hellofresh/action-changed-files","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellofresh%2Faction-changed-files","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellofresh%2Faction-changed-files/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellofresh%2Faction-changed-files/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellofresh%2Faction-changed-files/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hellofresh","download_url":"https://codeload.github.com/hellofresh/action-changed-files/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hellofresh%2Faction-changed-files/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28658976,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"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":["github-actions","open-source","wiz-reliability-platform-cloud-runtime"],"created_at":"2026-01-22T08:04:08.378Z","updated_at":"2026-01-22T08:04:22.852Z","avatar_url":"https://github.com/hellofresh.png","language":"Python","readme":"# action-changed-files \n\n![GitHub release (latest by date)](https://img.shields.io/github/v/release/hellofresh/action-changed-files?style=for-the-badge)\n![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/hellofresh/action-changed-files?style=for-the-badge)\n![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/hellofresh/action-changed-files/test.yaml?label=Status\u0026style=for-the-badge\u0026branch=master)\n![GitHub last commit](https://img.shields.io/github/last-commit/hellofresh/action-changed-files?style=for-the-badge)\n![GitHub Release Date](https://img.shields.io/github/release-date/hellofresh/action-changed-files?style=for-the-badge)\n![GitHub issues](https://img.shields.io/github/issues-raw/hellofresh/action-changed-files?style=for-the-badge)\n\n![GitHub](https://img.shields.io/github/license/hellofresh/action-changed-files?style=for-the-badge)\n\n\nGenerate a GitHub Actions job matrix based on changed files (with an extra twist).\n\n## Problem statement\n\nRepositories are often composed of multiple modules or directories that are built \u0026 deployed differently. They can represent a part of the system, or a specific environment. Modules like this also often share some common files.\n\nThe (traditional) and easiest way to guarantee that all changes are properly tested in CI is to run all jobs for every single change, but this can lead to a very long verification time.\n\nIdeally, you want to be able to trigger (and skip) jobs based on the contents (and type) of a change.\n\n[Trigger paths](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#example-including-paths) and [matrix job strategy](https://docs.github.com/en/actions/learn-github-actions/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix) are two great features that can help reducing verification time, but they're still not flexible enough.\n\n## Example\n\n### Sample repository\n\n`neo` helps with generating a job matrix based on the changed files in a pull-request, or after merging it to the target branch.\n\nConsider the following repository directory structure:\n\n```\n├── infrastructure\n│   ├── live       # depends on terraform-modules\n|   |── staging    # depends on terraform-modules\n├── library\n│   ├── common\n│   ├── parser     # depends on library/common\n│   ├── network    # depends on library/common\n|── terraform-modules\n|── deploy.sh      # used in CI to deploy infrastructure\n|── Makefile       # used in CI to build library\n```\n\nand that we want to:\n\n* verify \u0026 deploy changes to infrastructure as code affecting the `live` and `staging` environments\n* build \u0026 test changes to `library/parser` and `library/network`\n\n### Sample workflow\n\n```yaml\nname: Sample workflow\n\non:\n  pull_request:\n    branches:\n      - master\n\njobs:\n  generate-matrix:\n    name: Generate job matrices\n    runs-on: ubuntu-latest\n    # don't forget to declare outputs here!\n    outputs:\n      matrix-infrastructure: ${{ steps.neo-infrastructure.outputs.matrix }}\n      matrix-library: ${{ steps.neo-library.outputs.matrix }}\n    steps:\n      - name: Generate matrix | Infrastructure\n        id: neo-infrastructure\n        uses: hellofresh/action-changed-files@v3\n        with:\n            pattern: infrastructure/(?P\u003cenvironment\u003e[^/]+)\n            default-patterns: |\n                terraform-modules\n                deploy.sh\n\n      - name: Generate matrix | Library\n        id: neo-library\n        uses: hellofresh/action-changed-files@v3\n        with:\n            pattern: library/(?P\u003clib\u003e(?!common)[^/]+)\n            default-patterns: |\n                library/common\n\n  infrastructure:\n    needs: [ generate-matrix ] # don't forget this!\n    strategy:\n      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-infrastructure) }}\n    if: ${{ fromJson(needs.generate-matrix.outputs.matrix-infrastructure).include[0] }} # skip if the matrix is empty!\n    steps:\n        - name: Deploy infrastructure\n          run: echo \"Deploying ${{ matrix.environment }}\"\n\n  build:\n    needs: [ generate-matrix ]\n    strategy:\n      matrix: ${{ fromJson(needs.generate-matrix.outputs.matrix-build) }}\n    if: ${{ fromJson(needs.generate-matrix.outputs.matrix-build).include[0] }}\n    steps:\n        - name: Building library\n          run: echo \"Building ${{ matrix.lib }}\"\n```\n\nLet's break down what will happen here with a few examples:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth\u003eChanged files\u003c/th\u003e\n        \u003cth\u003eBehaviour\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            infrastructure/live/main.tf\u003cbr\u003e\n            infrastructure/staging/main.tf\u003cbr\u003e\n        \u003c/td\u003e\n         \u003ctd\u003e\n            jobs.deploy[live]\u003cbr\u003e\n            jobs.deploy[staging]\u003cbr\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            library/parser/json.c\u003cbr\u003e\n            library/network/tcp.c\u003cbr\u003e\n        \u003c/td\u003e\n         \u003ctd\u003e\n            jobs.build[parser]\u003cbr\u003e\n            jobs.build[network]\u003cbr\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            terraform-modules/aws.tf\u003cbr\u003e\n            library/common/printer.c\u003cbr\u003e\n        \u003c/td\u003e\n         \u003ctd\u003e\n            jobs.deploy[live]\u003cbr\u003e\n            jobs.deploy[staging]\u003cbr\u003e\n            jobs.build[parser]\u003cbr\u003e\n            jobs.build[network]\u003cbr\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n### Change statuses\n\nEach matrix entry in the output JSON will also be annotated with an additional `reason` field that can help handling corner-cases like deleting a directory. If all matches of a set of groups have the same status, the `reason` field will be set to it.\n\nExample: if you use pattern `(?P\u003cmodule\u003edatabase-us|database-fr)` and all files in the `database-us` directory are deleted, the job matrix will look like:\n\n```json\n[\n    {\n        \"module\": \"database-us\",\n        \"reason\": \"deleted\"\n    },\n    {\n        \"module\": \"database-fr\",\n        \"reason\": \"?\"\n    }\n]\n```\n\nThe same applies to any status, like `added` or `modified`.\n\nNote: if a pattern matching to the same set of groups were caused by multiple type of changes, the `reason` field is marked as `?`.\n\n### Logging and debugging\nBy default the log level for the action is `INFO` but can be overriden by setting `NEO_LOG_LEVEL` env variable \nexample:\n```yaml\n  sample-job:\n    name: Test action\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.sample-step.outputs.matrix }}\n      matrix-length: ${{ steps.sample-step.outputs.matrix-length }}\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v3\n      - name: Generate matrix\n        id: sample-step\n        uses: hellofresh/action-changed-files@v3\n        env:\n          NEO_LOG_LEVEL: DEBUG\n        with:\n          pattern: (?P\u003cdir\u003e[^/]+)/\n          defaults: true\n          default-patterns: |\n            .github/**\n\n```\n\n## Reference\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003cth width=\"20%\"\u003eInput parameter name\u003c/th\u003e\n        \u003cth\u003eType\u003c/th\u003e\n        \u003cth\u003eRequired\u003c/th\u003e\n        \u003cth\u003eDescription\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003epattern\u003c/td\u003e\n        \u003ctd\u003estring\u003c/td\u003e\n        \u003ctd\u003e\u003cb\u003eyes\u003c/b\u003e\u003c/td\u003e\n        \u003ctd\u003e\n            Regular expression pattern with named groups. Changed files will be matched against this pattern and named groups will be extracted into the matrix. See \u003ca href=\"https://docs.python.org/3/howto/regex.html#non-capturing-and-named-groups\"\u003ethe relevant section of the Python documentation\u003c/a\u003e for the syntax reference.\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003edefaults\u003c/td\u003e\n        \u003ctd\u003eboolean\u003c/td\u003e\n        \u003ctd\u003eno\u003c/td\u003e\n        \u003ctd\u003e\n            if true, and no changed files match the pattern, recursively apply the pattern on all the files of the repository to generate a matrix of all possible combinations (a.k.a. run everything for changes to common files)\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003edefault-patterns\u003c/td\u003e\n        \u003ctd\u003elist[string]\u003c/td\u003e\n        \u003ctd\u003eno\u003c/td\u003e\n        \u003ctd\u003e\n            similar to the 'defaults' flag, except we match changed files on the provided UNIX-style glob pattern\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellofresh%2Faction-changed-files","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhellofresh%2Faction-changed-files","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhellofresh%2Faction-changed-files/lists"}