Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add a script to pull tasks from GitHub
- Loading branch information
1 parent
d6130d6
commit 062a196
Showing
6 changed files
with
195 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"zone.bytes.linear" = "OmniFocus + GitHub"; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
"label" = "Pull from GitHub"; | ||
"shortLabel" = "Pull from GH"; | ||
"mediumLabel" = "Pull from GitHub"; | ||
"longLabel" = "Pull Tasks from GitHub"; | ||
"paletteLabel" = "Pull"; |
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
"use strict"; | ||
(() => { | ||
let creds = new Credentials(); | ||
var action = new PlugIn.Action(async () => { | ||
try { | ||
let req = URL.FetchRequest.fromString("https://api.github.com/graphql"); | ||
if (req === null || req.url === null || req.url.host === null) { | ||
throw "could not parse the URL for GitHub's GraphQL API"; | ||
} | ||
///////////////////////////////////// | ||
// Step 1: make sure we have creds // | ||
///////////////////////////////////// | ||
let stored = creds.read(req.url.host); | ||
let login = null; | ||
let key = null; | ||
if (stored === null || app.optionKeyDown) { | ||
let credsForm = new Form(); | ||
credsForm.addField(new Form.Field.String("login", "Login")); | ||
credsForm.addField(new Form.Field.Password("key", "API Key")); | ||
await credsForm.show("Let's set up: we need your GitHub username and an API key with the\n`repo` permission to pull issues from your assigned repos.\n\nCreate this at https://github.com/settings/tokens\n\nYou can get back here in the future to rotate tokens by holding\noption while activating the workflow.", "Save Key"); | ||
login = credsForm.values.login; | ||
key = credsForm.values.key; | ||
creds.write(req.url.host, login, key); | ||
} | ||
else { | ||
login = stored.user; | ||
key = stored.password; | ||
} | ||
//////////////////////////// | ||
// Step 2: get the issues // | ||
//////////////////////////// | ||
req.method = "POST"; | ||
req.bodyString = `{"query":"{ search(type: ISSUE, query: \\"is:issue assignee:${login} state:open\\", last: 100) { nodes { ... on Issue { number title body url repository { name owner { login } } } } } }"}`; | ||
req.headers = { | ||
"Content-Type": "application/json", | ||
"Authorization": `bearer ${key}`, | ||
}; | ||
let resp = await (req.fetch().catch((err) => { | ||
console.error("Problem fetching issues:", err); | ||
let alert = new Alert("Problem fetching from GitHub", err); | ||
alert.show(); | ||
throw err; | ||
})); | ||
if (resp.bodyString === null) { | ||
throw "body string was null. Did the request succeed?"; | ||
} | ||
let body = JSON.parse(resp.bodyString); | ||
let toFocus = []; | ||
for (let issue of body.data.search.nodes) { | ||
let gitHubTag = flattenedTags.byName("from GitHub") || new Tag("from GitHub"); | ||
let orgTag = gitHubTag.tagNamed(issue.repository.owner.login) || new Tag(issue.repository.owner.login, gitHubTag); | ||
let repoTag = orgTag.tagNamed(issue.repository.name) || new Tag(issue.repository.name, orgTag); | ||
let repo = `${issue.repository.owner.login}/${issue.repository.name}`; | ||
let projectName = `${repo}#${issue.number}: ${issue.title}`; | ||
let project = flattenedProjects.byName(projectName) || new Project(projectName); | ||
project.addTag(repoTag); | ||
project.note = `${issue.url}\n\n---\n\n${issue.body}`; | ||
toFocus.push(project); | ||
if (project.tasks.length === 0) { | ||
new Task(`what needs to be done for ${repo}#${issue.number}`, project); | ||
} | ||
} | ||
if (app.platformName === "macOS") { | ||
document.windows[0].perspective = Perspective.BuiltIn.Projects; | ||
document.windows[0].focus = toFocus; | ||
} | ||
} | ||
catch (err) { | ||
console.error(err); | ||
throw err; | ||
} | ||
}); | ||
return action; | ||
})(); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
(() => { | ||
let creds = new Credentials(); | ||
|
||
var action = new PlugIn.Action(async () => { | ||
try { | ||
let req = URL.FetchRequest.fromString("https://api.github.com/graphql"); | ||
if (req === null || req.url === null || req.url.host === null) { | ||
throw "could not parse the URL for GitHub's GraphQL API" | ||
} | ||
|
||
///////////////////////////////////// | ||
// Step 1: make sure we have creds // | ||
///////////////////////////////////// | ||
let stored = creds.read(req.url.host); | ||
|
||
let login = null; | ||
let key = null; | ||
|
||
if (stored === null || app.optionKeyDown) { | ||
let credsForm = new Form(); | ||
credsForm.addField(new Form.Field.String("login", "Login")); | ||
credsForm.addField(new Form.Field.Password("key", "API Key")); | ||
|
||
await credsForm.show("Let's set up: we need your GitHub username and an API key with the\n`repo` permission to pull issues from your assigned repos.\n\nCreate this at https://github.com/settings/tokens\n\nYou can get back here in the future to rotate tokens by holding\noption while activating the workflow.", "Save Key"); | ||
login = (credsForm.values as { login: string }).login; | ||
key = (credsForm.values as { key: string }).key; | ||
|
||
creds.write(req.url.host, login, key); | ||
} else { | ||
login = stored.user; | ||
key = stored.password; | ||
} | ||
|
||
//////////////////////////// | ||
// Step 2: get the issues // | ||
//////////////////////////// | ||
req.method = "POST"; | ||
req.bodyString = `{"query":"{ search(type: ISSUE, query: \\"is:issue assignee:${login} state:open\\", last: 100) { nodes { ... on Issue { number title body url repository { name owner { login } } } } } }"}`; | ||
req.headers = { | ||
"Content-Type": "application/json", | ||
"Authorization": `bearer ${key}`, | ||
}; | ||
|
||
let resp = await (req.fetch().catch((err) => { | ||
console.error("Problem fetching issues:", err); | ||
let alert = new Alert("Problem fetching from GitHub", err); | ||
alert.show(); | ||
throw err; | ||
})); | ||
|
||
if (resp.bodyString === null) { | ||
throw "body string was null. Did the request succeed?" | ||
} | ||
|
||
let body = JSON.parse(resp.bodyString); | ||
|
||
////////////////////////////////// | ||
// Step 3: make the tasks in OF // | ||
////////////////////////////////// | ||
type Issue = { | ||
number: number, | ||
title: string, | ||
body: string, | ||
url: string, | ||
repository: { | ||
name: string, | ||
owner: { | ||
login: string, | ||
}, | ||
}, | ||
}; | ||
|
||
let toFocus: Array<Project> = []; | ||
for (let issue of body.data.search.nodes as Issue[]) { | ||
let gitHubTag = flattenedTags.byName("from GitHub") || new Tag("from GitHub"); | ||
let orgTag = gitHubTag.tagNamed(issue.repository.owner.login) || new Tag(issue.repository.owner.login, gitHubTag); | ||
let repoTag = orgTag.tagNamed(issue.repository.name) || new Tag(issue.repository.name, orgTag); | ||
|
||
let repo = `${issue.repository.owner.login}/${issue.repository.name}`; | ||
let projectName = `${repo}#${issue.number}: ${issue.title}`; | ||
let project = flattenedProjects.byName(projectName) || new Project(projectName); | ||
project.addTag(repoTag); | ||
project.note = `${issue.url}\n\n---\n\n${issue.body}`; | ||
toFocus.push(project); | ||
|
||
if (project.tasks.length === 0) { | ||
new Task(`what needs to be done for ${repo}#${issue.number}`, project); | ||
} | ||
} | ||
|
||
if (app.platformName === "macOS") { | ||
document.windows[0].perspective = Perspective.BuiltIn.Projects; | ||
document.windows[0].focus = toFocus as SectionArray; | ||
} | ||
} catch (err) { | ||
console.error(err); | ||
throw err; | ||
} | ||
}); | ||
|
||
return action; | ||
})(); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"author": "Brian Hicks", | ||
"identifier": "zone.bytes.github", | ||
"defaultLocale": "en", | ||
"version": "1.0", | ||
"description": "Work with GitHub from OmniFocus", | ||
"actions": [ | ||
{ | ||
"image": "icon.png", | ||
"identifier": "pull" | ||
} | ||
] | ||
} |