You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.5 KiB
TypeScript

import type { Deploy, GitDeploy, GitRef, ShellDeploy } from '@/config'
import type { Job, Worker } from '@/jobs'
import path from 'path'
import { exists, normalizeURL, sleep } from '@/lib/utils'
import { runCommand } from '@/runners'
import { debug } from '@/logger'
const toSafePath = (target: string) => {
return '.' + path.posix.normalize('/' + target)
}
function getDeployDirectory(deploy: GitDeploy): string {
const { url, ref } = deploy
const repoSlug = url
.replace(/(^\w+:|^)\/\//, '') // strip protocol
.replace(/[^a-zA-Z]+/g, '-') // only keep letters, other symbols become dashes
.replace(/^\-|\-$/g, '') // remove leading or trailing dashes
const slug =
ref.type === 'default'
? `${deploy.name}_${repoSlug}`
: `${deploy.name}_${repoSlug}@${ref.value}`
return `${import.meta.env.CLONE_PATH ?? `${import.meta.env.DATA_PATH}/clone`}/${slug}`
}
async function cloneOrUpdateRepo(deploy: Deploy & { url: string; ref: GitRef }) {
const repoDir = getDeployDirectory(deploy)
if (await exists(repoDir)) {
await runCommand(`git -C "${repoDir}" pull`)
} else {
await runCommand(`mkdir -p "${repoDir}"`)
await runCommand(`git clone "${normalizeURL(deploy.url)}" "${repoDir}"`)
}
if (deploy.ref.type !== 'default') {
await runCommand(`git -C "${repoDir}" checkout "${deploy.ref.value}"`)
}
}
export async function shellRunner(deploy: ShellDeploy) {
const { path, env } = deploy.options
const repoDir = getDeployDirectory(deploy)
await cloneOrUpdateRepo(deploy)
const script = [
// mode to correct directory
`cd ${repoDir}`,
// append env variables
Object.entries(env ?? {})
.map(([key, value]) => `export ${key}="${value.replace(/"/g, '\\"')}"`)
.join('\n'),
// launch program
toSafePath(path ?? './deploy.sh'),
].join('\n\n')
await runCommand(script)
}
export function createDeployJob(deploy: Deploy, submitter: any): Job & Worker {
return {
name: deploy.name,
submitter,
submittedAt: new Date(),
async work() {
debug('[Runner]', `Deploying "${deploy.name}"`)
await sleep(1000)
// TODO: Add other deploy types
if (deploy.type === 'shell') await shellRunner(deploy)
else {
throw new Error(`deploy type "${deploy.type}" not yet implemented`)
}
debug('[Runner]', 'Finished deploy')
},
}
}