Skip to content

Commit 0a0c55a

Browse files
author
Dmytro Bondar
authored
Fix os detection and archive extension (#124)
1 parent d00ce1c commit 0a0c55a

File tree

2 files changed

+99
-113
lines changed

2 files changed

+99
-113
lines changed

src/run.test.ts

Lines changed: 79 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -6,84 +6,74 @@ import * as path from 'path'
66
import * as core from '@actions/core'
77

88
describe('run.ts', () => {
9+
const downloadBaseURL = 'https://test.tld'
10+
11+
// Cleanup mocks after each test to ensure that subsequent tests are not affected by the mocks.
12+
afterEach(() => {
13+
jest.restoreAllMocks()
14+
})
15+
916
test('getExecutableExtension() - return .exe when os is Windows', () => {
10-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
17+
jest.spyOn(os, 'platform').mockReturnValue('win32')
1118

1219
expect(run.getExecutableExtension()).toBe('.exe')
13-
expect(os.type).toHaveBeenCalled()
20+
expect(os.platform).toHaveBeenCalled()
1421
})
1522

1623
test('getExecutableExtension() - return empty string for non-windows OS', () => {
17-
jest.spyOn(os, 'type').mockReturnValue('Darwin')
24+
jest.spyOn(os, 'platform').mockReturnValue('darwin')
1825

1926
expect(run.getExecutableExtension()).toBe('')
20-
expect(os.type).toHaveBeenCalled()
27+
expect(os.platform).toHaveBeenCalled()
2128
})
2229

23-
test('getHelmDownloadURL() - return the URL to download helm for Linux', () => {
24-
const downloadBaseURL = 'https://test.tld'
30+
test('getHelmDownloadURL() - return the URL to download helm for Linux amd64', () => {
31+
jest.spyOn(os, 'platform').mockReturnValue('linux')
32+
jest.spyOn(os, 'arch').mockReturnValue('x64')
33+
const expected = 'https://test.tld/helm-v3.8.0-linux-amd64.tar.gz'
2534

26-
jest.spyOn(os, 'type').mockReturnValue('Linux')
27-
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
28-
const helmLinuxUrl = 'https://test.tld/helm-v3.8.0-linux-amd64.zip'
29-
30-
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
31-
helmLinuxUrl
32-
)
33-
expect(os.type).toHaveBeenCalled()
35+
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
36+
expect(os.platform).toHaveBeenCalled()
3437
expect(os.arch).toHaveBeenCalled()
38+
})
3539

36-
// arm64
37-
jest.spyOn(os, 'type').mockReturnValue('Linux')
38-
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
39-
const helmLinuxArm64Url = 'https://test.tld/helm-v3.8.0-linux-arm64.zip'
40+
test('getHelmDownloadURL() - return the URL to download helm for Linux arm64', () => {
41+
jest.spyOn(os, 'platform').mockReturnValue('linux')
42+
jest.spyOn(os, 'arch').mockReturnValue('arm64')
43+
const expected = 'https://test.tld/helm-v3.8.0-linux-arm64.tar.gz'
4044

41-
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
42-
helmLinuxArm64Url
43-
)
44-
expect(os.type).toHaveBeenCalled()
45+
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
46+
expect(os.platform).toHaveBeenCalled()
4547
expect(os.arch).toHaveBeenCalled()
4648
})
4749

48-
test('getHelmDownloadURL() - return the URL to download helm for Darwin', () => {
49-
const downloadBaseURL = 'https://test.tld'
50-
51-
jest.spyOn(os, 'type').mockReturnValue('Darwin')
52-
jest.spyOn(os, 'arch').mockReturnValueOnce('unknown')
53-
const helmDarwinUrl = 'https://test.tld/helm-v3.8.0-darwin-amd64.zip'
50+
test('getHelmDownloadURL() - return the URL to download helm for Darwin x64', () => {
51+
jest.spyOn(os, 'platform').mockReturnValue('darwin')
52+
jest.spyOn(os, 'arch').mockReturnValue('x64')
53+
const expected = 'https://test.tld/helm-v3.8.0-darwin-amd64.tar.gz'
5454

55-
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
56-
helmDarwinUrl
57-
)
58-
expect(os.type).toHaveBeenCalled()
55+
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
56+
expect(os.platform).toHaveBeenCalled()
5957
expect(os.arch).toHaveBeenCalled()
58+
})
6059

61-
// arm64
62-
jest.spyOn(os, 'type').mockReturnValue('Darwin')
63-
jest.spyOn(os, 'arch').mockReturnValueOnce('arm64')
64-
const helmDarwinArm64Url = 'https://test.tld/helm-v3.8.0-darwin-arm64.zip'
60+
test('getHelmDownloadURL() - return the URL to download helm for Darwin arm64', () => {
61+
jest.spyOn(os, 'platform').mockReturnValue('darwin')
62+
jest.spyOn(os, 'arch').mockReturnValue('arm64')
63+
const expected = 'https://test.tld/helm-v3.8.0-darwin-arm64.tar.gz'
6564

66-
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
67-
helmDarwinArm64Url
68-
)
69-
expect(os.type).toHaveBeenCalled()
65+
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
66+
expect(os.platform).toHaveBeenCalled()
7067
expect(os.arch).toHaveBeenCalled()
7168
})
7269

73-
test('getValidVersion() - return version with v prepended', () => {
74-
expect(run.getValidVersion('3.8.0')).toBe('v3.8.0')
75-
})
76-
7770
test('getHelmDownloadURL() - return the URL to download helm for Windows', () => {
78-
const downloadBaseURL = 'https://test.tld'
79-
80-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
71+
jest.spyOn(os, 'platform').mockReturnValue('win32')
72+
jest.spyOn(os, 'arch').mockReturnValue('x64')
8173

82-
const helmWindowsUrl = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
83-
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(
84-
helmWindowsUrl
85-
)
86-
expect(os.type).toHaveBeenCalled()
74+
const expected = 'https://test.tld/helm-v3.8.0-windows-amd64.zip'
75+
expect(run.getHelmDownloadURL(downloadBaseURL, 'v3.8.0')).toBe(expected)
76+
expect(os.platform).toHaveBeenCalled()
8777
})
8878

8979
test('getLatestHelmVersion() - return the latest version of HELM', async () => {
@@ -101,6 +91,10 @@ describe('run.ts', () => {
10191
expect(await run.getLatestHelmVersion()).toBe('v3.13.3')
10292
})
10393

94+
test('getValidVersion() - return version with v prepended', () => {
95+
expect(run.getValidVersion('3.8.0')).toBe('v3.8.0')
96+
})
97+
10498
test('walkSync() - return path to the all files matching fileToFind in dir', () => {
10599
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
106100
if (file == 'mainFolder')
@@ -120,6 +114,7 @@ describe('run.ts', () => {
120114
'file21' as unknown as fs.Dirent,
121115
'file22' as unknown as fs.Dirent
122116
]
117+
return []
123118
})
124119
jest.spyOn(core, 'debug').mockImplementation()
125120
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
@@ -154,6 +149,7 @@ describe('run.ts', () => {
154149
'file21' as unknown as fs.Dirent,
155150
'file22' as unknown as fs.Dirent
156151
]
152+
return []
157153
})
158154
jest.spyOn(core, 'debug').mockImplementation()
159155
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
@@ -171,13 +167,14 @@ describe('run.ts', () => {
171167
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
172168
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
173169
if (file == 'mainFolder') return ['helm.exe' as unknown as fs.Dirent]
170+
return []
174171
})
175172
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
176173
const isDirectory =
177174
(file as string).indexOf('folder') == -1 ? false : true
178175
return {isDirectory: () => isDirectory} as fs.Stats
179176
})
180-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
177+
jest.spyOn(os, 'platform').mockReturnValue('win32')
181178

182179
expect(run.findHelm('mainFolder')).toBe(
183180
path.join('mainFolder', 'helm.exe')
@@ -188,11 +185,13 @@ describe('run.ts', () => {
188185
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
189186
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => {
190187
if (file == 'mainFolder') return []
188+
return []
191189
})
192190
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
193191
return {isDirectory: () => true} as fs.Stats
194192
})
195-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
193+
jest.spyOn(os, 'platform').mockReturnValue('win32')
194+
196195
expect(() => run.findHelm('mainFolder')).toThrow(
197196
'Helm executable not found in path mainFolder'
198197
)
@@ -203,11 +202,9 @@ describe('run.ts', () => {
203202
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
204203
const response = JSON.stringify([{tag_name: 'v4.0.0'}])
205204
jest.spyOn(fs, 'readFileSync').mockReturnValue(response)
206-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
205+
jest.spyOn(os, 'platform').mockReturnValue('win32')
207206
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
208-
jest
209-
.spyOn(toolCache, 'extractZip')
210-
.mockResolvedValue('pathToUnzippedHelm')
207+
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
211208
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
212209
jest
213210
.spyOn(fs, 'readdirSync')
@@ -218,9 +215,7 @@ describe('run.ts', () => {
218215
return {isDirectory: () => isDirectory} as fs.Stats
219216
})
220217

221-
const baseURL = 'https://test.tld'
222-
223-
expect(await run.downloadHelm(baseURL, 'v4.0.0')).toBe(
218+
expect(await run.downloadHelm(downloadBaseURL, 'v4.0.0')).toBe(
224219
path.join('pathToCachedDir', 'helm.exe')
225220
)
226221
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v4.0.0')
@@ -240,26 +235,33 @@ describe('run.ts', () => {
240235
jest.spyOn(toolCache, 'downloadTool').mockImplementation(async () => {
241236
throw 'Unable to download'
242237
})
243-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
244-
245-
const baseURL = 'https://test.tld'
238+
jest.spyOn(os, 'platform').mockReturnValue('win32')
246239

247-
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
248-
'Failed to download Helm from location https://test.tld/helm-v3.2.1-windows-amd64.zip'
240+
const downloadUrl = 'https://test.tld/helm-v3.2.1-windows-amd64.zip'
241+
await expect(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
242+
`Failed to download Helm from location ${downloadUrl}`
249243
)
250244
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
251-
expect(toolCache.downloadTool).toHaveBeenCalledWith(
252-
'https://test.tld/helm-v3.2.1-windows-amd64.zip'
253-
)
245+
expect(toolCache.downloadTool).toHaveBeenCalledWith(`${downloadUrl}`)
254246
})
255247

256248
test('downloadHelm() - return path to helm tool with same version from toolCache', async () => {
257249
jest.spyOn(toolCache, 'find').mockReturnValue('pathToCachedDir')
250+
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
251+
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
252+
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
253+
jest.spyOn(os, 'platform').mockReturnValue('win32')
258254
jest.spyOn(fs, 'chmodSync').mockImplementation(() => {})
255+
jest
256+
.spyOn(fs, 'readdirSync')
257+
.mockReturnValue(['helm.exe' as unknown as fs.Dirent])
258+
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
259+
const isDirectory =
260+
(file as string).indexOf('folder') == -1 ? false : true
261+
return {isDirectory: () => isDirectory} as fs.Stats
262+
})
259263

260-
const baseURL = 'https://test.tld'
261-
262-
expect(await run.downloadHelm(baseURL, 'v3.2.1')).toBe(
264+
expect(await run.downloadHelm(downloadBaseURL, 'v3.2.1')).toBe(
263265
path.join('pathToCachedDir', 'helm.exe')
264266
)
265267
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')
@@ -272,22 +274,19 @@ describe('run.ts', () => {
272274
test('downloadHelm() - throw error is helm is not found in path', async () => {
273275
jest.spyOn(toolCache, 'find').mockReturnValue('')
274276
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
275-
jest.spyOn(os, 'type').mockReturnValue('Windows_NT')
276-
jest.spyOn(fs, 'chmodSync').mockImplementation()
277-
jest
278-
.spyOn(toolCache, 'extractZip')
279-
.mockResolvedValue('pathToUnzippedHelm')
280277
jest.spyOn(toolCache, 'cacheDir').mockResolvedValue('pathToCachedDir')
278+
jest.spyOn(toolCache, 'downloadTool').mockResolvedValue('pathToTool')
279+
jest.spyOn(toolCache, 'extractZip').mockResolvedValue('extractedPath')
280+
jest.spyOn(os, 'platform').mockReturnValue('win32')
281+
jest.spyOn(fs, 'chmodSync').mockImplementation()
281282
jest.spyOn(fs, 'readdirSync').mockImplementation((file, _) => [])
282283
jest.spyOn(fs, 'statSync').mockImplementation((file) => {
283284
const isDirectory =
284285
(file as string).indexOf('folder') == -1 ? false : true
285286
return {isDirectory: () => isDirectory} as fs.Stats
286287
})
287288

288-
const baseURL = 'https://test.tld'
289-
290-
await expect(run.downloadHelm(baseURL, 'v3.2.1')).rejects.toThrow(
289+
await expect(run.downloadHelm(downloadBaseURL, 'v3.2.1')).rejects.toThrow(
291290
'Helm executable not found in path pathToCachedDir'
292291
)
293292
expect(toolCache.find).toHaveBeenCalledWith('helm', 'v3.2.1')

src/run.ts

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -61,41 +61,24 @@ export async function getLatestHelmVersion(): Promise<string> {
6161
}
6262
}
6363

64+
export function getArch(): string {
65+
return os.arch() === 'x64' ? 'amd64' : os.arch()
66+
}
67+
68+
export function getPlatform(): string {
69+
return os.platform() === 'win32' ? 'windows' : os.platform()
70+
}
71+
72+
export function getArchiveExtension(): string {
73+
return os.platform() === 'win32' ? 'zip' : 'tar.gz'
74+
}
75+
6476
export function getExecutableExtension(): string {
65-
if (os.type().match(/^Win/)) {
66-
return '.exe'
67-
}
68-
return ''
77+
return os.platform() === 'win32' ? '.exe' : ''
6978
}
7079

71-
const LINUX = 'Linux'
72-
const MAC_OS = 'Darwin'
73-
const WINDOWS = 'Windows_NT'
74-
const ARM64 = 'arm64'
7580
export function getHelmDownloadURL(baseURL: string, version: string): string {
76-
const arch = os.arch()
77-
const operatingSystem = os.type()
78-
79-
let urlPath = ''
80-
81-
switch (true) {
82-
case operatingSystem == LINUX && arch == ARM64:
83-
urlPath = util.format(`/helm-%s-linux-arm64.zip`, version)
84-
break
85-
case operatingSystem == LINUX:
86-
urlPath = util.format(`/helm-%s-linux-amd64.zip`, version)
87-
break
88-
case operatingSystem == MAC_OS && arch == ARM64:
89-
urlPath = util.format(`/helm-%s-darwin-arm64.zip`, version)
90-
break
91-
case operatingSystem == MAC_OS:
92-
urlPath = util.format(`/helm-%s-darwin-amd64.zip`, version)
93-
break
94-
case operatingSystem == WINDOWS:
95-
default:
96-
urlPath = util.format(`/helm-%s-windows-amd64.zip`, version)
97-
}
98-
81+
const urlPath = `helm-${version}-${getPlatform()}-${getArch()}.${getArchiveExtension()}`
9982
const url = new URL(urlPath, baseURL)
10083
return url.toString()
10184
}
@@ -121,9 +104,13 @@ export async function downloadHelm(
121104
}
122105

123106
fs.chmodSync(helmDownloadPath, '777')
124-
const unzipedHelmPath = await toolCache.extractZip(helmDownloadPath)
107+
const extractedPath =
108+
getPlatform() === 'windows'
109+
? await toolCache.extractZip(helmDownloadPath)
110+
: await toolCache.extractTar(helmDownloadPath)
111+
125112
cachedToolpath = await toolCache.cacheDir(
126-
unzipedHelmPath,
113+
extractedPath,
127114
helmToolName,
128115
version
129116
)

0 commit comments

Comments
 (0)