昨今、タスク管理のサービスは様々ありますが、僕はGitHubにプライペートなリポジトリを作ってissueをタスク管理の仕組みとして使っています。
そんな中でいくつかのissueを連続して登録するときに「毎回ボタンをポチポチ押すのが面倒だな〜」と思うことがあったので、slackからバシバシissue登録できる仕組みを作ってみました。
目次
GitHubのissueでタスク管理する
いままでTodoistやTrelloを試してきましたが、なかなかしっくりこなくて、あっちのサービス・こっちのサービスと渡り歩いてきました。
ある時、「なるべくGitHubのissueに登録して管理している。細かな作業はそれ用のリポジトリを作っている。」という知り合いがいて、それをヒントにGitHubにタスク管理用のプライペートリポジトリ作って、issueでタスク管理するようにし始めました。
issueの一覧はTodoリストとして確認できるし、Projectを作ればカンバン方式で案件の進捗具合を確認できます。
さらには、issueを作ったりcloseしたりするとcontributionsのグラフに色がついて活動してる感じがでます。
大事ですよね。活動してる”風”。
ただ、issueを登録するときの煩わしさと仲良くする必要がありまして…

issueを1件登録するために「New issue」ボタン押す→タイトル入力→「Submit new issue」ボタン押す…
というややめんどくさい手順が必要になります。
issue1件だけならいいのですが、タイミング的に複数件一気に登録したいときは面倒くささ100倍です…
そんな面倒くささを解消するために、普段開きっぱなしにしているslackからサクッとissue登録するための仕組みを作ってみました。
slackからGitHubにissueを登録する仕組み
前置きが長くなりましたが、今回作ったslackからGitHubにissueを登録する仕組みを紹介します。
構成
構成というか、使うサービス・仕組みはこちら▼
- slack
- Google App Script
- GitHub GraphQL API v4
slackからスラッシュコマンドでGoogle App Scriptで作ったWebアプリを実行します。
Google App Scriptを使っているのは、自分だけが使うオレオレツールなのでWebアプリのURLがわけわからんURLでも問題ないのと、GASならサーバーとかドメインとか気にしなくていいのでお手軽だからです。
GitHubへのissue登録はREST APIではなくGraphQL APIを使ってみます。
ココらへんは単に「せっかくだから使ってみよう」と思っただけです。自分だけしか使わないツールなので動かなくなってもいいのでなるべく挑戦していきます。
GitHubへissueを登録するGoogle App Script
GitHub GraphQL API v4を使ったissueの取得・登録は以前に試した記事をご参考にしてください。


作ったGASのコードはこちら▼
/**
* Config
*/
var ACCESS_TOKEN = '作成したアクセストークン';
var ENDPOINT = 'https://api.github.com/graphql';
var REPO_ID = 'issue登録するリポジトリのID';
/**
* doGet
*/
function doGet(e) {
return createTextOutput('Hello World!');
}
/**
* doPost
*/
function doPost(e) {
//受け取ったパラメーターの分解
var param = parseParameter(e);
if(param.title=='') {
return createTextOutput('titleの指定は必須です。');
}
createGitHubIssue(param.title,param.body,param.project,param.label);
return createTextOutput('');
}
/**
* パラメーターの分解
*/
function parseParameter(e) {
var param = e.parameter.text.split(' ')
//title
var title = param[0];
param.shift();
//body
var body = '';
if(param.length>=1) {
//残りを全部本文にする
body = param.join(' ');
}
//projectとlabelは後で分解方法考える
var param_data = {
'title': title,
'body': body,
'project' : '',
'label' : '',
};
return param_data;
}
/**
* Issue登録
*/
function createGitHubIssue(title,body,project,label) {
//mutation
var mutation = createMutation(title,body,project,label);
var options = {
'method' : 'post',
'contentType' : 'application/json',
'headers' : {
'Authorization' : 'Bearer ' + ACCESS_TOKEN,
'Accept' : 'application/vnd.github.starfire-preview+json',
},
'payload' : JSON.stringify({query:mutation})
};
return post(options);
}
/**
* Issue作成mutation作成
*/
function createMutation(title,body,project,label) {
return 'mutation {\
createIssue('+createIssueInput(title,body,project,label)+') {\
issue {\
title,\
url\
}\
}\
}';
}
/**
* Issue作成の為のinputを作成
*/
function createIssueInput(title,body,project,label) {
var repositoryId = 'repositoryId:"'+REPO_ID+'"';
title = ',title:"'+title+'"';
if(body!='') {
body = ',body:"'+body+'"';
}
if(project!='') {
project = ', projectIds:['+getProjectIds(project)+']';
}
if(label!='') {
label = ',labelIds:['+getLabelIds(label)+']';
}
return 'input:{'+repositoryId+title+body+project+label+'}';
}
/**
* プロジェクトIDの取得
*/
function getProjectIds(project) {
return '';
}
/**
* ラベルIDの取得
*/
function getLabelIds(label) {
return '';
}
/**
* queryの実行
*/
function getGitHubData(query) {
var options = {
'method' : 'post',
'contentType' : 'application/json',
'headers' : {
'Authorization' : 'Bearer ' + ACCESS_TOKEN
},
'payload' : JSON.stringify({query:query})
};
return post(options);
}
/**
* UrlFetchApp.fetch
*/
function post(options) {
//Issue登録のときの'Accept' : 'application/vnd.github.starfire-preview+json' がなくなればもう少しさっぱりまとめられる
var response = UrlFetchApp.fetch(ENDPOINT, options);
var json = JSON.parse(response.getContentText());
Logger.log(json);
return json;
}
/**
* 結果返却用JSON作成
*/
function createJSONOutput(data) {
return ContentService.createTextOutput(JSON.stringify(data)).setMimeType(ContentService.MimeType.JSON);
}
/**
* 結果返却用テキスト作成
*/
function createTextOutput(text) {
return ContentService.createTextOutput(text);
}
Google App Scriptを作成したらウェブアプリケーションとして登録し、URLを取得しておきます。

ウェブアプリケーションとして登録する手順は前々回の記事を参考にしてください▼

slackのスラッシュコマンドを登録
slackから実行するコマンドを以下のリンクから登録します。

「Create an App」をクリックします。

アプリの名前と有効化するワークスペースを選択します。

続いて、「Slash Commands」メニューを選択し、「Create New Command」をクリックします。

スラッシュコマンドの設定で以下の内容を入力します。
- Command : slackで自分が入力することになるコマンド名
- Request URL : GASをウェブアプリケーションとして登録したURL
- Short Description : アプリの簡単な説明
- User Hint : コマンドを入力したときに表示される入力のヒント

設定が完了したら、「Install App」メニューを選択し、「Install App to Workspace」をクリックします。

実際にSlackでスラッシュコマンドを入力してみて、サジェストされればOKです!
Slackからissueを登録

issueの登録はスラッシュコマンドの後にタイトルと本文をスペース区切りで入力します。
1つ目はタイトルとして登録され、残りは全て本文になります。本文は一応複数行の登録に対応したつもりです。

GitHub Appをワークスペースにインストールしてリポジトリをsubscribeしておけば、issue登録時に通知を受け取れます。
GASのreturnで組み込むこともできますが、GitHub Appに任せたほうがアイコンとかもいい感じにでるのでオススメです。
まとめ
これでサクサクとslackからissueを登録できるようになりました!
GASを使ってるので、やろうと思えば定期的にissueやマイルストーンなども作れそうなのでいろいろ自動化ができるかなーと思います。
ではまた。