/ src / set-tokens.ts
set-tokens.ts
  1  import * as core from '@actions/core';
  2  import * as exec from '@actions/exec';
  3  import * as github from '@actions/github';
  4  import * as io from '@actions/io';
  5  import path from 'path';
  6  import fs from 'fs';
  7  // eslint-disable-next-line @typescript-eslint/no-var-requires
  8  const cpSpawnSync = require('child_process').spawnSync;
  9  // eslint-disable-next-line @typescript-eslint/no-var-requires
 10  const cpexec = require('child_process').execFileSync;
 11  import {Inputs} from './interfaces';
 12  import {getHomeDir} from './utils';
 13  import {getServerUrl} from './git-utils';
 14  
 15  export async function setSSHKey(inps: Inputs, publishRepo: string): Promise<string> {
 16    core.info('[INFO] setup SSH deploy key');
 17  
 18    const homeDir = await getHomeDir();
 19    const sshDir = path.join(homeDir, '.ssh');
 20    await io.mkdirP(sshDir);
 21    await exec.exec('chmod', ['700', sshDir]);
 22  
 23    const knownHosts = path.join(sshDir, 'known_hosts');
 24    // ssh-keyscan -t rsa github.com or serverUrl >> ~/.ssh/known_hosts on Ubuntu
 25    const cmdSSHkeyscanOutput = `\
 26  # ${getServerUrl().host}.com:22 SSH-2.0-babeld-1f0633a6
 27  ${
 28    getServerUrl().host
 29  } ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
 30  `;
 31    fs.writeFileSync(knownHosts, cmdSSHkeyscanOutput + '\n');
 32    core.info(`[INFO] wrote ${knownHosts}`);
 33    await exec.exec('chmod', ['600', knownHosts]);
 34  
 35    const idRSA = path.join(sshDir, 'github');
 36    fs.writeFileSync(idRSA, inps.DeployKey + '\n');
 37    core.info(`[INFO] wrote ${idRSA}`);
 38    await exec.exec('chmod', ['600', idRSA]);
 39  
 40    const sshConfigPath = path.join(sshDir, 'config');
 41    const sshConfigContent = `\
 42  Host ${getServerUrl().host}
 43      HostName ${getServerUrl().host}
 44      IdentityFile ~/.ssh/github
 45      User git
 46  `;
 47    fs.writeFileSync(sshConfigPath, sshConfigContent + '\n');
 48    core.info(`[INFO] wrote ${sshConfigPath}`);
 49    await exec.exec('chmod', ['600', sshConfigPath]);
 50  
 51    if (process.platform === 'win32') {
 52      core.warning(`\
 53  Currently, the deploy_key option is not supported on the windows-latest.
 54  Watch https://github.com/peaceiris/actions-gh-pages/issues/87
 55  `);
 56  
 57      await cpSpawnSync('Start-Process', ['powershell.exe', '-Verb', 'runas']);
 58      await cpSpawnSync('sh', ['-c', '\'eval "$(ssh-agent)"\''], {shell: true});
 59      await exec.exec('sc', ['config', 'ssh-agent', 'start=auto']);
 60      await exec.exec('sc', ['start', 'ssh-agent']);
 61    }
 62    await cpexec('ssh-agent', ['-a', '/tmp/ssh-auth.sock']);
 63    core.exportVariable('SSH_AUTH_SOCK', '/tmp/ssh-auth.sock');
 64    await exec.exec('ssh-add', [idRSA]);
 65  
 66    return `git@${getServerUrl().host}:${publishRepo}.git`;
 67  }
 68  
 69  export function setGithubToken(
 70    githubToken: string,
 71    publishRepo: string,
 72    publishBranch: string,
 73    externalRepository: string,
 74    ref: string,
 75    eventName: string
 76  ): string {
 77    core.info('[INFO] setup GITHUB_TOKEN');
 78  
 79    core.debug(`ref: ${ref}`);
 80    core.debug(`eventName: ${eventName}`);
 81    let isProhibitedBranch = false;
 82  
 83    if (externalRepository) {
 84      throw new Error(`\
 85  The generated GITHUB_TOKEN (github_token) does not support to push to an external repository.
 86  Use deploy_key or personal_token.
 87  `);
 88    }
 89  
 90    if (eventName === 'push') {
 91      isProhibitedBranch = ref.match(new RegExp(`^refs/heads/${publishBranch}$`)) !== null;
 92      if (isProhibitedBranch) {
 93        throw new Error(`\
 94  You deploy from ${publishBranch} to ${publishBranch}
 95  This operation is prohibited to protect your contents
 96  `);
 97      }
 98    }
 99  
100    return `https://x-access-token:${githubToken}@${getServerUrl().host}/${publishRepo}.git`;
101  }
102  
103  export function setPersonalToken(personalToken: string, publishRepo: string): string {
104    core.info('[INFO] setup personal access token');
105    return `https://x-access-token:${personalToken}@${getServerUrl().host}/${publishRepo}.git`;
106  }
107  
108  export function getPublishRepo(externalRepository: string, owner: string, repo: string): string {
109    if (externalRepository) {
110      return externalRepository;
111    }
112    return `${owner}/${repo}`;
113  }
114  
115  export async function setTokens(inps: Inputs): Promise<string> {
116    try {
117      const publishRepo = getPublishRepo(
118        inps.ExternalRepository,
119        github.context.repo.owner,
120        github.context.repo.repo
121      );
122      if (inps.DeployKey) {
123        return setSSHKey(inps, publishRepo);
124      } else if (inps.GithubToken) {
125        const context = github.context;
126        const ref = context.ref;
127        const eventName = context.eventName;
128        return setGithubToken(
129          inps.GithubToken,
130          publishRepo,
131          inps.PublishBranch,
132          inps.ExternalRepository,
133          ref,
134          eventName
135        );
136      } else if (inps.PersonalToken) {
137        return setPersonalToken(inps.PersonalToken, publishRepo);
138      } else {
139        throw new Error('not found deploy key or tokens');
140      }
141    } catch (e) {
142      throw new Error(e.message);
143    }
144  }