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 }