@htekdev/actions-debugger 1.0.22 → 1.0.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/errors/caching-artifacts/artifact-minimum-retention-one-day.yml +153 -0
  2. package/errors/caching-artifacts/cache-api-propagation-delay-post-save.yml +128 -0
  3. package/errors/caching-artifacts/cache-backend-internal-error-skipped.yml +75 -0
  4. package/errors/caching-artifacts/cache-hit-step-id-case-sensitive-mismatch.yml +95 -0
  5. package/errors/caching-artifacts/cache-save-post-step-skipped-on-failure.yml +114 -0
  6. package/errors/concurrency-timing/deploy-pages-in-progress-deployment-wedged.yml +70 -0
  7. package/errors/concurrency-timing/deployment-review-timeout-expired.yml +88 -0
  8. package/errors/concurrency-timing/job-concurrency-scope-per-run-not-global.yml +81 -0
  9. package/errors/concurrency-timing/merge-queue-concurrency-cancel-blocks-all.yml +86 -0
  10. package/errors/concurrency-timing/reusable-workflow-github-workflow-context-cancel.yml +124 -0
  11. package/errors/concurrency-timing/runner-scale-set-jobs-never-start.yml +123 -0
  12. package/errors/concurrency-timing/runner-temp-dir-race-concurrent-workers.yml +90 -0
  13. package/errors/known-unsolved/artifact-download-url-unauthenticated-404.yml +98 -0
  14. package/errors/known-unsolved/checkout-v6-credentials-docker-run-manual.yml +105 -0
  15. package/errors/known-unsolved/concurrency-groups-repo-scoped-only.yml +138 -0
  16. package/errors/known-unsolved/matrix-256-job-limit.yml +142 -0
  17. package/errors/known-unsolved/merge-group-paths-filter-not-supported.yml +137 -0
  18. package/errors/known-unsolved/no-job-allow-failure.yml +73 -0
  19. package/errors/known-unsolved/reusable-secrets-inherit-not-deep-forwarded.yml +113 -0
  20. package/errors/known-unsolved/schedule-cron-hours-long-queue-drift.yml +101 -0
  21. package/errors/permissions-auth/checkout-persist-credentials-token-write.yml +90 -0
  22. package/errors/permissions-auth/create-github-app-token-cross-job-token-revoked.yml +95 -0
  23. package/errors/permissions-auth/github-token-contents-write-missing-git-push.yml +117 -0
  24. package/errors/permissions-auth/org-actions-policy-blocks-unapproved-action.yml +106 -0
  25. package/errors/runner-environment/codeql-action-v2-deprecated.yml +110 -0
  26. package/errors/runner-environment/macos-26-openssl-3-system-library-breaking.yml +114 -0
  27. package/errors/runner-environment/macos-26-ruby-34-default-upgrade.yml +114 -0
  28. package/errors/runner-environment/macos-26-xcode-default-265-pin-required.yml +99 -0
  29. package/errors/runner-environment/macos-latest-label-switches-to-macos26.yml +127 -0
  30. package/errors/runner-environment/node20-removed-toolcache-default-node22.yml +104 -0
  31. package/errors/runner-environment/org-runner-group-dispatch-null.yml +102 -0
  32. package/errors/runner-environment/powershell-74-76-threadjob-module-rename.yml +124 -0
  33. package/errors/runner-environment/self-hosted-runner-not-found.yml +134 -0
  34. package/errors/runner-environment/self-hosted-runner-selinux-service-exec-failure.yml +116 -0
  35. package/errors/runner-environment/service-container-no-healthcheck.yml +158 -0
  36. package/errors/runner-environment/setup-node-v5-corepack-pnpm-not-found.yml +101 -0
  37. package/errors/runner-environment/setup-node-yarn-not-installed-self-hosted.yml +76 -0
  38. package/errors/runner-environment/setup-python-externally-managed-env-error.yml +95 -0
  39. package/errors/runner-environment/windows-2019-runner-retired-june2025.yml +118 -0
  40. package/errors/runner-environment/windows-2022-docker-daemon-not-started.yml +108 -0
  41. package/errors/silent-failures/cache-hit-output-string-not-boolean.yml +96 -0
  42. package/errors/silent-failures/checkout-lfs-pointer-not-content.yml +105 -0
  43. package/errors/silent-failures/reusable-workflow-output-skipped-contains-secret.yml +115 -0
  44. package/errors/silent-failures/setup-node-silent-download-exit-zero.yml +105 -0
  45. package/errors/silent-failures/setup-python-truncated-manifest-silent-exit.yml +111 -0
  46. package/errors/silent-failures/undefined-env-expression-empty-string-silent.yml +115 -0
  47. package/errors/silent-failures/windows-powershell-github-output-bash-syntax.yml +118 -0
  48. package/errors/triggers/fork-pr-first-time-contributor-approval-required.yml +142 -0
  49. package/errors/triggers/on-push-branches-glob-star-no-slash-match.yml +78 -0
  50. package/errors/triggers/pull-request-target-env-protection-default-branch-eval.yml +117 -0
  51. package/errors/triggers/required-status-check-renamed-never-passes.yml +87 -0
  52. package/errors/triggers/schedule-cron-self-hosted-runner-not-triggered.yml +107 -0
  53. package/errors/triggers/workflow-run-checkout-uses-default-branch.yml +114 -0
  54. package/errors/yaml-syntax/composite-action-run-shell-missing.yml +90 -0
  55. package/errors/yaml-syntax/composite-action-secrets-context-unavailable.yml +99 -0
  56. package/errors/yaml-syntax/github-script-octokit-renamed-to-github.yml +130 -0
  57. package/errors/yaml-syntax/labeler-v5-config-format-breaking.yml +67 -0
  58. package/errors/yaml-syntax/reusable-workflow-nesting-depth-exceeded.yml +113 -0
  59. package/errors/yaml-syntax/runs-on-expression-array-syntax-error.yml +121 -0
  60. package/errors/yaml-syntax/setup-go-matrix-version-float-coercion.yml +69 -0
  61. package/package.json +1 -1
@@ -0,0 +1,98 @@
1
+ id: known-unsolved-027
2
+ title: "Artifact Download URLs Require GitHub Authentication (404 for Unauthenticated Users)"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - upload-artifact
7
+ - download
8
+ - authentication
9
+ - public-access
10
+ - known-limitation
11
+ patterns:
12
+ - regex: "artifact.*download.*404|artifact.*not found.*auth"
13
+ flags: "i"
14
+ - regex: "artifact.*only.*registered|artifact.*guest.*not found"
15
+ flags: "i"
16
+ error_messages:
17
+ - "404 Not Found when downloading artifact URL without a GitHub session"
18
+ - "Resource not accessible by integration"
19
+ - "Must have push access to repository to list workflow run artifacts"
20
+ root_cause: |
21
+ All GitHub Actions artifact download URLs — both the UI links on the Actions tab and the archive
22
+ URLs returned by the REST API (GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/zip)
23
+ — require GitHub authentication. Unauthenticated visitors to public repositories receive a
24
+ 404 Not Found response regardless of the artifact's age or the repository's visibility.
25
+
26
+ This was not always the case. Prior to a GitHub platform change (around late 2020), direct
27
+ artifact archive URLs were publicly accessible without a GitHub account. The change was made
28
+ without a formal deprecation announcement, breaking projects that distributed nightly builds
29
+ or pre-release binaries via artifact URLs linked from documentation or release pages.
30
+
31
+ The REST API endpoint for listing artifacts (GET /repos/{owner}/{repo}/actions/artifacts)
32
+ also requires authentication, preventing anonymous services from discovering or linking
33
+ current artifact URLs.
34
+
35
+ 185 reactions on actions/upload-artifact#51 (open since Feb 2020).
36
+ fix: |
37
+ There is no way to make GitHub Actions artifacts publicly accessible without authentication.
38
+
39
+ Alternatives for distributing build outputs to unauthenticated users:
40
+ 1. GitHub Releases — release assets attached via `softprops/action-gh-release` are publicly
41
+ downloadable without a GitHub account.
42
+ 2. GitHub Pages — deploy build outputs as static files; pages are publicly accessible.
43
+ 3. External storage (S3, GCS, Azure Blob Storage) — upload artifacts to a public bucket
44
+ and provide a stable URL.
45
+ 4. nightly.link proxy — a free service that fetches artifacts via GitHub App auth and
46
+ provides a public redirect URL. URL format:
47
+ https://nightly.link/{owner}/{repo}/workflows/{workflow}/{branch}/{artifact-name}.zip
48
+ fix_code:
49
+ - language: yaml
50
+ label: "Alternative: publish as GitHub Release asset (publicly accessible)"
51
+ code: |
52
+ jobs:
53
+ build-and-release:
54
+ runs-on: ubuntu-latest
55
+ permissions:
56
+ contents: write
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ - run: ./build.sh -o dist/output.zip
60
+
61
+ # Release assets are publicly downloadable without GitHub login
62
+ - uses: softprops/action-gh-release@v2
63
+ with:
64
+ tag_name: nightly-${{ github.run_number }}
65
+ files: dist/output.zip
66
+ prerelease: true
67
+
68
+ - language: yaml
69
+ label: "Alternative: deploy to GitHub Pages (publicly accessible static files)"
70
+ code: |
71
+ jobs:
72
+ deploy-pages:
73
+ runs-on: ubuntu-latest
74
+ permissions:
75
+ pages: write
76
+ id-token: write
77
+ environment:
78
+ name: github-pages
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+ - run: ./build.sh -o ./public
82
+
83
+ - uses: actions/upload-pages-artifact@v3
84
+ with:
85
+ path: ./public
86
+ - uses: actions/deploy-pages@v4
87
+ prevention:
88
+ - "Never publish artifact download URLs as public links — they are always authentication-gated."
89
+ - "For public distribution of build outputs, use GitHub Releases, GitHub Pages, or an external CDN."
90
+ - "Use nightly.link for zero-config public access to the latest artifact in open-source projects."
91
+ - "Document the authentication requirement in README when directing contributors to artifacts."
92
+ docs:
93
+ - url: "https://github.com/actions/upload-artifact/issues/51"
94
+ label: "actions/upload-artifact #51 — Artifact URLs require GitHub account (185 reactions)"
95
+ - url: "https://nightly.link"
96
+ label: "nightly.link — Public proxy for GitHub Actions artifacts"
97
+ - url: "https://docs.github.com/en/rest/actions/artifacts"
98
+ label: "GitHub REST API — Actions Artifacts (requires auth)"
@@ -0,0 +1,105 @@
1
+ id: known-unsolved-024
2
+ title: "checkout@v6 Git Credentials Inaccessible Inside Manually Invoked Docker Containers"
3
+ category: known-unsolved
4
+ severity: error
5
+ tags:
6
+ - checkout
7
+ - docker
8
+ - credentials
9
+ - git-auth
10
+ - includeif
11
+ - v6
12
+ patterns:
13
+ - regex: "fatal: could not read Username for.*No such device or address"
14
+ flags: "i"
15
+ - regex: "fatal: Authentication failed for.*github\\.com"
16
+ flags: "i"
17
+ - regex: "includeIf\\.gitdir.*git-credentials.*config"
18
+ flags: "i"
19
+ error_messages:
20
+ - "fatal: could not read Username for 'https://github.com': No such device or address"
21
+ - "fatal: Authentication failed for 'https://github.com/org/repo.git'"
22
+ - "remote: Repository not found."
23
+ root_cause: |
24
+ actions/checkout@v6 changed the credential persistence mechanism from HTTP Authorization
25
+ headers written directly into .git/config (the v5 approach) to path-based includeIf.gitdir
26
+ directives that reference a credentials file stored in $RUNNER_TEMP.
27
+
28
+ This mechanism works for GitHub-managed Docker container actions (using: docker), where
29
+ the runner automatically mounts $RUNNER_TEMP into the container as /github/runner_temp
30
+ and configures paths to match. However, it breaks for any workflow step that runs its own
31
+ docker run commands or scripts that spin up Docker containers manually, because:
32
+
33
+ 1. The $RUNNER_TEMP directory is not mounted into the custom container.
34
+ 2. Even if mounted, the includeIf.gitdir path condition requires the workspace to be
35
+ mounted at /github/workspace for the condition to evaluate as true.
36
+ 3. Any docker run at a non-standard path will not satisfy the gitdir condition even if
37
+ the credentials file is accessible.
38
+
39
+ Any workflow step that runs docker run outside of a formal Docker action and then performs
40
+ authenticated repository operations (fetch, clone, publish) inside that container will
41
+ fail to authenticate, even with persist-credentials: true.
42
+
43
+ As of June 2026, a fix is in progress upstream (switching from includeIf.gitdir to
44
+ include.path would eliminate the path-matching requirement) but not yet released.
45
+ No fully clean universal workaround exists.
46
+ Reported in actions/checkout#2359 (12 reactions, open Jan 2026).
47
+ fix: |
48
+ No complete fix available until checkout releases an updated credential mechanism.
49
+
50
+ Option 1 (recommended until fix released): Pin to actions/checkout@v5.
51
+ v5 uses HTTP Authorization headers written directly into .git/config, visible inside any
52
+ Docker container that mounts the workspace. No path-based includeIf is involved.
53
+
54
+ Option 2: Mount RUNNER_TEMP at the expected path inside docker run.
55
+ Add -v "$RUNNER_TEMP:/github/runner_temp" to the docker run command AND mount the
56
+ workspace at /github/workspace. Both mounts are required simultaneously.
57
+
58
+ Option 3: Pass the token explicitly to the container via environment variable.
59
+ Set the GitHub token as an env variable and configure the credential helper inside
60
+ the container entrypoint to use it via the token-embedded remote URL.
61
+ fix_code:
62
+ - language: yaml
63
+ label: "Option 1: Pin to checkout@v5 (recommended until upstream fix)"
64
+ code: |
65
+ - name: Checkout repository
66
+ uses: actions/checkout@v5
67
+ with:
68
+ fetch-depth: 0
69
+ token: ${{ secrets.GITHUB_TOKEN }}
70
+ - language: yaml
71
+ label: "Option 2: Mount RUNNER_TEMP and workspace at expected paths"
72
+ code: |
73
+ - name: Checkout repository
74
+ uses: actions/checkout@v6
75
+ with:
76
+ persist-credentials: true
77
+ - name: Run docker with credentials accessible
78
+ run: |
79
+ docker run \
80
+ -v "$GITHUB_WORKSPACE:/github/workspace" \
81
+ -v "$RUNNER_TEMP:/github/runner_temp" \
82
+ -w /github/workspace \
83
+ my-image:latest ./scripts/build.sh
84
+ - language: yaml
85
+ label: "Option 3: Pass token to container entrypoint"
86
+ code: |
87
+ - name: Run docker with explicit token
88
+ env:
89
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
90
+ run: |
91
+ docker run -e GH_TOKEN="${GH_TOKEN}" my-image:latest ./scripts/release.sh
92
+ prevention:
93
+ - "Do not upgrade to checkout@v6 if your workflow contains manual docker run steps that perform authenticated repository operations inside the container."
94
+ - "Use formal Docker container actions (using: docker in action.yml) instead of manual docker run steps when repository operations inside containers are needed."
95
+ - "Pin checkout to an explicit version and use Dependabot/Renovate to control upgrade timing."
96
+ - "Track actions/checkout#2359 for the upstream fix when released."
97
+ docs:
98
+ - url: "https://github.com/actions/checkout/issues/2359"
99
+ label: "actions/checkout#2359 — checkout@v6 credentials broken with Docker container actions (Jan 2026)"
100
+ - url: "https://github.com/actions/checkout/issues/2386"
101
+ label: "actions/checkout#2386 — related Docker credential issue"
102
+ - url: "https://github.com/actions/checkout/releases/tag/v6.0.0"
103
+ label: "checkout v6.0.0 release notes — credential mechanism change"
104
+ - url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-docker-container-action"
105
+ label: "Creating a Docker container action"
@@ -0,0 +1,138 @@
1
+ id: known-unsolved-023
2
+ title: "Concurrency Groups Are Repository-Scoped — Cannot Synchronize Workflows Across Repositories"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - concurrency
7
+ - cross-repository
8
+ - scoping
9
+ - deployment
10
+ - mutex
11
+ - known-limit
12
+ - organization
13
+ patterns:
14
+ - regex: "concurrency.*cross.?repo|cross.?repo.*concurrency"
15
+ flags: "i"
16
+ - regex: "concurrency.*organization|global.*concurrency|multi.?repo.*concurrency"
17
+ flags: "i"
18
+ - regex: "concurrency only works within a single repository"
19
+ flags: "i"
20
+ error_messages:
21
+ - "GitHub Actions concurrency only works within a single repository"
22
+ - "Concurrency groups cannot be shared across repositories — identical group names in different repos run in parallel"
23
+ root_cause: |
24
+ GitHub Actions `concurrency:` groups are evaluated strictly within a single repository.
25
+ Two workflows in different repositories that define identical `concurrency.group` strings
26
+ (e.g., `group: deploy-production`) run in PARALLEL with no coordination — the group
27
+ name has no cross-repository meaning.
28
+
29
+ This is a hard platform-level scope boundary. GitHub's concurrency implementation stores
30
+ group membership state per-repository, so there is no shared namespace between repos.
31
+
32
+ Common scenarios where this surprises teams:
33
+ - Multiple application repos deploying to a shared staging/production environment
34
+ - A monorepo split into microservice repos that must not deploy simultaneously
35
+ - Platform teams providing reusable deploy workflows called from many repos
36
+ - Organizations trying to limit total simultaneous cloud deployments across a fleet
37
+ - Trying to prevent two repos from running the same database migration at once
38
+
39
+ The behavior is counterintuitive because the same concurrency group string CAN
40
+ coordinate same-repo workflows — so teams naturally assume it works cross-repo too.
41
+
42
+ Source: Stack Overflow #79690697 (Make workflow run sequentially for reusable workflow
43
+ — accepted answer explicitly states: "GitHub Actions' concurrency only works within
44
+ a single repository")
45
+ Source: ben-z/gh-action-mutex (community workaround for cross-repo mutex, 500+ stars)
46
+ Source: GitHub Actions docs (concurrency group scope is per-repository)
47
+ fix: |
48
+ There is no native GitHub Actions concurrency primitive that works cross-repository.
49
+ Use one of these architectural workarounds:
50
+
51
+ Workaround 1 — Orchestrator repository with repository_dispatch (recommended):
52
+ Create a central orchestrator repo. Each application repo sends a
53
+ `repository_dispatch` event to the orchestrator. The orchestrator runs the shared
54
+ workflow sequentially using its own concurrency group (single-repo scope is fine
55
+ here because all dispatch events arrive at one repo).
56
+
57
+ Workaround 2 — External mutex via ben-z/gh-action-mutex:
58
+ Uses a dedicated lock repository's branch as a distributed mutex. Works across
59
+ repos because the lock state lives in one shared repository.
60
+
61
+ Workaround 3 — Environment deployment protection with single-slot reviewers:
62
+ A deployment environment with required reviewers can throttle approval-gated
63
+ deployments. Multiple jobs can still enter "waiting" simultaneously, but the
64
+ gate prevents concurrent execution if reviewers approve only one at a time.
65
+
66
+ Workaround 4 — External coordination service (Redis, DynamoDB, Azure Service Bus):
67
+ For production systems at scale, use a lock/queue service all workflows can reach.
68
+ Requires infrastructure management but provides the most reliable behavior.
69
+ fix_code:
70
+ - language: yaml
71
+ label: "Orchestrator pattern: all repos dispatch to a central repo that serializes deploys"
72
+ code: |
73
+ # In each application repo — sends dispatch to orchestrator
74
+ name: Trigger Orchestrated Deploy
75
+ on:
76
+ push:
77
+ branches: [main]
78
+ jobs:
79
+ dispatch:
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - name: Dispatch to orchestrator
83
+ run: |
84
+ gh api /repos/myorg/deploy-orchestrator/dispatches \
85
+ --method POST \
86
+ -F event_type=deploy \
87
+ -F client_payload[repo]="${{ github.repository }}" \
88
+ -F client_payload[sha]="${{ github.sha }}"
89
+ env:
90
+ GH_TOKEN: ${{ secrets.ORCHESTRATOR_DISPATCH_PAT }}
91
+
92
+ ---
93
+ # In deploy-orchestrator repo — single-repo concurrency works correctly here
94
+ name: Orchestrated Deploy
95
+ on:
96
+ repository_dispatch:
97
+ types: [deploy]
98
+ concurrency:
99
+ group: deploy-production # Scoped to orchestrator repo — works as intended
100
+ cancel-in-progress: false # Queue all deployments; never skip one
101
+ jobs:
102
+ deploy:
103
+ runs-on: ubuntu-latest
104
+ steps:
105
+ - run: |
106
+ echo "Deploying ${{ github.event.client_payload.repo }} @ ${{ github.event.client_payload.sha }}"
107
+ # ... deploy logic ...
108
+
109
+ - language: yaml
110
+ label: "External mutex using ben-z/gh-action-mutex for cross-repo locking"
111
+ code: |
112
+ jobs:
113
+ deploy:
114
+ runs-on: ubuntu-latest
115
+ steps:
116
+ - name: Acquire cross-repo deployment lock
117
+ uses: ben-z/gh-action-mutex@v1.0-alpha-7
118
+ with:
119
+ branch: mutex-deploy-production # Branch in the shared lock repo
120
+ repo-token: ${{ secrets.MUTEX_REPO_PAT }}
121
+ repository: myorg/locks # Dedicated lock repository
122
+
123
+ - name: Deploy
124
+ run: ./deploy.sh
125
+
126
+ # Lock is automatically released when the job completes (success or failure)
127
+ prevention:
128
+ - "Do not assume identical concurrency group names coordinate across repositories — they have no cross-repo effect."
129
+ - "Design cross-repo deployment sequencing with an explicit architecture before scaling to multiple repos."
130
+ - "Document the serialization mechanism in your runbooks — this is a common architecture surprise for new team members."
131
+ - "Prefer a single orchestrator repo pattern from the start when cross-repo ordering is a requirement."
132
+ docs:
133
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/using-concurrency"
134
+ label: "GitHub Docs: Using concurrency in GitHub Actions (repo-scoped)"
135
+ - url: "https://stackoverflow.com/questions/79690697/make-workflow-run-sequentially-allowing-one-job-run-at-a-time-for-github-action-reusable-workflow"
136
+ label: "Stack Overflow #79690697: Cross-repo sequential GitHub Actions execution"
137
+ - url: "https://github.com/ben-z/gh-action-mutex"
138
+ label: "ben-z/gh-action-mutex — cross-repo mutex via shared lock repository"
@@ -0,0 +1,142 @@
1
+ id: known-unsolved-022
2
+ title: "Job Matrix Hard Limit: Maximum 256 Jobs Per Workflow Run"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - matrix
7
+ - strategy
8
+ - job-limit
9
+ - scale
10
+ - known-limit
11
+ - monorepo
12
+ patterns:
13
+ - regex: "256 jobs|matrix.*256|256.*matrix"
14
+ flags: "i"
15
+ - regex: "Job matrix generate.*more than|maximum.*jobs.*workflow.*run"
16
+ flags: "i"
17
+ - regex: "matrix.*maximum.*jobs|generates more than 256"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Job matrix generates more than 256 jobs"
21
+ - "A job matrix can generate a maximum of 256 jobs per workflow run"
22
+ - "The job was not run because it would exceed the maximum number of jobs in a workflow run"
23
+ root_cause: |
24
+ GitHub Actions enforces a hard limit of 256 jobs per workflow run for job matrix strategies.
25
+ This limit applies equally to GitHub-hosted and self-hosted runners and cannot be raised
26
+ via repository or organization settings.
27
+
28
+ The limit is evaluated at workflow run creation time against the total number of matrix
29
+ job combinations. If the computed combination count exceeds 256, the run is blocked.
30
+
31
+ Common matrix combinations that silently approach or exceed the limit:
32
+ - 3 OS × 4 Node.js versions × 22 packages = 264 jobs ❌
33
+ - 4 cloud regions × 4 environments × 17 services = 272 jobs ❌
34
+ - 5 browsers × 4 OS × 13 test shards = 260 jobs ❌
35
+
36
+ This is a long-standing documented constraint. As of the GitHub Actions limits page,
37
+ the 256-job cap has not been increased and no per-organization override is available.
38
+
39
+ Practical impact grows over time: monorepos and test suites that start within the limit
40
+ gradually approach it as services and configuration dimensions are added, with no
41
+ warning until a push suddenly fails workflow creation.
42
+
43
+ Source: GitHub Docs — Usage limits (256 jobs / workflow run)
44
+ Source: cloudposse/github-action-matrix-extended (widely-used community workaround)
45
+ Source: huggingface/transformers PR#28773 (real-world 2-level split at scale)
46
+ fix: |
47
+ There is no way to raise the 256-job limit via settings. Use one of these workarounds:
48
+
49
+ Workaround 1 — Nested matrix via reusable workflows (extends limit to 256² = 65,536):
50
+ Split work into "slices" at the top-level matrix (up to 256 slices), then call a
51
+ reusable workflow that runs its own matrix (up to 256 jobs per slice). Each slice
52
+ × jobs combination stays within the per-run limit.
53
+
54
+ Workaround 2 — `github-action-matrix-extended` by cloudposse:
55
+ Automates the nested slice pattern and supports up to 3 levels (256³ theoretical max).
56
+ Outputs JSON structure consumed by nested matrix strategy calls.
57
+
58
+ Workaround 3 — Path-change filtering via `dorny/paths-filter`:
59
+ Only generate matrix entries for packages/services that changed in the PR. Keeps
60
+ CI fast AND well under the job limit for most runs.
61
+
62
+ Workaround 4 — Reduce matrix dimensions with `include`/`exclude`:
63
+ Test all OS on the latest version; test all versions on one OS. Use `exclude:` to
64
+ prune uncommon OS × version combinations that rarely catch real issues.
65
+ fix_code:
66
+ - language: yaml
67
+ label: "Nested reusable workflow split: top-level generates slices, called workflow runs sub-matrix"
68
+ code: |
69
+ # outer.yml — up to 256 slices × called workflow's matrix (256 each)
70
+ name: Test Suite
71
+ on: [push]
72
+
73
+ jobs:
74
+ generate-slices:
75
+ runs-on: ubuntu-latest
76
+ outputs:
77
+ slices: ${{ steps.gen.outputs.slices }}
78
+ steps:
79
+ - id: gen
80
+ run: |
81
+ # Generate slice IDs from your service list (split into groups)
82
+ python3 -c "
83
+ import json, math
84
+ services = ['svc-' + str(i) for i in range(300)]
85
+ slice_size = 10
86
+ slices = [services[i:i+slice_size] for i in range(0, len(services), slice_size)]
87
+ print('slices=' + json.dumps([json.dumps(s) for s in slices]))
88
+ " >> $GITHUB_OUTPUT
89
+
90
+ run-slice:
91
+ needs: generate-slices
92
+ strategy:
93
+ matrix:
94
+ slice: ${{ fromJSON(needs.generate-slices.outputs.slices) }}
95
+ fail-fast: false
96
+ uses: ./.github/workflows/test-slice.yml
97
+ with:
98
+ services: ${{ matrix.slice }} # JSON string of services for this slice
99
+
100
+ - language: yaml
101
+ label: "Path filtering: only run matrix jobs for changed packages"
102
+ code: |
103
+ jobs:
104
+ detect-changes:
105
+ runs-on: ubuntu-latest
106
+ outputs:
107
+ matrix: ${{ steps.filter.outputs.changes }}
108
+ steps:
109
+ - uses: actions/checkout@v4
110
+ - id: filter
111
+ uses: dorny/paths-filter@v3
112
+ with:
113
+ filters: |
114
+ service-a: ['services/a/**']
115
+ service-b: ['services/b/**']
116
+ service-c: ['services/c/**']
117
+ # ... define one filter per service
118
+
119
+ test:
120
+ needs: detect-changes
121
+ if: needs.detect-changes.outputs.matrix != '[]'
122
+ strategy:
123
+ matrix:
124
+ service: ${{ fromJSON(needs.detect-changes.outputs.matrix) }}
125
+ runs-on: ubuntu-latest
126
+ steps:
127
+ - uses: actions/checkout@v4
128
+ - run: npm test --workspace=services/${{ matrix.service }}
129
+ prevention:
130
+ - "Track total matrix job count — when exceeding 200, plan a nested split before hitting the 256 wall."
131
+ - "Implement path-change filtering early in the project lifecycle to prevent combinatorial explosion."
132
+ - "Prefer `include`/`exclude` pruning over full combinatorial matrices for OS × version coverage."
133
+ - "Design your CI architecture with the 256-job ceiling in mind, especially for monorepos."
134
+ docs:
135
+ - url: "https://docs.github.com/en/actions/administering-github-actions/usage-limits-billing-and-administration#usage-limits"
136
+ label: "GitHub Docs: Usage limits — Job Matrix (256 jobs per workflow run)"
137
+ - url: "https://github.com/cloudposse/github-action-matrix-extended"
138
+ label: "cloudposse/github-action-matrix-extended — nested matrix workaround"
139
+ - url: "https://github.com/dorny/paths-filter"
140
+ label: "dorny/paths-filter — change-based matrix filtering"
141
+ - url: "https://github.com/huggingface/transformers/pull/28773"
142
+ label: "huggingface/transformers PR#28773: Real-world 2-level matrix split"
@@ -0,0 +1,137 @@
1
+ id: known-unsolved-028
2
+ title: "merge_group Event Does Not Support paths, branches, or tags Filters"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - merge_group
7
+ - merge-queue
8
+ - paths
9
+ - branches
10
+ - filters
11
+ - monorepo
12
+ - known-limitation
13
+ patterns:
14
+ - regex: "merge_group:\\s*\\n\\s+paths:"
15
+ flags: "ms"
16
+ - regex: "merge_group:\\s*\\n\\s+branches:"
17
+ flags: "ms"
18
+ error_messages:
19
+ - "on:\n merge_group:\n paths:\n - 'src/**'"
20
+ - "workflow triggered for merge_group despite paths filter"
21
+ root_cause: |
22
+ The merge_group event (used with GitHub's merge queue feature) does not support
23
+ the standard event activity filters that other events support. Specifically,
24
+ the following filters are silently IGNORED when listed under merge_group:
25
+
26
+ - paths and paths-ignore
27
+ - branches and branches-ignore
28
+ - tags
29
+
30
+ When a workflow defines:
31
+ on:
32
+ pull_request:
33
+ paths: ['src/**']
34
+ merge_group:
35
+ paths: ['src/**'] # silently ignored
36
+
37
+ The paths filter applies to pull_request but NOT to merge_group. The workflow
38
+ always triggers for every merge_group event regardless of which files changed,
39
+ even if no files in src/** were modified.
40
+
41
+ This is particularly painful for monorepos that use paths filters to scope CI
42
+ workflows to service boundaries — the merge queue bypasses those boundaries
43
+ and runs all required checks for every PR regardless of which service changed.
44
+
45
+ The merge_group event only supports filtering by:
46
+ types: [checks_requested] (default and only supported activity type)
47
+
48
+ GitHub has acknowledged this is a known limitation with no native fix planned.
49
+ fix: |
50
+ There is no native path filtering for merge_group. Workarounds:
51
+
52
+ 1. Step-level change detection: Use a job step with dorny/paths-filter or
53
+ tj-actions/changed-files to detect whether relevant files changed, then
54
+ gate subsequent steps on that output. This allows individual steps to
55
+ short-circuit while the job still runs (satisfying required check status).
56
+
57
+ 2. Gate job pattern: Add a detect-changes job that runs paths detection and
58
+ exposes outputs. Downstream jobs use needs: + if: to conditionally run
59
+ based on the detected changes.
60
+
61
+ 3. Accept always-run: For merge queue, it is generally safer to run all
62
+ required checks regardless of file changes. This ensures complete
63
+ validation before merging and avoids stale-cache scenarios.
64
+ fix_code:
65
+ - language: yaml
66
+ label: "Workaround — step-level paths filter inside merge_group triggered job"
67
+ code: |
68
+ on:
69
+ pull_request:
70
+ paths: ['src/**'] # pull_request respects this filter
71
+ merge_group: # merge_group ignores all path/branch filters
72
+
73
+ jobs:
74
+ build:
75
+ runs-on: ubuntu-latest
76
+ steps:
77
+ - uses: actions/checkout@v4
78
+ with:
79
+ fetch-depth: 0
80
+
81
+ - uses: dorny/paths-filter@v3
82
+ id: changes
83
+ with:
84
+ filters: |
85
+ src:
86
+ - 'src/**'
87
+
88
+ - name: Build (skip if no src changes on pull_request)
89
+ if: steps.changes.outputs.src == 'true' || github.event_name == 'merge_group'
90
+ run: npm run build
91
+ shell: bash
92
+
93
+ - language: yaml
94
+ label: "Workaround — detect-changes gate job for monorepo required checks"
95
+ code: |
96
+ on:
97
+ pull_request:
98
+ merge_group:
99
+
100
+ jobs:
101
+ detect-changes:
102
+ runs-on: ubuntu-latest
103
+ outputs:
104
+ src-changed: ${{ steps.filter.outputs.src }}
105
+ steps:
106
+ - uses: actions/checkout@v4
107
+ with:
108
+ fetch-depth: 0
109
+ - uses: dorny/paths-filter@v3
110
+ id: filter
111
+ with:
112
+ filters: |
113
+ src:
114
+ - 'src/**'
115
+
116
+ build:
117
+ needs: detect-changes
118
+ if: needs.detect-changes.outputs.src-changed == 'true' || github.event_name == 'merge_group'
119
+ runs-on: ubuntu-latest
120
+ steps:
121
+ - uses: actions/checkout@v4
122
+ - run: npm run build
123
+ shell: bash
124
+ prevention:
125
+ - "Do not add paths: or branches: under merge_group: — they are silently ignored."
126
+ - "For monorepo required checks, plan for merge_group always running all required checks regardless of file changes."
127
+ - "Use step-level change detection (dorny/paths-filter, tj-actions/changed-files) to short-circuit expensive work inside jobs."
128
+ - "Document that merge queue bypasses path filters in your monorepo CI design documentation."
129
+ docs:
130
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#merge_group"
131
+ label: "GitHub Docs: merge_group event — supported filter types"
132
+ - url: "https://stackoverflow.com/questions/76655935/when-does-a-github-workflow-trigger-for-merge-group-and-is-it-restricted-by-branch"
133
+ label: "Stack Overflow: merge_group trigger and branch restrictions (Score: 7, 9K views)"
134
+ - url: "https://github.com/orgs/community/discussions/90533"
135
+ label: "GitHub Community: merge_group does not support path filters"
136
+ - url: "https://github.com/dorny/paths-filter"
137
+ label: "dorny/paths-filter: step-level changed-files detection for monorepos"