|
| 1 | +/* eslint-disable no-template-curly-in-string */ |
| 2 | +import { HTTPError } from 'got' |
| 3 | +import * as yaml from 'js-yaml' |
| 4 | +import { exists, writeFile } from 'mz/fs' |
| 5 | +import { GitHubClient } from './github' |
| 6 | +import { createSourcegraphBotNpmToken } from './npm' |
| 7 | +import * as sodium from 'tweetsodium' |
| 8 | + |
| 9 | +const createGitHubSecret = async ({ |
| 10 | + repoName, |
| 11 | + name, |
| 12 | + value, |
| 13 | + githubClient, |
| 14 | +}: { |
| 15 | + repoName: string |
| 16 | + name: string |
| 17 | + value: string |
| 18 | + githubClient: GitHubClient |
| 19 | +}): Promise<void> => { |
| 20 | + // Get public key for repository |
| 21 | + const { keyId, key } = await githubClient.get<{ keyId: string; key: string }>( |
| 22 | + `repos/sourcegraph/${repoName}/actions/secrets/public-key`, |
| 23 | + { |
| 24 | + responseType: 'json', |
| 25 | + resolveBodyOnly: true, |
| 26 | + } |
| 27 | + ) |
| 28 | + |
| 29 | + // Convert the message and key to Uint8Array's (Buffer implements that interface) |
| 30 | + const messageBytes = Buffer.from(value) |
| 31 | + const keyBytes = Buffer.from(key, 'base64') |
| 32 | + |
| 33 | + // Encrypt using LibSodium. |
| 34 | + const encryptedBytes = sodium.seal(messageBytes, keyBytes) |
| 35 | + |
| 36 | + // Base64 the encrypted secret |
| 37 | + const encryptedValue = Buffer.from(encryptedBytes).toString('base64') |
| 38 | + |
| 39 | + await githubClient.post(`repos/sourcegraph/${repoName}/actions/secrets/${name}`, { |
| 40 | + json: { |
| 41 | + encrypted_value: encryptedValue, |
| 42 | + key_id: keyId, |
| 43 | + }, |
| 44 | + }) |
| 45 | +} |
| 46 | + |
| 47 | +export async function initGitHubWorkflow({ |
| 48 | + hasTests, |
| 49 | + repoName, |
| 50 | + githubClient, |
| 51 | +}: { |
| 52 | + hasTests: boolean |
| 53 | + repoName: string |
| 54 | + githubClient: GitHubClient |
| 55 | +}): Promise<void> { |
| 56 | + console.log('⚙️ Setting up GitHub Actions Workflow') |
| 57 | + if (await exists('.github/workflows/build.yml')) { |
| 58 | + console.log('.github/workflows/build.yml already exists, skipping') |
| 59 | + } else { |
| 60 | + const workflowYaml = { |
| 61 | + name: 'build', |
| 62 | + on: ['push', 'pull_request'], |
| 63 | + env: { |
| 64 | + FORCE_COLOR: 3, |
| 65 | + }, |
| 66 | + jobs: { |
| 67 | + build: { |
| 68 | + 'runs-on': 'ubuntu-latest', |
| 69 | + steps: [ |
| 70 | + { uses: 'actions/checkout@v2' }, |
| 71 | + { |
| 72 | + name: 'Use Node.js', |
| 73 | + uses: 'actions/setup-node@v2', |
| 74 | + with: { |
| 75 | + 'node-version': '14.x', |
| 76 | + }, |
| 77 | + }, |
| 78 | + { run: 'yarn' }, |
| 79 | + { run: 'yarn run prettier-check' }, |
| 80 | + { run: 'yarn run eslint' }, |
| 81 | + { run: 'yarn run build' }, |
| 82 | + ...(hasTests |
| 83 | + ? [ |
| 84 | + { run: 'yarn test' }, |
| 85 | + { run: 'nyc report --reporter json' }, |
| 86 | + { |
| 87 | + name: 'Upload coverage to Codecov', |
| 88 | + uses: 'codecov/codecov-action@v1', |
| 89 | + }, |
| 90 | + ] |
| 91 | + : []), |
| 92 | + { |
| 93 | + name: 'release', |
| 94 | + if: |
| 95 | + "github.repository_owner == 'sourcegraph' && github.event_name == 'push' && github.ref == 'refs/heads/master'", |
| 96 | + run: 'yarn run semantic-release', |
| 97 | + env: { |
| 98 | + GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}', |
| 99 | + NPM_TOKEN: '${{ secrets.NPM_TOKEN }}', |
| 100 | + }, |
| 101 | + }, |
| 102 | + ], |
| 103 | + }, |
| 104 | + }, |
| 105 | + } |
| 106 | + await writeFile('.github/workflows/build.yml', yaml.dump(workflowYaml)) |
| 107 | + } |
| 108 | + |
| 109 | + const secretName = 'NPM_TOKEN' |
| 110 | + try { |
| 111 | + await githubClient.get(`repos/sourcegraph/${repoName}/actions/secrets/${secretName}`, { |
| 112 | + responseType: 'json', |
| 113 | + resolveBodyOnly: true, |
| 114 | + }) |
| 115 | + console.log('🔑 NPM_TOKEN already set in GitHub secrets, skipping creation') |
| 116 | + } catch (error) { |
| 117 | + if (!(error instanceof HTTPError) || error.response.statusCode !== 404) { |
| 118 | + throw error |
| 119 | + } |
| 120 | + const npmToken = await createSourcegraphBotNpmToken() |
| 121 | + console.log('🔑 Setting NPM_TOKEN GitHub secret') |
| 122 | + await createGitHubSecret({ |
| 123 | + repoName, |
| 124 | + name: secretName, |
| 125 | + value: npmToken, |
| 126 | + githubClient, |
| 127 | + }) |
| 128 | + } |
| 129 | +} |
0 commit comments