Adds allDuplicatedNamedJobs mode (#11)

diff --git a/README.md b/README.md
index e81c66b..b212dd9 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,7 @@
     - [Fail-fast source workflow runs with failed jobs and corresponding triggered runs](#fail-fast-source-workflow-runs-with-failed-jobs-and-corresponding-triggered-runs)
     - [Fail-fast for triggered workflow runs with failed jobs](#fail-fast-for-triggered-workflow-runs-with-failed-jobs)
     - [Cancel another workflow run](#cancel-another-workflow-run)
+    - [Cancel all duplicates for named jobs](#cancel-all-duplicates-for-named-jobs)
   - [Repositories that do not use Pull Requests from forks](#repositories-that-do-not-use-pull-requests-from-forks)
     - [Cancel duplicate runs for "self" workflow](#cancel-duplicate-runs-for-self-workflow)
     - [Cancel "self" workflow run](#cancel-self-workflow-run)
@@ -112,20 +113,21 @@
 | `notifyPRCancel`         | no       |              | Boolean. If set to true, it notifies the cancelled PRs with a comment containing reason why they are being cancelled.                                                                                            |
 | `notifyPRCancelMessage`  | no       |              | Optional cancel message to use instead of the default one when notifyPRCancel is true.  It is only used in 'self' cancelling mode.                                                                               |
 | `notifyPRMessageStart`   | no       |              | Only for workflow_run events triggered by the PRs. If not empty, it notifies those PRs with the message specified at the start of the workflow - adding the link to the triggered workflow_run.                  |
-| `jobNameRegexps`         | no       |              | An array of job name regexps. Only runs containing any job name matching any of of the regexp in this array are considered for cancelling in `failedJobs` and `namedJobs` cancel modes.                          |
+| `jobNameRegexps`         | no       |              | An array of job name regexps. Only runs containing any job name matching any of of the regexp in this array are considered for cancelling in `failedJobs` and `namedJobs` and `allDuplicateNamedJobs` modes.     |
 | `skipEventTypes`         | no       |              | Array of event names that should be skipped when cancelling (JSON-encoded string). This might be used in order to skip direct pushes or scheduled events.                                                        |
 | `workflowFileName`       | no       |              | Name of the workflow file. It can be used if you want to cancel a different workflow than yours.                                                                                                                 |
 
 
 The job cancel modes work as follows:
 
-| Cancel Mode     | No `sourceRunId` specified                                             | The `sourceRunId` set to `${{ github.event.workflow_run.id }}`                      |
-|-----------------|------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
-| `duplicates`    | Cancels duplicate runs from the same repo/branch as current run.       | Cancels duplicate runs for the same repo/branch as the source run.                  |
-| `allDuplicates` | Cancels duplicate runs from all running workflows.                     | Cancels duplicate runs from all running workflows.                                  |
-| `self`          | Cancels self run.                                                      | Cancel the `sourceRunId` run.                                                       |
-| `failedJobs`    | Cancels all runs of own workflow that have matching jobs that failed.  | Cancels all runs of the `sourceRunId` workflow that have matching jobs that failed. |
-| `namedJobs`     | Cancels all runs of own workflow that have matching jobs.              | Cancels all runs of the `sourceRunId` workflow that have matching jobs.             |
+| Cancel Mode              | No `sourceRunId` specified                                                   | The `sourceRunId` set to `${{ github.event.workflow_run.id }}`                      |
+|--------------------------|------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
+| `duplicates`             | Cancels duplicate runs from the same repo/branch as current run.             | Cancels duplicate runs for the same repo/branch as the source run.                  |
+| `allDuplicates`          | Cancels duplicate runs from all running workflows.                           | Cancels duplicate runs from all running workflows.                                  |
+| `self`                   | Cancels self run.                                                            | Cancel the `sourceRunId` run.                                                       |
+| `failedJobs`             | Cancels all runs of own workflow that have matching jobs that failed.        | Cancels all runs of the `sourceRunId` workflow that have matching jobs that failed. |
+| `namedJobs`              | Cancels all runs of own workflow that have matching jobs.                    | Cancels all runs of the `sourceRunId` workflow that have matching jobs.             |
+| `allDuplicatedNamedJobs` | Cancels all duplicate runs of own workflow that share matching jobs pattern. | Cancels all runs of the `sourceRunId` workflow that share matching job pattern.     |
 
 
 ## Outputs
@@ -163,7 +165,7 @@
     name: "Cancel duplicate workflow runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel duplicate workflow runs"
         with:
           cancelMode: allDuplicates
@@ -231,7 +233,7 @@
     name: "Cancel duplicate workflow runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel duplicate workflow runs"
         with:
           cancelMode: duplicates
@@ -292,7 +294,7 @@
       sourceHeadSha: ${{ steps.cancel.outputs.sourceHeadSha }}
       sourceEvent: ${{ steps.cancel.outputs.sourceEvent }}
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         id: cancel
         name: "Cancel duplicate CI runs"
         with:
@@ -305,7 +307,7 @@
             that you will not see in the list of checks.
 
             You can checks the status of those images in:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel duplicate Cancelling runs"
         with:
           cancelMode: namedJobs
@@ -355,7 +357,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: "Cancel the self CI workflow run"
-        uses: potiuk/cancel-workflow-runs@v4_1
+        uses: potiuk/cancel-workflow-runs@master
         with:
           cancelMode: self
           notifyPRCancel: true
@@ -384,7 +386,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: "Cancel the self Cancelling workflow run"
-        uses: potiuk/cancel-workflow-runs@v4_1
+        uses: potiuk/cancel-workflow-runs@master
         with:
           cancelMode: self
           notifyPRCancel: true
@@ -417,7 +419,7 @@
     name: "Fail fast CI runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Fail fast CI runs"
         with:
           cancelMode: failedJobs
@@ -458,7 +460,7 @@
     name: "Fail fast CI runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Fail fast CI. Source run: ${{ github.event.workflow_run.id }}"
         id: cancel-failed
         with:
@@ -481,7 +483,7 @@
             echo "::set-output name=matching-regexp::${REGEXP}"
       - name: "Cancel triggered 'Cancelling' runs for the cancelled failed runs"
         if: steps.cancel-failed.outputs.cancelledRuns != '[]'
-        uses: potiuk/cancel-workflow-runs@v4_1
+        uses: potiuk/cancel-workflow-runs@master
         with:
           cancelMode: namedJobs
           token: ${{ secrets.GITHUB_TOKEN }}
@@ -516,7 +518,7 @@
     name: "Fail fast Canceling runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Fail fast Canceling runs"
         with:
           cancelMode: failedJobs
@@ -541,7 +543,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: "Cancel the self CI workflow run"
-        uses: potiuk/cancel-workflow-runs@v4_1
+        uses: potiuk/cancel-workflow-runs@master
         with:
           cancelMode: duplicates
           cancelFutureDuplicates: true
@@ -549,6 +551,42 @@
           workflowFileName: other_workflow.yml
 ```
 
+### Cancel all duplicates for named jobs
+
+Cancels all duplicated runs for all jobs that match specified regular expression.
+Note that it does not take into account the branch of the runs. It will cancel all duplicates with
+the same match for jobs, no matter what branch originated it.
+
+This is useful in case of job names generated dynamically.
+
+In the case below, for all the runs that have job names generated containing Branch/Repo/Event combination
+that have the same match, the duplicates will get cancelled leaving only the most recent run for each exact
+match.
+
+Note that the match must be identical. If there are two jobs that have a different Branch
+they will both match the same pattern, but they are not considered duplicates.
+
+```yaml
+on:
+  push:
+  workflow_run:
+    workflows: ['CI']
+    types: ['requested']
+
+jobs:
+  cancel-self-failed-runs:
+    name: "Cancel the self workflow run"
+    runs-on: ubuntu-latest
+    steps:
+      - uses: potiuk/cancel-workflow-runs@master
+        name: "Cancel past CI runs"
+        with:
+          cancelMode: allDuplicatedNamedJobs
+          token: ${{ secrets.GITHUB_TOKEN }}
+          jobNameRegexps: '["Branch: .* Repo: .* Event: .* "]'
+          notifyPRCancel: true
+```
+
 
 
 ## Repositories that do not use Pull Requests from forks
@@ -582,7 +620,7 @@
     name: "Cancel duplicate workflow runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel duplicate workflow runs"
         with:
           cancelMode: duplicates
@@ -606,7 +644,7 @@
     runs-on: ubuntu-latest
     steps:
       - name: "Cancel the self workflow run"
-        uses: potiuk/cancel-workflow-runs@v4_1
+        uses: potiuk/cancel-workflow-runs@master
         with:
           cancelMode: self
           token: ${{ secrets.GITHUB_TOKEN }}
@@ -632,7 +670,7 @@
     name: "Cancel failed runs"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel failed runs"
         with:
           cancelMode: failedJobs
@@ -664,7 +702,7 @@
     name: "Cancel the self workflow run"
     runs-on: ubuntu-latest
     steps:
-      - uses: potiuk/cancel-workflow-runs@v4_1
+      - uses: potiuk/cancel-workflow-runs@master
         name: "Cancel past CI runs"
         with:
           cancelMode: namedJobs
diff --git a/dist/index.js b/dist/index.js
index 6f047aa..2a806db 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1485,15 +1485,17 @@
     CancelMode["SELF"] = "self";
     CancelMode["FAILED_JOBS"] = "failedJobs";
     CancelMode["NAMED_JOBS"] = "namedJobs";
+    CancelMode["ALL_DUPLICATED_NAMED_JOBS"] = "allDuplicatedNamedJobs";
 })(CancelMode || (CancelMode = {}));
 /**
  * Converts the source of a run object into a string that can be used as map key in maps where we keep
  * arrays of runs per source group
- * @param sourceGroup the object identifying the source of the run (Pull Request, Master Push)
+ * @param triggeringRunInfo the object identifying the triggering workflow
  * @returns the unique string id for the source group
  */
-function getSourceGroupId(sourceGroup) {
-    return `:${sourceGroup.workflowId}:${sourceGroup.headRepo}:${sourceGroup.headBranch}:${sourceGroup.eventName}`;
+function getSourceGroupId(triggeringRunInfo) {
+    return (`:${triggeringRunInfo.workflowId}:${triggeringRunInfo.headRepo}` +
+        `:${triggeringRunInfo.headBranch}:${triggeringRunInfo.eventName}`);
 }
 /**
  * Creates query parameters selecting all runs that share the same source group as we have. This can
@@ -1501,18 +1503,18 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param status - status of the run that we are querying for
- * @param mySourceGroup - source group of the originating run
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return query parameters merged with the listWorkflowRuns criteria
  */
-function createListRunsQueryRunsSameSource(repositoryInfo, status, mySourceGroup) {
+function createListRunsQueryRunsSameSource(repositoryInfo, status, triggeringRunInfo) {
     const request = {
         owner: repositoryInfo.owner,
         repo: repositoryInfo.repo,
         // eslint-disable-next-line @typescript-eslint/camelcase
-        workflow_id: mySourceGroup.workflowId,
+        workflow_id: triggeringRunInfo.workflowId,
         status,
-        branch: mySourceGroup.headBranch,
-        event: mySourceGroup.eventName
+        branch: triggeringRunInfo.headBranch,
+        event: triggeringRunInfo.eventName
     };
     return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request);
 }
@@ -1520,19 +1522,18 @@
  * Creates query parameters selecting only specific run Id.
  * @param repositoryInfo - information about the repository used
  * @param status - status of the run that we are querying for
- * @param workflowId - Id of the workflow to retrieve
- * @param runId - run Id to retrieve
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return query parameters merged with the listWorkflowRuns criteria
  */
-function createListRunsQuerySpecificRunId(repositoryInfo, status, workflowId, runId) {
+function createListRunsQuerySpecificRunId(repositoryInfo, status, triggeringRunInfo) {
     const request = {
         owner: repositoryInfo.owner,
         repo: repositoryInfo.repo,
         // eslint-disable-next-line @typescript-eslint/camelcase
-        workflow_id: workflowId,
+        workflow_id: triggeringRunInfo.workflowId,
         status,
         // eslint-disable-next-line @typescript-eslint/camelcase
-        run_id: runId.toString()
+        run_id: triggeringRunInfo.runId.toString()
     };
     return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request);
 }
@@ -1572,15 +1573,33 @@
  * Returns true if the string matches any of the regexps in array of regexps
  * @param stringToMatch string to match
  * @param regexps array of regexp to match the string against
- * @return true if there is a match
+ * @return array of [matched (boolean), [array of matched strings]]
  */
 function matchInArray(stringToMatch, regexps) {
+    let matched = false;
+    const allMatches = [];
     for (const regexp of regexps) {
-        if (stringToMatch.match(regexp)) {
-            return true;
+        const match = stringToMatch.match(regexp);
+        if (match) {
+            matched = true;
+            allMatches.push(match[0]);
         }
     }
-    return false;
+    return [matched, allMatches];
+}
+/**
+ * Adds workflow run to the array in the map indexed by key.
+ * @param key key to use
+ * @param runItem run Item to add
+ * @param mapOfWorkflowRunCandidates map of workflow runs to add the run item to
+ */
+function addWorkflowRunToMap(key, runItem, mapOfWorkflowRunCandidates) {
+    let arrayOfRuns = mapOfWorkflowRunCandidates.get(key);
+    if (arrayOfRuns === undefined) {
+        arrayOfRuns = [];
+        mapOfWorkflowRunCandidates.set(key, arrayOfRuns);
+    }
+    arrayOfRuns.push(runItem);
 }
 /**
  * Returns true if the runId specified has jobs matching the regexp and optionally checks if those
@@ -1591,7 +1610,7 @@
  * @param runId - Id of the run to retrieve jobs for
  * @param jobNameRegexps - array of job name regexps
  * @param checkIfFailed - whether to check the 'failed' status of matched jobs
- * @return true if there is a match
+ * @return array of [matched (boolean), array of matches]
  */
 function jobsMatchingNames(repositoryInfo, runId, jobNameRegexps, checkIfFailed) {
     var e_1, _a;
@@ -1603,18 +1622,22 @@
         else {
             core.info(`\nChecking if runId ${runId} has job names matching any of the ${jobNameRegexps}\n`);
         }
+        const allMatches = [];
+        let matched = false;
         try {
             for (var _b = __asyncValues(repositoryInfo.octokit.paginate.iterator(listJobs)), _c; _c = yield _b.next(), !_c.done;) {
                 const item = _c.value;
-                for (const job of item.data.jobs) {
+                for (const job of item.data) {
                     core.info(`    The job name: ${job.name}, Conclusion: ${job.conclusion}`);
-                    if (matchInArray(job.name, jobNameRegexps)) {
+                    const [jobMatched, jobMatches] = matchInArray(job.name, jobNameRegexps);
+                    if (jobMatched) {
+                        allMatches.push(...jobMatches);
+                        matched = true;
                         if (checkIfFailed) {
                             // Only fail the build if one of the matching jobs fail
                             if (job.conclusion === 'failure') {
                                 core.info(`    The Job ${job.name} matches one of the ${jobNameRegexps} regexps and it failed.` +
-                                    ` Cancelling run.`);
-                                return true;
+                                    ` It will be added to the candidates.`);
                             }
                             else {
                                 core.info(`    The Job ${job.name} matches one of the ${jobNameRegexps} regexps but it did not fail. ` +
@@ -1623,8 +1646,8 @@
                         }
                         else {
                             // Fail the build if any of the job names match
-                            core.info(`    The Job ${job.name} matches one of the ${jobNameRegexps} regexps. Cancelling run.`);
-                            return true;
+                            core.info(`    The Job ${job.name} matches one of the ${jobNameRegexps} regexps. ` +
+                                `It will be added to the candidates.`);
                         }
                     }
                 }
@@ -1637,7 +1660,7 @@
             }
             finally { if (e_1) throw e_1.error; }
         }
-        return false;
+        return [matched, allMatches];
     });
 }
 /**
@@ -1711,67 +1734,74 @@
 /**
  * True if the request is candidate for cancelling in case of duplicate deletion
  * @param runItem item to check
- * @param headRepo head Repo that we are checking against
  * @param cancelFutureDuplicates whether future duplicates are being cancelled
- * @param sourceRunId the source Run Id that originates the request
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if we determine that the run Id should be cancelled
  */
-function isCandidateForCancellingDuplicate(runItem, headRepo, cancelFutureDuplicates, sourceRunId) {
+function checkCandidateForCancellingDuplicate(runItem, cancelFutureDuplicates, triggeringRunInfo, mapOfWorkflowRunCandidates) {
     const runHeadRepo = runItem.head_repository.full_name;
-    if (headRepo !== undefined && runHeadRepo !== headRepo) {
+    if (triggeringRunInfo.headRepo !== undefined &&
+        runHeadRepo !== triggeringRunInfo.headRepo) {
         core.info(`\nThe run ${runItem.id} is from a different ` +
-            `repo: ${runHeadRepo} (expected ${headRepo}). Not cancelling it\n`);
-        return false;
+            `repo: ${runHeadRepo} (expected ${triggeringRunInfo.headRepo}). Not adding as candidate to cancel.\n`);
     }
     if (cancelFutureDuplicates) {
         core.info(`\nCancel Future Duplicates: Returning run id that might be duplicate or my own run: ${runItem.id}.\n`);
-        return true;
+        addWorkflowRunToMap(getSourceGroupId(triggeringRunInfo), runItem, mapOfWorkflowRunCandidates);
     }
     else {
-        if (runItem.id === sourceRunId) {
+        if (runItem.id === triggeringRunInfo.runId) {
             core.info(`\nThis is my own run ${runItem.id}. Not returning myself!\n`);
-            return false;
         }
-        else if (runItem.id > sourceRunId) {
-            core.info(`\nThe run ${runItem.id} is started later than my own run ${sourceRunId}. Not returning it\n`);
-            return false;
+        else if (runItem.id > triggeringRunInfo.runId) {
+            core.info(`\nThe run ${runItem.id} is started later than my own ` +
+                `run ${triggeringRunInfo.runId}. Not returning it\n`);
         }
         core.info(`\nFound duplicate of my own run: ${runItem.id}.\n`);
-        return true;
     }
 }
 /**
- * Should the run is candidate for cancelling in SELF cancelling mode?
+ * Should the run be candidate for cancelling in SELF cancelling mode?
  * @param runItem run item
- * @param sourceRunId source run id
- * @return true if the run item is self
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  */
-function isCandidateForCancellingSelf(runItem, sourceRunId) {
-    if (runItem.id === sourceRunId) {
-        core.info(`\nReturning the "source" run: ${runItem.id}.\n`);
-        return true;
+function checkCandidateForCancellingSelf(runItem, triggeringRunInfo, mapOfWorkflowRunCandidates) {
+    if (runItem.id === triggeringRunInfo.runId) {
+        core.info(`\nAdding the "source" run: ${runItem.id} to candidates.\n`);
+        addWorkflowRunToMap(getSourceGroupId(triggeringRunInfo), runItem, mapOfWorkflowRunCandidates);
     }
-    else {
-        return false;
-    }
+}
+/**
+ * Should the run be candidate for cancelling of all duplicates
+ * @param runItem run item
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
+ */
+function checkCandidateForAllDuplicates(runItem, triggeringRunInfo, mapOfWorkflowRunCandidates) {
+    core.info(`\nAdding the run: ${runItem.id} to candidates.\n`);
+    addWorkflowRunToMap(getSourceGroupId(triggeringRunInfo), runItem, mapOfWorkflowRunCandidates);
 }
 /**
  * Should the run is candidate for cancelling in naming job cancelling mode?
  * @param repositoryInfo - information about the repository used
  * @param runItem run item
  * @param jobNamesRegexps array of regexps to match job names against
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if the run item contains jobs with names matching the pattern
  */
-function isCandidateForCancellingNamedJobs(repositoryInfo, runItem, jobNamesRegexps) {
+function checkCandidateForCancellingNamedJobs(repositoryInfo, runItem, jobNamesRegexps, triggeringRunInfo, mapOfWorkflowRunCandidates) {
     return __awaiter(this, void 0, void 0, function* () {
         // Cancel all jobs that have failed jobs (no matter when started)
-        if (yield jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, false)) {
-            core.info(`\nSome jobs have matching names in ${runItem.id} . Returning it.\n`);
-            return true;
+        const [matched, allMatches] = yield jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, false);
+        if (matched) {
+            core.info(`\nSome jobs have matching names in ${runItem.id}: ${allMatches}. Adding it candidates.\n`);
+            addWorkflowRunToMap(getSourceGroupId(triggeringRunInfo), runItem, mapOfWorkflowRunCandidates);
         }
         else {
-            core.info(`\nNone of the jobs match name in ${runItem.id}. Returning it.\n`);
-            return false;
+            core.info(`\nNone of the jobs match name in ${runItem.id}.\n`);
         }
     });
 }
@@ -1780,67 +1810,92 @@
  * @param repositoryInfo - information about the repository used
  * @param runItem run item
  * @param jobNamesRegexps array of regexps to match job names against
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if the run item contains failed jobs with names matching the pattern
  */
-function isCandidateForCancellingFailedJobs(repositoryInfo, runItem, jobNamesRegexps) {
+function checkCandidateForCancellingFailedJobs(repositoryInfo, runItem, jobNamesRegexps, triggeringRunInfo, mapOfWorkflowRunCandidates) {
     return __awaiter(this, void 0, void 0, function* () {
         // Cancel all jobs that have failed jobs (no matter when started)
-        if (yield jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, true)) {
-            core.info(`\nSome matching named jobs failed in ${runItem.id} . Cancelling it.\n`);
-            return true;
+        const [matched, allMatches] = yield jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, true);
+        if (matched) {
+            core.info(`\nSome matching named jobs failed in ${runItem.id}: ${allMatches}. Adding it to candidates.\n`);
+            addWorkflowRunToMap(getSourceGroupId(triggeringRunInfo), runItem, mapOfWorkflowRunCandidates);
         }
         else {
-            core.info(`\nNone of the matching jobs failed in ${runItem.id}. Not cancelling it.\n`);
-            return false;
+            core.info(`\nNone of the matching jobs failed in ${runItem.id}. Not adding as candidate to cancel.\n`);
         }
     });
 }
 /**
- * Determines whether the run is candidate to be cancelled depending on the mode used
+ * Checks if the run is candidate for duplicate cancelling of named jobs. It adds it to the map
+ * including the match as a key for duplicate detection.
  * @param repositoryInfo - information about the repository used
  * @param runItem - run item
- * @param headRepo - head repository
+ * @param jobNamesRegexps - array of regexps to match job names against
+ * @param mapOfWorkflowRunCandidates - map of runs to update
+ */
+function checkCandidateForDuplicateNamedJobs(repositoryInfo, runItem, jobNamesRegexps, mapOfWorkflowRunCandidates) {
+    return __awaiter(this, void 0, void 0, function* () {
+        const [matched, allMatches] = yield jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, false);
+        if (matched) {
+            for (const match of allMatches) {
+                // This is the only case where we are not using source group to cancelling candidates but
+                // the match of job names
+                addWorkflowRunToMap(match, runItem, mapOfWorkflowRunCandidates);
+            }
+        }
+    });
+}
+/**
+ * Determines whether the run is candidate to be cancelled depending on the mode used and add it to the map
+ * of workflow names if it is.
+ * @param repositoryInfo - information about the repository used
+ * @param runItem - run item
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode
  * @param cancelFutureDuplicates - whether to cancel future duplicates
- * @param sourceRunId - what is the source run id
  * @param jobNamesRegexps - what are the regexps for job names
  * @param skipEventTypes - which events should be skipped
- * @return true if the run id is candidate for cancelling
+ * @param mapOfWorkflowRunCandidates - map of workflow runs to add candidates to
  */
-function isCandidateForCancelling(repositoryInfo, runItem, headRepo, cancelMode, cancelFutureDuplicates, sourceRunId, jobNamesRegexps, skipEventTypes) {
+function checkCandidateForCancelling(repositoryInfo, runItem, triggeringRunInfo, cancelMode, cancelFutureDuplicates, jobNamesRegexps, skipEventTypes, mapOfWorkflowRunCandidates) {
     return __awaiter(this, void 0, void 0, function* () {
         if ('completed' === runItem.status.toString()) {
-            core.info(`\nThe run ${runItem.id} is completed. Not cancelling it.\n`);
-            return false;
+            core.info(`\nThe run ${runItem.id} is completed. Not adding as candidate to cancel.\n`);
+            return;
         }
         if (!CANCELLABLE_EVENT_TYPES.includes(runItem.event.toString())) {
             core.info(`\nThe run ${runItem.id} is (${runItem.event} event - not ` +
-                `in ${CANCELLABLE_EVENT_TYPES}). Not cancelling it.\n`);
-            return false;
+                `in ${CANCELLABLE_EVENT_TYPES}). Not adding as candidate to cancel.\n`);
+            return;
         }
         if (skipEventTypes.includes(runItem.event.toString())) {
             core.info(`\nThe run ${runItem.id} is (${runItem.event} event - ` +
-                `it is in skipEventTypes ${skipEventTypes}). Not cancelling it.\n`);
-            return false;
+                `it is in skipEventTypes ${skipEventTypes}). Not adding as candidate to cancel.\n`);
+            return;
         }
         if (cancelMode === CancelMode.FAILED_JOBS) {
-            return yield isCandidateForCancellingFailedJobs(repositoryInfo, runItem, jobNamesRegexps);
+            yield checkCandidateForCancellingFailedJobs(repositoryInfo, runItem, jobNamesRegexps, triggeringRunInfo, mapOfWorkflowRunCandidates);
         }
         else if (cancelMode === CancelMode.NAMED_JOBS) {
-            return yield isCandidateForCancellingNamedJobs(repositoryInfo, runItem, jobNamesRegexps);
+            yield checkCandidateForCancellingNamedJobs(repositoryInfo, runItem, jobNamesRegexps, triggeringRunInfo, mapOfWorkflowRunCandidates);
         }
         else if (cancelMode === CancelMode.SELF) {
-            return isCandidateForCancellingSelf(runItem, sourceRunId);
+            checkCandidateForCancellingSelf(runItem, triggeringRunInfo, mapOfWorkflowRunCandidates);
         }
         else if (cancelMode === CancelMode.DUPLICATES) {
-            return isCandidateForCancellingDuplicate(runItem, headRepo, cancelFutureDuplicates, sourceRunId);
+            checkCandidateForCancellingDuplicate(runItem, cancelFutureDuplicates, triggeringRunInfo, mapOfWorkflowRunCandidates);
         }
         else if (cancelMode === CancelMode.ALL_DUPLICATES) {
-            core.info(`Returning candidate ${runItem.id} for "all_duplicates" cancelling.`);
-            return true;
+            checkCandidateForAllDuplicates(runItem, triggeringRunInfo, mapOfWorkflowRunCandidates);
+        }
+        else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
+            yield checkCandidateForDuplicateNamedJobs(repositoryInfo, runItem, jobNamesRegexps, mapOfWorkflowRunCandidates);
+            return;
         }
         else {
-            throw Error(`\nWrong cancel mode ${cancelMode}! This should never happen.\n`);
+            throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it!.\n`);
         }
     });
 }
@@ -1871,35 +1926,35 @@
  * @param repositoryInfo - information about the repository used
  * @param statusValues - status values we want to check
  * @param cancelMode - cancel mode to use
- * @param sourceWorkflowId - source workflow id
- * @param sourceRunId - source run id
- * @param sourceEventName - name of the source event
- * @param mySourceGroup - source of the run that originated it
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return map of the run items matching grouped by workflow run id
  */
-function getWorkflowRunsMatchingCriteria(repositoryInfo, statusValues, cancelMode, sourceWorkflowId, sourceRunId, sourceEventName, mySourceGroup) {
+function getWorkflowRunsMatchingCriteria(repositoryInfo, statusValues, cancelMode, triggeringRunInfo) {
     return __awaiter(this, void 0, void 0, function* () {
         return yield getWorkflowRuns(repositoryInfo, statusValues, cancelMode, function (status) {
             if (cancelMode === CancelMode.SELF) {
                 core.info(`\nFinding runs for my own run: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-                    `Workflow ID:${sourceWorkflowId}, Source Run id: ${sourceRunId}\n`);
-                return createListRunsQuerySpecificRunId(repositoryInfo, status, sourceWorkflowId, sourceRunId);
+                    `Workflow ID:${triggeringRunInfo.workflowId},` +
+                    `Source Run id: ${triggeringRunInfo.runId}\n`);
+                return createListRunsQuerySpecificRunId(repositoryInfo, status, triggeringRunInfo);
             }
             else if (cancelMode === CancelMode.FAILED_JOBS ||
                 cancelMode === CancelMode.NAMED_JOBS ||
-                cancelMode === CancelMode.ALL_DUPLICATES) {
+                cancelMode === CancelMode.ALL_DUPLICATES ||
+                cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
                 core.info(`\nFinding runs for all runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-                    `Status: ${status} Workflow ID:${sourceWorkflowId}\n`);
-                return createListRunsQueryAllRuns(repositoryInfo, status, sourceWorkflowId);
+                    `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}\n`);
+                return createListRunsQueryAllRuns(repositoryInfo, status, triggeringRunInfo.workflowId);
             }
             else if (cancelMode === CancelMode.DUPLICATES) {
                 core.info(`\nFinding duplicate runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-                    `Status: ${status} Workflow ID:${sourceWorkflowId}, Head Branch: ${mySourceGroup.headBranch},` +
-                    `Event name: ${sourceEventName}\n`);
-                return createListRunsQueryRunsSameSource(repositoryInfo, status, mySourceGroup);
+                    `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}, ` +
+                    `Head Branch: ${triggeringRunInfo.headBranch},` +
+                    `Event name: ${triggeringRunInfo.eventName}\n`);
+                return createListRunsQueryRunsSameSource(repositoryInfo, status, triggeringRunInfo);
             }
             else {
-                throw Error(`\nWrong cancel mode ${cancelMode}! This should never happen.\n`);
+                throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it.\n`);
             }
         });
     });
@@ -1948,42 +2003,28 @@
     });
 }
 /**
- * Maps found workflow runs into groups - filters out the workflows that are not eligible for canceling
+ * Maps found workflow runs into groups - filters out the workflows that are not eligible for cancelling
  * (depends on cancel Mode) and assigns each workflow to groups - where workflow runs from the
  * same group are put together in one array - in a map indexed by the source group id.
  *
  * @param repositoryInfo - information about the repository used
- * @param headRepo - head repository the event comes from
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode to use
  * @param cancelFutureDuplicates - whether to cancel future duplicates
- * @param sourceRunId - source run id for the run
  * @param jobNameRegexps - regexps for job names
  * @param skipEventTypes - array of event names to skip
  * @param workflowRuns - map of workflow runs found
- * @parm map where key is the source group id and value is array of workflow run item candidates to cancel
+ * @parm maps with string key and array of run items as value. The key might be
+ *       * source group id (allDuplicates mode)
+ *       * matching job name (allDuplicatedMatchingJobNames mode)
  */
-function filterAndMapWorkflowRunsToGroups(repositoryInfo, headRepo, cancelMode, cancelFutureDuplicates, sourceRunId, jobNameRegexps, skipEventTypes, workflowRuns) {
+function filterAndMapWorkflowRunsToGroups(repositoryInfo, triggeringRunInfo, cancelMode, cancelFutureDuplicates, jobNameRegexps, skipEventTypes, workflowRuns) {
     return __awaiter(this, void 0, void 0, function* () {
         const mapOfWorkflowRunCandidates = new Map();
         for (const [key, runItem] of workflowRuns) {
-            core.info(`\nChecking run number: ${key}, RunId: ${runItem.id}, Url: ${runItem.url}. Status ${runItem.status},` +
+            core.info(`\nChecking run number: ${key} RunId: ${runItem.id} Url: ${runItem.url} Status ${runItem.status}` +
                 ` Created at ${runItem.created_at}\n`);
-            if (yield isCandidateForCancelling(repositoryInfo, runItem, headRepo, cancelMode, cancelFutureDuplicates, sourceRunId, jobNameRegexps, skipEventTypes)) {
-                const candidateSourceGroup = {
-                    workflowId: retrieveWorkflowIdFromUrl(runItem.workflow_url),
-                    headBranch: runItem.head_branch,
-                    headRepo: runItem.head_repository.full_name,
-                    eventName: runItem.event
-                };
-                const sourceGroupId = getSourceGroupId(candidateSourceGroup);
-                let workflowRunArray = mapOfWorkflowRunCandidates.get(sourceGroupId);
-                if (workflowRunArray === undefined) {
-                    workflowRunArray = [];
-                    mapOfWorkflowRunCandidates.set(sourceGroupId, workflowRunArray);
-                }
-                core.info(`The candidate ${runItem.id} has been added to ${sourceGroupId} group of candidates`);
-                workflowRunArray.push(runItem);
-            }
+            yield checkCandidateForCancelling(repositoryInfo, runItem, triggeringRunInfo, cancelMode, cancelFutureDuplicates, jobNameRegexps, skipEventTypes, mapOfWorkflowRunCandidates);
         }
         return mapOfWorkflowRunCandidates;
     });
@@ -2011,7 +2052,7 @@
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - my own run id
  * @param pullRequestNumber - number of pull request
- * @param reason reason for canceling
+ * @param reason reason for cancelling
  */
 function notifyPR(repositoryInfo, selfRunId, pullRequestNumber, reason) {
     return __awaiter(this, void 0, void 0, function* () {
@@ -2027,9 +2068,9 @@
  * @param notifyPRCancel - whether to notify the PR when cancelling
  * @param selfRunId - what is the self run id
  * @param sourceGroupId - what is the source group id
- * @param reason - reason for canceling
+ * @param reason - reason for cancelling
  */
-function cancelAllRunsInTheSourceGroup(repositoryInfo, sortedRunItems, notifyPRCancel, selfRunId, sourceGroupId, reason) {
+function cancelAllRunsInTheGroup(repositoryInfo, sortedRunItems, notifyPRCancel, selfRunId, sourceGroupId, reason) {
     return __awaiter(this, void 0, void 0, function* () {
         core.info(`\n###### Cancelling runs for ${sourceGroupId} starting from the most recent  ##########\n` +
             `\n     Number of runs to cancel: ${sortedRunItems.length}\n`);
@@ -2051,39 +2092,40 @@
     });
 }
 /**
- * Cancels found runs in a smart way. It takes all the found runs group by the source group, sorts them
- * descending according to create date in each of the source groups and cancels them in that order -
- * optionally skipping the first found run in each source group in case of duplicates.
+ * Cancels found runs per group. It takes all the found groups, sorts them
+ * descending according to create date in each of the groups and cancels them in that order -
+ * optionally skipping the first found run in each source group in case of duplicate cancelling.
  *
  * @param repositoryInfo - information about the repository used
- * @param mapOfWorkflowRunsCandidatesToCancel map of all workflow run candidates
+ * @param mapOfWorkflowRunCandidatesCandidatesToCancel map of all workflow run candidates
  * @param cancelMode - cancel mode
  * @param cancelFutureDuplicates - whether to cancel future duplicates
  * @param notifyPRCancel - whether to notify PRs with comments
  * @param selfRunId - self run Id
- * @param reason - reason for canceling
+ * @param reason - reason for cancelling
  */
-function cancelTheRunsPerGroup(repositoryInfo, mapOfWorkflowRunsCandidatesToCancel, cancelMode, cancelFutureDuplicates, notifyPRCancel, selfRunId, reason) {
+function cancelTheRunsPerGroup(repositoryInfo, mapOfWorkflowRunCandidatesCandidatesToCancel, cancelMode, cancelFutureDuplicates, notifyPRCancel, selfRunId, reason) {
     return __awaiter(this, void 0, void 0, function* () {
         const cancelledRuns = [];
-        for (const [sourceGroupId, candidatesArray] of mapOfWorkflowRunsCandidatesToCancel) {
+        for (const [groupId, candidatesArray] of mapOfWorkflowRunCandidatesCandidatesToCancel) {
             // Sort from most recent date - this way we always kill current one at the end (if we kill it at all)
             const sortedRunItems = candidatesArray.sort((runItem1, runItem2) => runItem2.created_at.localeCompare(runItem1.created_at));
             if (sortedRunItems.length > 0) {
                 if ((cancelMode === CancelMode.DUPLICATES && cancelFutureDuplicates) ||
-                    cancelMode === CancelMode.ALL_DUPLICATES) {
+                    cancelMode === CancelMode.ALL_DUPLICATES ||
+                    cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
                     core.info(`\nSkipping the first run (${sortedRunItems[0].id}) of all the matching ` +
-                        `duplicates for '${sourceGroupId}'. This one we are going to leave in peace!\n`);
+                        `duplicates for '${groupId}'. This one we are going to leave in peace!\n`);
                     sortedRunItems.shift();
                 }
                 if (sortedRunItems.length === 0) {
-                    core.info(`\nNo duplicates to cancel for ${sourceGroupId}!\n`);
+                    core.info(`\nNo duplicates to cancel for ${groupId}!\n`);
                     continue;
                 }
-                cancelledRuns.push(...(yield cancelAllRunsInTheSourceGroup(repositoryInfo, sortedRunItems, notifyPRCancel, selfRunId, sourceGroupId, reason)));
+                cancelledRuns.push(...(yield cancelAllRunsInTheGroup(repositoryInfo, sortedRunItems, notifyPRCancel, selfRunId, groupId, reason)));
             }
             else {
-                core.info(`\n######  There are no runs to cancel for ${sourceGroupId} ##########\n`);
+                core.info(`\n######  There are no runs to cancel for ${groupId} ##########\n`);
             }
         }
         return cancelledRuns;
@@ -2093,14 +2135,7 @@
  * Find and cancels runs based on the criteria chosen.
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - number of own run id
- * @param sourceWorkflowId - source workflow id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param sourceRunId - source run id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param headRepo - head repository that triggered the workflow (repo from which PR came)
- * @param headBranch - branch of the PR that triggered the workflow (when it is triggered by PR)
- * @param sourceEventName - name of the event that triggered the workflow
- *        (different than self event name for workflow_run)
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
  * @param notifyPRCancel - whether to notify in PRs about cancelling
@@ -2110,18 +2145,12 @@
  * @param reason - reason for cancelling
  * @return array of canceled workflow run ids
  */
-function findAndCancelRuns(repositoryInfo, selfRunId, sourceWorkflowId, sourceRunId, headRepo, headBranch, sourceEventName, cancelMode, cancelFutureDuplicates, notifyPRCancel, notifyPRMessageStart, jobNameRegexps, skipEventTypes, reason) {
+function findAndCancelRuns(repositoryInfo, selfRunId, triggeringRunInfo, cancelMode, cancelFutureDuplicates, notifyPRCancel, notifyPRMessageStart, jobNameRegexps, skipEventTypes, reason) {
     return __awaiter(this, void 0, void 0, function* () {
         const statusValues = ['queued', 'in_progress'];
-        const mySourceGroup = {
-            headBranch,
-            headRepo,
-            eventName: sourceEventName,
-            workflowId: sourceWorkflowId
-        };
-        const workflowRuns = yield getWorkflowRunsMatchingCriteria(repositoryInfo, statusValues, cancelMode, sourceWorkflowId, sourceRunId, sourceEventName, mySourceGroup);
-        const mapOfWorkflowRunsCandidatesToCancel = yield filterAndMapWorkflowRunsToGroups(repositoryInfo, headRepo, cancelMode, cancelFutureDuplicates, sourceRunId, jobNameRegexps, skipEventTypes, workflowRuns);
-        return yield cancelTheRunsPerGroup(repositoryInfo, mapOfWorkflowRunsCandidatesToCancel, cancelMode, cancelFutureDuplicates, notifyPRCancel, selfRunId, reason);
+        const workflowRuns = yield getWorkflowRunsMatchingCriteria(repositoryInfo, statusValues, cancelMode, triggeringRunInfo);
+        const mapOfWorkflowRunCandidatesCandidatesToCancel = yield filterAndMapWorkflowRunsToGroups(repositoryInfo, triggeringRunInfo, cancelMode, cancelFutureDuplicates, jobNameRegexps, skipEventTypes, workflowRuns);
+        return yield cancelTheRunsPerGroup(repositoryInfo, mapOfWorkflowRunCandidatesCandidatesToCancel, cancelMode, cancelFutureDuplicates, notifyPRCancel, selfRunId, reason);
     });
 }
 /**
@@ -2138,12 +2167,12 @@
     return value;
 }
 /**
- * Gets origin of the runId - if this is a workflow run, it returns the information about the source run
+ * Gets source run using  of the runId - if this is a workflow run, it returns the information about the source run
  * @param repositoryInfo - information about the repository used
  * @param runId - run id of the run to check
- * @return information about the triggering workflow
+ * @return information about the triggering run
  */
-function getOrigin(repositoryInfo, runId) {
+function getTriggeringRunInfo(repositoryInfo, runId) {
     return __awaiter(this, void 0, void 0, function* () {
         const reply = yield repositoryInfo.octokit.actions.getWorkflowRun({
             owner: repositoryInfo.owner,
@@ -2160,6 +2189,8 @@
             pullRequest = yield findPullRequest(repositoryInfo, sourceRun.head_repository.owner.login, sourceRun.head_branch, sourceRun.head_sha);
         }
         return {
+            workflowId: retrieveWorkflowIdFromUrl(reply.data.workflow_url),
+            runId,
             headRepo: reply.data.head_repository.full_name,
             headBranch: reply.data.head_branch,
             headSha: reply.data.head_sha,
@@ -2174,14 +2205,7 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - number of own run id
- * @param sourceWorkflowId - source workflow id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param sourceRunId - source run id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param headRepo - head repository that triggered the workflow (repo from which PR came)
- * @param headBranch - branch of the PR that triggered the workflow (when it is triggered by PR)
- * @param sourceEventName - name of the event that triggered the workflow
- *        (different than self event name for workflow_run)
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
  * @param notifyPRCancel - whether to notify in PRs about cancelling
@@ -2191,41 +2215,51 @@
  * @param jobNameRegexps - array of regular expressions to match hob names in case of named modes
  * @param skipEventTypes - array of event names that should be skipped
  */
-function performCancelJob(repositoryInfo, selfRunId, sourceWorkflowId, sourceRunId, headRepo, headBranch, sourceEventName, cancelMode, notifyPRCancel, notifyPRCancelMessage, notifyPRMessageStart, jobNameRegexps, skipEventTypes, cancelFutureDuplicates) {
+function performCancelJob(repositoryInfo, selfRunId, triggeringRunInfo, cancelMode, notifyPRCancel, notifyPRCancelMessage, notifyPRMessageStart, jobNameRegexps, skipEventTypes, cancelFutureDuplicates) {
     return __awaiter(this, void 0, void 0, function* () {
         core.info('\n###################################################################################\n');
-        core.info(`All parameters: owner: ${repositoryInfo.owner}, repo: ${repositoryInfo.repo}, run id: ${sourceRunId}, ` +
-            `head repo ${headRepo}, headBranch: ${headBranch}, ` +
-            `sourceEventName: ${sourceEventName}, cancelMode: ${cancelMode}, jobNames: ${jobNameRegexps}`);
+        core.info(`All parameters: owner: ${repositoryInfo.owner}, repo: ${repositoryInfo.repo}, ` +
+            `run id: ${triggeringRunInfo.runId}, ` +
+            `head repo ${triggeringRunInfo.headRepo}, headBranch: ${triggeringRunInfo.headBranch}, ` +
+            `sourceEventName: ${triggeringRunInfo.eventName}, ` +
+            `cancelMode: ${cancelMode}, jobNames: ${jobNameRegexps}`);
         core.info('\n###################################################################################\n');
         let reason = '';
         if (cancelMode === CancelMode.SELF) {
-            core.info(`# Cancelling source run: ${sourceRunId} for workflow ${sourceWorkflowId}.`);
+            core.info(`# Cancelling source run: ${triggeringRunInfo.runId} ` +
+                `for workflow ${triggeringRunInfo.workflowId}.`);
             reason = notifyPRCancelMessage
                 ? notifyPRCancelMessage
                 : `The job has been cancelled by another workflow.`;
         }
         else if (cancelMode === CancelMode.FAILED_JOBS) {
-            core.info(`# Cancel all runs for workflow ${sourceWorkflowId} where job names matching ${jobNameRegexps} failed.`);
+            core.info(`# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
+                `where job names matching ${jobNameRegexps} failed.`);
             reason = `It has some failed jobs matching ${jobNameRegexps}.`;
         }
         else if (cancelMode === CancelMode.NAMED_JOBS) {
-            core.info(`# Cancel all runs for workflow ${sourceWorkflowId} have job names matching ${jobNameRegexps}.`);
+            core.info(`# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
+                `have job names matching ${jobNameRegexps}.`);
             reason = `It has jobs matching ${jobNameRegexps}.`;
         }
         else if (cancelMode === CancelMode.DUPLICATES) {
-            core.info(`# Cancel duplicate runs for workflow ${sourceWorkflowId} for same triggering branch as own run Id.`);
-            reason = `It is an earlier duplicate of ${sourceWorkflowId} run.`;
+            core.info(`# Cancel duplicate runs for workflow ${triggeringRunInfo.workflowId} ` +
+                `for same triggering branch as own run Id.`);
+            reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`;
         }
         else if (cancelMode === CancelMode.ALL_DUPLICATES) {
-            core.info(`# Cancel all duplicates runs started for workflow ${sourceWorkflowId}.`);
-            reason = `It is an earlier duplicate of ${sourceWorkflowId} run.`;
+            core.info(`# Cancel all duplicates runs started for workflow ${triggeringRunInfo.workflowId}.`);
+            reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`;
+        }
+        else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
+            core.info(`# Cancel all duplicate named jobs matching the patterns ${jobNameRegexps}.`);
+            reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`;
         }
         else {
-            throw Error(`Wrong cancel mode ${cancelMode}! This should never happen.`);
+            throw Error(`Wrong cancel mode ${cancelMode}! Please correct it.`);
         }
         core.info('\n###################################################################################\n');
-        return yield findAndCancelRuns(repositoryInfo, selfRunId, sourceWorkflowId, sourceRunId, headRepo, headBranch, sourceEventName, cancelMode, cancelFutureDuplicates, notifyPRCancel, notifyPRMessageStart, jobNameRegexps, skipEventTypes, reason);
+        return yield findAndCancelRuns(repositoryInfo, selfRunId, triggeringRunInfo, cancelMode, cancelFutureDuplicates, notifyPRCancel, notifyPRMessageStart, jobNameRegexps, skipEventTypes, reason);
     });
 }
 /**
@@ -2235,27 +2269,27 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param workflowFileName - optional workflow file name
- * @param sourceRunId - source run id of the workfow
+ * @param runId - run id of the workflow
  * @param selfRunId - self run id
  * @return workflow id that is associate with the workflow we are going to act on.
  */
-function retrieveWorkflowId(repositoryInfo, workflowFileName, sourceRunId, selfRunId) {
+function retrieveWorkflowId(repositoryInfo, workflowFileName, runId, selfRunId) {
     return __awaiter(this, void 0, void 0, function* () {
-        let sourceWorkflowId;
+        let workflowId;
         if (workflowFileName) {
-            sourceWorkflowId = workflowFileName;
-            core.info(`\nFinding runs for another workflow found by ${workflowFileName} name: ${sourceWorkflowId}\n`);
+            workflowId = workflowFileName;
+            core.info(`\nFinding runs for another workflow found by ${workflowFileName} name: ${workflowId}\n`);
         }
         else {
-            sourceWorkflowId = yield getWorkflowId(repositoryInfo, sourceRunId);
-            if (sourceRunId === selfRunId) {
-                core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`);
+            workflowId = yield getWorkflowId(repositoryInfo, runId);
+            if (runId === selfRunId) {
+                core.info(`\nFinding runs for my own workflow ${workflowId}\n`);
             }
             else {
-                core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`);
+                core.info(`\nFinding runs for source workflow ${workflowId}\n`);
             }
         }
-        return sourceWorkflowId;
+        return workflowId;
     });
 }
 /**
@@ -2273,15 +2307,15 @@
  * are verified and in case od unexpected combination found, approrpriate error is raised.
  *
  * @param eventName - name of the event to act on
- * @param sourceRunId - run id of the triggering event
+ * @param runId - run id of the triggering event
  * @param selfRunId - our own run id
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether future duplicate cancelling is enabled
  * @param jobNameRegexps - array of regular expression of job names
  */
-function performSanityChecks(eventName, sourceRunId, selfRunId, cancelMode, cancelFutureDuplicates, jobNameRegexps) {
+function performSanityChecks(eventName, runId, selfRunId, cancelMode, cancelFutureDuplicates, jobNameRegexps) {
     if (eventName === 'workflow_run' &&
-        sourceRunId === selfRunId &&
+        runId === selfRunId &&
         cancelMode === CancelMode.DUPLICATES) {
         throw Error(`You cannot run "workflow_run" in ${cancelMode} cancelMode without "sourceId" input.` +
             'It will likely not work as you intended - it will cancel runs which are not duplicates!' +
@@ -2293,9 +2327,19 @@
             CancelMode.SELF,
             CancelMode.ALL_DUPLICATES
         ].includes(cancelMode)) {
-        throw Error(`You cannot specify jobNames on ${cancelMode} cancelMode.`);
+        throw Error(`You cannot specify jobNamesRegexps on ${cancelMode} cancelMode.`);
     }
-    if (cancelMode === CancelMode.ALL_DUPLICATES && !cancelFutureDuplicates) {
+    if (jobNameRegexps.length === 0 &&
+        [
+            CancelMode.NAMED_JOBS,
+            CancelMode.FAILED_JOBS,
+            CancelMode.ALL_DUPLICATED_NAMED_JOBS
+        ].includes(cancelMode)) {
+        throw Error(`You must specify jobNamesRegexps on ${cancelMode} cancelMode.`);
+    }
+    if ((cancelMode === CancelMode.ALL_DUPLICATES ||
+        cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) &&
+        !cancelFutureDuplicates) {
         throw Error(`The  ${cancelMode} cancelMode has to have cancelFutureDuplicates set to true.`);
     }
 }
@@ -2303,42 +2347,39 @@
  * Produces basic outputs for the action. This does not include cancelled workflow run id - those are
  * set after cancelling is done.
  *
- * @param triggeringWorkflowInfo
+ * @param triggeringRunInfo
  */
-function produceBasicOutputs(triggeringWorkflowInfo) {
-    verboseOutput('sourceHeadRepo', triggeringWorkflowInfo.headRepo);
-    verboseOutput('sourceHeadBranch', triggeringWorkflowInfo.headBranch);
-    verboseOutput('sourceHeadSha', triggeringWorkflowInfo.headSha);
-    verboseOutput('sourceEvent', triggeringWorkflowInfo.eventName);
-    verboseOutput('pullRequestNumber', triggeringWorkflowInfo.pullRequest
-        ? triggeringWorkflowInfo.pullRequest.number.toString()
+function produceBasicOutputs(triggeringRunInfo) {
+    verboseOutput('sourceHeadRepo', triggeringRunInfo.headRepo);
+    verboseOutput('sourceHeadBranch', triggeringRunInfo.headBranch);
+    verboseOutput('sourceHeadSha', triggeringRunInfo.headSha);
+    verboseOutput('sourceEvent', triggeringRunInfo.eventName);
+    verboseOutput('pullRequestNumber', triggeringRunInfo.pullRequest
+        ? triggeringRunInfo.pullRequest.number.toString()
         : '');
-    verboseOutput('mergeCommitSha', triggeringWorkflowInfo.mergeCommitSha
-        ? triggeringWorkflowInfo.mergeCommitSha
-        : '');
-    verboseOutput('targetCommitSha', triggeringWorkflowInfo.mergeCommitSha
-        ? triggeringWorkflowInfo.mergeCommitSha
-        : triggeringWorkflowInfo.headSha);
+    verboseOutput('mergeCommitSha', triggeringRunInfo.mergeCommitSha ? triggeringRunInfo.mergeCommitSha : '');
+    verboseOutput('targetCommitSha', triggeringRunInfo.mergeCommitSha
+        ? triggeringRunInfo.mergeCommitSha
+        : triggeringRunInfo.headSha);
 }
 /**
  * Notifies the PR that the action has started.
  *
  * @param repositoryInfo information about the repository
- * @param triggeringWorkflowInfo information about the triggering workflow
- * @param sourceRunId run id of the source workflow
+ * @param triggeringRunInfo information about the triggering workflow
  * @param selfRunId self run id
  * @param notifyPRMessageStart whether to notify about the start of the action
  */
-function notifyActionStart(repositoryInfo, triggeringWorkflowInfo, sourceRunId, selfRunId, notifyPRMessageStart) {
+function notifyActionStart(repositoryInfo, triggeringRunInfo, selfRunId, notifyPRMessageStart) {
     return __awaiter(this, void 0, void 0, function* () {
-        if (notifyPRMessageStart && triggeringWorkflowInfo.pullRequest) {
+        if (notifyPRMessageStart && triggeringRunInfo.pullRequest) {
             const selfWorkflowRunUrl = `https://github.com/${repositoryInfo.owner}/${repositoryInfo.repo}` +
                 `/actions/runs/${selfRunId}`;
             yield repositoryInfo.octokit.issues.createComment({
                 owner: repositoryInfo.owner,
                 repo: repositoryInfo.repo,
                 // eslint-disable-next-line @typescript-eslint/camelcase
-                issue_number: triggeringWorkflowInfo.pullRequest.number,
+                issue_number: triggeringRunInfo.pullRequest.number,
                 body: `${notifyPRMessageStart} [The workflow run](${selfWorkflowRunUrl})`
             });
         }
@@ -2383,10 +2424,10 @@
             `Event name: ${eventName}, CancelMode: ${cancelMode}, ` +
             `sourceWorkflowId: ${sourceWorkflowId}, sourceRunId: ${sourceRunId}, selfRunId: ${selfRunId}, ` +
             `jobNames: ${jobNameRegexps}`);
-        const triggeringWorkflowInfo = yield getOrigin(repositoryInfo, sourceRunId);
-        produceBasicOutputs(triggeringWorkflowInfo);
-        yield notifyActionStart(repositoryInfo, triggeringWorkflowInfo, sourceRunId, selfRunId, notifyPRMessageStart);
-        const cancelledRuns = yield performCancelJob(repositoryInfo, selfRunId, sourceWorkflowId, sourceRunId, triggeringWorkflowInfo.headRepo, triggeringWorkflowInfo.headBranch, triggeringWorkflowInfo.eventName, cancelMode, notifyPRCancel, notifyPRCancelMessage, notifyPRMessageStart, jobNameRegexps, skipEventTypes, cancelFutureDuplicates);
+        const triggeringRunInfo = yield getTriggeringRunInfo(repositoryInfo, sourceRunId);
+        produceBasicOutputs(triggeringRunInfo);
+        yield notifyActionStart(repositoryInfo, triggeringRunInfo, selfRunId, notifyPRMessageStart);
+        const cancelledRuns = yield performCancelJob(repositoryInfo, selfRunId, triggeringRunInfo, cancelMode, notifyPRCancel, notifyPRCancelMessage, notifyPRMessageStart, jobNameRegexps, skipEventTypes, cancelFutureDuplicates);
         verboseOutput('cancelledRuns', JSON.stringify(cancelledRuns));
     });
 }
diff --git a/src/main.ts b/src/main.ts
index 19b00b3..abf39f1 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -21,21 +21,8 @@
   ALL_DUPLICATES = 'allDuplicates',
   SELF = 'self',
   FAILED_JOBS = 'failedJobs',
-  NAMED_JOBS = 'namedJobs'
-}
-
-/**
- * Stores information uniquely identifying the run by it's triggering source:
- * It is the workflow id, Head Repo and Branch the change originates from and event name that originates it.
- *
- * All Runs coming from the same Pull Request share the same Source Group. Also all pushes to master
- * share the same Source Group
- */
-interface WorkflowRunSourceGroup {
-  workflowId: number | string
-  headRepo: string
-  headBranch: string
-  eventName: string
+  NAMED_JOBS = 'namedJobs',
+  ALL_DUPLICATED_NAMED_JOBS = 'allDuplicatedNamedJobs'
 }
 
 /**
@@ -51,7 +38,9 @@
 /**
  * Stores information about the workflow info that triggered the current workflow.
  */
-interface TriggeringWorkflowInfo {
+interface TriggeringRunInfo {
+  workflowId: number
+  runId: number
   headRepo: string
   headBranch: string
   headSha: string
@@ -63,11 +52,14 @@
 /**
  * Converts the source of a run object into a string that can be used as map key in maps where we keep
  * arrays of runs per source group
- * @param sourceGroup the object identifying the source of the run (Pull Request, Master Push)
+ * @param triggeringRunInfo the object identifying the triggering workflow
  * @returns the unique string id for the source group
  */
-function getSourceGroupId(sourceGroup: WorkflowRunSourceGroup): string {
-  return `:${sourceGroup.workflowId}:${sourceGroup.headRepo}:${sourceGroup.headBranch}:${sourceGroup.eventName}`
+function getSourceGroupId(triggeringRunInfo: TriggeringRunInfo): string {
+  return (
+    `:${triggeringRunInfo.workflowId}:${triggeringRunInfo.headRepo}` +
+    `:${triggeringRunInfo.headBranch}:${triggeringRunInfo.eventName}`
+  )
 }
 
 /**
@@ -76,22 +68,22 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param status - status of the run that we are querying for
- * @param mySourceGroup - source group of the originating run
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return query parameters merged with the listWorkflowRuns criteria
  */
 function createListRunsQueryRunsSameSource(
   repositoryInfo: RepositoryInfo,
   status: string,
-  mySourceGroup: WorkflowRunSourceGroup
+  triggeringRunInfo: TriggeringRunInfo
 ): rest.RequestOptions {
   const request = {
     owner: repositoryInfo.owner,
     repo: repositoryInfo.repo,
     // eslint-disable-next-line @typescript-eslint/camelcase
-    workflow_id: mySourceGroup.workflowId,
+    workflow_id: triggeringRunInfo.workflowId,
     status,
-    branch: mySourceGroup.headBranch,
-    event: mySourceGroup.eventName
+    branch: triggeringRunInfo.headBranch,
+    event: triggeringRunInfo.eventName
   }
   return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request)
 }
@@ -99,24 +91,22 @@
  * Creates query parameters selecting only specific run Id.
  * @param repositoryInfo - information about the repository used
  * @param status - status of the run that we are querying for
- * @param workflowId - Id of the workflow to retrieve
- * @param runId - run Id to retrieve
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return query parameters merged with the listWorkflowRuns criteria
  */
 function createListRunsQuerySpecificRunId(
   repositoryInfo: RepositoryInfo,
   status: string,
-  workflowId: number | string,
-  runId: number
+  triggeringRunInfo: TriggeringRunInfo
 ): rest.RequestOptions {
   const request = {
     owner: repositoryInfo.owner,
     repo: repositoryInfo.repo,
     // eslint-disable-next-line @typescript-eslint/camelcase
-    workflow_id: workflowId,
+    workflow_id: triggeringRunInfo.workflowId,
     status,
     // eslint-disable-next-line @typescript-eslint/camelcase
-    run_id: runId.toString()
+    run_id: triggeringRunInfo.runId.toString()
   }
   return repositoryInfo.octokit.actions.listWorkflowRuns.endpoint.merge(request)
 }
@@ -168,15 +158,44 @@
  * Returns true if the string matches any of the regexps in array of regexps
  * @param stringToMatch string to match
  * @param regexps array of regexp to match the string against
- * @return true if there is a match
+ * @return array of [matched (boolean), [array of matched strings]]
  */
-function matchInArray(stringToMatch: string, regexps: string[]): boolean {
+function matchInArray(
+  stringToMatch: string,
+  regexps: string[]
+): [boolean, string[]] {
+  let matched = false
+  const allMatches: string[] = []
   for (const regexp of regexps) {
-    if (stringToMatch.match(regexp)) {
-      return true
+    const match = stringToMatch.match(regexp)
+    if (match) {
+      matched = true
+      allMatches.push(match[0])
     }
   }
-  return false
+  return [matched, allMatches]
+}
+
+/**
+ * Adds workflow run to the array in the map indexed by key.
+ * @param key key to use
+ * @param runItem run Item to add
+ * @param mapOfWorkflowRunCandidates map of workflow runs to add the run item to
+ */
+function addWorkflowRunToMap(
+  key: string,
+  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): void {
+  let arrayOfRuns = mapOfWorkflowRunCandidates.get(key)
+  if (arrayOfRuns === undefined) {
+    arrayOfRuns = []
+    mapOfWorkflowRunCandidates.set(key, arrayOfRuns)
+  }
+  arrayOfRuns.push(runItem)
 }
 
 /**
@@ -188,14 +207,14 @@
  * @param runId - Id of the run to retrieve jobs for
  * @param jobNameRegexps - array of job name regexps
  * @param checkIfFailed - whether to check the 'failed' status of matched jobs
- * @return true if there is a match
+ * @return array of [matched (boolean), array of matches]
  */
 async function jobsMatchingNames(
   repositoryInfo: RepositoryInfo,
   runId: number,
   jobNameRegexps: string[],
   checkIfFailed: boolean
-): Promise<boolean> {
+): Promise<[boolean, string[]]> {
   const listJobs = createJobsForWorkflowRunQuery(repositoryInfo, runId)
   if (checkIfFailed) {
     core.info(
@@ -206,18 +225,22 @@
       `\nChecking if runId ${runId} has job names matching any of the ${jobNameRegexps}\n`
     )
   }
+  const allMatches: string[] = []
+  let matched = false
   for await (const item of repositoryInfo.octokit.paginate.iterator(listJobs)) {
-    for (const job of item.data.jobs) {
+    for (const job of item.data) {
       core.info(`    The job name: ${job.name}, Conclusion: ${job.conclusion}`)
-      if (matchInArray(job.name, jobNameRegexps)) {
+      const [jobMatched, jobMatches] = matchInArray(job.name, jobNameRegexps)
+      if (jobMatched) {
+        allMatches.push(...jobMatches)
+        matched = true
         if (checkIfFailed) {
           // Only fail the build if one of the matching jobs fail
           if (job.conclusion === 'failure') {
             core.info(
               `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps and it failed.` +
-                ` Cancelling run.`
+                ` It will be added to the candidates.`
             )
-            return true
           } else {
             core.info(
               `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps but it did not fail. ` +
@@ -227,14 +250,14 @@
         } else {
           // Fail the build if any of the job names match
           core.info(
-            `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps. Cancelling run.`
+            `    The Job ${job.name} matches one of the ${jobNameRegexps} regexps. ` +
+              `It will be added to the candidates.`
           )
-          return true
         }
       }
     }
   }
-  return false
+  return [matched, allMatches]
 }
 
 /**
@@ -310,86 +333,135 @@
 /**
  * True if the request is candidate for cancelling in case of duplicate deletion
  * @param runItem item to check
- * @param headRepo head Repo that we are checking against
  * @param cancelFutureDuplicates whether future duplicates are being cancelled
- * @param sourceRunId the source Run Id that originates the request
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if we determine that the run Id should be cancelled
  */
-function isCandidateForCancellingDuplicate(
+function checkCandidateForCancellingDuplicate(
   runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
-  headRepo: string,
   cancelFutureDuplicates: boolean,
-  sourceRunId: number
-): boolean {
+  triggeringRunInfo: TriggeringRunInfo,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): void {
   const runHeadRepo = runItem.head_repository.full_name
-  if (headRepo !== undefined && runHeadRepo !== headRepo) {
+  if (
+    triggeringRunInfo.headRepo !== undefined &&
+    runHeadRepo !== triggeringRunInfo.headRepo
+  ) {
     core.info(
       `\nThe run ${runItem.id} is from a different ` +
-        `repo: ${runHeadRepo} (expected ${headRepo}). Not cancelling it\n`
+        `repo: ${runHeadRepo} (expected ${triggeringRunInfo.headRepo}). Not adding as candidate to cancel.\n`
     )
-    return false
   }
   if (cancelFutureDuplicates) {
     core.info(
       `\nCancel Future Duplicates: Returning run id that might be duplicate or my own run: ${runItem.id}.\n`
     )
-    return true
+    addWorkflowRunToMap(
+      getSourceGroupId(triggeringRunInfo),
+      runItem,
+      mapOfWorkflowRunCandidates
+    )
   } else {
-    if (runItem.id === sourceRunId) {
+    if (runItem.id === triggeringRunInfo.runId) {
       core.info(`\nThis is my own run ${runItem.id}. Not returning myself!\n`)
-      return false
-    } else if (runItem.id > sourceRunId) {
+    } else if (runItem.id > triggeringRunInfo.runId) {
       core.info(
-        `\nThe run ${runItem.id} is started later than my own run ${sourceRunId}. Not returning it\n`
+        `\nThe run ${runItem.id} is started later than my own ` +
+          `run ${triggeringRunInfo.runId}. Not returning it\n`
       )
-      return false
     }
     core.info(`\nFound duplicate of my own run: ${runItem.id}.\n`)
-    return true
   }
 }
 
 /**
- * Should the run is candidate for cancelling in SELF cancelling mode?
+ * Should the run be candidate for cancelling in SELF cancelling mode?
  * @param runItem run item
- * @param sourceRunId source run id
- * @return true if the run item is self
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  */
-function isCandidateForCancellingSelf(
+function checkCandidateForCancellingSelf(
   runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
-  sourceRunId: number
-): boolean {
-  if (runItem.id === sourceRunId) {
-    core.info(`\nReturning the "source" run: ${runItem.id}.\n`)
-    return true
-  } else {
-    return false
+  triggeringRunInfo: TriggeringRunInfo,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): void {
+  if (runItem.id === triggeringRunInfo.runId) {
+    core.info(`\nAdding the "source" run: ${runItem.id} to candidates.\n`)
+    addWorkflowRunToMap(
+      getSourceGroupId(triggeringRunInfo),
+      runItem,
+      mapOfWorkflowRunCandidates
+    )
   }
 }
 
 /**
+ * Should the run be candidate for cancelling of all duplicates
+ * @param runItem run item
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
+ */
+function checkCandidateForAllDuplicates(
+  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
+  triggeringRunInfo: TriggeringRunInfo,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): void {
+  core.info(`\nAdding the run: ${runItem.id} to candidates.\n`)
+  addWorkflowRunToMap(
+    getSourceGroupId(triggeringRunInfo),
+    runItem,
+    mapOfWorkflowRunCandidates
+  )
+}
+
+/**
  * Should the run is candidate for cancelling in naming job cancelling mode?
  * @param repositoryInfo - information about the repository used
  * @param runItem run item
  * @param jobNamesRegexps array of regexps to match job names against
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if the run item contains jobs with names matching the pattern
  */
-async function isCandidateForCancellingNamedJobs(
+async function checkCandidateForCancellingNamedJobs(
   repositoryInfo: RepositoryInfo,
   runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
-  jobNamesRegexps: string[]
-): Promise<boolean> {
+  jobNamesRegexps: string[],
+  triggeringRunInfo: TriggeringRunInfo,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): Promise<void> {
   // Cancel all jobs that have failed jobs (no matter when started)
-  if (
-    await jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, false)
-  ) {
+  const [matched, allMatches] = await jobsMatchingNames(
+    repositoryInfo,
+    runItem.id,
+    jobNamesRegexps,
+    false
+  )
+  if (matched) {
     core.info(
-      `\nSome jobs have matching names in ${runItem.id} . Returning it.\n`
+      `\nSome jobs have matching names in ${runItem.id}: ${allMatches}. Adding it candidates.\n`
     )
-    return true
+    addWorkflowRunToMap(
+      getSourceGroupId(triggeringRunInfo),
+      runItem,
+      mapOfWorkflowRunCandidates
+    )
   } else {
-    core.info(`\nNone of the jobs match name in ${runItem.id}. Returning it.\n`)
-    return false
+    core.info(`\nNone of the jobs match name in ${runItem.id}.\n`)
   }
 }
 
@@ -398,99 +470,165 @@
  * @param repositoryInfo - information about the repository used
  * @param runItem run item
  * @param jobNamesRegexps array of regexps to match job names against
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param mapOfWorkflowRunCandidates - map of the workflow runs to add candidates to
  * @return true if the run item contains failed jobs with names matching the pattern
  */
-async function isCandidateForCancellingFailedJobs(
+async function checkCandidateForCancellingFailedJobs(
   repositoryInfo: RepositoryInfo,
   runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
-  jobNamesRegexps: string[]
-): Promise<boolean> {
+  jobNamesRegexps: string[],
+  triggeringRunInfo: TriggeringRunInfo,
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): Promise<void> {
   // Cancel all jobs that have failed jobs (no matter when started)
-  if (
-    await jobsMatchingNames(repositoryInfo, runItem.id, jobNamesRegexps, true)
-  ) {
+  const [matched, allMatches] = await jobsMatchingNames(
+    repositoryInfo,
+    runItem.id,
+    jobNamesRegexps,
+    true
+  )
+  if (matched) {
     core.info(
-      `\nSome matching named jobs failed in ${runItem.id} . Cancelling it.\n`
+      `\nSome matching named jobs failed in ${runItem.id}: ${allMatches}. Adding it to candidates.\n`
     )
-    return true
+    addWorkflowRunToMap(
+      getSourceGroupId(triggeringRunInfo),
+      runItem,
+      mapOfWorkflowRunCandidates
+    )
   } else {
     core.info(
-      `\nNone of the matching jobs failed in ${runItem.id}. Not cancelling it.\n`
+      `\nNone of the matching jobs failed in ${runItem.id}. Not adding as candidate to cancel.\n`
     )
-    return false
   }
 }
 
 /**
- * Determines whether the run is candidate to be cancelled depending on the mode used
+ * Checks if the run is candidate for duplicate cancelling of named jobs. It adds it to the map
+ * including the match as a key for duplicate detection.
  * @param repositoryInfo - information about the repository used
  * @param runItem - run item
- * @param headRepo - head repository
- * @param cancelMode - cancel mode
- * @param cancelFutureDuplicates - whether to cancel future duplicates
- * @param sourceRunId - what is the source run id
- * @param jobNamesRegexps - what are the regexps for job names
- * @param skipEventTypes - which events should be skipped
- * @return true if the run id is candidate for cancelling
+ * @param jobNamesRegexps - array of regexps to match job names against
+ * @param mapOfWorkflowRunCandidates - map of runs to update
  */
-async function isCandidateForCancelling(
+async function checkCandidateForDuplicateNamedJobs(
   repositoryInfo: RepositoryInfo,
   runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
-  headRepo: string,
+  jobNamesRegexps: string[],
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): Promise<void> {
+  const [matched, allMatches] = await jobsMatchingNames(
+    repositoryInfo,
+    runItem.id,
+    jobNamesRegexps,
+    false
+  )
+  if (matched) {
+    for (const match of allMatches) {
+      // This is the only case where we are not using source group to cancelling candidates but
+      // the match of job names
+      addWorkflowRunToMap(match, runItem, mapOfWorkflowRunCandidates)
+    }
+  }
+}
+
+/**
+ * Determines whether the run is candidate to be cancelled depending on the mode used and add it to the map
+ * of workflow names if it is.
+ * @param repositoryInfo - information about the repository used
+ * @param runItem - run item
+ * @param triggeringRunInfo - information about the workflow that triggered the run
+ * @param cancelMode - cancel mode
+ * @param cancelFutureDuplicates - whether to cancel future duplicates
+ * @param jobNamesRegexps - what are the regexps for job names
+ * @param skipEventTypes - which events should be skipped
+ * @param mapOfWorkflowRunCandidates - map of workflow runs to add candidates to
+ */
+async function checkCandidateForCancelling(
+  repositoryInfo: RepositoryInfo,
+  runItem: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem,
+  triggeringRunInfo: TriggeringRunInfo,
   cancelMode: CancelMode,
   cancelFutureDuplicates: boolean,
-  sourceRunId: number,
   jobNamesRegexps: string[],
-  skipEventTypes: string[]
-): Promise<boolean> {
+  skipEventTypes: string[],
+  mapOfWorkflowRunCandidates: Map<
+    string,
+    rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
+  >
+): Promise<void> {
   if ('completed' === runItem.status.toString()) {
-    core.info(`\nThe run ${runItem.id} is completed. Not cancelling it.\n`)
-    return false
+    core.info(
+      `\nThe run ${runItem.id} is completed. Not adding as candidate to cancel.\n`
+    )
+    return
   }
   if (!CANCELLABLE_EVENT_TYPES.includes(runItem.event.toString())) {
     core.info(
       `\nThe run ${runItem.id} is (${runItem.event} event - not ` +
-        `in ${CANCELLABLE_EVENT_TYPES}). Not cancelling it.\n`
+        `in ${CANCELLABLE_EVENT_TYPES}). Not adding as candidate to cancel.\n`
     )
-    return false
+    return
   }
   if (skipEventTypes.includes(runItem.event.toString())) {
     core.info(
       `\nThe run ${runItem.id} is (${runItem.event} event - ` +
-        `it is in skipEventTypes ${skipEventTypes}). Not cancelling it.\n`
+        `it is in skipEventTypes ${skipEventTypes}). Not adding as candidate to cancel.\n`
     )
-    return false
+    return
   }
   if (cancelMode === CancelMode.FAILED_JOBS) {
-    return await isCandidateForCancellingFailedJobs(
+    await checkCandidateForCancellingFailedJobs(
       repositoryInfo,
       runItem,
-      jobNamesRegexps
+      jobNamesRegexps,
+      triggeringRunInfo,
+      mapOfWorkflowRunCandidates
     )
   } else if (cancelMode === CancelMode.NAMED_JOBS) {
-    return await isCandidateForCancellingNamedJobs(
+    await checkCandidateForCancellingNamedJobs(
       repositoryInfo,
       runItem,
-      jobNamesRegexps
+      jobNamesRegexps,
+      triggeringRunInfo,
+      mapOfWorkflowRunCandidates
     )
   } else if (cancelMode === CancelMode.SELF) {
-    return isCandidateForCancellingSelf(runItem, sourceRunId)
-  } else if (cancelMode === CancelMode.DUPLICATES) {
-    return isCandidateForCancellingDuplicate(
+    checkCandidateForCancellingSelf(
       runItem,
-      headRepo,
+      triggeringRunInfo,
+      mapOfWorkflowRunCandidates
+    )
+  } else if (cancelMode === CancelMode.DUPLICATES) {
+    checkCandidateForCancellingDuplicate(
+      runItem,
       cancelFutureDuplicates,
-      sourceRunId
+      triggeringRunInfo,
+      mapOfWorkflowRunCandidates
     )
   } else if (cancelMode === CancelMode.ALL_DUPLICATES) {
-    core.info(
-      `Returning candidate ${runItem.id} for "all_duplicates" cancelling.`
+    checkCandidateForAllDuplicates(
+      runItem,
+      triggeringRunInfo,
+      mapOfWorkflowRunCandidates
     )
-    return true
+  } else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
+    await checkCandidateForDuplicateNamedJobs(
+      repositoryInfo,
+      runItem,
+      jobNamesRegexps,
+      mapOfWorkflowRunCandidates
+    )
+    return
   } else {
-    throw Error(
-      `\nWrong cancel mode ${cancelMode}! This should never happen.\n`
-    )
+    throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it!.\n`)
   }
 }
 
@@ -524,25 +662,14 @@
  * @param repositoryInfo - information about the repository used
  * @param statusValues - status values we want to check
  * @param cancelMode - cancel mode to use
- * @param sourceWorkflowId - source workflow id
- * @param sourceRunId - source run id
- * @param sourceEventName - name of the source event
- * @param mySourceGroup - source of the run that originated it
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @return map of the run items matching grouped by workflow run id
  */
 async function getWorkflowRunsMatchingCriteria(
   repositoryInfo: RepositoryInfo,
   statusValues: string[],
-  cancelMode:
-    | CancelMode
-    | CancelMode.DUPLICATES
-    | CancelMode.ALL_DUPLICATES
-    | CancelMode.FAILED_JOBS
-    | CancelMode.NAMED_JOBS,
-  sourceWorkflowId: number | string,
-  sourceRunId: number,
-  sourceEventName: string,
-  mySourceGroup: WorkflowRunSourceGroup
+  cancelMode: CancelMode,
+  triggeringRunInfo: TriggeringRunInfo
 ): Promise<Map<number, rest.ActionsListWorkflowRunsResponseWorkflowRunsItem>> {
   return await getWorkflowRuns(
     repositoryInfo,
@@ -552,43 +679,43 @@
       if (cancelMode === CancelMode.SELF) {
         core.info(
           `\nFinding runs for my own run: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-            `Workflow ID:${sourceWorkflowId}, Source Run id: ${sourceRunId}\n`
+            `Workflow ID:${triggeringRunInfo.workflowId},` +
+            `Source Run id: ${triggeringRunInfo.runId}\n`
         )
         return createListRunsQuerySpecificRunId(
           repositoryInfo,
           status,
-          sourceWorkflowId,
-          sourceRunId
+          triggeringRunInfo
         )
       } else if (
         cancelMode === CancelMode.FAILED_JOBS ||
         cancelMode === CancelMode.NAMED_JOBS ||
-        cancelMode === CancelMode.ALL_DUPLICATES
+        cancelMode === CancelMode.ALL_DUPLICATES ||
+        cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS
       ) {
         core.info(
           `\nFinding runs for all runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-            `Status: ${status} Workflow ID:${sourceWorkflowId}\n`
+            `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}\n`
         )
         return createListRunsQueryAllRuns(
           repositoryInfo,
           status,
-          sourceWorkflowId
+          triggeringRunInfo.workflowId
         )
       } else if (cancelMode === CancelMode.DUPLICATES) {
         core.info(
           `\nFinding duplicate runs: Owner: ${repositoryInfo.owner}, Repo: ${repositoryInfo.repo}, ` +
-            `Status: ${status} Workflow ID:${sourceWorkflowId}, Head Branch: ${mySourceGroup.headBranch},` +
-            `Event name: ${sourceEventName}\n`
+            `Status: ${status} Workflow ID:${triggeringRunInfo.workflowId}, ` +
+            `Head Branch: ${triggeringRunInfo.headBranch},` +
+            `Event name: ${triggeringRunInfo.eventName}\n`
         )
         return createListRunsQueryRunsSameSource(
           repositoryInfo,
           status,
-          mySourceGroup
+          triggeringRunInfo
         )
       } else {
-        throw Error(
-          `\nWrong cancel mode ${cancelMode}! This should never happen.\n`
-        )
+        throw Error(`\nWrong cancel mode ${cancelMode}! Please correct it.\n`)
       }
     }
   )
@@ -653,26 +780,26 @@
 }
 
 /**
- * Maps found workflow runs into groups - filters out the workflows that are not eligible for canceling
+ * Maps found workflow runs into groups - filters out the workflows that are not eligible for cancelling
  * (depends on cancel Mode) and assigns each workflow to groups - where workflow runs from the
  * same group are put together in one array - in a map indexed by the source group id.
  *
  * @param repositoryInfo - information about the repository used
- * @param headRepo - head repository the event comes from
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode to use
  * @param cancelFutureDuplicates - whether to cancel future duplicates
- * @param sourceRunId - source run id for the run
  * @param jobNameRegexps - regexps for job names
  * @param skipEventTypes - array of event names to skip
  * @param workflowRuns - map of workflow runs found
- * @parm map where key is the source group id and value is array of workflow run item candidates to cancel
+ * @parm maps with string key and array of run items as value. The key might be
+ *       * source group id (allDuplicates mode)
+ *       * matching job name (allDuplicatedMatchingJobNames mode)
  */
 async function filterAndMapWorkflowRunsToGroups(
   repositoryInfo: RepositoryInfo,
-  headRepo: string,
+  triggeringRunInfo: TriggeringRunInfo,
   cancelMode: CancelMode,
   cancelFutureDuplicates: boolean,
-  sourceRunId: number,
   jobNameRegexps: string[],
   skipEventTypes: string[],
   workflowRuns: Map<
@@ -685,40 +812,19 @@
   const mapOfWorkflowRunCandidates = new Map()
   for (const [key, runItem] of workflowRuns) {
     core.info(
-      `\nChecking run number: ${key}, RunId: ${runItem.id}, Url: ${runItem.url}. Status ${runItem.status},` +
+      `\nChecking run number: ${key} RunId: ${runItem.id} Url: ${runItem.url} Status ${runItem.status}` +
         ` Created at ${runItem.created_at}\n`
     )
-    if (
-      await isCandidateForCancelling(
-        repositoryInfo,
-        runItem,
-        headRepo,
-        cancelMode,
-        cancelFutureDuplicates,
-        sourceRunId,
-        jobNameRegexps,
-        skipEventTypes
-      )
-    ) {
-      const candidateSourceGroup: WorkflowRunSourceGroup = {
-        workflowId: retrieveWorkflowIdFromUrl(runItem.workflow_url),
-        headBranch: runItem.head_branch,
-        headRepo: runItem.head_repository.full_name,
-        eventName: runItem.event
-      }
-      const sourceGroupId = getSourceGroupId(candidateSourceGroup)
-      let workflowRunArray:
-        | rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
-        | undefined = mapOfWorkflowRunCandidates.get(sourceGroupId)
-      if (workflowRunArray === undefined) {
-        workflowRunArray = []
-        mapOfWorkflowRunCandidates.set(sourceGroupId, workflowRunArray)
-      }
-      core.info(
-        `The candidate ${runItem.id} has been added to ${sourceGroupId} group of candidates`
-      )
-      workflowRunArray.push(runItem)
-    }
+    await checkCandidateForCancelling(
+      repositoryInfo,
+      runItem,
+      triggeringRunInfo,
+      cancelMode,
+      cancelFutureDuplicates,
+      jobNameRegexps,
+      skipEventTypes,
+      mapOfWorkflowRunCandidates
+    )
   }
   return mapOfWorkflowRunCandidates
 }
@@ -749,7 +855,7 @@
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - my own run id
  * @param pullRequestNumber - number of pull request
- * @param reason reason for canceling
+ * @param reason reason for cancelling
  */
 async function notifyPR(
   repositoryInfo: RepositoryInfo,
@@ -774,9 +880,9 @@
  * @param notifyPRCancel - whether to notify the PR when cancelling
  * @param selfRunId - what is the self run id
  * @param sourceGroupId - what is the source group id
- * @param reason - reason for canceling
+ * @param reason - reason for cancelling
  */
-async function cancelAllRunsInTheSourceGroup(
+async function cancelAllRunsInTheGroup(
   repositoryInfo: RepositoryInfo,
   sortedRunItems: rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[],
   notifyPRCancel: boolean,
@@ -813,21 +919,21 @@
 }
 
 /**
- * Cancels found runs in a smart way. It takes all the found runs group by the source group, sorts them
- * descending according to create date in each of the source groups and cancels them in that order -
- * optionally skipping the first found run in each source group in case of duplicates.
+ * Cancels found runs per group. It takes all the found groups, sorts them
+ * descending according to create date in each of the groups and cancels them in that order -
+ * optionally skipping the first found run in each source group in case of duplicate cancelling.
  *
  * @param repositoryInfo - information about the repository used
- * @param mapOfWorkflowRunsCandidatesToCancel map of all workflow run candidates
+ * @param mapOfWorkflowRunCandidatesCandidatesToCancel map of all workflow run candidates
  * @param cancelMode - cancel mode
  * @param cancelFutureDuplicates - whether to cancel future duplicates
  * @param notifyPRCancel - whether to notify PRs with comments
  * @param selfRunId - self run Id
- * @param reason - reason for canceling
+ * @param reason - reason for cancelling
  */
 async function cancelTheRunsPerGroup(
   repositoryInfo: RepositoryInfo,
-  mapOfWorkflowRunsCandidatesToCancel: Map<
+  mapOfWorkflowRunCandidatesCandidatesToCancel: Map<
     string,
     rest.ActionsListWorkflowRunsResponseWorkflowRunsItem[]
   >,
@@ -839,9 +945,9 @@
 ): Promise<number[]> {
   const cancelledRuns: number[] = []
   for (const [
-    sourceGroupId,
+    groupId,
     candidatesArray
-  ] of mapOfWorkflowRunsCandidatesToCancel) {
+  ] of mapOfWorkflowRunCandidatesCandidatesToCancel) {
     // Sort from most recent date - this way we always kill current one at the end (if we kill it at all)
     const sortedRunItems = candidatesArray.sort((runItem1, runItem2) =>
       runItem2.created_at.localeCompare(runItem1.created_at)
@@ -849,31 +955,32 @@
     if (sortedRunItems.length > 0) {
       if (
         (cancelMode === CancelMode.DUPLICATES && cancelFutureDuplicates) ||
-        cancelMode === CancelMode.ALL_DUPLICATES
+        cancelMode === CancelMode.ALL_DUPLICATES ||
+        cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS
       ) {
         core.info(
           `\nSkipping the first run (${sortedRunItems[0].id}) of all the matching ` +
-            `duplicates for '${sourceGroupId}'. This one we are going to leave in peace!\n`
+            `duplicates for '${groupId}'. This one we are going to leave in peace!\n`
         )
         sortedRunItems.shift()
       }
       if (sortedRunItems.length === 0) {
-        core.info(`\nNo duplicates to cancel for ${sourceGroupId}!\n`)
+        core.info(`\nNo duplicates to cancel for ${groupId}!\n`)
         continue
       }
       cancelledRuns.push(
-        ...(await cancelAllRunsInTheSourceGroup(
+        ...(await cancelAllRunsInTheGroup(
           repositoryInfo,
           sortedRunItems,
           notifyPRCancel,
           selfRunId,
-          sourceGroupId,
+          groupId,
           reason
         ))
       )
     } else {
       core.info(
-        `\n######  There are no runs to cancel for ${sourceGroupId} ##########\n`
+        `\n######  There are no runs to cancel for ${groupId} ##########\n`
       )
     }
   }
@@ -884,14 +991,7 @@
  * Find and cancels runs based on the criteria chosen.
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - number of own run id
- * @param sourceWorkflowId - source workflow id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param sourceRunId - source run id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param headRepo - head repository that triggered the workflow (repo from which PR came)
- * @param headBranch - branch of the PR that triggered the workflow (when it is triggered by PR)
- * @param sourceEventName - name of the event that triggered the workflow
- *        (different than self event name for workflow_run)
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
  * @param notifyPRCancel - whether to notify in PRs about cancelling
@@ -904,11 +1004,7 @@
 async function findAndCancelRuns(
   repositoryInfo: RepositoryInfo,
   selfRunId: number,
-  sourceWorkflowId: number | string,
-  sourceRunId: number,
-  headRepo: string,
-  headBranch: string,
-  sourceEventName: string,
+  triggeringRunInfo: TriggeringRunInfo,
   cancelMode: CancelMode,
   cancelFutureDuplicates: boolean,
   notifyPRCancel: boolean,
@@ -918,34 +1014,24 @@
   reason: string
 ): Promise<number[]> {
   const statusValues = ['queued', 'in_progress']
-  const mySourceGroup: WorkflowRunSourceGroup = {
-    headBranch,
-    headRepo,
-    eventName: sourceEventName,
-    workflowId: sourceWorkflowId
-  }
   const workflowRuns = await getWorkflowRunsMatchingCriteria(
     repositoryInfo,
     statusValues,
     cancelMode,
-    sourceWorkflowId,
-    sourceRunId,
-    sourceEventName,
-    mySourceGroup
+    triggeringRunInfo
   )
-  const mapOfWorkflowRunsCandidatesToCancel = await filterAndMapWorkflowRunsToGroups(
+  const mapOfWorkflowRunCandidatesCandidatesToCancel = await filterAndMapWorkflowRunsToGroups(
     repositoryInfo,
-    headRepo,
+    triggeringRunInfo,
     cancelMode,
     cancelFutureDuplicates,
-    sourceRunId,
     jobNameRegexps,
     skipEventTypes,
     workflowRuns
   )
   return await cancelTheRunsPerGroup(
     repositoryInfo,
-    mapOfWorkflowRunsCandidatesToCancel,
+    mapOfWorkflowRunCandidatesCandidatesToCancel,
     cancelMode,
     cancelFutureDuplicates,
     notifyPRCancel,
@@ -969,15 +1055,15 @@
 }
 
 /**
- * Gets origin of the runId - if this is a workflow run, it returns the information about the source run
+ * Gets source run using  of the runId - if this is a workflow run, it returns the information about the source run
  * @param repositoryInfo - information about the repository used
  * @param runId - run id of the run to check
- * @return information about the triggering workflow
+ * @return information about the triggering run
  */
-async function getOrigin(
+async function getTriggeringRunInfo(
   repositoryInfo: RepositoryInfo,
   runId: number
-): Promise<TriggeringWorkflowInfo> {
+): Promise<TriggeringRunInfo> {
   const reply = await repositoryInfo.octokit.actions.getWorkflowRun({
     owner: repositoryInfo.owner,
     repo: repositoryInfo.repo,
@@ -1001,6 +1087,8 @@
   }
 
   return {
+    workflowId: retrieveWorkflowIdFromUrl(reply.data.workflow_url),
+    runId,
     headRepo: reply.data.head_repository.full_name,
     headBranch: reply.data.head_branch,
     headSha: reply.data.head_sha,
@@ -1015,14 +1103,7 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param selfRunId - number of own run id
- * @param sourceWorkflowId - source workflow id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param sourceRunId - source run id that triggered the workflow
- *        (might be different than self for workflow_run)
- * @param headRepo - head repository that triggered the workflow (repo from which PR came)
- * @param headBranch - branch of the PR that triggered the workflow (when it is triggered by PR)
- * @param sourceEventName - name of the event that triggered the workflow
- *        (different than self event name for workflow_run)
+ * @param triggeringRunInfo - information about the workflow that triggered the run
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether to cancel future duplicates for duplicate cancelling
  * @param notifyPRCancel - whether to notify in PRs about cancelling
@@ -1035,11 +1116,7 @@
 async function performCancelJob(
   repositoryInfo: RepositoryInfo,
   selfRunId: number,
-  sourceWorkflowId: number | string,
-  sourceRunId: number,
-  headRepo: string,
-  headBranch: string,
-  sourceEventName: string,
+  triggeringRunInfo: TriggeringRunInfo,
   cancelMode: CancelMode,
   notifyPRCancel: boolean,
   notifyPRCancelMessage: string,
@@ -1052,9 +1129,11 @@
     '\n###################################################################################\n'
   )
   core.info(
-    `All parameters: owner: ${repositoryInfo.owner}, repo: ${repositoryInfo.repo}, run id: ${sourceRunId}, ` +
-      `head repo ${headRepo}, headBranch: ${headBranch}, ` +
-      `sourceEventName: ${sourceEventName}, cancelMode: ${cancelMode}, jobNames: ${jobNameRegexps}`
+    `All parameters: owner: ${repositoryInfo.owner}, repo: ${repositoryInfo.repo}, ` +
+      `run id: ${triggeringRunInfo.runId}, ` +
+      `head repo ${triggeringRunInfo.headRepo}, headBranch: ${triggeringRunInfo.headBranch}, ` +
+      `sourceEventName: ${triggeringRunInfo.eventName}, ` +
+      `cancelMode: ${cancelMode}, jobNames: ${jobNameRegexps}`
   )
   core.info(
     '\n###################################################################################\n'
@@ -1062,33 +1141,42 @@
   let reason = ''
   if (cancelMode === CancelMode.SELF) {
     core.info(
-      `# Cancelling source run: ${sourceRunId} for workflow ${sourceWorkflowId}.`
+      `# Cancelling source run: ${triggeringRunInfo.runId} ` +
+        `for workflow ${triggeringRunInfo.workflowId}.`
     )
     reason = notifyPRCancelMessage
       ? notifyPRCancelMessage
       : `The job has been cancelled by another workflow.`
   } else if (cancelMode === CancelMode.FAILED_JOBS) {
     core.info(
-      `# Cancel all runs for workflow ${sourceWorkflowId} where job names matching ${jobNameRegexps} failed.`
+      `# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
+        `where job names matching ${jobNameRegexps} failed.`
     )
     reason = `It has some failed jobs matching ${jobNameRegexps}.`
   } else if (cancelMode === CancelMode.NAMED_JOBS) {
     core.info(
-      `# Cancel all runs for workflow ${sourceWorkflowId} have job names matching ${jobNameRegexps}.`
+      `# Cancel all runs for workflow ${triggeringRunInfo.workflowId} ` +
+        `have job names matching ${jobNameRegexps}.`
     )
     reason = `It has jobs matching ${jobNameRegexps}.`
   } else if (cancelMode === CancelMode.DUPLICATES) {
     core.info(
-      `# Cancel duplicate runs for workflow ${sourceWorkflowId} for same triggering branch as own run Id.`
+      `# Cancel duplicate runs for workflow ${triggeringRunInfo.workflowId} ` +
+        `for same triggering branch as own run Id.`
     )
-    reason = `It is an earlier duplicate of ${sourceWorkflowId} run.`
+    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
   } else if (cancelMode === CancelMode.ALL_DUPLICATES) {
     core.info(
-      `# Cancel all duplicates runs started for workflow ${sourceWorkflowId}.`
+      `# Cancel all duplicates runs started for workflow ${triggeringRunInfo.workflowId}.`
     )
-    reason = `It is an earlier duplicate of ${sourceWorkflowId} run.`
+    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
+  } else if (cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) {
+    core.info(
+      `# Cancel all duplicate named jobs matching the patterns ${jobNameRegexps}.`
+    )
+    reason = `It is an earlier duplicate of ${triggeringRunInfo.workflowId} run.`
   } else {
-    throw Error(`Wrong cancel mode ${cancelMode}! This should never happen.`)
+    throw Error(`Wrong cancel mode ${cancelMode}! Please correct it.`)
   }
   core.info(
     '\n###################################################################################\n'
@@ -1097,11 +1185,7 @@
   return await findAndCancelRuns(
     repositoryInfo,
     selfRunId,
-    sourceWorkflowId,
-    sourceRunId,
-    headRepo,
-    headBranch,
-    sourceEventName,
+    triggeringRunInfo,
     cancelMode,
     cancelFutureDuplicates,
     notifyPRCancel,
@@ -1119,31 +1203,31 @@
  *
  * @param repositoryInfo - information about the repository used
  * @param workflowFileName - optional workflow file name
- * @param sourceRunId - source run id of the workfow
+ * @param runId - run id of the workflow
  * @param selfRunId - self run id
  * @return workflow id that is associate with the workflow we are going to act on.
  */
 async function retrieveWorkflowId(
   repositoryInfo: RepositoryInfo,
   workflowFileName: string | null,
-  sourceRunId: number,
+  runId: number,
   selfRunId: number
 ): Promise<string | number> {
-  let sourceWorkflowId
+  let workflowId
   if (workflowFileName) {
-    sourceWorkflowId = workflowFileName
+    workflowId = workflowFileName
     core.info(
-      `\nFinding runs for another workflow found by ${workflowFileName} name: ${sourceWorkflowId}\n`
+      `\nFinding runs for another workflow found by ${workflowFileName} name: ${workflowId}\n`
     )
   } else {
-    sourceWorkflowId = await getWorkflowId(repositoryInfo, sourceRunId)
-    if (sourceRunId === selfRunId) {
-      core.info(`\nFinding runs for my own workflow ${sourceWorkflowId}\n`)
+    workflowId = await getWorkflowId(repositoryInfo, runId)
+    if (runId === selfRunId) {
+      core.info(`\nFinding runs for my own workflow ${workflowId}\n`)
     } else {
-      core.info(`\nFinding runs for source workflow ${sourceWorkflowId}\n`)
+      core.info(`\nFinding runs for source workflow ${workflowId}\n`)
     }
   }
-  return sourceWorkflowId
+  return workflowId
 }
 /**
  * Sets output but also prints the output value in the logs.
@@ -1161,7 +1245,7 @@
  * are verified and in case od unexpected combination found, approrpriate error is raised.
  *
  * @param eventName - name of the event to act on
- * @param sourceRunId - run id of the triggering event
+ * @param runId - run id of the triggering event
  * @param selfRunId - our own run id
  * @param cancelMode - cancel mode used
  * @param cancelFutureDuplicates - whether future duplicate cancelling is enabled
@@ -1169,7 +1253,7 @@
  */
 function performSanityChecks(
   eventName: string,
-  sourceRunId: number,
+  runId: number,
   selfRunId: number,
   cancelMode: CancelMode,
   cancelFutureDuplicates: boolean,
@@ -1177,7 +1261,7 @@
 ): void {
   if (
     eventName === 'workflow_run' &&
-    sourceRunId === selfRunId &&
+    runId === selfRunId &&
     cancelMode === CancelMode.DUPLICATES
   ) {
     throw Error(
@@ -1195,10 +1279,27 @@
       CancelMode.ALL_DUPLICATES
     ].includes(cancelMode)
   ) {
-    throw Error(`You cannot specify jobNames on ${cancelMode} cancelMode.`)
+    throw Error(
+      `You cannot specify jobNamesRegexps on ${cancelMode} cancelMode.`
+    )
   }
 
-  if (cancelMode === CancelMode.ALL_DUPLICATES && !cancelFutureDuplicates) {
+  if (
+    jobNameRegexps.length === 0 &&
+    [
+      CancelMode.NAMED_JOBS,
+      CancelMode.FAILED_JOBS,
+      CancelMode.ALL_DUPLICATED_NAMED_JOBS
+    ].includes(cancelMode)
+  ) {
+    throw Error(`You must specify jobNamesRegexps on ${cancelMode} cancelMode.`)
+  }
+
+  if (
+    (cancelMode === CancelMode.ALL_DUPLICATES ||
+      cancelMode === CancelMode.ALL_DUPLICATED_NAMED_JOBS) &&
+    !cancelFutureDuplicates
+  ) {
     throw Error(
       `The  ${cancelMode} cancelMode has to have cancelFutureDuplicates set to true.`
     )
@@ -1209,32 +1310,28 @@
  * Produces basic outputs for the action. This does not include cancelled workflow run id - those are
  * set after cancelling is done.
  *
- * @param triggeringWorkflowInfo
+ * @param triggeringRunInfo
  */
-function produceBasicOutputs(
-  triggeringWorkflowInfo: TriggeringWorkflowInfo
-): void {
-  verboseOutput('sourceHeadRepo', triggeringWorkflowInfo.headRepo)
-  verboseOutput('sourceHeadBranch', triggeringWorkflowInfo.headBranch)
-  verboseOutput('sourceHeadSha', triggeringWorkflowInfo.headSha)
-  verboseOutput('sourceEvent', triggeringWorkflowInfo.eventName)
+function produceBasicOutputs(triggeringRunInfo: TriggeringRunInfo): void {
+  verboseOutput('sourceHeadRepo', triggeringRunInfo.headRepo)
+  verboseOutput('sourceHeadBranch', triggeringRunInfo.headBranch)
+  verboseOutput('sourceHeadSha', triggeringRunInfo.headSha)
+  verboseOutput('sourceEvent', triggeringRunInfo.eventName)
   verboseOutput(
     'pullRequestNumber',
-    triggeringWorkflowInfo.pullRequest
-      ? triggeringWorkflowInfo.pullRequest.number.toString()
+    triggeringRunInfo.pullRequest
+      ? triggeringRunInfo.pullRequest.number.toString()
       : ''
   )
   verboseOutput(
     'mergeCommitSha',
-    triggeringWorkflowInfo.mergeCommitSha
-      ? triggeringWorkflowInfo.mergeCommitSha
-      : ''
+    triggeringRunInfo.mergeCommitSha ? triggeringRunInfo.mergeCommitSha : ''
   )
   verboseOutput(
     'targetCommitSha',
-    triggeringWorkflowInfo.mergeCommitSha
-      ? triggeringWorkflowInfo.mergeCommitSha
-      : triggeringWorkflowInfo.headSha
+    triggeringRunInfo.mergeCommitSha
+      ? triggeringRunInfo.mergeCommitSha
+      : triggeringRunInfo.headSha
   )
 }
 
@@ -1242,19 +1339,17 @@
  * Notifies the PR that the action has started.
  *
  * @param repositoryInfo information about the repository
- * @param triggeringWorkflowInfo information about the triggering workflow
- * @param sourceRunId run id of the source workflow
+ * @param triggeringRunInfo information about the triggering workflow
  * @param selfRunId self run id
  * @param notifyPRMessageStart whether to notify about the start of the action
  */
 async function notifyActionStart(
   repositoryInfo: RepositoryInfo,
-  triggeringWorkflowInfo: TriggeringWorkflowInfo,
-  sourceRunId: number,
+  triggeringRunInfo: TriggeringRunInfo,
   selfRunId: number,
   notifyPRMessageStart: string
 ): Promise<void> {
-  if (notifyPRMessageStart && triggeringWorkflowInfo.pullRequest) {
+  if (notifyPRMessageStart && triggeringRunInfo.pullRequest) {
     const selfWorkflowRunUrl =
       `https://github.com/${repositoryInfo.owner}/${repositoryInfo.repo}` +
       `/actions/runs/${selfRunId}`
@@ -1262,7 +1357,7 @@
       owner: repositoryInfo.owner,
       repo: repositoryInfo.repo,
       // eslint-disable-next-line @typescript-eslint/camelcase
-      issue_number: triggeringWorkflowInfo.pullRequest.number,
+      issue_number: triggeringRunInfo.pullRequest.number,
       body: `${notifyPRMessageStart} [The workflow run](${selfWorkflowRunUrl})`
     })
   }
@@ -1331,13 +1426,15 @@
       `jobNames: ${jobNameRegexps}`
   )
 
-  const triggeringWorkflowInfo = await getOrigin(repositoryInfo, sourceRunId)
-  produceBasicOutputs(triggeringWorkflowInfo)
+  const triggeringRunInfo = await getTriggeringRunInfo(
+    repositoryInfo,
+    sourceRunId
+  )
+  produceBasicOutputs(triggeringRunInfo)
 
   await notifyActionStart(
     repositoryInfo,
-    triggeringWorkflowInfo,
-    sourceRunId,
+    triggeringRunInfo,
     selfRunId,
     notifyPRMessageStart
   )
@@ -1345,11 +1442,7 @@
   const cancelledRuns = await performCancelJob(
     repositoryInfo,
     selfRunId,
-    sourceWorkflowId,
-    sourceRunId,
-    triggeringWorkflowInfo.headRepo,
-    triggeringWorkflowInfo.headBranch,
-    triggeringWorkflowInfo.eventName,
+    triggeringRunInfo,
     cancelMode,
     notifyPRCancel,
     notifyPRCancelMessage,