Google Pub/Sub Cron Job using Google Apps Script

Jan Krynauw
3 min readSep 13, 2018

--

This is a simple example of how you could use a Trigger in Google App Script (GAS) to launch (i.e. publish) a Pub/Sub message.

We cover the following:

  1. Create a new Google App Script
  2. Setup OAuth2
  3. Create a Service Account to use with the OAuth2
  4. Create a the REST call to Pub/Sub
  5. Setup the Trigger

Create a new Google App Script instance

We’ll use a Google Sheet to host our script. This makes the OAuth2 easier in that we could use a Sheet Sidebar to facilitate the authentication process.

Add the OAuth2 Library to you GAS script

More details on this is available here, but in short add a libary (Resources -> Libraries… ) using the following key:

1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF

Create a new file ( File -> New -> Script File ) and name it say service.gs with the following code:

function getService() {
return OAuth2.createService('MyPubSub')
.setAuthorizationBaseUrl('https://accounts.google.com/o/oauth2/auth')
.setTokenUrl('https://accounts.google.com/o/oauth2/token')
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setCallbackFunction('authCallback')
.setPropertyStore(PropertiesService.getUserProperties())
.setScope(['https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/pubsub','https://www.googleapis.com/auth/script.external_request'])
.setParam('access_type', 'offline')
.setParam('approval_prompt', 'force')
.setParam('login_hint', Session.getActiveUser().getEmail());
}
function authCallback(request) {
var service = getService();
var isAuthorized = service.handleCallback(request);
if (isAuthorized) {
return HtmlService.createHtmlOutput('Success! You can close this tab.');
} else {
return HtmlService.createHtmlOutput('Denied. You can close this tab');
}
}
// Reset the service
function reset() {
var service = getService();
service.reset();
}
var CLIENT_ID = '.....apps.googleusercontent.com';
var CLIENT_SECRET = '....';
/**
* Logs the redirect URI to register.
*/
function logRedirectUri() {
var service = getService();
Logger.log(service.getRedirectUri());
}

Note that the Scope above is set to Pub/Sub as we will be sending a Pub/Sub REST request.

Create a Google Service Account

You need a CLIENT_ID and CLIENT_SECRET for the above.

This is a standard setup on the Google Cloud Console.

Goto the Google Cloud Console Credentials page -> Create credentials -> OAuth client ID -> Web application and ensure you populate the Authorised redirect URIs field with https://script.google.com/macros/d/[SCRIPT_ID]/usercallback where the SCRIPT_ID is specific to your Google App Script ( File -> Project Properties -> Script ID )

If this is the first time you create credentials you will need to setup the OAuth consent screen just follow the prompts.

Create the Pub/Sub Script

Create another script file ( File -> New -> Script file ) and add the following:

function pubsub(project, topic, attr, data) {
var ss = SpreadsheetApp.getActive();
var service = getService();

if (!service.hasAccess()) {
var authorizationUrl = service.getAuthorizationUrl();
var template = HtmlService.createTemplate(
'<a href="<?= authorizationUrl ?>" target="_blank">Authorize</a>. ' +
'Reopen the sidebar when the authorization is complete.');
template.authorizationUrl = authorizationUrl;
var page = template.evaluate();
SpreadsheetApp.getUi().showSidebar(page);

} else {
var url = 'https://pubsub.googleapis.com/v1/projects/[PROJECT]/topics/[TOPIC]:publish'
.replace("[TOPIC]", topic)
.replace("[PROJECT]", project);

// The data attribute is of 'string' type and needs to be base64 Encoded!
var body = {
messages: [
{
attributes: attr,
data: Utilities.base64Encode(data)
}]
};

var response = UrlFetchApp.fetch(url, {
method: "POST",
contentType: 'application/json',
muteHttpExceptions: true,
payload: JSON.stringify(body),
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});

var result = JSON.parse(response.getContentText());
var message = JSON.stringify(result);
return {
log: message
}
} //end of if
}

You could now use a simple trigger to run your Pub/Sub cron job:

Our first trigger has been running for almost 7 years every 5 minutes. :)

--

--