Skip to content

Commit 1e0e8ac

Browse files
authoredMar 20, 2025
Merge pull request #38 from m7kvqbe1/add-issue-parameter
Add "issue-number" as parameter
2 parents 732156a + 4438dbe commit 1e0e8ac

File tree

4 files changed

+139
-66
lines changed

4 files changed

+139
-66
lines changed
 

‎README.md

+46
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ A GitHub Action to move issues between GitHub Projects V2 columns based on speci
1313
| `ignored-columns` | Comma-separated list of column names to ignore (e.g., "Ready, In Progress, In Review, Done"). | Yes |
1414
| `default-column` | The column to move the issue to when a target label is removed. If not specified, no action will be taken on unlabeling. | No |
1515
| `skip-if-not-in-project` | Skip moving the issue if it is not already in the project (default: `false`) | No |
16+
| `issue-number` | Issue number to handle (default: derived from issue itself) | No |
1617

1718
## Example Workflow
1819

@@ -47,3 +48,48 @@ Get the latest `{release}` tag from https://github.com/m7kvqbe1/github-action-mo
4748
- If a default column is specified, the issue will be moved to that column.
4849
- If no default column is specified, no action will be taken.
4950
- The action will not move issues that are already in one of the ignored columns.
51+
52+
## Advanced Behavior
53+
54+
When a pull request is closed, one might want to move the issue, too.
55+
Then, the issue number has to be determined based on the pull request.
56+
For instance, this can be done with the [ticket-check-action](https://github.com/neofinancial/ticket-check-action/pull/58).
57+
Then, one can move the issue to another state as intended.
58+
59+
Example: Move the issue to "In Progress" as soon as a PR is opened or reopened:
60+
61+
```yaml
62+
name: Mark issue as in progress
63+
64+
on:
65+
pull_request_target:
66+
67+
jobs:
68+
move_issue:
69+
runs-on: ubuntu-latest
70+
permissions:
71+
issues: write
72+
steps:
73+
- name: Determine issue number
74+
id: get_issue_number
75+
uses: koppor/ticket-check-action@add-output
76+
with:
77+
token: ${{ secrets.GITHUB_TOKEN }}
78+
ticketLink: 'https://github.com/:owner/:repo/issues/%ticketNumber%'
79+
ticketPrefix: '#'
80+
titleRegex: '^#(?<ticketNumber>\d+)'
81+
branchRegex: '^(?<ticketNumber>\d+)'
82+
bodyRegex: '#(?<ticketNumber>\d+)'
83+
bodyURLRegex: 'http(s?):\/\/(github.com)(\/:owner)(\/:repo)(\/issues)\/(?<ticketNumber>\d+)'
84+
outputOnly: true
85+
- name: Move issue "In progress"
86+
uses: m7kvqbe1/github-action-move-issues/@main
87+
with:
88+
github-token: ${{ secrets.GH_TOKEN_ACTION_MOVE_ISSUE }}
89+
project-url: "https://github.com/users/koppor/projects/7"
90+
target-labels: "📍 Assigned"
91+
target-column: "In progress"
92+
ignored-columns: ""
93+
default-column: "In progress"
94+
issue-number: ${{ steps.get_issue_number.outputs.ticketNumber }}
95+
```

‎action.yml

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ inputs:
2121
default-column:
2222
description: 'The column to move the issue to when a target label is removed. If not specified, no action will be taken on unlabeling.'
2323
required: false
24+
issue-number:
25+
description: 'The issue number to use. Useful for triggering on PRs'
26+
required: false
2427
skip-if-not-in-project:
2528
description: 'If set to "true", skip moving the issue if it is not already in the project.'
2629
required: false

‎dist/index.js

+45-33
Original file line numberDiff line numberDiff line change
@@ -34913,67 +34913,77 @@ const run = async () => {
3491334913
const targetColumn = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput("target-column");
3491434914
const ignoredColumns = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput("ignored-columns");
3491534915
const defaultColumn = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput("default-column", { required: false });
34916+
const issueNumberParam = _actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput("issue-number", { required: false });
3491634917

3491734918
const TARGET_COLUMN = targetColumn.trim();
3491834919
const TARGET_LABELS = parseCommaSeparatedInput(targetLabels);
3491934920
const IGNORED_COLUMNS = parseCommaSeparatedInput(ignoredColumns);
3492034921
const DEFAULT_COLUMN = defaultColumn ? defaultColumn.trim() : null;
34922+
const ISSUE_NUMBER_PARAM = issueNumberParam ? issueNumberParam.trim() : null;
3492134923

3492234924
const SKIP_IF_NOT_IN_PROJECT =
3492334925
_actions_core__WEBPACK_IMPORTED_MODULE_0__.getInput("skip-if-not-in-project") === "true";
3492434926

3492534927
const octokit = _actions_github__WEBPACK_IMPORTED_MODULE_1__.getOctokit(token);
3492634928

34927-
let issue = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.payload.issue;
34928-
if (!issue || !issue.node_id) {
34929-
throw new Error("Invalid or missing issue object");
34930-
}
34929+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Determing issue number...");
34930+
const issueNumber = ISSUE_NUMBER_PARAM ? ISSUE_NUMBER_PARAM : _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.issue.number;
34931+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Issue number: " + issueNumber);
3493134932

34932-
const issueNumber = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.issue.number;
34933-
const { owner, repo } = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.repo;
3493434933
// The issue might have been updated by a previous GitHub action; therefore, we refetch the issue data
34934+
const { owner, repo } = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.repo;
34935+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("owner: " + owner + " repo: " + repo);
3493534936
const { data: updatedIssue } = await octokit.rest.issues.get({
3493634937
owner,
3493734938
repo,
3493834939
issue_number: issueNumber,
3493934940
});
34940-
issue = updatedIssue;
34941+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Udpated issue " + updatedIssue);
34942+
const issue = updatedIssue;
34943+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Issue " + issue);
34944+
34945+
if (!issue || !issue.node_id) {
34946+
throw new Error("Invalid or missing issue object");
34947+
}
3494134948

3494234949
const eventName = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.eventName;
3494334950
const action = _actions_github__WEBPACK_IMPORTED_MODULE_1__.context.payload.action;
3494434951
const projectData = await getProjectData(octokit, projectUrl);
3494534952

34946-
if (eventName === "issue_comment") {
34947-
if (action === "created") {
34948-
// a comment was created on an issue
34949-
const hasTargetLabel = issue.labels.some((label) =>
34950-
TARGET_LABELS.includes(label.name)
34953+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Event: " + eventName);
34954+
34955+
if ((eventName === "issue_comment") || (eventName === "pull_request") || (eventName === "pull_request_target") || ISSUE_NUMBER_PARAM) {
34956+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Hit issue or PR");
34957+
34958+
const hasTargetLabel = issue.labels.some((label) =>
34959+
TARGET_LABELS.includes(label.name)
34960+
);
34961+
if (hasTargetLabel) {
34962+
// Proceed as if the label was added to the issue
34963+
await processIssueItem(
34964+
octokit,
34965+
projectData,
34966+
issue,
34967+
TARGET_COLUMN,
34968+
IGNORED_COLUMNS,
34969+
SKIP_IF_NOT_IN_PROJECT
34970+
);
34971+
} else {
34972+
// Proceed as if the label was removed from the issue
34973+
await moveIssueToDefaultColumn(
34974+
octokit,
34975+
projectData,
34976+
issue,
34977+
DEFAULT_COLUMN,
34978+
IGNORED_COLUMNS
3495134979
);
34952-
if (hasTargetLabel) {
34953-
// Proceed as if the label was added to the issue
34954-
await processIssueItem(
34955-
octokit,
34956-
projectData,
34957-
issue,
34958-
TARGET_COLUMN,
34959-
IGNORED_COLUMNS,
34960-
SKIP_IF_NOT_IN_PROJECT
34961-
);
34962-
} else {
34963-
// Proceed as if the label was removed from the issue
34964-
await moveIssueToDefaultColumn(
34965-
octokit,
34966-
projectData,
34967-
issue,
34968-
DEFAULT_COLUMN,
34969-
IGNORED_COLUMNS
34970-
);
34971-
}
34972-
return;
3497334980
}
34981+
return;
3497434982
}
3497534983

3497634984
if (action === "labeled") {
34985+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Hit labeled");
34986+
3497734987
await handleLabeledEvent(
3497834988
octokit,
3497934989
issue,
@@ -34987,6 +34997,8 @@ const run = async () => {
3498734997
}
3498834998

3498934999
if (action === "unlabeled" && DEFAULT_COLUMN) {
35000+
_actions_core__WEBPACK_IMPORTED_MODULE_0__.debug("Hit unlabeled");
35001+
3499035002
await handleUnlabeledEvent(
3499135003
octokit,
3499235004
issue,

‎index.js

+45-33
Original file line numberDiff line numberDiff line change
@@ -391,67 +391,77 @@ const run = async () => {
391391
const targetColumn = core.getInput("target-column");
392392
const ignoredColumns = core.getInput("ignored-columns");
393393
const defaultColumn = core.getInput("default-column", { required: false });
394+
const issueNumberParam = core.getInput("issue-number", { required: false });
394395

395396
const TARGET_COLUMN = targetColumn.trim();
396397
const TARGET_LABELS = parseCommaSeparatedInput(targetLabels);
397398
const IGNORED_COLUMNS = parseCommaSeparatedInput(ignoredColumns);
398399
const DEFAULT_COLUMN = defaultColumn ? defaultColumn.trim() : null;
400+
const ISSUE_NUMBER_PARAM = issueNumberParam ? issueNumberParam.trim() : null;
399401

400402
const SKIP_IF_NOT_IN_PROJECT =
401403
core.getInput("skip-if-not-in-project") === "true";
402404

403405
const octokit = github.getOctokit(token);
404406

405-
let issue = github.context.payload.issue;
406-
if (!issue || !issue.node_id) {
407-
throw new Error("Invalid or missing issue object");
408-
}
407+
core.debug("Determing issue number...");
408+
const issueNumber = ISSUE_NUMBER_PARAM ? ISSUE_NUMBER_PARAM : github.context.issue.number;
409+
core.debug("Issue number: " + issueNumber);
409410

410-
const issueNumber = github.context.issue.number;
411-
const { owner, repo } = github.context.repo;
412411
// The issue might have been updated by a previous GitHub action; therefore, we refetch the issue data
412+
const { owner, repo } = github.context.repo;
413+
core.debug("owner: " + owner + " repo: " + repo);
413414
const { data: updatedIssue } = await octokit.rest.issues.get({
414415
owner,
415416
repo,
416417
issue_number: issueNumber,
417418
});
418-
issue = updatedIssue;
419+
core.debug("Udpated issue " + updatedIssue);
420+
const issue = updatedIssue;
421+
core.debug("Issue " + issue);
422+
423+
if (!issue || !issue.node_id) {
424+
throw new Error("Invalid or missing issue object");
425+
}
419426

420427
const eventName = github.context.eventName;
421428
const action = github.context.payload.action;
422429
const projectData = await getProjectData(octokit, projectUrl);
423430

424-
if (eventName === "issue_comment") {
425-
if (action === "created") {
426-
// a comment was created on an issue
427-
const hasTargetLabel = issue.labels.some((label) =>
428-
TARGET_LABELS.includes(label.name)
431+
core.debug("Event: " + eventName);
432+
433+
if ((eventName === "issue_comment") || (eventName === "pull_request") || (eventName === "pull_request_target") || ISSUE_NUMBER_PARAM) {
434+
core.debug("Hit issue or PR");
435+
436+
const hasTargetLabel = issue.labels.some((label) =>
437+
TARGET_LABELS.includes(label.name)
438+
);
439+
if (hasTargetLabel) {
440+
// Proceed as if the label was added to the issue
441+
await processIssueItem(
442+
octokit,
443+
projectData,
444+
issue,
445+
TARGET_COLUMN,
446+
IGNORED_COLUMNS,
447+
SKIP_IF_NOT_IN_PROJECT
448+
);
449+
} else {
450+
// Proceed as if the label was removed from the issue
451+
await moveIssueToDefaultColumn(
452+
octokit,
453+
projectData,
454+
issue,
455+
DEFAULT_COLUMN,
456+
IGNORED_COLUMNS
429457
);
430-
if (hasTargetLabel) {
431-
// Proceed as if the label was added to the issue
432-
await processIssueItem(
433-
octokit,
434-
projectData,
435-
issue,
436-
TARGET_COLUMN,
437-
IGNORED_COLUMNS,
438-
SKIP_IF_NOT_IN_PROJECT
439-
);
440-
} else {
441-
// Proceed as if the label was removed from the issue
442-
await moveIssueToDefaultColumn(
443-
octokit,
444-
projectData,
445-
issue,
446-
DEFAULT_COLUMN,
447-
IGNORED_COLUMNS
448-
);
449-
}
450-
return;
451458
}
459+
return;
452460
}
453461

454462
if (action === "labeled") {
463+
core.debug("Hit labeled");
464+
455465
await handleLabeledEvent(
456466
octokit,
457467
issue,
@@ -465,6 +475,8 @@ const run = async () => {
465475
}
466476

467477
if (action === "unlabeled" && DEFAULT_COLUMN) {
478+
core.debug("Hit unlabeled");
479+
468480
await handleUnlabeledEvent(
469481
octokit,
470482
issue,

0 commit comments

Comments
 (0)
Please sign in to comment.