Skip to content
Draft
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
5 changes: 1 addition & 4 deletions github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ Please make sure Commander is installed in your [Slack workspace](https://slack.

## Requirements

In order to use this command set, you need to set up a Personal Access Token on GitHub with repo access. And save the token as a secret with `github_token` as the key name. Use `/nc secret_create` to create secrets.

Generate a token with `repo` access [here](https://github.com/settings/tokens) or click [here](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line) to learn how to create a Personal Access Token on GitHub.
In order to use this command set, you need to add ![github as oauth provider](https://nimbella.com/docs/commander/slack/oauth#adding-github-as-an-oauth-provider).

Create a secret named `github_repos` to avoid passing repository (`-r`) to commands.

Expand All @@ -43,7 +41,6 @@ For commands that only work with single repository the first repository in `gith

Only for Github Enterprise version, you need to specify the host. Below are the ways to do it, you can follow any of them
- Specify `--host` or `-h` while invoking the command.
- Append the host name to your `github_token` following this format: `access_token@github_host`. For example `mysecret@example.com`.

- Create a secret with key name `github_host` using `/nc secret_create`, and add the host as the value.

Expand Down
60 changes: 57 additions & 3 deletions github/commands.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ commands:
optional: true
options:
- name: q
value: query
value: query
- name: r
value: repositories
- name: l
Expand Down Expand Up @@ -119,11 +119,12 @@ commands:
- name: c
value: comment_id
- name: b
value: body
value: body
- name: h
value: host
issues:
description: Manage Issues and PRs
description: Manage Issues
main: main
parameters:
- name: action
optional: true
Expand Down Expand Up @@ -198,5 +199,58 @@ commands:
value: milestone_number
- name: h
value: host
billing:
description: See Billing Details
parameters:
- name: entity
options:
- name: t
value: type
- name: o
value: org
- name: u
value: user
- name: h
value: host
hooks:
description: Manage Hooks
parameters:
- name: action
pulls:
description: Manage Pulls
parameters:
- name: action
options:
- name: r
value: repository
- name: p
value: pr_number
- name: i
value: issue
- name: a
value: assignees
- name: t
value: title
- name: b
value: body
- name: head
value: head
- name: base
value: base
- name: l
value: labels
- name: s
value: state
- name: reason
value: reason
- name: list_option
value: list_option
- name: o
value: org
- name: h
value: host
- name: d
deploy:
description: Deploys a compatible project from GitHub repo to Nimbella
github:
description: View GitHub command set documentation
138 changes: 138 additions & 0 deletions github/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
const axios = require('axios');

const headers = {
'Content-Type': 'application/json',
};
const requestThreshold = 3
const requestTimeout = 1000 * 5 // 5 seconds
const baseURL = 'https://api.github.com'

async function Request(url, action, method, data, token) {
if (!token && !['list', 'get'].includes(action)) {
return Fail('*please run /nc oauth_create github. See <https://nimbella.com/docs/commander/slack/oauth#adding-github-as-an-oauth-provider | github as oauth provider>*')
}
if (token) {
headers.Authorization = `Bearer ${token}`;
}
return axios({
method: method,
url,
headers,
data,
timeout: requestTimeout
})
}


const UpdateURL = (url) => {
if (url.includes('|')) {
url = (url.split('|')[1] || '').replace('>', '')
} else {
url = url.replace('<', '').replace('>', '')
}
if (!url.startsWith('http')) {
url = 'https://' + url;
}
if (!url.includes('api')) {
url += '/api/v3';
}
return url
}


const GetErrorMessage = (error) => {
console.error(error)
if (error.response && error.response.status === 403) {
return `:warning: *The api rate limit has been exhausted.*`
} else if (error.response && error.response.status && error.response.data) {
return `Error: ${error.response.status} ${error.response.data.message}`
} else {
return error.message
}
};

const GetHeader = (res, token, topic, action) => {
if (res && res.headers) {
const tokenMessage = token ? '' : '*For greater limits you can add <https://nimbella.com/docs/commander/slack/oauth#adding-github-as-an-oauth-provider | github as oauth provider>';
const currReading = parseInt(res.headers['x-ratelimit-remaining']);
let header = `\n${Capitalize(topic)} *${Capitalize(action)}* Request Result:`;
if (currReading < requestThreshold) {
header = `:warning: *You are about to reach the api rate limit.* ${tokenMessage}`;
}
if (currReading === 0) {
header = `:warning: *The api rate limit has been exhausted.* ${tokenMessage}`;
}
return { header, currReading }
}
return { header: '', currReading: 0 }
}

const GetFooter = () => {
return {
type: 'context',
elements: [
Text('add _github command-set_ to your Slack with <https://nimbella.com/product/commander/ | Commander>'),
],
}
}

const Fail = (msg, err) => {
let errMsg
if (err) errMsg = GetErrorMessage(err)
const response = {
response_type: 'in_channel',
blocks: [Section(`${msg || errMsg || '*couldn\'t get action results*'}`)],
};
return response
};

const GetRepository = (github_repos, repository) => {
const default_repos = repository ? repository : github_repos;
if (default_repos) {
repository = default_repos.split(',').map(repo => repo.trim())[0];
}
return repository
}

const GetBaseUrl = (host, secrets) => {
return UpdateURL(host || secrets.github_host || baseURL)
}

const Image = (source, alt) => ({
type: 'image',
image_url: source,
alt_text: alt,
});

const Text = (text) => ({
type: 'mrkdwn',
text: text
// Convert markdown links to slack format.
.replace(/!*\[(.*)\]\((.*)\)/g, '<$2|$1>')
// Replace markdown headings with slack bold
.replace(/#+\s(.+)(?:R(?!#(?!#)).*)*/g, '*$1*'),
});

const Section = (text) => ({
type: 'section',
text: Text(text),
});

const GetPrettyDate = (date) => {
return `<!date^${Math.floor(new Date(date).getTime() / 1000)}^{date_pretty} at {time}|${date}>`
}

const Capitalize = s => (s && s[0].toUpperCase() + s.slice(1)) || ""

module.exports = {
GetHeader,
GetFooter,
GetRepository,
GetPrettyDate,
GetBaseUrl,
Fail,
Request,
Image,
Text,
Section
}
Loading