Skip to content

Commit 900d337

Browse files
authored
Merge pull request #26 from nearform/feature/autoclosing-issue
Automatic closing of the issue when released
2 parents b07f817 + a5ca3c0 commit 900d337

12 files changed

+549
-300
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# github-action-notify-release
22

3+
GitHub Action that automatically creates an issue with an overview of the commits that are waiting to be released. After creating the release, the issue will be automatically closed during next action run.
4+
35
## Usage
46
Configure this action in your workflows providing the inputs described below in order to get notified in `x` days after the repo has been updated but no npm release has happened.
57

@@ -9,6 +11,9 @@ Configure this action in your workflows providing the inputs described below in
911
### `stale-days: 7`
1012
_Optional_ The number of days after which unreleased commits should be considered stale and should notify for a release. Default is `7`.
1113

14+
### `commit-messages-lines: 1`
15+
_Optional_ Limit the number of first x lines from commit messages that will be added in the issue description. No truncation when set to `0`. Default is `1`.
16+
1217
## Notes
1318
- Checks and compares npm last modified date and git latest repo update.
1419
- If the repo doesn't have an npm package linked the run will exit with a warning log.

dist/index.js

Lines changed: 153 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -5889,6 +5889,115 @@ function wrappy (fn, cb) {
58895889
}
58905890

58915891

5892+
/***/ }),
5893+
5894+
/***/ 465:
5895+
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
5896+
5897+
"use strict";
5898+
5899+
const github = __nccwpck_require__(438);
5900+
const { logInfo } = __nccwpck_require__(653);
5901+
5902+
const ISSUE_LABEL = 'notify-release';
5903+
const ISSUE_TITLE = 'Release pending!';
5904+
const STATE_OPEN = 'open';
5905+
const STATE_CLOSED = 'closed';
5906+
5907+
async function createIssue(token, issueBody) {
5908+
const octokit = github.getOctokit(token);
5909+
5910+
return octokit.issues.create({
5911+
...github.context.repo,
5912+
title: ISSUE_TITLE,
5913+
body: issueBody,
5914+
labels: [ISSUE_LABEL],
5915+
});
5916+
}
5917+
5918+
async function getLastOpenPendingIssue(token) {
5919+
const octokit = github.getOctokit(token);
5920+
const { owner, repo } = github.context.repo;
5921+
5922+
const pendingIssues = await octokit.request(`GET /repos/{owner}/{repo}/issues`, {
5923+
owner,
5924+
repo,
5925+
creator: 'app/github-actions',
5926+
state: STATE_OPEN,
5927+
sort: 'created',
5928+
direction: 'desc',
5929+
labels: ISSUE_LABEL
5930+
});
5931+
5932+
return pendingIssues.data.length ? pendingIssues.data[0] : null;
5933+
}
5934+
5935+
async function updateLastOpenPendingIssue(token, issueBody, issueNo) {
5936+
const octokit = github.getOctokit(token);
5937+
const { owner, repo } = github.context.repo;
5938+
5939+
const updatedIssue = await octokit.request(`PATCH /repos/{owner}/{repo}/issues/${issueNo}`, {
5940+
owner,
5941+
repo,
5942+
title: ISSUE_TITLE,
5943+
body: issueBody
5944+
});
5945+
5946+
return updatedIssue.data.length ? updatedIssue.data[0] : null;
5947+
}
5948+
5949+
async function createOrUpdateIssue(token, unreleasedCommits, pendingIssue, latestRelease, commitMessageLines) {
5950+
const commitStr = unreleasedCommits.map((commit) => `Commit: ${formatCommitMessage(commit.commit.message, commitMessageLines)}
5951+
Author: ${commit.commit.author.name}
5952+
5953+
`).join('');
5954+
const issueBody = `Unreleased commits have been found which are pending release, please publish the changes.
5955+
5956+
### Commits since the last release
5957+
${commitStr}`;
5958+
5959+
if (pendingIssue) {
5960+
await updateLastOpenPendingIssue(token, issueBody, pendingIssue.number);
5961+
logInfo(`Issue ${pendingIssue.number} has been updated`);
5962+
} else {
5963+
const issueNo = await createIssue(token, issueBody);
5964+
logInfo(`New issue has been created. Issue No. - ${issueNo}`);
5965+
}
5966+
}
5967+
5968+
function formatCommitMessage(fullCommitMessage, numberOfLines) {
5969+
if (!numberOfLines || numberOfLines < 0) {
5970+
return fullCommitMessage;
5971+
}
5972+
return fullCommitMessage
5973+
.split('\n')
5974+
.slice(0, numberOfLines)
5975+
.join('\n')
5976+
.trim();
5977+
}
5978+
5979+
async function closeIssue(token, issueNo) {
5980+
const octokit = github.getOctokit(token);
5981+
const { owner, repo } = github.context.repo;
5982+
5983+
await octokit.request(`PATCH /repos/{owner}/{repo}/issues/${issueNo}`, {
5984+
owner,
5985+
repo,
5986+
state: STATE_CLOSED
5987+
});
5988+
logInfo(`Closed issue no. - ${issueNo}`);
5989+
}
5990+
5991+
module.exports = {
5992+
createIssue,
5993+
getLastOpenPendingIssue,
5994+
updateLastOpenPendingIssue,
5995+
formatCommitMessage,
5996+
createOrUpdateIssue,
5997+
closeIssue
5998+
};
5999+
6000+
58926001
/***/ }),
58936002

58946003
/***/ 653:
@@ -5910,121 +6019,94 @@ exports.logWarning = log(warning);
59106019

59116020
/***/ }),
59126021

5913-
/***/ 26:
6022+
/***/ 254:
59146023
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
59156024

59166025
"use strict";
59176026

5918-
const github = __nccwpck_require__(438);
59196027

5920-
async function getLatestRelease(token) {
5921-
const octokit = github.getOctokit(token);
5922-
const { owner, repo } = github.context.repo;
5923-
5924-
const allReleasesResp = await octokit.request(`GET /repos/{owner}/{repo}/releases`, {
5925-
owner,
5926-
repo,
5927-
});
6028+
const { logInfo } = __nccwpck_require__(653);
6029+
const { getLatestRelease, getUnreleasedCommits } = __nccwpck_require__(26);
6030+
const { createOrUpdateIssue, getLastOpenPendingIssue, closeIssue } = __nccwpck_require__(465);
59286031

5929-
return allReleasesResp.data.length ? allReleasesResp.data[0] : null;
5930-
}
6032+
async function runAction(token, staleDays, commitMessageLines) {
6033+
const latestRelease = await getLatestRelease(token);
59316034

5932-
async function getUnreleasedCommits(token, latestReleaseDate, staleDays) {
5933-
const octokit = github.getOctokit(token);
5934-
const { owner, repo } = github.context.repo;
6035+
if (!latestRelease) {
6036+
return logInfo('Could not find latest release');
6037+
}
59356038

5936-
const allCommitsResp = await octokit.request(`GET /repos/{owner}/{repo}/commits`, {
5937-
owner,
5938-
repo,
5939-
since: latestReleaseDate,
5940-
});
6039+
logInfo(`Latest release - name:${latestRelease.name}, created:${latestRelease.created_at},
6040+
Tag:${latestRelease.tag_name}, author:${latestRelease.author.login}`);
59416041

5942-
const staleDate = new Date().getTime() - (staleDays * 24 * 60 * 60 * 1000);
6042+
let pendingIssue = await getLastOpenPendingIssue(token);
6043+
const unreleasedCommits = await getUnreleasedCommits(
6044+
token,
6045+
latestRelease.created_at,
6046+
staleDays,
6047+
);
59436048

5944-
for (const commit of allCommitsResp.data) {
5945-
const commitDate = new Date(commit.commit.committer.date).getTime();
5946-
if (commitDate < staleDate) {
5947-
return allCommitsResp.data;
6049+
if (unreleasedCommits.length) {
6050+
await createOrUpdateIssue(token, unreleasedCommits, pendingIssue, latestRelease, commitMessageLines);
6051+
} else {
6052+
logInfo('No pending commits found');
6053+
if (pendingIssue && Date.parse(latestRelease.created_at) > Date.parse(pendingIssue.updated_at)) {
6054+
await closeIssue(token, pendingIssue.number);
59486055
}
59496056
}
5950-
5951-
return [];
59526057
}
59536058

59546059
module.exports = {
5955-
getLatestRelease,
5956-
getUnreleasedCommits,
6060+
runAction,
59576061
};
59586062

59596063

59606064
/***/ }),
59616065

5962-
/***/ 608:
6066+
/***/ 26:
59636067
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
59646068

59656069
"use strict";
59666070

59676071
const github = __nccwpck_require__(438);
59686072

5969-
async function createIssue(token, issueTitle, issueBody, label) {
5970-
const octokit = github.getOctokit(token);
5971-
5972-
return octokit.issues.create({
5973-
...github.context.repo,
5974-
title: issueTitle,
5975-
body: issueBody,
5976-
labels: [label],
5977-
});
5978-
}
5979-
5980-
async function getLastOpenPendingIssue(token, latestReleaseDate, label) {
6073+
async function getLatestRelease(token) {
59816074
const octokit = github.getOctokit(token);
59826075
const { owner, repo } = github.context.repo;
59836076

5984-
const pendingIssues = await octokit.request(`GET /repos/{owner}/{repo}/issues`, {
6077+
const allReleasesResp = await octokit.request(`GET /repos/{owner}/{repo}/releases/latest`, {
59856078
owner,
59866079
repo,
5987-
since: latestReleaseDate,
5988-
creator: 'app/github-actions',
5989-
state: 'open',
5990-
sort: 'created',
5991-
direction: 'desc',
5992-
labels: label
59936080
});
59946081

5995-
return pendingIssues.data.length ? pendingIssues.data[0] : null;
6082+
return allReleasesResp.data;
59966083
}
59976084

5998-
async function updateLastOpenPendingIssue(token, issueTitle, issueBody, issueNo) {
6085+
async function getUnreleasedCommits(token, latestReleaseDate, staleDays) {
59996086
const octokit = github.getOctokit(token);
60006087
const { owner, repo } = github.context.repo;
60016088

6002-
const updatedIssue = await octokit.request(`PATCH /repos/{owner}/{repo}/issues/${issueNo}`, {
6089+
const allCommitsResp = await octokit.request(`GET /repos/{owner}/{repo}/commits`, {
60036090
owner,
60046091
repo,
6005-
title: issueTitle,
6006-
body: issueBody
6092+
since: latestReleaseDate,
60076093
});
60086094

6009-
return updatedIssue.data.length ? updatedIssue.data[0] : null;
6010-
}
6095+
const staleDate = new Date().getTime() - (staleDays * 24 * 60 * 60 * 1000);
60116096

6012-
function formatCommitMessage(fullCommitMessage, numberOfLines) {
6013-
if (!numberOfLines || numberOfLines < 0) {
6014-
return fullCommitMessage;
6097+
for (const commit of allCommitsResp.data) {
6098+
const commitDate = new Date(commit.commit.committer.date).getTime();
6099+
if (commitDate < staleDate) {
6100+
return allCommitsResp.data;
6101+
}
60156102
}
6016-
return fullCommitMessage
6017-
.split('\n')
6018-
.slice(0, numberOfLines)
6019-
.join('\n')
6020-
.trim();
6103+
6104+
return [];
60216105
}
60226106

60236107
module.exports = {
6024-
createIssue,
6025-
getLastOpenPendingIssue,
6026-
updateLastOpenPendingIssue,
6027-
formatCommitMessage,
6108+
getLatestRelease,
6109+
getUnreleasedCommits,
60286110
};
60296111

60306112

@@ -6185,54 +6267,16 @@ var __webpack_exports__ = {};
61856267

61866268
const core = __nccwpck_require__(186);
61876269
const { logInfo } = __nccwpck_require__(653);
6188-
const { getLatestRelease, getUnreleasedCommits } = __nccwpck_require__(26);
6189-
const { createIssue, getLastOpenPendingIssue, updateLastOpenPendingIssue, formatCommitMessage } = __nccwpck_require__(608);
6270+
6271+
const { runAction } = __nccwpck_require__(254);
61906272

61916273
async function run() {
61926274
try {
61936275
const token = core.getInput('github-token', { required: true });
61946276
const staleDays = Number(core.getInput('stale-days'));
61956277
const commitMessageLines = Number(core.getInput('commit-messages-lines'));
6196-
const latestRelease = await getLatestRelease(token);
6197-
const label = 'notify-release';
6198-
6199-
if (!latestRelease) {
6200-
return logInfo('Could not find latest release');
6201-
}
6202-
6203-
logInfo(`Latest release - name:${latestRelease.name}, created:${latestRelease.created_at},
6204-
Tag:${latestRelease.tag_name}, author:${latestRelease.author.login}`);
6205-
6206-
const unreleasedCommits = await getUnreleasedCommits(
6207-
token,
6208-
latestRelease.created_at,
6209-
staleDays,
6210-
);
6211-
6212-
if (unreleasedCommits.length) {
6213-
const commitStr = unreleasedCommits.map((commit) => `Commit: ${formatCommitMessage(commit.commit.message, commitMessageLines)}
6214-
Author: ${commit.commit.author.name}
62156278

6216-
`).join('');
6217-
const issueBody = `Unreleased commits have been found which are pending release, please publish the changes.
6218-
6219-
### Commits since the last release
6220-
${commitStr}`;
6221-
const issueTitle = 'Release pending!';
6222-
6223-
const lastPendingIssue = await getLastOpenPendingIssue(token, latestRelease.created_at, label);
6224-
6225-
if (lastPendingIssue) {
6226-
await updateLastOpenPendingIssue(token, issueTitle, issueBody, lastPendingIssue.number);
6227-
logInfo(`Issue ${lastPendingIssue.number} has been updated`);
6228-
} else {
6229-
const issueNo = await createIssue(token, issueTitle, issueBody, label);
6230-
logInfo(`New issue has been created. Issue No. - ${JSON.stringify(issueNo.data.number)}`);
6231-
}
6232-
6233-
} else {
6234-
logInfo('No pending commits found');
6235-
}
6279+
return await runAction(token, staleDays, commitMessageLines);
62366280
} catch (error) {
62376281
logInfo(error.message);
62386282
core.setFailed(error.message);

0 commit comments

Comments
 (0)