Let It Go

This commit is contained in:
Alexey Igrychev
2020-05-25 14:27:28 +01:00
commit fe3767b155
34 changed files with 199960 additions and 0 deletions

34
src/build-and-publish.ts Normal file
View File

@@ -0,0 +1,34 @@
import * as core from '@actions/core'
import {Manager} from './manager'
import {
ProcessGitHubContext,
SetupKubeConfig,
ValidateWerfVersion
} from './common'
async function run(): Promise<void> {
try {
ProcessGitHubContext()
const kubeConfigBase64Data = core.getInput('kube-config-base64-data')
if (kubeConfigBase64Data !== '') {
SetupKubeConfig(kubeConfigBase64Data)
}
const m = new Manager()
await m.Install()
const versionOutput = await m.GetOutput(['version'])
ValidateWerfVersion(versionOutput)
process.env.GITHUB_TOKEN =
process.env.GITHUB_TOKEN || core.getInput('github-token')
await m.PerformCIEnv()
await m.Exec(['build-and-publish'])
} catch (error) {
core.setFailed(error.message)
}
}
run()

33
src/cleanup.ts Normal file
View File

@@ -0,0 +1,33 @@
import * as core from '@actions/core'
import {Manager} from './manager'
import {
ProcessGitHubContext,
SetupKubeConfig,
ValidateWerfVersion
} from './common'
async function run(): Promise<void> {
try {
ProcessGitHubContext()
const kubeConfigBase64Data = core.getInput('kube-config-base64-data')
if (kubeConfigBase64Data !== '') {
SetupKubeConfig(kubeConfigBase64Data)
}
const m = new Manager()
await m.Install()
const versionOutput = await m.GetOutput(['version'])
ValidateWerfVersion(versionOutput)
process.env.GITHUB_TOKEN = core.getInput('github-token')
await m.PerformCIEnv()
await m.Exec(['cleanup'])
} catch (error) {
core.setFailed(error.message)
}
}
run()

53
src/common.ts Normal file
View File

@@ -0,0 +1,53 @@
import * as core from '@actions/core'
import * as tmp from 'tmp'
import * as fs from 'fs'
import * as semver from 'semver'
import {context} from '@actions/github'
import {String} from 'typescript-string-operations'
const minimalWerfVersion = 'v1.1.17'
export async function SetupKubeConfig(
kubeConfigBase64Data: string
): Promise<void> {
const tmpFile = tmp.fileSync({keep: true})
const buf = Buffer.from(kubeConfigBase64Data, 'base64').toString('ascii')
fs.writeFileSync(tmpFile.name, buf)
process.env.KUBECONFIG = tmpFile.name
core.exportVariable('KUBECONFIG', tmpFile.name)
}
export function ProcessGitHubContext(): void {
if (context.eventName === 'pull_request') {
if (context.payload.pull_request) {
const baseSha = context.payload.pull_request.base.sha
const headSha = context.payload.pull_request.head.sha
process.env.WERF_VIRTUAL_MERGE = '1'
process.env.WERF_VIRTUAL_MERGE_FROM_COMMIT = headSha
process.env.WERF_VIRTUAL_MERGE_INTO_COMMIT = baseSha
core.exportVariable('WERF_VIRTUAL_MERGE', '1')
core.exportVariable('WERF_VIRTUAL_MERGE_FROM_COMMIT', headSha)
core.exportVariable('WERF_VIRTUAL_MERGE_INTO_COMMIT', baseSha)
}
}
}
export function ValidateWerfVersion(version: string): void {
const ver = semver.coerce(version)
if (ver) {
if (semver.gte(ver, minimalWerfVersion)) {
return
}
}
throw new Error(
String.Format(
'werf version {0} is not supported (expected version should be equal or lower than {1})',
version.trim(),
minimalWerfVersion
)
)
}

35
src/converge.ts Normal file
View File

@@ -0,0 +1,35 @@
import * as core from '@actions/core'
import {Manager} from './manager'
import {
ProcessGitHubContext,
SetupKubeConfig,
ValidateWerfVersion
} from './common'
async function run(): Promise<void> {
try {
ProcessGitHubContext()
const kubeConfigBase64Data = core.getInput('kube-config-base64-data')
if (kubeConfigBase64Data !== '') {
SetupKubeConfig(kubeConfigBase64Data)
}
const m = new Manager()
await m.Install()
const versionOutput = await m.GetOutput(['version'])
ValidateWerfVersion(versionOutput)
process.env.GITHUB_TOKEN =
process.env.GITHUB_TOKEN || core.getInput('github-token')
await m.PerformCIEnv()
process.env.WERF_ENV = core.getInput('env')
await m.Exec(['converge'])
} catch (error) {
core.setFailed(error.message)
}
}
run()

35
src/deploy.ts Normal file
View File

@@ -0,0 +1,35 @@
import * as core from '@actions/core'
import {Manager} from './manager'
import {
ProcessGitHubContext,
SetupKubeConfig,
ValidateWerfVersion
} from './common'
async function run(): Promise<void> {
try {
ProcessGitHubContext()
const kubeConfigBase64Data = core.getInput('kube-config-base64-data')
if (kubeConfigBase64Data !== '') {
SetupKubeConfig(kubeConfigBase64Data)
}
const m = new Manager()
await m.Install()
const versionOutput = await m.GetOutput(['version'])
ValidateWerfVersion(versionOutput)
process.env.GITHUB_TOKEN =
process.env.GITHUB_TOKEN || core.getInput('github-token')
await m.PerformCIEnv()
process.env.WERF_ENV = core.getInput('env')
await m.Exec(['deploy'])
} catch (error) {
core.setFailed(error.message)
}
}
run()

13
src/install.ts Normal file
View File

@@ -0,0 +1,13 @@
import * as core from '@actions/core'
import {Manager} from './manager'
async function run(): Promise<void> {
try {
const m = new Manager()
await m.Install()
} catch (error) {
core.setFailed(error.message)
}
}
run()

168
src/manager.ts Normal file
View File

@@ -0,0 +1,168 @@
import * as core from '@actions/core'
import * as exec from '@actions/exec'
import * as cache from '@actions/tool-cache'
import * as path from 'path'
import * as io from '@actions/io'
import * as request from 'superagent'
import * as fs from 'fs'
import {String} from 'typescript-string-operations'
import * as crypto from 'crypto'
import * as tmp from 'tmp'
import * as dotenv from 'dotenv'
const WERF_API_GET_CHANNEL_VERSION_URL_METHOD =
'https://werf.io/api/getChannelVersionURL'
const WERF_API_GET_VERSION_URL_METHOD = 'https://werf.io/api/getVersionURL'
export class Manager {
private readonly group: string
private readonly channel: string
private readonly version: string
private readonly os: string
private readonly arch: string
private binaryPath: string | undefined
constructor() {
this.group = core.getInput('group').trim()
this.channel = core.getInput('channel').trim()
this.version = core.getInput('version').trim()
if (process.platform.toString() === 'win32') {
this.os = 'windows'
} else {
this.os = process.platform.toString()
}
this.arch = process.arch
}
public async Install(): Promise<void> {
const actualBinaryUrl = await this._getActualBinaryUrl()
const cachedPath = cache.find(
'werf',
Manager._toolVersionCacheID(actualBinaryUrl)
)
if (cachedPath) {
this.binaryPath = path.join(cachedPath, 'werf')
} else {
this.binaryPath = await this._downloadAndCache(actualBinaryUrl)
}
const binaryDirPath = path.parse(this.binaryPath).dir
core.addPath(binaryDirPath)
}
public async PerformCIEnv(): Promise<void> {
const tmpFile = tmp.fileSync()
const tmpFilePath = tmpFile.name
await this.Exec(['ci-env', 'github', '--as-env-file', '-o', tmpFilePath])
dotenv.config({path: tmpFilePath})
tmpFile.removeCallback()
}
public async Exec(
args: string[],
options?: exec.ExecOptions | undefined
): Promise<void> {
if (!this.binaryPath) {
core.setFailed('runtime error: werf binary is not found')
process.exit(1)
}
await exec.exec(this.binaryPath, args, options)
}
public async GetOutput(args: string[]): Promise<string> {
let stdOut = ''
const options = {
windowsVerbatimArguments: false,
listeners: {
stdout: (data: Buffer) => {
stdOut += data.toString()
}
}
}
await this.Exec(args, options)
return stdOut
}
private async _getActualBinaryUrl(): Promise<string> {
try {
let url: string
let query: {}
if (this.version !== '') {
url = WERF_API_GET_VERSION_URL_METHOD
query = {
version: this.version,
os: this.os,
arch: this.arch
}
} else {
url = WERF_API_GET_CHANNEL_VERSION_URL_METHOD
query = {
group: this.group,
channel: this.channel,
os: this.os,
arch: this.arch
}
}
const resp = await request.get(url).query(query)
return resp.body.data.toString()
} catch (err) {
if (err.response && err.response.error) {
let errMessage = err.response.error.message
if (err.response.text) {
errMessage = String.Format('{0}\n{1}', errMessage, err.response.text)
}
throw Error(errMessage)
}
throw Error(err)
}
}
private async _downloadAndCache(binaryUrl: string): Promise<string> {
const downloadedBinaryPath = await cache.downloadTool(binaryUrl)
const parsedDownloadedBinaryPath = path.parse(downloadedBinaryPath)
const cacheDownloadToolDir = parsedDownloadedBinaryPath.dir
const tmpWerfVersionBinaryPath = path.join(cacheDownloadToolDir, 'werf.tmp')
const werfVersionDir = path.join(
cacheDownloadToolDir,
parsedDownloadedBinaryPath.name
)
const werfVersionBinaryPath = path.join(
werfVersionDir,
String.Format('werf{0}', parsedDownloadedBinaryPath.ext)
)
// werf-x.x.x -> werf.tmp
// werf.tmp -> werf-x.x.x/werf
await io.mv(downloadedBinaryPath, tmpWerfVersionBinaryPath)
await io.mkdirP(werfVersionDir)
await io.mv(tmpWerfVersionBinaryPath, werfVersionBinaryPath)
if (this.os !== 'windows') {
fs.chmodSync(werfVersionBinaryPath, 0o755)
}
await cache.cacheDir(
werfVersionDir,
'werf',
Manager._toolVersionCacheID(binaryUrl)
)
return werfVersionBinaryPath
}
private static _toolVersionCacheID(binaryUrl: string): string {
const md5sum = crypto.createHash('md5')
return md5sum.update(binaryUrl).digest('hex').toString()
}
}