├── README.md └── UpdateLabels.gs /README.md: -------------------------------------------------------------------------------- 1 | # GitHubGmailLabels 2 | This is a Google Apps Script that updates Gmail labels for GitHub notification mails based on their corresponding GitHub issue tracker labels. 3 | 4 | ## Setup 5 | 1. Go to [script.google.com](https://script.google.com). It will automatically create a new script. Paste in this script from UpdateLabels.gs. 6 | 2. Edit the CUSTOM_MAPPING variable to establish a mapping between GitHub issue labels and Gmail labels. 7 | 3. Add the Gmail labels that you want to be marked as important in the MARK_IMPORTANT list. (note these are the Gmail labels and not the GitHub labels) 8 | 4. Set either to use a strict_mode or not, if not using strict_mode: All other labels will be mapped as is under a project label. 9 | 5. (Optional, but recommended) [Create a GitHub access token](https://github.com/settings/tokens/new) and paste its value into the ACCESS_TOKEN variable. This will increase the rate limit on API calls. 10 | 6. Name and save your script. 11 | 7. [Install a time-driven trigger](https://developers.google.com/apps-script/guides/triggers/installable#managing_triggers_manually) by clicking on the clock button, clicking "Click here to add one now", and configuring how often you want the script to run. 12 | 13 | ## Future work 14 | I haven't had time to look at the way apps scripts are published to make this installable, and whether it could be configurable if it was installable. 15 | 16 | I think the same approach could also be used to label mails from crbug and rietveld. 17 | -------------------------------------------------------------------------------- /UpdateLabels.gs: -------------------------------------------------------------------------------- 1 | // To create an access token, go to https://github.com/settings/tokens/new 2 | // You do NOT need any write permissions, public_repo only should be fine. 3 | // This script will sometimes work without an access token, but it may be 4 | // throttled. 5 | var ACCESS_TOKEN = null; 6 | 7 | // Add an entry to this custom mapping for each label you want to see added to 8 | // your Gmail messages. 9 | // Key: github label. 10 | // Value: Gmail label. 11 | // Labels not in this list will automatically be mapped to project/label 12 | // in Gmail 13 | // Custom mapping can also include project names. Gmail will not nest the 14 | // labels under the projects automatically, but if you create a label with 15 | // the project name in Gmail, all labels containig the project name will 16 | // be nested underneath it. 17 | var CUSTOM_MAPPING = { 18 | // 'Project-A/myproject' : 'My Project', 19 | // 'Project-A/myproject/Label A' : 'My Project/Label A', 20 | // 'Project-A/myproject/Label B' : 'labelB', 21 | // 'Project-A/myproject/Label C' : 'My Project/labelC', 22 | }; 23 | 24 | var MARK_IMPORTANT = [ 25 | // 'labelB', 26 | // 'My Project/labelC', 27 | ]; 28 | 29 | // Set this to true to ignore any labels not mentioned in the custom labels. 30 | var strict_mode = false; 31 | 32 | // Returns a Gmail label if one already exists, otherwise creates a new one. 33 | function getOrCreateLabel(labelName) { 34 | var label = GmailApp.getUserLabelByName(labelName); 35 | if (!label) { 36 | label = GmailApp.createLabel(labelName); 37 | } 38 | return label; 39 | } 40 | 41 | // Add a time-driven trigger to run this function as often as you'd like your 42 | // mails to be auto-labeled. Documentation on time-based triggers: 43 | // https://developers.google.com/apps-script/guides/triggers/installable#managing_triggers_manually 44 | function updateNewGithubNotificationThreadLabels() { 45 | // There isn't a built-in way for an apps script to just check all the emails 46 | // since it last ran. So we do a search for GitHub notification mails from the 47 | // last day, and store a property with info about the ones that haven't 48 | // changed. 49 | var threads = GmailApp.search('from:notifications@github.com newer_than:1d'); 50 | var seenThreads = JSON.parse( 51 | PropertiesService.getUserProperties().getProperty('seenThreads') || '{}'); 52 | for (var i = 0; i < threads.length; i++) { 53 | // Check if this thread has been processed before and update the cache. 54 | var threadId = threads[i].getId(); 55 | var threadTime = String(threads[i].getLastMessageDate()); 56 | if (seenThreads[threadId] == threadTime) { 57 | // Already applied labels to this thread, no updates since then. 58 | continue; 59 | } 60 | seenThreads[threadId] = threadTime; 61 | var thread = threads[i]; 62 | 63 | // Parse the thread subject to get the GitHub issue id. 64 | var subject = thread.getFirstMessageSubject(); 65 | var match = subject.match(/.*\(#([\d]+)\)/); 66 | if (match) { 67 | // This thread has an issue id, so it must be about a bug. 68 | var issueId = match[1]; 69 | 70 | // Parse the to: field of the first message to get the GitHub project/repo. 71 | // Unfortunately there is no API for getting a single message so need to 72 | // pull all of them. 73 | var messages = thread.getMessages(); 74 | var project = messages[0].getTo().match(/\"(.*)\" \ -1) 116 | GmailApp.markThreadImportant(thread); 117 | } 118 | } 119 | } 120 | PropertiesService.getUserProperties().setProperty( 121 | 'seenThreads', JSON.stringify(seenThreads)); 122 | } 123 | --------------------------------------------------------------------------------