1
votes

When creating a new repo using the GitHub API with Apps Script, I'm getting response code 404 with the error:

{"message":"Not Found","documentation_url":"https://developer.github.com/v3"}

The token ID that I'm using works for creating a new file, so I know that the token ID is valid. Also, the user ID that I'm using works for creating a new file with some other Apps Script code.

The documentation gives a url ending of:

POST /user/repos

I'm assuming that "user" needs to be replaced with the user name, and "repos" needs to be replaced with what the new repo name will be.

The url that I'm trying is:

https://api.github.com/blueprinter/AAA_NewRepo

I've also tried the url:

https://api.github.com/blueprinter/repos/AAA_NewRepo

I've also tried adding a name key to the options object:

name:po.repoName

I've also tried adding a payload with an object with a name key to the stringify payload object:

  data = {
    name:po.repoName
  }

  payload = JSON.stringify(data);

  options = {
    method: 'post',
    muteHttpExceptions: true,
    contentType: "application/json",
    headers: {
      Authorization: "Bearer " + myToken
    },
    responseType: 'json',
    payload:payload
  }

The code:

function createNewRepo_(po) {
try{
  var data,myToken,options,payload,rslt,rspnsCode,apiBaseUrl,url;

  /*
    https://developer.github.com/v3/repos/#create
    POST /user/repos - 

    po.userName - The user name in the GitHub account
    po.repoName - The name of the repository to put the file into
  */

  //Logger.log('po: ' + JSON.stringify(po))

  apiBaseUrl = 'https://api.github.com';//Every url must have this at the beginning

  if (!po.userName) {
    po.userName = getMyGitHubInfo_('userName');  
  }

  url = apiBaseUrl + "/" + po.userName + "/" + po.repoName;
  Logger.log('url 23: ' + url)

  myToken = getGitHubToken();

  payload = JSON.stringify(data);

  options = {
    method: 'post',
    muteHttpExceptions: true,
    contentType: "application/json",
    headers: {
      Authorization: "Bearer " + myToken
    },
    responseType: 'json'
  }

  //Logger.log('options 39: ' + JSON.stringify(options))

  rslt = UrlFetchApp.fetch(url,options);

  rspnsCode = rslt.getResponseCode();
  Logger.log('rspnsCode 44: ' + rspnsCode)

  if (rspnsCode !== 200 && rspnsCode !== 201) {
    throw new Error('Response coming back from GitHub is: ' + rspnsCode + "\n\n" + rslt.getContentText());
  }

  Logger.log('rslt.getContentText(): ' + rslt.getContentText())
  Logger.log('typeof rslt: ' + typeof rslt)

  data = JSON.parse(rslt);//Even though the returned value is an object it must be parsed into JSON

  Logger.log('data' + JSON.stringify(data))
}catch(e) {
  Logger.log("Error: " + e.message + "\nStack: " + e.stack)
  //errorHandling(e);//Run centralized error handling function
  return false;
}
}

function getMyGitHubInfo_(k) {
  var o;

  o = {
    userName:'git_hub_user_ID_Here',//Your user name
  }

  if (k) {
    return o[k];
  } else {
    return o;
  }
}
1
Have you tried just POST /user/repos?(no replacement). Also, show how you get the access token. - TheMaster
I think that @TheMaster 's comment is correct. When your above sample script of options is used, please request using UrlFetchApp.fetch("https://api.github.com/user/repos", options). Ref In this case, please add repo to the scopes. Please be careful this. - Tanaike
@TheMaster The access token can be retrieved by developer.github.com/apps/building-oauth-apps/… - Tanaike
I just tried /user/repos without replacing anything in the url, but then created an object with a name key, and a value of the new repo name, then stringified the object and added it as the payload, and it worked. So, I was using the wrong url. I shouldn't have been trying to replace user with the user ID, or repos with the repo name. That url isn't meant to be modified, which I didn't understand. About the only thing left was adding the repo name in the payload, so I finally figured that out. - Alan Wells

1 Answers

2
votes

The problem is on the url endpoint, should be always https://api.github.com/user/repos for creating repositories.

I've build a simplified example to show how to create a repository using AppsScript and Github API:

function createNewRepo() {
  try {
  apiBaseUrl = 'https://api.github.com/user/repos';
  options = {
    method: 'post',
    muteHttpExceptions: true,
    contentType: "application/json",
    headers: {
      Authorization: "Bearer " +  getService().getAccessToken(),
    },
    responseType: 'json',
    payload: JSON.stringify({
      "name": "Hellosssss-World",
      "description": "This is your first repository",
      "homepage": "https://github.com",
      "private": false,
      "has_issues": true,
      "has_projects": true,
      "has_wiki": true
    })
  }
  var response = UrlFetchApp.fetch(apiBaseUrl,options);
  var responseCode = response.getResponseCode();
  data = JSON.parse(response);//Even though the returned value is an object it must be parsed into JSON

  if (responseCode !== 200 && responseCode !== 201) {
    throw new Error('Response coming back from GitHub is: ' + responseCode + "\n\n" + response.getContentText());
  }
    else {
      Logger.log('A new repository was succesfully created');
      Logger.log('Name: ' + data.name);
      Logger.log('Url: ' + data.url);
    }
  }
  catch(e) {
  Logger.log("Error: " + e.message + "\nStack: " + e.stack)
  //errorHandling(e);//Run centralized error handling function
  }
}

But to run this function you have to be authenticated, to do it so, we can use this code sample to get authenticated on Github using AppsScript, again, use this code in your AppsScript project:

var CLIENT_ID = 'YOUR_CLIENT_ID';
var CLIENT_SECRET = 'YOUR_CLIENT_SECRET_ID';

/**
 * Authorizes and makes a request to the GitHub API.
 */
function OauthGitHub() {
  var service = getService();
  if (service.hasAccess()) {
    var url = 'https://api.github.com/user/repos';
    var response = UrlFetchApp.fetch(url, {
      headers: {
        Authorization: 'Bearer ' + service.getAccessToken()
      }
    });
    var result = JSON.parse(response.getContentText());
    Logger.log(JSON.stringify(result, null, 2));
  } else {
    var authorizationUrl = service.getAuthorizationUrl();
    Logger.log('Open the following URL and re-run the script: %s',
        authorizationUrl);
  }
}

/**
 * Reset the authorization state, so that it can be re-tested.
 */
function reset() {
  getService().reset();
}

/**
 * Configures the service.
 */
function getService() {
  return OAuth2.createService('GitHub')
      // Set the endpoint URLs.
      .setAuthorizationBaseUrl('https://github.com/login/oauth/authorize')
      .setTokenUrl('https://github.com/login/oauth/access_token')

      // Set the client ID and secret.
      .setClientId(CLIENT_ID)
      .setClientSecret(CLIENT_SECRET)

      // Set the name of the callback function that should be invoked to
      // complete the OAuth flow.
      .setCallbackFunction('authCallback')

      // Set the property store where authorized tokens should be persisted.
      .setPropertyStore(PropertiesService.getUserProperties())
      .setScope('repo');

}

/**
 * Handles the OAuth callback.
 */
function authCallback(request) {
  var service = getService();
  var authorized = service.handleCallback(request);
  if (authorized) {
    return HtmlService.createHtmlOutput('Success!');
  } else {
    return HtmlService.createHtmlOutput('Denied.');
  }
}

/**
 * Logs the redict URI to register.
 */
function logRedirectUri() {
  Logger.log(OAuth2.getRedirectUri());
}

Remember that you have to add the Oauth library to your project:

  1. Click on the menu item "Resources > Libraries..."
  2. In the "Find a Library" text box
  3. Enter the script ID 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF and click the "Select" button.
  4. Choose a version in the dropdown box (usually best to pick the latest version).
  5. Click the "Save" button.

And now you need to authorize your application on Github and add your keys to the above code.

Now you are ready: - Run the OauthGitHub() function - Check the logs, you'll find a url to log-in on Github, paste it to your browser and log-in - Your credentials will be stored on your AppScript project so you do not have to repeat this process.

Now you can run createNewRepo() and start creating Github repos like a demon or build new apps script functions using any other endpoint of the Github API.

Good luck out there.