tauri-build/src/build-project.ts
2022-05-10 20:14:27 +02:00

129 lines
3.5 KiB
TypeScript

import {run} from '@tauri-apps/cli'
import {basename, dirname, join, posix, resolve, sep} from 'path'
import glob from 'tiny-glob'
import * as core from '@actions/core'
import {
exec,
ExecOptionsWithStringEncoding,
spawn,
SpawnOptionsWithoutStdio
} from 'child_process'
interface BuildOptions {
runner?: string
projectPath?: string
configPath?: string
debug?: boolean
args?: string[]
target?: string
}
export async function buildProject(options: BuildOptions): Promise<string[]> {
let args: string[] = options.args || []
if (options.configPath) {
args.push('--config', options.configPath)
}
if (options.target) {
args.push('--target', options.target)
}
if (options.projectPath) {
const newCwd = resolve(process.cwd(), options.projectPath)
core.debug(`changing working directory: ${process.cwd()} -> ${newCwd}`)
process.chdir(newCwd)
}
if (options.runner) {
core.info(`running ${options.runner} with args: build ${args.join(' ')}`)
await spawnCmd(options.runner, ['build', ...args])
} else {
core.info(`running builtin runner with args: build ${args.join(' ')}`)
await run(['build', ...args], '')
}
const crateDir = await glob(`./**/Cargo.toml`).then(([manifest]) => join(process.cwd(), dirname(manifest)))
const metaRaw = await execCmd('cargo', ['metadata', '--no-deps', '--format-version', '1'], { cwd: crateDir })
const meta = JSON.parse(metaRaw)
const targetDir = meta.target_directory
const profile = options.debug ? 'debug' : 'release'
const bundleDir = options.target
? join(targetDir, options.target, profile, 'bundle')
: join(targetDir, profile, 'bundle')
const macOSExts = ['app', 'app.tar.gz', 'app.tar.gz.sig', 'dmg']
const linuxExts = [
'AppImage',
'AppImage.tar.gz',
'AppImage.tar.gz.sig',
'deb'
]
const windowsExts = ['msi', 'msi.zip', 'msi.zip.sig']
const artifactsLookupPattern = `${bundleDir}/*/!(linuxdeploy)*.{${[...macOSExts, linuxExts, windowsExts].join(',')}}`
core.debug(`Looking for artifacts using this pattern: ${artifactsLookupPattern}`)
const artifacts = await glob(artifactsLookupPattern, { absolute: true, filesOnly: false })
let i = 0;
for (const artifact of artifacts) {
if (artifact.endsWith('.app') && !artifacts.some(a => a.endsWith('.app.tar.gz'))) {
await execCmd('tar', ['czf', `${artifact}.tar.gz`, '-C', dirname(artifact), basename(artifact)])
artifacts[i] += '.tar.gz'
} else if (artifact.endsWith('.app')) {
// we can't upload a directory
artifacts.splice(i, 1);
}
i++
}
return artifacts
}
async function spawnCmd(
cmd: string,
args: string[],
options: SpawnOptionsWithoutStdio = {}
) {
return new Promise((resolve, reject) => {
const child = spawn(cmd, args, {...options, stdio: ['pipe', 'inherit', 'inherit'], shell: true})
child.on('exit', () => resolve)
child.on('error', error => {
reject(error)
})
if (child.stdin) {
child.stdin.on('error', error => {
reject(error)
})
}
})
}
async function execCmd(
cmd: string,
args: string[],
options: Omit<ExecOptionsWithStringEncoding, 'encoding'> = {}
): Promise<string> {
return new Promise((resolve, reject) => {
exec(
`${cmd} ${args.join(' ')}`,
{...options, encoding: 'utf-8'},
(error, stdout, stderr) => {
if (error) {
console.error(`Failed to execute cmd ${cmd} with args: ${args.join(' ')}. reason: ${error}`);
reject(stderr)
} else {
resolve(stdout)
}
}
)
})
}