Skip to content

Instantly share code, notes, and snippets.

@retyui
Last active Aug 26, 2018
Embed
What would you like to do?
React Native auto deploy your application to Google Drive
yarn add fs-extra googleapis@33 mime-types shelljs

deploy.js

'use strict';

const { resolve } = require('path');

const { shareAnyone, upload } = require('./Drive');
const { exec } = require('./shell');
const { getCurrentBranch } = require('./utils');

(async function MAIN() {
  try {
    const hash = (await exec('git rev-parse --verify HEAD')).substr(0, 6);
    const branch = getCurrentBranch(await exec('git branch'));
    const fileNameOnDrive = `esentai (${branch}|${hash}).apk`;

    console.log('Upload ...');
    console.time(`Upload end ${fileNameOnDrive}`);

    const { data } = await upload(
      resolve(
        __dirname,
        '../android/app/build/outputs/apk/release/app-release.apk',
      ),
      fileNameOnDrive,
    );

    console.timeEnd(`Upload end ${fileNameOnDrive}`);

    await shareAnyone(data.id);

    console.log(' --- Download link:', data.webContentLink);
  } catch (e) {
    console.log('\n\n\n --- Error: \n\n\n');
    console.error(e.errors ? e.errors : e);
  }
})();

auth.js

'use strict';

const { writeJson, readJson } = require('fs-extra');
const { google } = require('googleapis');
const { createInterface } = require('readline');
const crypto = require('crypto');

const SCOPES = ['https://www.googleapis.com/auth/drive'];
const TOKEN_PATH = `token-${crypto
  .createHash('md5')
  .update(SCOPES.toString())
  .digest('hex')}.json`;

const getAccessToken = oAuth2Client => {
  const authUrl = oAuth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES,
  });

  console.log('Authorize this app by visiting this url:', authUrl);

  const rl = createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  return new Promise((res, rej) => {
    rl.question('Enter the code from that page here: ', code => {
      rl.close();
      oAuth2Client.getToken(code, async (err, token) => {
        if (err) {
          console.error('Error retrieving access token', err);

          rej(err);
        }

        oAuth2Client.setCredentials(token);

        // Store the token to disk for later program executions
        try {
          await writeJson(TOKEN_PATH, token);

          console.log('Token stored to', TOKEN_PATH);
        } catch (error) {
          console.error(error);
          rej(error);
        }

        res(oAuth2Client);
      });
    });
  });
};

let credentials;

try {
  credentials = require('./credentials.json');
} catch (e) {
  // Authorize a client with credentials, then call the Google Drive API.
  return console.log('Error loading client secret file:', e);
}

const authorize = async () => {
  const { client_secret, client_id, redirect_uris } = credentials.installed;
  const oAuth2Client = new google.auth.OAuth2(
    client_id,
    client_secret,
    redirect_uris[0],
  );

  try {
    const token = await readJson(TOKEN_PATH);

    oAuth2Client.setCredentials(token);

    return oAuth2Client;
  } catch (e) {
    await getAccessToken(oAuth2Client);

    return oAuth2Client;
  }
};

module.exports = authorize;

Drive.js

'use strict';

const fs = require('fs');
const mime = require('mime-types');
const { google } = require('googleapis');

const authorize = require('./auth');

const getDrive = async () =>
  google.drive({ version: 'v3', auth: await authorize() });

const shareAnyone = async fileId => {
  const drive = await getDrive();

  return drive.permissions.create({
    fileId,
    requestBody: {
      type: 'anyone',
      role: 'reader',
    },
  });
};

const upload = async (filePath, name) => {
  const fileMetadata = {
    name,
  };

  const media = {
    mimeType: mime.lookup(filePath),
    body: fs.createReadStream(filePath),
  };

  const drive = await getDrive();
  // const fileSize = fs.statSync(filePath).size;

  return drive.files.create(
    {
      resource: fileMetadata,
      media,
      fields: '*',
    },
    /*{
      onUploadProgress: evt => {
        const progress = (evt.bytesRead / fileSize) * 100;

        process.stdout.clearLine();
        process.stdout.cursorTo(0);
        process.stdout.write(`${Math.round(progress)}% complete`);
      },
    },*/
  );
};

module.exports = {
  getDrive,
  shareAnyone,
  upload,
};

shell.js

'use strict';

const shell = require('shelljs');

const exec = (command, options = { silent: true }) =>
  new Promise((res, rej) => {
    shell.exec(command, options, (code, stdout, stderr) => {
      if (code !== 0) {
        rej(stderr);
      }

      res(stdout);
    });
  });

module.exports = {
  exec,
};

utils.js

'use strict';

const getCurrentBranch = gitBranchOutput => {
  const currentBr = gitBranchOutput.split('\n').find(e => /^\*\s/.test(e));

  if (currentBr) {
    return currentBr.replace('* ', '').replace('\n', '');
  }

  throw new Error(`Invalid output: ${gitBranchOutput}`);
};

module.exports = {
  getCurrentBranch,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment