Skip to content

Commit

Permalink
feat: incorporated SemVer support
Browse files Browse the repository at this point in the history
  • Loading branch information
jbristowe committed May 3, 2022
1 parent 1b210f2 commit eba997b
Showing 1 changed file with 123 additions and 29 deletions.
152 changes: 123 additions & 29 deletions src/octopus-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@ import {
extractZip
} from '@actions/tool-cache'
import {debug, info, setFailed} from '@actions/core'
import {Downloads} from './download'
import {HttpClient} from '@actions/http-client'
import {join, dirname} from 'path'
import {v4} from 'uuid'
import {OctopusCLIVersionFetcher} from './octopusCLIVersionFetcher'

const osPlatform: string = os.platform()
const platform: string =
osPlatform === 'win32' ? 'win' : osPlatform === 'darwin' ? 'osx' : 'linux'
const ext: string = osPlatform === 'win32' ? 'zip' : 'tar.gz'
const octopusTools = `https://download.octopusdeploy.com/octopus-tools`
const latestUrl = `${octopusTools}/latest.json`
const baseUrl = `https://g.octopushq.com/`
const versionsUrl = `${baseUrl}/OctopusCLIVersions`
const latestToolsUrl = `${baseUrl}/LatestTools`
const http: HttpClient = new HttpClient(
'action-install-octopus-cli',
undefined,
Expand All @@ -26,40 +25,128 @@ const http: HttpClient = new HttpClient(
}
)

interface OctopusCliDownload {
interface LatestToolsResponse {
latest: string
downloads: DownloadOption[]
}

type Primitive = undefined | null | boolean | number | string

interface Dictionary {
[key: string]: Primitive
}

type DownloadOption = {
version: string
url: string
template: string
location: string
extension: string
platform?: string
architecture?: string
}

const getLatest = async (): Promise<Downloads | null> => {
return (await http.getJson<Downloads>(latestUrl)).result
export interface Endpoint {
downloadUrl: string
version: string
}

interface VersionsResponse {
versions: string[]
}

const getDownloadUrl = async (version: string): Promise<OctopusCliDownload> => {
let versionToDownload: string = version
if (version === 'latest') {
try {
const downloads: Downloads | null = await getLatest()
if (downloads !== null) {
versionToDownload = downloads.latest
}
} catch (e: unknown) {
if (e instanceof Error) {
setFailed(e)
}
const getVersions = async (): Promise<VersionsResponse | null> => {
return (await http.getJson<VersionsResponse>(versionsUrl)).result
}

const getDownloadUrl = async (versionSpec: string): Promise<Endpoint> => {
if (versionSpec === 'latest') {
versionSpec = '*'
}

const versionsResponse: VersionsResponse | null = await getVersions()
if (versionsResponse === null) {
setFailed(`✕ Unable to get versions...`)
throw new Error(`✕ Unable to get versions...`)
}

let version: string | null = versionSpec
try {
version = new OctopusCLIVersionFetcher(
versionsResponse.versions
).getVersion(versionSpec)
info(`Latest version: ${version}`)
} catch (e: unknown) {
if (e instanceof Error) {
setFailed(e)
}
}

const downloadUrl = `${octopusTools}/${versionToDownload}/OctopusTools.${versionToDownload}.${platform}-x64.${ext}`
if (version === null) {
setFailed(
`✕ The version specified (${version}) is not available to download.`
)
throw new Error(
`✕ The version specified (${version}) is not available to download.`
)
}

debug(`Attempting to find Octopus CLI version ${version}`)

const latestToolsResponse = await http.getJson<LatestToolsResponse>(
latestToolsUrl
)

if (
latestToolsResponse.result === null ||
latestToolsResponse.result === undefined
) {
throw Error(
`Failed to resolve Octopus CLI version ${version}. Endpoint returned ${latestToolsResponse.statusCode} status code.`
)
}

let platform = 'linux'
switch (osPlatform) {
case 'darwin':
platform = 'osx'
break
case 'win32':
platform = 'win'
break
}

let downloadUrl: string | undefined

for (const download of latestToolsResponse.result.downloads) {
if (download.platform === platform) {
const result = {...download, version}
downloadUrl = applyTemplate(result, download.template)
}
}

if (downloadUrl === undefined || downloadUrl === null) {
throw Error(`Failed to resolve endpoint URL to download: ${downloadUrl}`)
}

const statusCode = (await http.head(downloadUrl)).message.statusCode
if (statusCode !== 200) {
setFailed(`✕ Octopus CLI version not found: ${versionToDownload}`)
throw new Error(`Octopus CLI version not found: ${versionToDownload}`)
setFailed(`✕ Octopus CLI version not found: ${version}`)
throw new Error(`Octopus CLI version not found: ${version}`)
}

info(`✓ Octopus CLI version found: ${versionToDownload}`)
return {version: versionToDownload, url: downloadUrl}
info(`✓ Octopus CLI version found: ${version}`)
return {downloadUrl, version}
}

function applyTemplate(dictionary: Dictionary, template: string): string {
return Object.keys(dictionary).reduce(
(result, key) =>
result.replace(
new RegExp(`{${key}}`, 'g'),
dictionary[key] ? String(dictionary[key]) : ''
),
template
)
}

export async function installOctopusCli(version: string): Promise<string> {
Expand All @@ -68,19 +155,26 @@ export async function installOctopusCli(version: string): Promise<string> {
info(`⬇️ Downloading Octopus CLI ${octopusCliDownload.version}...`)
const dest = join(process.env['RUNNER_TEMP'] || '', `${v4()}.${ext}`)
await fs.mkdir(dirname(dest), {recursive: true})
const downloadPath: string = await downloadTool(octopusCliDownload.url, dest)
const downloadPath: string = await downloadTool(
octopusCliDownload.downloadUrl,
dest
)
debug(`Downloaded to ${downloadPath}`)

info(`📦 Extracting Octopus CLI ${octopusCliDownload.version}...`)
let extPath = ''
if (osPlatform === 'win32') {
extPath = await extractZip(downloadPath)
} else if (octopusCliDownload.url.endsWith('.gz')) {
} else if (octopusCliDownload.downloadUrl.endsWith('.gz')) {
extPath = await extractTar(downloadPath)
}
debug(`Extracted to ${extPath}`)

const cachePath: string = await cacheDir(extPath, 'octo', version)
const cachePath: string = await cacheDir(
extPath,
'octo',
octopusCliDownload.version
)
debug(`Cached to ${cachePath}`)

const exePath: string = join(
Expand Down

0 comments on commit eba997b

Please sign in to comment.