semver#Range TypeScript Examples
The following examples show how to use
semver#Range.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.ts From xcodebuild with The Unlicense | 4 votes |
async function main() {
const cwd = core.getInput('working-directory')
if (cwd) {
process.chdir(cwd)
}
const swiftPM = fs.existsSync('Package.swift')
const platform = getPlatformInput('platform')
const selected = await xcselect(
getRangeInput('xcode'),
getRangeInput('swift')
)
const action = getAction(selected, platform)
const configuration = getConfiguration()
const warningsAsErrors = core.getBooleanInput('warnings-as-errors')
const destination = await getDestination(selected, platform)
const identity = getIdentity(core.getInput('code-sign-identity'), platform)
const xcpretty = verbosity() == 'xcpretty'
core.info(`» Selected Xcode ${selected}`)
const reason: string | false = shouldGenerateXcodeproj()
if (reason) {
generateXcodeproj(reason)
}
const apiKey = await getAppStoreConnectApiKey()
await configureKeychain()
await configureProvisioningProfiles()
await build(await getScheme())
if (core.getInput('upload-logs') == 'always') {
await uploadLogs()
}
//// immediate funcs
function getPlatformInput(input: string): Platform | undefined {
const value = core.getInput(input)
if (!value) return undefined
return value as Platform
}
function getRangeInput(input: string): Range | undefined {
const value = core.getInput(input)
if (!value) return undefined
try {
return new Range(value)
} catch (error) {
throw new Error(
`failed to parse semantic version range from '${value}': ${error}`
)
}
}
function shouldGenerateXcodeproj(): string | false {
if (!swiftPM) return false
if (platform == 'watchOS' && semver.lt(selected, '12.5.0')) {
// watchOS prior to 12.4 will fail to `xcodebuild` a SwiftPM project
// failing trying to build the test modules, so we generate a project
return 'Xcode <12.5 fails to build Swift Packages for watchOS if tests exist'
} else if (semver.lt(selected, '11.0.0')) {
return 'Xcode <11 cannot build'
} else if (warningsAsErrors) {
// `build` with SwiftPM projects will build the tests too, and if there are warnings in the
// tests we will then fail to build (it's common that the tests may have ok warnings)
//TODO only do this if there are test targets
return '`warningsAsErrors` is set'
}
return false
}
function generateXcodeproj(reason: string) {
core.startGroup('Generating `.xcodeproj`')
try {
core.info(`Generating \`.xcodeproj\` ∵ ${reason}`)
spawn('swift', ['package', 'generate-xcodeproj'])
} finally {
core.endGroup()
}
}
async function getAppStoreConnectApiKey(): Promise<string[] | undefined> {
const key = core.getInput('authentication-key-base64')
if (!key) return
if (semver.lt(selected, '13.0.0')) {
core.notice(
'Ignoring authentication-key-base64 because it requires Xcode 13 or later.'
)
return
}
const keyId = core.getInput('authentication-key-id')
const keyIssuerId = core.getInput('authentication-key-issuer-id')
if (!keyId || !keyIssuerId) {
throw new Error(
'authentication-key-base64 requires authentication-key-id and authentication-key-issuer-id.'
)
}
// The user should have already stored these as encrypted secrets, but we'll
// be paranoid on their behalf.
core.setSecret(key)
core.setSecret(keyId)
core.setSecret(keyIssuerId)
const keyPath = await createAppStoreConnectApiKeyFile(key)
return [
'-allowProvisioningDeviceRegistration',
'-allowProvisioningUpdates',
'-authenticationKeyPath',
keyPath,
'-authenticationKeyID',
keyId,
'-authenticationKeyIssuerID',
keyIssuerId,
]
}
async function configureKeychain() {
const certificate = core.getInput('code-sign-certificate')
if (!certificate) return
if (process.env.RUNNER_OS != 'macOS') {
throw new Error('code-sign-certificate requires macOS.')
}
const passphrase = core.getInput('code-sign-certificate-passphrase')
if (!passphrase) {
throw new Error(
'code-sign-certificate requires code-sign-certificate-passphrase.'
)
}
await core.group('Configuring code signing', async () => {
await createKeychain(certificate, passphrase)
})
}
async function configureProvisioningProfiles() {
const mobileProfiles = core.getMultilineInput(
'mobile-provisioning-profiles-base64'
)
const profiles = core.getMultilineInput('provisioning-profiles-base64')
if (!mobileProfiles || !profiles) return
await createProvisioningProfiles(profiles, mobileProfiles)
}
async function build(scheme?: string) {
if (warningsAsErrors && actionIsTestable(action)) {
await xcodebuild('build', scheme)
}
await xcodebuild(action, scheme)
}
//// helper funcs
async function xcodebuild(action?: string, scheme?: string) {
if (action === 'none') return
const title = ['xcodebuild', action].filter((x) => x).join(' ')
await core.group(title, async () => {
let args = destination
if (scheme) args = args.concat(['-scheme', scheme])
if (identity) args = args.concat(identity)
if (verbosity() == 'quiet') args.push('-quiet')
if (configuration) args = args.concat(['-configuration', configuration])
if (apiKey) args = args.concat(apiKey)
args = args.concat([
'-resultBundlePath',
`${action ?? 'xcodebuild'}.xcresult`,
])
switch (action) {
case 'build':
if (warningsAsErrors) args.push(warningsAsErrorsFlags)
break
case 'test':
case 'build-for-testing':
if (core.getBooleanInput('code-coverage')) {
args = args.concat(['-enableCodeCoverage', 'YES'])
}
break
}
if (action) args.push(action)
await xcodebuildX(args, xcpretty)
})
}
//NOTE this is not nearly clever enough I think
async function getScheme(): Promise<string | undefined> {
const scheme = core.getInput('scheme')
if (scheme) {
return scheme
}
if (swiftPM) {
return getSchemeFromPackage()
}
}
}
Example #2
Source File: lib.ts From xcodebuild with The Unlicense | 4 votes |
export async function xcselect(xcode?: Range, swift?: Range): Promise<SemVer> {
if (swift) {
return selectSwift(swift)
} else if (xcode) {
return selectXcode(xcode)
}
const gotDotSwiftVersion = dotSwiftVersion()
if (gotDotSwiftVersion) {
core.info(`» \`.swift-version\` » ~> ${gotDotSwiftVersion}`)
return selectSwift(gotDotSwiftVersion)
} else {
// figure out the GHA image default Xcode’s version
const devdir = await exec('xcode-select', ['--print-path'])
const xcodePath = path.dirname(path.dirname(devdir))
const version = await mdls(xcodePath)
if (version) {
return version
} else {
// shouldn’t happen, but this action needs to know the Xcode version
// or we cannot function, this way we are #continuously-resilient
return selectXcode()
}
}
async function selectXcode(range?: Range): Promise<SemVer> {
const rv = (await xcodes())
.filter(([, v]) => (range ? semver.satisfies(v, range) : true))
.sort((a, b) => semver.compare(a[1], b[1]))
.pop()
if (!rv) throw new Error(`No Xcode ~> ${range}`)
spawn('sudo', ['xcode-select', '--switch', rv[0]])
return rv[1]
}
async function selectSwift(range: Range): Promise<SemVer> {
const rv1 = await xcodes()
const rv2 = await Promise.all(rv1.map(swiftVersion))
const rv3 = rv2
.filter(([, , sv]) => semver.satisfies(sv, range))
.sort((a, b) => semver.compare(a[1], b[1]))
.pop()
if (!rv3) throw new Error(`No Xcode with Swift ~> ${range}`)
core.info(`» Selected Swift ${rv3[2]}`)
spawn('sudo', ['xcode-select', '--switch', rv3[0]])
return rv3[1]
async function swiftVersion([DEVELOPER_DIR, xcodeVersion]: [
string,
SemVer
]): Promise<[string, SemVer, SemVer]> {
// This command emits 'swift-driver version: ...' to stderr.
const stdout = await exec(
'swift',
['--version'],
{ DEVELOPER_DIR },
false
)
const matches = stdout.match(/Swift version (.+?)\s/m)
if (!matches || !matches[1])
throw new Error(
`failed to extract Swift version from Xcode ${xcodeVersion}`
)
const version = semver.coerce(matches[1])
if (!version)
throw new Error(
`failed to parse Swift version from Xcode ${xcodeVersion}`
)
return [DEVELOPER_DIR, xcodeVersion, version]
}
}
function dotSwiftVersion(): Range | undefined {
if (!fs.existsSync('.swift-version')) return undefined
const version = fs.readFileSync('.swift-version').toString().trim()
try {
// A .swift-version of '5.0' indicates a SemVer Range of '>=5.0.0 <5.1.0'
return new Range('~' + version)
} catch (error) {
core.warning(
`Failed to parse Swift version from .swift-version: ${error}`
)
}
}
}