Skip to content

Commit 8f5e559

Browse files
committed
fix: download the correct CLI signature for Windows
The signature for windows CLI follows the format: coder-windows-amd64.exe.asc Currently it is coded to coder-windows-amd64.asc which means the plugin always fail to find any signature for windows cli
1 parent c7af603 commit 8f5e559

File tree

4 files changed

+138
-84
lines changed

4 files changed

+138
-84
lines changed

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dependencies {
5757
// required by the unit tests
5858
testImplementation(kotlin("test-junit5"))
5959
testImplementation("io.mockk:mockk:1.13.12")
60+
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.9.0")
6061
// required by IntelliJ test framework
6162
testImplementation("junit:junit:4.13.2")
6263

src/main/kotlin/com/coder/gateway/settings/CoderSettings.kt

Lines changed: 24 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.coder.gateway.settings
22

3-
import com.coder.gateway.cli.gpg.VerificationResult
43
import com.coder.gateway.util.Arch
54
import com.coder.gateway.util.OS
65
import com.coder.gateway.util.expand
@@ -9,7 +8,6 @@ import com.coder.gateway.util.getOS
98
import com.coder.gateway.util.safeHost
109
import com.coder.gateway.util.toURL
1110
import com.coder.gateway.util.withPath
12-
import com.github.weisj.jsvg.B
1311
import com.intellij.openapi.diagnostic.Logger
1412
import java.net.URL
1513
import java.nio.file.Files
@@ -168,6 +166,11 @@ open class CoderSettings(
168166
val fallbackOnCoderForSignatures: Boolean
169167
get() = state.fallbackOnCoderForSignatures
170168

169+
/**
170+
* Default CLI binary name based on OS and architecture
171+
*/
172+
val defaultCliBinaryNameByOsAndArch: String get() = getCoderCLIForOS(getOS(), getArch())
173+
171174
/**
172175
* Default CLI signature name based on OS and architecture
173176
*/
@@ -281,9 +284,8 @@ open class CoderSettings(
281284
*/
282285
fun binSource(url: URL): URL {
283286
state.binarySource.let {
284-
val binaryName = getCoderCLIForOS(getOS(), getArch())
285287
return if (it.isBlank()) {
286-
url.withPath("/bin/$binaryName")
288+
url.withPath("/bin/$defaultCliBinaryNameByOsAndArch")
287289
} else {
288290
logger.info("Using binary source override $it")
289291
try {
@@ -393,44 +395,19 @@ open class CoderSettings(
393395
}
394396

395397
/**
396-
* Return the name of the binary (with extension) for the provided OS and architecture.
398+
* Returns the name of the binary (with extension) for the provided OS and architecture.
397399
*/
398-
private fun getCoderCLIForOS(
399-
os: OS?,
400-
arch: Arch?,
401-
): String {
400+
private fun getCoderCLIForOS(os: OS?, arch: Arch?): String {
402401
logger.debug("Resolving binary for $os $arch")
403-
return buildCoderFileName(os, arch)
404-
}
405402

406-
/**
407-
* Return the name of the signature file (.asc) for the provided OS and architecture.
408-
*/
409-
private fun getCoderSignatureForOS(
410-
os: OS?,
411-
arch: Arch?,
412-
): String {
413-
logger.debug("Resolving signature for $os $arch")
414-
return buildCoderFileName(os, arch, true)
415-
}
416-
417-
/**
418-
* Build the coder file name based on OS, architecture, and whether it's a signature file.
419-
*/
420-
private fun buildCoderFileName(
421-
os: OS?,
422-
arch: Arch?,
423-
isSignature: Boolean = false
424-
): String {
425-
if (os == null) {
426-
logger.error("Could not resolve client OS and architecture, defaulting to WINDOWS AMD64")
427-
return if (isSignature) "coder-windows-amd64.asc" else "coder-windows-amd64.exe"
428-
}
429-
430-
val osName = when (os) {
431-
OS.WINDOWS -> "windows"
432-
OS.LINUX -> "linux"
433-
OS.MAC -> "darwin"
403+
val (osName, extension) = when (os) {
404+
OS.WINDOWS -> "windows" to ".exe"
405+
OS.LINUX -> "linux" to ""
406+
OS.MAC -> "darwin" to ""
407+
null -> {
408+
logger.error("Could not resolve client OS and architecture, defaulting to WINDOWS AMD64")
409+
return "coder-windows-amd64.exe"
410+
}
434411
}
435412

436413
val archName = when (arch) {
@@ -440,14 +417,17 @@ open class CoderSettings(
440417
else -> "amd64" // default fallback
441418
}
442419

443-
val extension = if (isSignature) ".asc" else when (os) {
444-
OS.WINDOWS -> ".exe"
445-
OS.LINUX, OS.MAC -> ""
446-
}
447-
448420
return "coder-$osName-$archName$extension"
449421
}
450422

423+
/**
424+
* Returns the name of the signature file (.asc) for the provided OS and architecture.
425+
*/
426+
private fun getCoderSignatureForOS(os: OS?, arch: Arch?): String {
427+
logger.debug("Resolving signature for $os $arch")
428+
return "${getCoderCLIForOS(os, arch)}.asc"
429+
}
430+
451431
companion object {
452432
val logger = Logger.getInstance(CoderSettings::class.java.simpleName)
453433
}

src/main/kotlin/com/coder/gateway/util/OS.kt

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import java.util.Locale
44

55
fun getOS(): OS? = OS.from(System.getProperty("os.name"))
66

7-
fun getArch(): Arch? = Arch.from(System.getProperty("os.arch").lowercase(Locale.getDefault()))
7+
fun getArch(): Arch? = Arch.from(System.getProperty("os.arch")?.lowercase(Locale.getDefault()))
88

99
enum class OS {
1010
WINDOWS,
1111
LINUX,
12-
MAC,
13-
;
12+
MAC;
1413

1514
companion object {
16-
fun from(os: String): OS? = when {
15+
fun from(os: String?): OS? = when {
16+
os.isNullOrBlank() -> null
1717
os.contains("win", true) -> {
1818
WINDOWS
1919
}
@@ -38,7 +38,8 @@ enum class Arch {
3838
;
3939

4040
companion object {
41-
fun from(arch: String): Arch? = when {
41+
fun from(arch: String?): Arch? = when {
42+
arch.isNullOrBlank() -> null
4243
arch.contains("amd64", true) || arch.contains("x86_64", true) -> AMD64
4344
arch.contains("arm64", true) || arch.contains("aarch64", true) -> ARM64
4445
arch.contains("armv7", true) -> ARMV7

src/test/kotlin/com/coder/gateway/settings/CoderSettingsTest.kt

Lines changed: 107 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,36 @@ package com.coder.gateway.settings
33
import com.coder.gateway.util.OS
44
import com.coder.gateway.util.getOS
55
import com.coder.gateway.util.withPath
6+
import org.junit.jupiter.api.Assertions
67
import java.net.URL
78
import java.nio.file.Path
9+
import kotlin.test.AfterTest
10+
import kotlin.test.BeforeTest
811
import kotlin.test.Test
912
import kotlin.test.assertContains
1013
import kotlin.test.assertEquals
1114
import kotlin.test.assertNotEquals
1215

1316
internal class CoderSettingsTest {
17+
private var originalOsName: String? = null
18+
private var originalOsArch: String? = null
19+
20+
private lateinit var store: CoderSettings
21+
22+
@BeforeTest
23+
fun setUp() {
24+
originalOsName = System.getProperty("os.name")
25+
originalOsArch = System.getProperty("os.arch")
26+
store = CoderSettings(CoderSettingsState())
27+
System.setProperty("intellij.testFramework.rethrow.logged.errors", "false")
28+
}
29+
30+
@AfterTest
31+
fun tearDown() {
32+
System.setProperty("os.name", originalOsName)
33+
System.setProperty("os.arch", originalOsArch)
34+
}
35+
1436
@Test
1537
fun testExpands() {
1638
val state = CoderSettingsState()
@@ -35,13 +57,13 @@ internal class CoderSettingsTest {
3557
CoderSettings(
3658
state,
3759
env =
38-
Environment(
39-
mapOf(
40-
"LOCALAPPDATA" to "/tmp/coder-gateway-test/localappdata",
41-
"HOME" to "/tmp/coder-gateway-test/home",
42-
"XDG_DATA_HOME" to "/tmp/coder-gateway-test/xdg-data",
60+
Environment(
61+
mapOf(
62+
"LOCALAPPDATA" to "/tmp/coder-gateway-test/localappdata",
63+
"HOME" to "/tmp/coder-gateway-test/home",
64+
"XDG_DATA_HOME" to "/tmp/coder-gateway-test/xdg-data",
65+
),
4366
),
44-
),
4567
)
4668
var expected =
4769
when (getOS()) {
@@ -59,12 +81,12 @@ internal class CoderSettingsTest {
5981
CoderSettings(
6082
state,
6183
env =
62-
Environment(
63-
mapOf(
64-
"XDG_DATA_HOME" to "",
65-
"HOME" to "/tmp/coder-gateway-test/home",
84+
Environment(
85+
mapOf(
86+
"XDG_DATA_HOME" to "",
87+
"HOME" to "/tmp/coder-gateway-test/home",
88+
),
6689
),
67-
),
6890
)
6991
expected = "/tmp/coder-gateway-test/home/.local/share/coder-gateway/localhost"
7092

@@ -78,13 +100,13 @@ internal class CoderSettingsTest {
78100
CoderSettings(
79101
state,
80102
env =
81-
Environment(
82-
mapOf(
83-
"LOCALAPPDATA" to "/ignore",
84-
"HOME" to "/ignore",
85-
"XDG_DATA_HOME" to "/ignore",
103+
Environment(
104+
mapOf(
105+
"LOCALAPPDATA" to "/ignore",
106+
"HOME" to "/ignore",
107+
"XDG_DATA_HOME" to "/ignore",
108+
),
86109
),
87-
),
88110
)
89111
expected = "/tmp/coder-gateway-test/data-dir/localhost"
90112
assertEquals(Path.of(expected).toAbsolutePath(), settings.dataDir(url))
@@ -131,13 +153,13 @@ internal class CoderSettingsTest {
131153
CoderSettings(
132154
state,
133155
env =
134-
Environment(
135-
mapOf(
136-
"APPDATA" to "/tmp/coder-gateway-test/cli-appdata",
137-
"HOME" to "/tmp/coder-gateway-test/cli-home",
138-
"XDG_CONFIG_HOME" to "/tmp/coder-gateway-test/cli-xdg-config",
156+
Environment(
157+
mapOf(
158+
"APPDATA" to "/tmp/coder-gateway-test/cli-appdata",
159+
"HOME" to "/tmp/coder-gateway-test/cli-home",
160+
"XDG_CONFIG_HOME" to "/tmp/coder-gateway-test/cli-xdg-config",
161+
),
139162
),
140-
),
141163
)
142164
var expected =
143165
when (getOS()) {
@@ -153,12 +175,12 @@ internal class CoderSettingsTest {
153175
CoderSettings(
154176
state,
155177
env =
156-
Environment(
157-
mapOf(
158-
"XDG_CONFIG_HOME" to "",
159-
"HOME" to "/tmp/coder-gateway-test/cli-home",
178+
Environment(
179+
mapOf(
180+
"XDG_CONFIG_HOME" to "",
181+
"HOME" to "/tmp/coder-gateway-test/cli-home",
182+
),
160183
),
161-
),
162184
)
163185
expected = "/tmp/coder-gateway-test/cli-home/.config/coderv2"
164186
assertEquals(Path.of(expected), settings.coderConfigDir)
@@ -169,14 +191,14 @@ internal class CoderSettingsTest {
169191
CoderSettings(
170192
state,
171193
env =
172-
Environment(
173-
mapOf(
174-
"CODER_CONFIG_DIR" to "/tmp/coder-gateway-test/coder-config-dir",
175-
"APPDATA" to "/ignore",
176-
"HOME" to "/ignore",
177-
"XDG_CONFIG_HOME" to "/ignore",
194+
Environment(
195+
mapOf(
196+
"CODER_CONFIG_DIR" to "/tmp/coder-gateway-test/coder-config-dir",
197+
"APPDATA" to "/ignore",
198+
"HOME" to "/ignore",
199+
"XDG_CONFIG_HOME" to "/ignore",
200+
),
178201
),
179-
),
180202
)
181203
expected = "/tmp/coder-gateway-test/coder-config-dir"
182204
assertEquals(Path.of(expected), settings.coderConfigDir)
@@ -402,4 +424,54 @@ internal class CoderSettingsTest {
402424
assertEquals(true, settings.ignoreSetupFailure)
403425
assertEquals("test ssh log directory", settings.sshLogDirectory)
404426
}
427+
428+
429+
@Test
430+
fun `Default CLI and signature for Windows AMD64`() =
431+
assertBinaryAndSignature("Windows 10", "amd64", "coder-windows-amd64.exe", "coder-windows-amd64.exe.asc")
432+
433+
@Test
434+
fun `Default CLI and signature for Windows ARM64`() =
435+
assertBinaryAndSignature("Windows 10", "aarch64", "coder-windows-arm64.exe", "coder-windows-arm64.exe.asc")
436+
437+
@Test
438+
fun `Default CLI and signature for Linux AMD64`() =
439+
assertBinaryAndSignature("Linux", "x86_64", "coder-linux-amd64", "coder-linux-amd64.asc")
440+
441+
@Test
442+
fun `Default CLI and signature for Linux ARM64`() =
443+
assertBinaryAndSignature("Linux", "aarch64", "coder-linux-arm64", "coder-linux-arm64.asc")
444+
445+
@Test
446+
fun `Default CLI and signature for Linux ARMV7`() =
447+
assertBinaryAndSignature("Linux", "armv7l", "coder-linux-armv7", "coder-linux-armv7.asc")
448+
449+
@Test
450+
fun `Default CLI and signature for Mac AMD64`() =
451+
assertBinaryAndSignature("Mac OS X", "x86_64", "coder-darwin-amd64", "coder-darwin-amd64.asc")
452+
453+
@Test
454+
fun `Default CLI and signature for Mac ARM64`() =
455+
assertBinaryAndSignature("Mac OS X", "aarch64", "coder-darwin-arm64", "coder-darwin-arm64.asc")
456+
457+
@Test
458+
fun `Default CLI and signature for unknown OS and Arch`() =
459+
assertBinaryAndSignature(null, null, "coder-windows-amd64.exe", "coder-windows-amd64.exe.asc")
460+
461+
@Test
462+
fun `Default CLI and signature for unknown Arch fallback on Linux`() =
463+
assertBinaryAndSignature("Linux", "mips64", "coder-linux-amd64", "coder-linux-amd64.asc")
464+
465+
private fun assertBinaryAndSignature(
466+
osName: String?,
467+
arch: String?,
468+
expectedBinary: String,
469+
expectedSignature: String
470+
) {
471+
if (osName == null) System.clearProperty("os.name") else System.setProperty("os.name", osName)
472+
if (arch == null) System.clearProperty("os.arch") else System.setProperty("os.arch", arch)
473+
474+
Assertions.assertEquals(expectedBinary, store.defaultCliBinaryNameByOsAndArch)
475+
Assertions.assertEquals(expectedSignature, store.defaultSignatureNameByOsAndArch)
476+
}
405477
}

0 commit comments

Comments
 (0)