@lamantin/fastpush
Version:
Typed fastlane frontend for pushing builds to store
147 lines (125 loc) • 4.73 kB
text/typescript
import shell from 'shelljs'
import { FastpushResult } from './cli/fastpush'
import { Hooks } from './cli/hooks'
import { assertPlatforms, Version } from './cli/utils'
import { ios } from './fastlane'
import { android, gradle, GradleArgs, supply } from './fastlane/android'
import { gym } from './fastlane/ios/gym'
import { match } from './fastlane/ios/match'
import { pilot } from './fastlane/ios/pilot'
import { incrementPackageJson } from './utils/increment/incrementPackageJson'
import { IOSPlatform, Platform, PlatformActions, platformTypes } from './utils/platform'
import { AndroidPlatform } from './utils/platform/AndroidPlatform'
import { ui } from './ui'
import { env } from './utils'
import { git } from './utils/git/git'
export const defaultHooks: Hooks = {
onFinish: null,
onStart: async (options: FastpushResult) => {
if (options.env) {
if (!options.silent) {
ui.message('Add environment file:' + options.env)
}
env.add(options.env)
}
if (options.silent) {
// don't assert clean
// don't assert environment
} else {
await git.assertClean()
await env.assert()
}
},
provideAndroidLanes: (options: FastpushResult) => {
const buildPayload: GradleArgs = {
build_type: 'Release',
}
if (options.flavor) {
// const flavorCapitalized = options.flavor.charAt(0).toUpperCase() + options.flavor.substring(1)
buildPayload.flavor = options.flavor
}
return [
gradle('clean'),
// todo: validate GradleArgTask
gradle(options.build, buildPayload),
supply({
track: options.track,
skip_upload_changelogs: options.skip,
skip_upload_images: options.skip,
skip_upload_metadata: options.skip,
skip_upload_screenshots: options.skip,
}),
]
},
provideIOSLanes: (options: FastpushResult) => {
return [
match('appstore'),
gym({ clean: true, scheme: options.scheme }),
pilot({ skip_waiting_for_build_processing: true, skip_submission: true }),
]
},
onPostPublish: async (platform: PlatformActions, versions: [Version, Version], buildNumbers: [number, number]) => {
const [oldVersion, version] = versions
const [oldBuild, build] = buildNumbers
const tag = `${platform.type}/${version}-${build}`
const whoami = process.env.USER || ''
git.commit(`Up version ${tag}`)
git.tag(tag, `Up version by ${whoami}`)
git.push()
},
}
export async function publish(options: FastpushResult, passedHooks?: Hooks) {
ui.success('==fastpush==')
ui.success('Setup for project: ' + options.project)
shell.cd(options.project)
// child_process.execSync('cd ' + options.project)
const hooks = {
...defaultHooks,
...passedHooks,
}
await hooks.onStart?.(options)
let platforms: Platform[] = []
if (options.android) {
platforms.push('android')
}
if (options.ios) {
platforms.push('ios')
}
ui.success(`Publishing for: [${platforms.join(', ')}]`)
try {
if (options.silent) {
// don't apply changes to platforms
if (!platforms || platforms.length <= 0) {
throw 'You should specify at least 1 platform for processing: ' + platformTypes
}
} else {
platforms = await assertPlatforms(platforms)
}
const [oldVersion, newVersion] = await incrementPackageJson(options.increment, `${options.project}/package.json`)
ui.success(`Up package.json version from [${oldVersion}] -> [${newVersion}]`)
if (platforms.includes('android')) {
const androidPlatform = new AndroidPlatform(options.project)
await distribute(options, androidPlatform, newVersion, hooks)
}
if (platforms.includes('ios')) {
await distribute(options, new IOSPlatform(options.project), newVersion, hooks)
}
await hooks.onFinish?.()
} catch (e) {
await hooks.onError?.(e)
}
}
async function distribute(options: FastpushResult, platform: PlatformActions, version: Version, hooks: Hooks) {
const [oldBuildNumber, newBuildNumber] = await platform.incrementBuildNumber()
ui.success(`Update ${platform.type} versionCode [${oldBuildNumber}] -> [${newBuildNumber}]`)
const [oldVersion, newVersion] = await platform.setVersionName(version)
ui.success(`Update ${platform.type} versionName [${oldVersion}] -> [${newVersion}]`)
if (platform.type === 'ios') {
await ios(hooks.provideIOSLanes(options), options.project)
} else if (platform.type === 'android') {
await android(hooks.provideAndroidLanes(options), options.project)
} else {
throw `Unexpected platform type ${platform.type}`
}
await hooks.onPostPublish?.(platform, [oldVersion, newVersion], [oldBuildNumber, newBuildNumber])
}