Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/publish to slack #26

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ A Gitlab release note generator that generates release note on latest tag

*(Note. if an issue or merge request that has 2 or more labels, that issue or merge request will be displayed again under the corresponding title)*

- Can be integrated as a CD service. Tutorial below

- Ability to send the generated release notes to Slack
- Can be integrated as a CD service. Tutorial below

## How it works
1. Find the latest tag
Expand All @@ -35,21 +36,22 @@ docker container run -e GITLAB_PERSONAL_TOKEN=gitlabSampleToken -e GITLAB_PROJEC
```

### Nodejs Method
- Fill in the parameters mainly `GITLAB_PERSONAL_TOKEN`, `GITLAB_PROJECT_ID`, `TARGET_BRANCH`(optional. Use it only if you want to find tags in the same specific branch) and `TARGET_TAG_REGEX` (optional. Can use it to distinguish master or develop branch version bump) in `app/env.js` or feed it in `process.env` through npm
- Fill in the parameters mainly `GITLAB_PERSONAL_TOKEN`, `GITLAB_PROJECT_ID`, `TARGET_BRANCH`(optional. Use it only if you want to find tags in the same specific branch), `TARGET_TAG_REGEX` (optional. Can use it to distinguish master or develop branch version bump), `PUBLISH_TO_SLACK` (optional) and `SLACK_WEBHOOK_URL` (optional) in `app/env.js` or feed it in `process.env` through npm
- `npm install`
- `npm start`
- After couple seconds, latest tag should have a release note
![](https://dl3.pushbulletusercontent.com/HIav5xaHjcerMtkHT3myQLnl5C9g1UP3/Screen%20Shot%202019-06-01%20at%204.27.18%20pm.png)

### Gitlab CI method
1. Need to pass in `gitlab personal access token` as a CI variable
2. c/p the `.sample.gitlab-ci.yml` to your gitlab ci.

2. Need to pass in `SLACK_WEBHOOK_URL` as a CI variable (optional)
3. c/p the `.sample.gitlab-ci.yml` to your gitlab ci.

What's included in the sample gitlab CI script

- `generate-release-note` job. Generates a release note on the tag after detecting tag push with this regex `/^[0-9]+.[0-9]+.[0-9]+(-[0-9]+)?$/`
- `tag-after-deployment` job (optional). Tag the commit that contains a version bump with this regex `/^[0-9]+.[0-9]+.[0-9]+(-[0-9]+)?$/`. **Require ssh key to work.**
3. Customise the gitlab ci script to your need
4. Customise the gitlab ci script to your need

Reference gitlab repo: [generator test](https://gitlab.com/jackzhang/generator-test)

Expand All @@ -58,7 +60,7 @@ Reference gitlab repo: [generator test](https://gitlab.com/jackzhang/generator-t

These can be specified using environment variables

* GITLAB_API_ENDPOINT: Your gitlab instaqnce's endpoint
* GITLAB_API_ENDPOINT: Your gitlab instance's endpoint
* Default https://gitlab.com/api/v4
* GITLAB_PERSONAL_TOKEN: Grant api read/access permission
* GITLAB_PROJECT_ID: Your project id that is located under settings > general
Expand All @@ -68,6 +70,8 @@ These can be specified using environment variables
* Default "Australia/Melbourne"
* ISSUE_CLOSED_SECONDS: The amount of seconds to search after the last commit, useful for Merge Requests that close their tickets a second after the commit.
* Default 0
* PUBLISH_TO_SLACK: Feature flag to turn on or off publishing release notes to Slack. (optional).
* SLACK_WEBHOOK_URL: Your Slack webhook URL to send the generated release notes to Slack (optional).

## Building and Running locally

Expand All @@ -87,6 +91,8 @@ docker container run \
-e GITLAB_PROJECT_ID=$GITLAB_PROJECT_ID \
-e TARGET_BRANCH=master \
-e TARGET_TAG_REGEX=^release-.*$ \
-e PUBLISH_TO_SLACK=true \
-e SLACK_WEBHOOK_URL=$SLACK_WEBHOOK_URL \
local-gitlab-release-note-generator

```
Expand Down
4 changes: 4 additions & 0 deletions app/adapters/gitlab.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ exports.updateTagReleaseByProjectIdTagNameAndTagId = async (projectId, tagName,
return Request({uri: `${Env.GITLAB_API_ENDPOINT}/projects/${projectId}/repository/tags/${tagName}/release`, method: "PUT", body, ...options});
};

exports.getProjectByProjectID = async (projectId) => {
return Request({uri: `${Env.GITLAB_API_ENDPOINT}/projects/${projectId}`, ...options});
};

4 changes: 3 additions & 1 deletion app/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ exports.NODE_ENV = process.env.NODE_ENV;

// will looks for issues closed this many seconds after the tag, this may happen if the issue is merged via a MR and automatially closed
// example -e GITLAB_ISSUE_SECOND_DELAY=60 will catch issues closed up to 60 seconds after the tag is created.
exports.ISSUE_CLOSED_SECONDS = process.env.ISSUE_CLOSED_SECONDS || "0"
exports.ISSUE_CLOSED_SECONDS = process.env.ISSUE_CLOSED_SECONDS || "0"
exports.PUBLISH_TO_SLACK = process.env.PUBLISH_TO_SLACK || false;
exports.SLACK_WEBHOOK_URL = process.env.SLACK_WEBHOOK_URL;
3 changes: 2 additions & 1 deletion app/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const Generator = require("./lib/generator");
const Publisher = require("./lib/publisher");
const Logger = require("./logger");

Generator.generate().then().catch(err => {
Generator.generate().then(notes => Publisher.publish(notes)).catch(err => {
Logger.error(err);
});
2 changes: 1 addition & 1 deletion app/lib/generator.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ exports.generate = async () => {
}

const changeLog = await ChangelogLib.getChangelogByStartAndEndDate(startDate, endDate);
const changeLogContent = await ChangelogLib.generateChangeLogContent(changeLog, {useSlack: false});
const changeLogContent = await ChangelogLib.generateChangeLogContent(changeLog, {useSlack: Env.PUBLISH_TO_SLACK});
Logger.debug(`Changelog: ${changeLogContent}`);
return await TagLib.upsertTagDescriptionByProjectIdAndTag(Env.GITLAB_PROJECT_ID, latestTag, changeLogContent);
};
7 changes: 7 additions & 0 deletions app/lib/project.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const Gitlab = require("../adapters/gitlab");

exports.getProjectName = async (projectId) => {
const { name } = await Gitlab.getProjectByProjectID(projectId);

return name;
};
39 changes: 39 additions & 0 deletions app/lib/publisher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const _ = require("lodash");
const request = require("request");
const Project = require("./project");
const Logger = require("../logger");
const Env = require("../env");

exports.publish = async (notes) => {
if (!Env.PUBLISH_TO_SLACK) {
Logger.info('PUBLISH_TO_SLACK is disabled. Skipping...');
return;
}

if (!Env.SLACK_WEBHOOK_URL) {
throw new Error('SLACK_WEBHOOK_URL is not defined. Skipping...');
}

Logger.info('Preparing Slack payload');

let projectName = await Project.getProjectName(Env.GITLAB_PROJECT_ID);

request({
method: 'POST',
uri: Env.SLACK_WEBHOOK_URL,
body: {
text: `*${projectName} Version ${notes.tag_name}* was just released! :tada:\n\n ${notes.description}`
},
json: true
}, (error, response) => {
if (error) {
throw new Error("An error occurred while sending Slack message. Slack Result: " + JSON.stringify(response));
}

if(response.statusCode != 200) {
return Logger.error(`An error occurred while sending Slack message - ${response.statusCode}: ${response.body}`);
}

return Logger.info(`Slack message sent successfully`);
});
};