Last active
July 27, 2020 04:55
-
-
Save addeeandra/1e2f2889f76ca318dfdebf2a45f2e945 to your computer and use it in GitHub Desktop.
Git Kanban to Airtable Basic Hooks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Host this code on a server and point your github webhooks to this file. | |
* it's a single directional API for Github to Airtable. It excludes the Airtable to Github. | |
* | |
* What to prepare? | |
* 1. Make an airtable Base, | |
* 2. Make a special table on airtable for Github Kanban (ex. Report), | |
* 3. Enable 'project' on Github to get the Kanban view, | |
* 4. Host the code, point the project webhooks to this code, | |
* 5. Make an issue in Github + sync it to the Kanban .. it'll created / updated on airtable too. | |
*/ | |
const GITHUB_TOKEN = 'your github api token'; | |
const AIR_TOKEN = 'your airtable api token'; | |
const AIR_BASE_ID = 'your airtable Base ID'; | |
const AIR_TABLE_ID = 'your airtable Base > Table Name'; // ex. "Report" | |
// the 905xxx is based on your Github Card ID (haha, map it yourself with ur own) | |
const COLUMN_CONFIG = [ | |
9050828 => '', | |
9050825 => 'TO DO', // To Do | |
9050831 => 'DOING', // In Progress | |
9050832 => 'DONE' // Done | |
]; | |
function write_log($tag, $content) { | |
file_put_contents('logs.txt', '['.date('Y-m-d').']['.$tag.'] '.$content.PHP_EOL , FILE_APPEND | LOCK_EX); | |
} | |
// SETUP AIRTABLE CURL | |
function aircurl($url, $method = 'GET', $payload = null, $json = true) { | |
$headers = ['Authorization: Bearer ' . AIR_TOKEN]; | |
// HEADERS : Content-Type | |
if (!is_null($payload) && $json) array_push($headers, 'Content-Type: application/json'); | |
else if (!is_null($payload) && !$json) array_push($headers, 'Content-Type: application/x-www-form-urlencoded'); | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
// METHOD | |
if ($method == 'POST') curl_setopt($ch, CURLOPT_POST, 1); | |
if (!in_array($method, ['POST', 'GET'])) curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); | |
// PAYLOAD | |
if (!is_null($payload) && $json) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); | |
else if (!is_null($payload)) curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); | |
// RESPONSE | |
$response = curl_exec($ch); | |
curl_close($ch); | |
return $response; | |
} | |
function gitcurl($url, $method = 'GET', $payload = null, $json = true) { | |
$headers = [ | |
'Authorization: token ' . GITHUB_TOKEN, | |
'User-Agent: GitAir-Integrator' | |
]; | |
// HEADERS : Content-Type | |
if (!is_null($payload) && $json) array_push($headers, 'Content-Type: application/json'); | |
else if (!is_null($payload)) array_push($headers, 'Content-Type: application/x-www-form-urlencoded'); | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |
// METHOD | |
if ($method == 'POST') curl_setopt($ch, CURLOPT_POST, 1); | |
if (!in_array($method, ['POST', 'GET'])) curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); | |
// PAYLOAD | |
if (!is_null($payload) && $json) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); | |
else if (!is_null($payload)) curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); | |
// RESPONSE | |
$response = curl_exec($ch); | |
curl_close($ch); | |
return $response; | |
} | |
// GET BACKLOG RECORDS | |
function get_backlog_records() { | |
return aircurl("https://api.airtable.com/v0/${AIR_BASE_ID}/${AIR_TABLE_ID}?view=Grid"); | |
} | |
function get_backlog_record_with_code($name) { | |
$raw_records = get_backlog_records(); | |
$air_payload_records = json_decode($raw_records, true); | |
$records = $air_payload_records['records']; | |
$record = null; | |
foreach ($records as $rec) if ($rec['fields']['GitCode'] == $name) $record = $rec; | |
return $record; | |
} | |
function create_backlog_record_with($git_project_card) { | |
if (is_null($git_project_card['note'])) { | |
$content = json_decode(gitcurl($git_project_card['content_url']), 1); | |
$name = $content['title']; | |
$note = $content['body']; | |
} else { | |
$name = 'NO #'.$git_project_card['id']; | |
$note = $git_project_card['note']; | |
} | |
$gitcode = (string) $git_project_card['id']; | |
$creator = $git_project_card['creator']['login']; | |
$author = $creator; | |
$status = COLUMN_CONFIG[$git_project_card['column_id']] ?: null; | |
return aircurl("https://api.airtable.com/v0/${AIR_BASE_ID}/${AIR_TABLE_ID}", 'POST', [ | |
'fields' => [ | |
'Name' => $name, | |
'Notes' => $note, | |
'Status' => $status, | |
'GitCode' => $gitcode, | |
'GitAuthor' => $author | |
] | |
]); | |
} | |
function delete_backlog_record_with($git_project_card) { | |
$record = get_backlog_record_with_code($git_project_card['id']); | |
if (is_null($record)) return; | |
return aircurl("https://api.airtable.com/v0/${AIR_BASE_ID}/${AIR_TABLE_ID}/" . $record['id'], 'DELETE'); | |
} | |
function update_backlog_record_with($git_project_card) { | |
$record = get_backlog_record_with_code($git_project_card['id']); | |
if (is_null($record)) { | |
return create_backlog_record_with($git_project_card); | |
} | |
if (is_null($git_project_card['note'])) { | |
$response = gitcurl($git_project_card['content_url']); | |
write_log('GIT RESPONSE', $response); | |
if (is_null($response)) { | |
$name = 'NO #'.$git_project_card['id']; | |
$note = $git_project_card['note']; | |
} else { | |
$content = json_decode($response, 1); | |
$name = $content['title']; | |
$note = $content['body']; | |
} | |
} else { | |
$name = 'NO #'.$git_project_card['id']; | |
$note = $git_project_card['note']; | |
} | |
$gitcode = (string) $git_project_card['id']; | |
$creator = $git_project_card['creator']['login']; | |
$author = $creator; | |
$status = COLUMN_CONFIG[$git_project_card['column_id']] ?: null; | |
return aircurl("https://api.airtable.com/v0/${AIR_BASE_ID}/${AIR_TABLE_ID}/" . $record['id'], 'PATCH', [ | |
'fields' => [ | |
'Name' => $name, | |
'Notes' => $note, | |
'Status' => $status, | |
'GitCode' => $gitcode, | |
'GitAuthor' => $author | |
] | |
]); | |
} | |
// LOG PAYLOAD | |
write_log('INIT HOOK', '--------------------------------------------------------------------'); | |
write_log('GIT PAYLOAD', $_POST['payload']); | |
$git_payload = json_decode($_POST['payload'], true); | |
$git_action = $git_payload['action']; | |
$card = $git_payload['project_card']; | |
write_log('ACTION', $git_action); | |
switch ($git_action) { | |
case 'created': | |
write_log('AIR CREATE', create_backlog_record_with($card)); | |
break; | |
case 'edited': | |
write_log('AIR EDITED', update_backlog_record_with($card)); | |
break; | |
case 'moved': | |
write_log('AIR MOVED', update_backlog_record_with($card)); | |
break; | |
case 'deleted': | |
write_log('AIR DELETE', delete_backlog_record_with($card)); | |
break; | |
default: | |
break; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment