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.

96 lines
2.8 KiB
TypeScript

import type { Deploy, GitDeploy, GitRef, ShellDeploy } from '@/config'
import type { DeployFunction, Job, JobBase } from '@/jobs'
import path from 'path'
import { exists, normalizeURL, sleep } from '@/lib/utils'
import { type Runner } 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(runner: Runner, deploy: Deploy & { url: string; ref: GitRef }) {
const repoDir = getDeployDirectory(deploy)
if (await exists(repoDir)) {
await runner.command(`git -C "${repoDir}" pull`, {
silent: true,
})
} else {
await runner.command(`mkdir -p "${repoDir}"`, {
silent: true,
})
await runner.command(`git clone "${normalizeURL(deploy.url)}" "${repoDir}"`, {
silent: true,
})
}
if (deploy.ref.type !== 'default') {
await runner.command(`git -C "${repoDir}" checkout "${deploy.ref.value}"`, {
silent: true,
})
}
}
export async function shellRunner(runner: Runner, deploy: ShellDeploy) {
await cloneOrUpdateRepo(runner, deploy)
const repoDir = getDeployDirectory(deploy)
const { path, env } = deploy.options
await runner.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')
)
}
export function createDeployJob(deploy: Deploy, submitter: any): [JobBase, DeployFunction] {
return [
{
name: deploy.name,
submitter,
},
async runner => {
debug('[Runner]', `Deploying "${deploy.name}"`)
await sleep(1000)
// TODO: Add other deploy types
if (deploy.type === 'shell') {
await shellRunner(runner, deploy)
} else {
throw new Error(`deploy type "${deploy.type}" not yet implemented`)
}
debug('[Runner]', 'Finished deploy')
},
]
}