Skip to content

Commit

Permalink
refactor: put issues comments behind config option
Browse files Browse the repository at this point in the history
  • Loading branch information
fgreinacher committed Feb 6, 2022
1 parent f4ce6bd commit 1a56987
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 36 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ Create a [personal access token](https://docs.gitlab.com/ce/user/profile/persona
| `gitlabApiPathPrefix` | The GitLab API prefix. | `GL_PREFIX` or `GITLAB_PREFIX` environment variable or CI provided environment variables if running on [GitLab CI/CD](https://docs.gitlab.com/ee/ci) or `/api/v4`. |
| `assets` | An array of files to upload to the release. See [assets](#assets). | - |
| `milestones` | An array of milestone titles to associate to the release. See [GitLab Release API](https://docs.gitlab.com/ee/api/releases/#create-a-release). | - |
| `postComments` | Post comments to issues and MRs associated with a release. | `false` |

#### assets

Expand Down
93 changes: 66 additions & 27 deletions lib/publish.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module.exports = async (pluginConfig, context) => {
logger,
commits,
} = context;
const {gitlabToken, gitlabUrl, gitlabApiUrl, assets, milestones} = resolveConfig(pluginConfig, context);
const {gitlabToken, gitlabUrl, gitlabApiUrl, assets, milestones, postComments} = resolveConfig(pluginConfig, context);
const assetsList = [];
const repoId = getRepoId(context, gitlabUrl, repositoryUrl);
const encodedRepoId = encodeURIComponent(repoId);
Expand Down Expand Up @@ -116,35 +116,74 @@ module.exports = async (pluginConfig, context) => {
throw error;
}

const commentRelatedIssues = async commit => {
const relatedMergeRequestsEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/commits/${commit}`);
const relatedMergeRequests = await got
.get(relatedMergeRequestsEndpoint, {
...apiOptions,
})
.json();

for (const relatedMergeRequest of relatedMergeRequests.filter(x => x.state === 'merged')) {
const relatedIssuesEndpoint = urlJoin(
gitlabApiUrl,
`/projects/${encodedRepoId}/merge_requests/${relatedMergeRequest.iid}/closes_issues`
);
/* eslint no-await-in-loop: "off" */
const relatedIssues = await got
.get(relatedIssuesEndpoint, {
if (postComments) {
try {
const postCommentToIssue = issueId => {
const issueNotesEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/issues/${issueId}/notes`);
debug('Posting issue note to %s', issueNotesEndpoint);
return got.post(issueNotesEndpoint, {
...apiOptions,
json: {
body: `:tada: This issue has been resolved in version ${gitTag} :tada:\n\nThe release is available on [Gitlab Release](../../releases/${gitTag})`,
},
});
};

const postCommentToMergeRequest = mergeRequestId => {
const mergeRequestNotesEndpoint = urlJoin(
gitlabApiUrl,
`/projects/${encodedRepoId}/merge_requests/${mergeRequestId}/notes`
);
debug('Posting MR note to %s', mergeRequestNotesEndpoint);
return got.post(mergeRequestNotesEndpoint, {
...apiOptions,
})
.json();
for (const relatedIssue of relatedIssues.filter(x => x.state === 'closed')) {
const issueNotesEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/issues/${relatedIssue.iid}/notes`);
await got.post(issueNotesEndpoint, {
body: `tada: This issue has been resolved in version ${gitTag} :tada:\n\nThe release is available on [Gitlab Release](../../releases/${gitTag})`,
json: {
body: `:tada: This MR is included in version ${gitTag} :tada:\n\nThe release is available on [Gitlab Release](../../releases/${gitTag})`,
},
});
}
};

const getRelatedMergeRequestIds = async commitHash => {
const relatedMergeRequestsEndpoint = urlJoin(
gitlabApiUrl,
`/projects/${encodedRepoId}/repository/commits/${commitHash}/merge_requests`
);
debug('Getting MRs from %s', relatedMergeRequestsEndpoint);
const relatedMergeRequests = await got
.get(relatedMergeRequestsEndpoint, {
...apiOptions,
})
.json();

return relatedMergeRequests.filter(x => x.state === 'merged').map(x => x.iid);
};

const getRelatedIssueIds = async mergeRequestId => {
const relatedIssuesEndpoint = urlJoin(
gitlabApiUrl,
`/projects/${encodedRepoId}/merge_requests/${mergeRequestId}/closes_issues`
);
debug('Getting related issues from %s', relatedIssuesEndpoint);
const relatedIssues = await got
.get(relatedIssuesEndpoint, {
...apiOptions,
})
.json();

return relatedIssues.filter(x => x.state === 'closed').map(x => x.iid);
};

const relatedMergeRequestIds = [
...new Set((await Promise.all(commits.map(x => x.hash).map(getRelatedMergeRequestIds))).flat()),
];
const relatedIssueIds = [...new Set((await Promise.all(relatedMergeRequestIds.map(getRelatedIssueIds))).flat())];
await Promise.all(relatedIssueIds.map(postCommentToIssue));
await Promise.all(relatedMergeRequestIds.map(postCommentToMergeRequest));
} catch (error) {
logger.error('An error occurred while posting comments to related issues and merge requests:\n%O', error);
throw error;
}
};

await Promise.all(commits.map(commit => commentRelatedIssues(commit)));
}

logger.log('Published GitLab release: %s', gitTag);

Expand Down
3 changes: 2 additions & 1 deletion lib/resolve-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const {castArray, isNil} = require('lodash');
const urlJoin = require('url-join');

module.exports = (
{gitlabUrl, gitlabApiPathPrefix, assets, milestones},
{gitlabUrl, gitlabApiPathPrefix, assets, milestones, postComments},
{
envCi: {service} = {},
env: {
Expand Down Expand Up @@ -41,5 +41,6 @@ module.exports = (
: urlJoin(defaultedGitlabUrl, isNil(userGitlabApiPathPrefix) ? '/api/v4' : userGitlabApiPathPrefix),
assets: assets ? castArray(assets) : assets,
milestones: milestones ? castArray(milestones) : milestones,
postComments: postComments === undefined ? false : postComments,
};
};
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions test/publish.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,54 @@ test.serial('Publish a release', async t => {
t.true(gitlab.isDone());
});

test.serial('Publish a release and post comments', async t => {
const owner = 'test_user';
const repo = 'test_repo';
const env = {GITLAB_TOKEN: 'gitlab_token'};
const pluginConfig = {postComments: true};
const nextRelease = {gitHead: '123', gitTag: 'v1.0.0', notes: 'Test release note body'};
const options = {repositoryUrl: `https://gitlab.com/${owner}/${repo}.git`};
const encodedRepoId = encodeURIComponent(`${owner}/${repo}`);
const commits = [{hash: 'abcdef'}, {hash: 'fedcba'}];
const gitlab = authenticate(env)
.post(`/projects/${encodedRepoId}/releases`, {
tag_name: nextRelease.gitTag,
description: nextRelease.notes,
assets: {
links: [],
},
})
.reply(200)
.get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`)
.reply(200, [
{iid: 1, state: 'merged'},
{iid: 2, state: 'closed'},
{iid: 3, state: 'merged'},
])
.get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`)
.reply(200, [{iid: 1, state: 'merged'}])
.get(`/projects/${encodedRepoId}/merge_requests/1/closes_issues`)
.reply(200, [
{iid: 11, state: 'closed'},
{iid: 12, state: 'open'},
{iid: 13, state: 'closed'},
])
.get(`/projects/${encodedRepoId}/merge_requests/3/closes_issues`)
.reply(200, [])
.post(`/projects/${encodedRepoId}/merge_requests/1/notes`)
.reply(200)
.post(`/projects/${encodedRepoId}/merge_requests/3/notes`)
.reply(200)
.post(`/projects/${encodedRepoId}/issues/11/notes`)
.reply(200)
.post(`/projects/${encodedRepoId}/issues/13/notes`)
.reply(200);

await publish(pluginConfig, {env, options, nextRelease, logger: t.context.logger, commits});

t.true(gitlab.isDone());
});

test.serial('Publish a release with assets', async t => {
const cwd = 'test/fixtures/files';
const owner = 'test_user';
Expand Down
29 changes: 22 additions & 7 deletions test/resolve-config.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ test('Returns user config', t => {
const gitlabUrl = 'https://host.com';
const gitlabApiPathPrefix = '/api/prefix';
const assets = ['file.js'];
const postComments = true;

t.deepEqual(resolveConfig({gitlabUrl, gitlabApiPathPrefix, assets}, {env: {GITLAB_TOKEN: gitlabToken}}), {
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets,
milestones: undefined,
});
t.deepEqual(
resolveConfig({gitlabUrl, gitlabApiPathPrefix, assets, postComments}, {env: {GITLAB_TOKEN: gitlabToken}}),
{
gitlabToken,
gitlabUrl,
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets,
milestones: undefined,
postComments,
}
);
});

test('Returns user config via environment variables', t => {
Expand All @@ -35,6 +40,7 @@ test('Returns user config via environment variables', t => {
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets,
milestones,
postComments: false,
}
);
});
Expand All @@ -53,6 +59,7 @@ test('Returns user config via alternative environment variables', t => {
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets,
milestones: undefined,
postComments: false,
}
);
});
Expand All @@ -68,6 +75,7 @@ test('Returns default config', t => {
gitlabApiUrl: urlJoin('https://gitlab.com', '/api/v4'),
assets: undefined,
milestones: undefined,
postComments: false,
});

t.deepEqual(resolveConfig({gitlabApiPathPrefix}, {env: {GL_TOKEN: gitlabToken}}), {
Expand All @@ -76,6 +84,7 @@ test('Returns default config', t => {
gitlabApiUrl: urlJoin('https://gitlab.com', gitlabApiPathPrefix),
assets: undefined,
milestones: undefined,
postComments: false,
});

t.deepEqual(resolveConfig({gitlabUrl}, {env: {GL_TOKEN: gitlabToken}}), {
Expand All @@ -84,6 +93,7 @@ test('Returns default config', t => {
gitlabApiUrl: urlJoin(gitlabUrl, '/api/v4'),
assets: undefined,
milestones: undefined,
postComments: false,
});
});

Expand All @@ -107,6 +117,7 @@ test('Returns default config via GitLab CI/CD environment variables', t => {
gitlabApiUrl: CI_API_V4_URL,
assets: undefined,
milestones: undefined,
postComments: false,
}
);
});
Expand Down Expand Up @@ -134,6 +145,7 @@ test('Returns user config over GitLab CI/CD environment variables', t => {
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets,
milestones: undefined,
postComments: false,
}
);
});
Expand Down Expand Up @@ -167,6 +179,7 @@ test('Returns user config via environment variables over GitLab CI/CD environmen
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets: undefined,
milestones: undefined,
postComments: false,
}
);
});
Expand Down Expand Up @@ -200,6 +213,7 @@ test('Returns user config via alternative environment variables over GitLab CI/C
gitlabApiUrl: urlJoin(gitlabUrl, gitlabApiPathPrefix),
assets: undefined,
milestones: undefined,
postComments: false,
}
);
});
Expand All @@ -224,6 +238,7 @@ test('Ignore GitLab CI/CD environment variables if not running on GitLab CI/CD',
gitlabApiUrl: urlJoin('https://gitlab.com', '/api/v4'),
assets: undefined,
milestones: undefined,
postComments: false,
}
);
});

0 comments on commit 1a56987

Please sign in to comment.