From 7b4322db04a943bafed9c980aac27c8d27e0e00d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 4 Dec 2024 13:31:39 +0100 Subject: [PATCH 01/21] Increase version to 4.0.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7a70dff1b..4fbfff50f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ # limitations under the License. group = net.kautler -version = 3.1.5-SNAPSHOT +version = 4.0.0-SNAPSHOT description = A GitHub action to install and setup a Linux distribution for the Windows Subsystem for Linux (WSL) org.gradle.caching = true From f2d2a634d48f658c715714ca56d4a012e9504217 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 4 Dec 2024 13:37:36 +0100 Subject: [PATCH 02/21] Add support for WSLv2 (#64) --- .github/workflows/test.main.kts | 656 ++++++++++++++---- .github/workflows/test.yaml | 593 ++++++++++++++-- action-types.yml | 3 + action.yml | 11 + readme/README_template.md | 29 +- .../github/action/setup_wsl/SetupWsl.kt | 54 +- 6 files changed, 1129 insertions(+), 217 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index c1cbb4716..7ad32ef86 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -32,7 +32,9 @@ import io.github.typesafegithub.workflows.actions.actions.SetupJava import io.github.typesafegithub.workflows.actions.actions.SetupJava.Distribution.Temurin import io.github.typesafegithub.workflows.actions.burrunan.GradleCacheAction import io.github.typesafegithub.workflows.actions.vampire.SetupWsl -import io.github.typesafegithub.workflows.actions.vampire.SetupWsl.Distribution +import io.github.typesafegithub.workflows.actions.vampire.SetupWsl.Distribution.Debian +import io.github.typesafegithub.workflows.actions.vampire.SetupWsl.Distribution.Ubuntu1604 +import io.github.typesafegithub.workflows.actions.vampire.SetupWsl.Distribution.Ubuntu1804 import io.github.typesafegithub.workflows.domain.CommandStep import io.github.typesafegithub.workflows.domain.ActionStep import io.github.typesafegithub.workflows.domain.JobOutputs.EMPTY @@ -57,67 +59,67 @@ val environments = listOf( "windows-latest" ) -val debian = mapOf( - "wsl-id" to "Debian", - "user-id" to "Debian", - "match-pattern" to "*Debian*", - "default-absent-tool" to "dos2unix" +val debian = Distribution( + wslId = "Debian", + userId = "Debian", + matchPattern = "*Debian*", + defaultAbsentTool = "dos2unix" ) -val alpine = mapOf( - "wsl-id" to "Alpine", - "user-id" to "Alpine", - "match-pattern" to "*Alpine*", - "default-absent-tool" to "dos2unix" +val alpine = Distribution( + wslId = "Alpine", + userId = "Alpine", + matchPattern = "*Alpine*", + defaultAbsentTool = "dos2unix" ) -val kali = mapOf( - "wsl-id" to "kali-linux", - "user-id" to "kali-linux", - "match-pattern" to "*Kali*", - "default-absent-tool" to "dos2unix" +val kali = Distribution( + wslId = "kali-linux", + userId = "kali-linux", + matchPattern = "*Kali*", + defaultAbsentTool = "dos2unix" ) -val openSuseLeap15_2 = mapOf( - "wsl-id" to "openSUSE-Leap-15.2", - "user-id" to "openSUSE-Leap-15.2", - "match-pattern" to "*openSUSE*Leap*15.2*", - "default-absent-tool" to "which" +val openSuseLeap15_2 = Distribution( + wslId = "openSUSE-Leap-15.2", + userId = "openSUSE-Leap-15.2", + matchPattern = "*openSUSE*Leap*15.2*", + defaultAbsentTool = "which" ) -val ubuntu2404 = mapOf( - "wsl-id" to "Ubuntu-24.04", - "user-id" to "Ubuntu-24.04", - "match-pattern" to "*Ubuntu*24.04*", - "default-absent-tool" to "dos2unix" +val ubuntu2404 = Distribution( + wslId = "Ubuntu-24.04", + userId = "Ubuntu-24.04", + matchPattern = "*Ubuntu*24.04*", + defaultAbsentTool = "dos2unix" ) -val ubuntu2204 = mapOf( - "wsl-id" to "Ubuntu", - "user-id" to "Ubuntu-22.04", - "match-pattern" to "*Ubuntu*22.04*", - "default-absent-tool" to "dos2unix" +val ubuntu2204 = Distribution( + wslId = "Ubuntu", + userId = "Ubuntu-22.04", + matchPattern = "*Ubuntu*22.04*", + defaultAbsentTool = "dos2unix" ) -val ubuntu2004 = mapOf( - "wsl-id" to "Ubuntu", - "user-id" to "Ubuntu-20.04", - "match-pattern" to "*Ubuntu*20.04*", - "default-absent-tool" to "dos2unix" +val ubuntu2004 = Distribution( + wslId = "Ubuntu", + userId = "Ubuntu-20.04", + matchPattern = "*Ubuntu*20.04*", + defaultAbsentTool = "dos2unix" ) -val ubuntu1804 = mapOf( - "wsl-id" to "Ubuntu-18.04", - "user-id" to "Ubuntu-18.04", - "match-pattern" to "*Ubuntu*18.04*", - "default-absent-tool" to "dos2unix" +val ubuntu1804 = Distribution( + wslId = "Ubuntu-18.04", + userId = "Ubuntu-18.04", + matchPattern = "*Ubuntu*18.04*", + defaultAbsentTool = "dos2unix" ) -val ubuntu1604 = mapOf( - "wsl-id" to "Ubuntu-16.04", - "user-id" to "Ubuntu-16.04", - "match-pattern" to "*Ubuntu*16.04*", - "default-absent-tool" to "dos2unix" +val ubuntu1604 = Distribution( + wslId = "Ubuntu-16.04", + userId = "Ubuntu-16.04", + matchPattern = "*Ubuntu*16.04*", + defaultAbsentTool = "dos2unix" ) val distributions = listOf( @@ -130,7 +132,7 @@ val distributions = listOf( ubuntu2004, ubuntu1804, ubuntu1604 -) +).map { it.asMap } val wslBash = Shell.Custom("wsl-bash {0}") @@ -153,7 +155,10 @@ workflowWithCopyright( ) val executeAction = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distribution.user-id")) + distribution = SetupWsl.Distribution.Custom(expr("matrix.distribution.user-id")), + _customInputs = mapOf( + "wsl-version" to "1" + ) ) val build = job( @@ -202,12 +207,14 @@ workflowWithCopyright( fun WorkflowBuilder.testJob( id: String, name: String, + condition: String? = null, _customArguments: Map = mapOf(), block: JobBuilder.() -> Unit, ) = job( id = id, name = name, needs = listOf(build), + condition = condition, runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = _customArguments ) { @@ -259,6 +266,41 @@ workflowWithCopyright( ) } + testJob( + id = "test_invalid_wsl_version", + name = """Test requesting WSL version ${expr("matrix.wsl-version")} on ${expr("matrix.environment")}""", + _customArguments = mapOf( + "strategy" to mapOf( + "fail-fast" to false, + "matrix" to mapOf( + "environment" to environments, + "wsl-version" to listOf("-1", "0"), + "include" to listOf( + mapOf( + "environment" to "windows-2019", + "wsl-version" to "2" + ) + ) + ) + ) + ) + ) { + executeActionStep = usesSelf( + action = executeAction.copy( + distribution = Debian, + _customInputs = mapOf( + "wsl-version" to expr("matrix.wsl-version") + ) + ), + continueOnError = true + ) + run( + name = "Test - action should fail if an invalid WSL version is given", + shell = Cmd, + command = "if '${expr("${executeActionStep.outcome}")}' NEQ 'failure' exit 1" + ) + } + testJob( id = "test_default_distribution", name = "Test default distribution on ${expr("matrix.environment")}", @@ -267,14 +309,17 @@ workflowWithCopyright( "fail-fast" to false, "matrix" to mapOf( "environment" to environments, - "distribution" to listOf(debian) + "distribution" to listOf(debian).map { it.asMap } ) ) ) ) { executeActionStep = usesSelf( action = SetupWsl( - update = true + update = true, + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) commonTests() @@ -315,12 +360,16 @@ workflowWithCopyright( ) { executeActionStep = usesSelf( action = executeAction.copy( - useCache = false + useCache = false, + _customInputs = mapOf( + // part of work-around for https://bugs.kali.org/view.php?id=8921 + "wsl-version" to expr(getWslVersionExpression(kali)) + ) ) ) verifyFailure( name = "Test - wsl-bash should fail if bash is not present by default", - conditionTransformer = { executeActionStep.successOnAlpineCondition }, + conditionTransformer = { executeActionStep.getSuccessOnDistributionCondition(alpine) }, verificationShell = null, verificationTransformer = { _, command -> """wsl sh -euc "${command.replace("==", "=")}"""" @@ -330,9 +379,10 @@ workflowWithCopyright( usesSelf( name = "Install Bash on Alpine", action = executeAction.copy( - additionalPackages = listOf("bash") + additionalPackages = listOf("bash"), + _customInputs = emptyMap() ), - condition = executeActionStep.successOnAlpineCondition + condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) commonTests() verifyFailure( @@ -355,7 +405,8 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Add wsl-sh wrapper", action = executeAction.copy( - wslShellCommand = "sh -eu" + wslShellCommand = "sh -eu", + _customInputs = emptyMap() ) ) runAfterSuccess( @@ -389,7 +440,9 @@ workflowWithCopyright( ) executeActionStep = usesSelfAfterSuccess( name = "Re-add wsl-bash wrapper", - action = executeAction + action = executeAction.copy( + _customInputs = emptyMap() + ) ) runAfterSuccess( name = "Test - wsl-bash should be present" @@ -413,25 +466,69 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use user test by default", // part of work-around for https://bugs.kali.org/view.php?id=8921 - conditionTransformer = { executeActionStep.successNotOnKaliCondition }, + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + }, action = executeAction.copy( additionalPackages = listOf("sudo"), - wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\""" + wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\""", + _customInputs = emptyMap() ) ) verifyCommandResult( name = "Test - wsl-bash should use test as default user", // part of work-around for https://bugs.kali.org/view.php?id=8921 - conditionTransformer = { executeActionStep.successNotOnKaliCondition }, + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + }, actualCommand = "whoami", expected = "test" ) executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use user test by default with inline script usage", // part of work-around for https://bugs.kali.org/view.php?id=8921 - conditionTransformer = { executeActionStep.successNotOnKaliCondition }, + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + }, action = executeAction.copy( - wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail '{0}'"""" + wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail '{0}'"""", + _customInputs = emptyMap() ) ) verifyCommandResult( @@ -442,7 +539,9 @@ workflowWithCopyright( deleteWslBash() executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use default user by default", - action = executeAction + action = executeAction.copy( + _customInputs = emptyMap() + ) ) verifyCommandResult( name = "Test - wsl-bash should use root as default user", @@ -457,7 +556,8 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use existing user test by default with extra parameter", action = executeAction.copy( - wslShellUser = "test" + wslShellUser = "test", + _customInputs = emptyMap() ) ) verifyCommandResult( @@ -473,7 +573,8 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use non-existing user test2 by default with extra parameter", action = executeAction.copy( - wslShellUser = "test2" + wslShellUser = "test2", + _customInputs = emptyMap() ) ) verifyCommandResult( @@ -495,7 +596,9 @@ workflowWithCopyright( ) executeActionStep = usesSelfAfterSuccess( name = "Make a no-op execution of the action", - action = executeAction + action = executeAction.copy( + _customInputs = emptyMap() + ) ) verifyCommandResult( name = "Test - wsl-bash should still use test2 as default user", @@ -529,9 +632,10 @@ workflowWithCopyright( usesSelf( name = "Install Bash on Alpine", action = executeAction.copy( - additionalPackages = listOf("bash") + additionalPackages = listOf("bash"), + _customInputs = emptyMap() ), - condition = executeActionStep.successOnAlpineCondition + condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) runAfterSuccess( name = "Test - /etc/wsl.conf should exist", @@ -569,14 +673,15 @@ workflowWithCopyright( usesSelf( name = "Install Bash on Alpine", action = executeAction.copy( - additionalPackages = listOf("bash") + additionalPackages = listOf("bash"), + _customInputs = emptyMap() ), - condition = executeActionStep.successOnAlpineCondition + condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) runAfterSuccess( name = "Test - /etc/wsl.conf should not exist", command = "[ ! -f /etc/wsl.conf ] || { cat /etc/wsl.conf; false; }", - conditionTransformer = { executeActionStep.successNotOnUbuntu2404Condition } + conditionTransformer = { executeActionStep.getSuccessNotOnDistributionCondition(ubuntu2404) } ) runAfterSuccess( name = "Test - C: should be mounted at /mnt/c", @@ -597,7 +702,8 @@ workflowWithCopyright( wslConf = """ [automount] root = / - """.trimIndent() + """.trimIndent(), + _customInputs = emptyMap() ) ) runAfterSuccess( @@ -624,11 +730,7 @@ workflowWithCopyright( "fail-fast" to false, "matrix" to mapOf( "environment" to environments, - "distribution" to ( - distributions - // part of work-around for https://bugs.kali.org/view.php?id=8921 - - kali - ) + "distribution" to distributions ) ) ) @@ -638,16 +740,198 @@ workflowWithCopyright( additionalPackages = listOf( expr("matrix.distribution.default-absent-tool"), "bash" + ), + _customInputs = mapOf( + // part of work-around for https://bugs.kali.org/view.php?id=8921 + "wsl-version" to expr(getWslVersionExpression(kali)) ) - ) + ), + // part of work-around for https://bugs.kali.org/view.php?id=8921 + condition = """ + |(matrix.distribution.user-id != '${kali.userId}') + ||| ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + |) + """.trimMargin() ) runAfterSuccess( name = "Test - ${expr("matrix.distribution.default-absent-tool")} should be installed", - command = "${expr("matrix.distribution.default-absent-tool")} --version" + command = "${expr("matrix.distribution.default-absent-tool")} --version", + // part of work-around for https://bugs.kali.org/view.php?id=8921 + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + } ) runAfterSuccess( name = "Test - bash should be installed", - command = "bash -c true" + command = "bash -c true", + // part of work-around for https://bugs.kali.org/view.php?id=8921 + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + } + ) + } + + testJob( + id = "test_installation_on_wsl_version", + name = """Test installation on WSLv${expr("matrix.wsl-version")} for "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", + _customArguments = mapOf( + "strategy" to mapOf( + "fail-fast" to false, + "matrix" to mapOf( + "environment" to (environments - "windows-2019"), + "distribution" to distributions, + "wsl-version" to (1..2).toList() + ) + ) + ) + ) { + executeActionStep = usesSelf( + action = executeAction.copy( + additionalPackages = listOf( + expr( + """ + (matrix.distribution.user-id == '${alpine.userId}') + && 'bash' + || '' + """.trimIndent() + ) + ), + _customInputs = mapOf( + "wsl-version" to expr("matrix.wsl-version") + ) + ) + ) + verifyCommandResult( + name = "Test - distribution should be running on WSLv${expr("matrix.wsl-version")}", + actualCommand = """ + cat + <(wsl.exe --list --verbose || true) + <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) + """.trimIndent().replace("\n", " "), + expectedPattern = """*${expr("matrix.distribution.wsl-id")}*\ ${expr("matrix.wsl-version")}*""" + ) + } + + testJob( + id = "test_switching_wsl_version_for_different_distributions", + name = """Test switching WSL version for different distributions on ${expr("matrix.environment")}""", + _customArguments = mapOf( + "strategy" to mapOf( + "fail-fast" to false, + "matrix" to mapOf( + "environment" to (environments - "windows-2019") + ) + ) + ) + ) { + usesSelf( + action = executeAction.copy( + distribution = Debian, + _customInputs = mapOf( + "wsl-version" to "1" + ) + ) + ) + usesSelf( + action = executeAction.copy( + distribution = Ubuntu1604, + _customInputs = mapOf( + "wsl-version" to "2" + ) + ) + ) + executeActionStep = usesSelf( + action = executeAction.copy( + distribution = Ubuntu1804, + _customInputs = mapOf( + "wsl-version" to "1" + ) + ) + ) + verifyCommandResult( + name = "Test - distributions should be running on their respective WSL version", + actualCommand = """ + cat + <(wsl.exe --list --verbose || true) + <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) + | sort -u + """.trimIndent().replace("\n", " "), + expectedPattern = """*${debian.wslId}*\ 1*${ubuntu1604.wslId}*\ 2*${ubuntu1804.wslId}*\ 1*""" + ) + } + + testJob( + id = "test_default_wsl_version", + name = """Test default WSL version for "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", + _customArguments = mapOf( + "strategy" to mapOf( + "fail-fast" to false, + "matrix" to mapOf( + "environment" to environments, + "distribution" to distributions + ) + ) + ) + ) { + executeActionStep = usesSelf( + action = executeAction.copy( + additionalPackages = listOf( + expr( + """ + (matrix.distribution.user-id == '${alpine.userId}') + && 'bash' + || '' + """.trimIndent() + ) + ), + _customInputs = emptyMap() + ) + ) + verifyCommandResult( + name = "Test - default WSL version should be WSLv2", + // on windows-2019 the version is not printed but the wrong + // default (anything but WSLv1) would already make the action execution fail + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& (matrix.environment != 'windows-2019') + """.trimMargin() + }, + actualCommand = """ + cat + <(wsl.exe --list --verbose || true) + <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) + """.trimIndent().replace("\n", " "), + expectedPattern = """*${expr("matrix.distribution.wsl-id")}*\ 2*""" ) } @@ -696,7 +980,9 @@ workflowWithCopyright( "distribution2" to ubuntu2004, "distribution3" to debian ) - ) + ).map { + it.mapValues { (_, distribution) -> distribution.asMap } + } ) ) ) @@ -704,26 +990,35 @@ workflowWithCopyright( usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution1.user-id")}", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distributions.distribution1.user-id")) + distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution1.user-id")), + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution2.user-id")}", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distributions.distribution2.user-id")) + distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution2.user-id")), + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution3.user-id")}", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distributions.distribution3.user-id")), - setAsDefault = false + distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution3.user-id")), + setAsDefault = false, + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) executeActionStep = usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution1.user-id")} again", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distributions.distribution1.user-id")) + distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution1.user-id")) ) ) verifyCommandResult( @@ -752,19 +1047,19 @@ workflowWithCopyright( "matrix" to mapOf( "environment" to environments, "distribution" to distributions, - "distribution2" to listOf(debian), + "distribution2" to listOf(debian).map { it.asMap }, "exclude" to environments.map { mapOf( "environment" to it, - "distribution" to debian, - "distribution2" to debian + "distribution" to debian.asMap, + "distribution2" to debian.asMap ) }, "include" to environments.map { mapOf( "environment" to it, - "distribution" to debian, - "distribution2" to ubuntu2004 + "distribution" to debian.asMap, + "distribution2" to ubuntu2004.asMap ) } ) @@ -773,46 +1068,95 @@ workflowWithCopyright( ) { usesSelf( action = executeAction.copy( - additionalPackages = listOf("bash") - ), - // part of work-around for https://bugs.kali.org/view.php?id=8921 - condition = "matrix.distribution.user-id != '${kali["user-id"]}'" - ) - // part of work-around for https://bugs.kali.org/view.php?id=8921 - usesSelf( - action = executeAction, - condition = "matrix.distribution.user-id == '${kali["user-id"]}'" + // part of work-around for https://bugs.kali.org/view.php?id=8921 + //additionalPackages = listOf("bash") + additionalPackages = listOf( + expr( + """ + |( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + |&& 'bash' + ||| '' + """.trimMargin() + ) + ), + _customInputs = mapOf( + // part of work-around for https://bugs.kali.org/view.php?id=8921 + // and https://bugs.kali.org/view.php?id=6672 + // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 + "wsl-version" to expr(getWslVersionExpression(kali, ubuntu2404)) + ) + ) ) usesSelf( name = "Update distribution", action = executeAction.copy( - update = true + update = true, + _customInputs = emptyMap() ), - // work-around for https://bugs.kali.org/view.php?id=6672 + // part of work-around for https://bugs.kali.org/view.php?id=6672 // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 condition = """ - (matrix.distribution.user-id != '${kali["user-id"]}') - && (matrix.distribution.user-id != '${ubuntu2404["user-id"]}') - """.trimIndent() + |( + | (matrix.distribution.user-id != '${kali.userId}') + | && (matrix.distribution.user-id != '${ubuntu2404.userId}') + |) + ||| ( + | ( + ${getWslVersionExpression(kali, ubuntu2404).prependIndent("| ")} + | ) == '2' + |) + """.trimMargin() ) executeActionStep = usesSelf( name = "Install default absent tool", action = executeAction.copy( - additionalPackages = listOf(expr("matrix.distribution.default-absent-tool")) + additionalPackages = listOf(expr("matrix.distribution.default-absent-tool")), + _customInputs = emptyMap() ), // part of work-around for https://bugs.kali.org/view.php?id=8921 - condition = "matrix.distribution.user-id != '${kali["user-id"]}'" + condition = """ + |(matrix.distribution.user-id != '${kali.userId}') + ||| ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + |) + """.trimMargin() ) runAfterSuccess( name = "Test - ${expr("matrix.distribution.default-absent-tool")} should be installed", command = "${expr("matrix.distribution.default-absent-tool")} --version", // part of work-around for https://bugs.kali.org/view.php?id=8921 - conditionTransformer = { executeActionStep.successNotOnKaliCondition } + conditionTransformer = { + """ + |( + ${it.prependIndent("| ")} + |) + |&& ( + | (matrix.distribution.user-id != '${kali.userId}') + | || ( + | ( + ${getWslVersionExpression(kali).prependIndent("| ")} + | ) == '2' + | ) + |) + """.trimMargin() + } ) executeActionStep = usesSelfAfterSuccess( name = "Execute action for ${expr("matrix.distribution2.user-id")}", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distribution2.user-id")) + distribution = SetupWsl.Distribution.Custom(expr("matrix.distribution2.user-id")), + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) verifyInstalledDistribution( @@ -821,7 +1165,9 @@ workflowWithCopyright( ) executeActionStep = usesSelfAfterSuccess( name = "Re-execute action", - action = executeAction + action = executeAction.copy( + _customInputs = emptyMap() + ) ) verifyInstalledDistribution( name = """Test - "${expr("matrix.distribution2.user-id")}" should still be the default distribution after re-running for "${expr("matrix.distribution.user-id")}"""", @@ -830,7 +1176,8 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Set as default", action = executeAction.copy( - setAsDefault = true + setAsDefault = true, + _customInputs = emptyMap() ) ) verifyInstalledDistribution( @@ -852,13 +1199,13 @@ workflowWithCopyright( "distributions" to listOf(ubuntu2204, ubuntu2004) .map { incompatibleUbuntu -> distributions - .filter { it != incompatibleUbuntu } + .filter { it != incompatibleUbuntu.asMap } .mapIndexed, Pair> { i, distribution -> "distribution${i + 1}" to distribution } .toMutableList() .apply { - add(0, "incompatibleUbuntu" to incompatibleUbuntu["user-id"]!!) + add(0, "incompatibleUbuntu" to incompatibleUbuntu.userId) } .toMap() } @@ -871,9 +1218,12 @@ workflowWithCopyright( usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution$it.user-id")}", action = SetupWsl( - distribution = Distribution.Custom(expr("matrix.distributions.distribution$it.user-id")), + distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution$it.user-id")), additionalPackages = if (it == 2) listOf("bash") else null, - setAsDefault = if (it >= 3) false else null + setAsDefault = if (it >= 3) false else null, + _customInputs = mapOf( + "wsl-version" to "1" + ) ) ) } @@ -881,26 +1231,25 @@ workflowWithCopyright( executeActionStep = localExecuteActionStep verifyInstalledDistribution( name = "Test - wsl-bash_${expr("matrix.distributions.distribution$i.user-id")} should use the correct distribution", - conditionTransformer = if (distributions[i] == ubuntu2004) { - { executeActionStep.getSuccessNotOnDistributionCondition(i, ubuntu2004["user-id"]!!) } + conditionTransformer = if (distributions[i] == ubuntu2004.asMap) { + { executeActionStep.getSuccessNotOnDistributionCondition(ubuntu2004, i) } } else { { it } }, // the formula adds 1 to the indices from ubuntu2004 on // to mitigate the double entry for the previous index - shell = Shell.Custom("wsl-bash_${distributions[min(1, i / (distributions.indexOf(ubuntu2004) + 1)) + i - 1]["user-id"]} {0}"), + shell = Shell.Custom("wsl-bash_${distributions[min(1, i / (distributions.indexOf(ubuntu2004.asMap) + 1)) + i - 1]["user-id"]} {0}"), expectedPatternExpression = "matrix.distributions.distribution$i.match-pattern" ) - if (distributions[i] == ubuntu2004) { + if (distributions[i] == ubuntu2004.asMap) { verifyInstalledDistribution( name = "Test - wsl-bash_${expr("matrix.distributions.distribution$i.user-id")} should use the correct distribution", - conditionTransformer = { executeActionStep.getSuccessNotOnDistributionCondition(i, ubuntu2204["user-id"]!!) }, + conditionTransformer = { executeActionStep.getSuccessNotOnDistributionCondition(ubuntu2204, i) }, shell = Shell.Custom("wsl-bash_${distributions[i]["user-id"]} {0}"), expectedPatternExpression = "matrix.distributions.distribution$i.match-pattern" ) } } - } } @@ -986,7 +1335,7 @@ fun JobBuilder<*>.usesSelf( ) fun JobBuilder<*>.deleteWslBashOnAlpine() = deleteWslBash( - conditionTransformer = { executeActionStep.successOnAlpineCondition } + conditionTransformer = { executeActionStep.getSuccessOnDistributionCondition(alpine)} ) fun JobBuilder<*>.deleteWslBash( @@ -1096,29 +1445,48 @@ val Step<*>.successCondition && (${outcome.eq(Success)}) """.trimIndent() -val Step<*>.successOnAlpineCondition - get() = """ - always() - && (${outcome.eq(Success)}) - && (matrix.distribution.user-id == '${alpine["user-id"]}') - """.trimIndent() +fun Step<*>.getSuccessOnDistributionCondition(distribution: Distribution, i: Int? = null) = + getSuccessOnOrNotOnDistributionCondition(distribution, true, i) -val Step<*>.successNotOnKaliCondition - get() = """ - always() - && (${outcome.eq(Success)}) - && (matrix.distribution.user-id != '${kali["user-id"]}') - """.trimIndent() +fun Step<*>.getSuccessNotOnDistributionCondition(distribution: Distribution, i: Int? = null) = + getSuccessOnOrNotOnDistributionCondition(distribution, false, i) -val Step<*>.successNotOnUbuntu2404Condition - get() = """ - always() - && (${outcome.eq(Success)}) - && (matrix.distribution.user-id != '${ubuntu2404["user-id"]}') - """.trimIndent() +fun Step<*>.getSuccessOnOrNotOnDistributionCondition(distribution: Distribution, on: Boolean = true, i: Int? = null) = """ + |( + ${successCondition.prependIndent("| ")} + |) + |&& (matrix.${i?.let { "distributions.distribution$it" } ?: "distribution"}.user-id ${if (on) "==" else "!="} '${distribution.userId}') +""".trimMargin() + +// part of work-around for https://bugs.kali.org/view.php?id=8921 +// and https://bugs.kali.org/view.php?id=6672 +// and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 +fun getWslVersionExpression(vararg wsl2Distributions: Distribution) = """ + |( + | ( + ${ + wsl2Distributions.joinToString( + separator = "\n| || ", + prefix = "| " + ) { "(matrix.distribution.user-id == '${it.userId}')" } + } + | ) + | && (matrix.environment != 'windows-2019') + |) + |&& '2' + ||| '1' +""".trimMargin() -fun Step<*>.getSuccessNotOnDistributionCondition(i: Int, distribution: String) = """ - always() - && (${outcome.eq(Success)}) - && (matrix.distributions.distribution$i.user-id != '$distribution') -""".trimIndent() +data class Distribution( + val wslId: String, + val userId: String, + val matchPattern: String, + val defaultAbsentTool: String +) { + val asMap = mapOf( + "wsl-id" to wslId, + "user-id" to userId, + "match-pattern" to matchPattern, + "default-absent-tool" to defaultAbsentTool + ) +} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 20b1c135f..7742c65a2 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -110,10 +110,51 @@ jobs: uses: './' with: distribution: '${{ matrix.distribution.user-id }}' + wsl-version: '1' - id: 'step-2' name: 'Test - action should fail if an invalid distribution is given' shell: 'cmd' run: 'if ''${{ steps.step-1.outcome }}'' NEQ ''failure'' exit 1' + test_invalid_wsl_version: + name: 'Test requesting WSL version ${{ matrix.wsl-version }} on ${{ matrix.environment }}' + runs-on: '${{ matrix.environment }}' + needs: + - 'build' + - 'check_yaml_consistency' + strategy: + fail-fast: false + matrix: + environment: + - 'windows-2019' + - 'windows-2022' + - 'windows-latest' + wsl-version: + - '-1' + - '0' + include: + - environment: 'windows-2019' + wsl-version: '2' + steps: + - id: 'step-0' + name: 'Restore built artifacts from cache' + uses: 'actions/cache/restore@v4' + with: + path: |- + action.yml + build/distributions/ + key: '${{ github.run_id }}' + fail-on-cache-miss: 'true' + - id: 'step-1' + name: 'Execute action' + continue-on-error: true + uses: './' + with: + distribution: 'Debian' + wsl-version: '${{ matrix.wsl-version }}' + - id: 'step-2' + name: 'Test - action should fail if an invalid WSL version is given' + shell: 'cmd' + run: 'if ''${{ steps.step-1.outcome }}'' NEQ ''failure'' exit 1' test_default_distribution: name: 'Test default distribution on ${{ matrix.environment }}' runs-on: '${{ matrix.environment }}' @@ -147,6 +188,7 @@ jobs: uses: './' with: update: 'true' + wsl-version: '1' - id: 'step-2' name: 'Test - wsl-bash should be available as custom shell' shell: 'wsl-bash {0}' @@ -384,29 +426,44 @@ jobs: with: distribution: '${{ matrix.distribution.user-id }}' use-cache: 'false' + wsl-version: |- + ${{ ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' }} - id: 'step-2' name: 'Test - wsl-bash should fail if bash is not present by default (provocation)' continue-on-error: true shell: 'wsl-bash {0}' run: ':' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-3' name: 'Test - wsl-bash should fail if bash is not present by default (verification)' run: 'wsl sh -euc "[ ''${{ steps.step-2.outcome }}'' = ''failure'' ]"' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-4' name: 'Delete wsl-bash' shell: 'cmd' run: 'DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}"' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-5' name: 'Install Bash on Alpine' @@ -415,8 +472,10 @@ jobs: distribution: '${{ matrix.distribution.user-id }}' additional-packages: 'bash' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-6' name: 'Test - wsl-bash should be available as custom shell' @@ -662,9 +721,25 @@ jobs: additional-packages: 'sudo' wsl-shell-command: 'bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\' if: |- - always() - && (steps.step-31.outcome == 'success') - && (matrix.distribution.user-id != 'kali-linux') + ( + always() + && (steps.step-31.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) - id: 'step-37' name: 'Test - wsl-bash should use test as default user' shell: 'wsl-bash {0}' @@ -672,9 +747,25 @@ jobs: whoami [ "$(whoami)" == 'test' ] if: |- - always() - && (steps.step-36.outcome == 'success') - && (matrix.distribution.user-id != 'kali-linux') + ( + always() + && (steps.step-36.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) - id: 'step-38' name: 'Set wsl-bash wrapper to use user test by default with inline script usage' uses: './' @@ -682,9 +773,25 @@ jobs: distribution: '${{ matrix.distribution.user-id }}' wsl-shell-command: 'bash -c "sudo -u test bash --noprofile --norc -euo pipefail ''{0}''"' if: |- - always() - && (steps.step-36.outcome == 'success') - && (matrix.distribution.user-id != 'kali-linux') + ( + always() + && (steps.step-36.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) - id: 'step-39' name: 'Test - wsl-bash should use test as default user with inline script usage' shell: 'wsl-bash {0}' @@ -885,13 +992,16 @@ jobs: wsl-conf: |- [automount] options = uid=1000 + wsl-version: '1' - id: 'step-2' name: 'Delete wsl-bash' shell: 'cmd' run: 'DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}"' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-3' name: 'Install Bash on Alpine' @@ -900,8 +1010,10 @@ jobs: distribution: '${{ matrix.distribution.user-id }}' additional-packages: 'bash' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-4' name: 'Test - /etc/wsl.conf should exist' @@ -986,13 +1098,16 @@ jobs: uses: './' with: distribution: '${{ matrix.distribution.user-id }}' + wsl-version: '1' - id: 'step-2' name: 'Delete wsl-bash' shell: 'cmd' run: 'DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}"' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-3' name: 'Install Bash on Alpine' @@ -1001,16 +1116,20 @@ jobs: distribution: '${{ matrix.distribution.user-id }}' additional-packages: 'bash' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id == 'Alpine') - id: 'step-4' name: 'Test - /etc/wsl.conf should not exist' shell: 'wsl-bash {0}' run: '[ ! -f /etc/wsl.conf ] || { cat /etc/wsl.conf; false; }' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) && (matrix.distribution.user-id != 'Ubuntu-24.04') - id: 'step-5' name: 'Test - C: should be mounted at /mnt/c' @@ -1081,6 +1200,10 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' + - wsl-id: 'kali-linux' + user-id: 'kali-linux' + match-pattern: '*Kali*' + default-absent-tool: 'dos2unix' - wsl-id: 'openSUSE-Leap-15.2' user-id: 'openSUSE-Leap-15.2' match-pattern: '*openSUSE*Leap*15.2*' @@ -1121,20 +1244,288 @@ jobs: with: distribution: '${{ matrix.distribution.user-id }}' additional-packages: '${{ matrix.distribution.default-absent-tool }} bash' + wsl-version: |- + ${{ ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' }} + if: |- + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) - id: 'step-2' name: 'Test - ${{ matrix.distribution.default-absent-tool }} should be installed' shell: 'wsl-bash {0}' run: '${{ matrix.distribution.default-absent-tool }} --version' if: |- - always() - && (steps.step-1.outcome == 'success') + ( + always() + && (steps.step-1.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) - id: 'step-3' name: 'Test - bash should be installed' shell: 'wsl-bash {0}' run: 'bash -c true' + if: |- + ( + always() + && (steps.step-1.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) + test_installation_on_wsl_version: + name: 'Test installation on WSLv${{ matrix.wsl-version }} for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }}' + runs-on: '${{ matrix.environment }}' + needs: + - 'build' + - 'check_yaml_consistency' + strategy: + fail-fast: false + matrix: + environment: + - 'windows-2022' + - 'windows-latest' + distribution: + - wsl-id: 'Debian' + user-id: 'Debian' + match-pattern: '*Debian*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Alpine' + user-id: 'Alpine' + match-pattern: '*Alpine*' + default-absent-tool: 'dos2unix' + - wsl-id: 'kali-linux' + user-id: 'kali-linux' + match-pattern: '*Kali*' + default-absent-tool: 'dos2unix' + - wsl-id: 'openSUSE-Leap-15.2' + user-id: 'openSUSE-Leap-15.2' + match-pattern: '*openSUSE*Leap*15.2*' + default-absent-tool: 'which' + - wsl-id: 'Ubuntu-24.04' + user-id: 'Ubuntu-24.04' + match-pattern: '*Ubuntu*24.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu' + user-id: 'Ubuntu-22.04' + match-pattern: '*Ubuntu*22.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu' + user-id: 'Ubuntu-20.04' + match-pattern: '*Ubuntu*20.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu-18.04' + user-id: 'Ubuntu-18.04' + match-pattern: '*Ubuntu*18.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu-16.04' + user-id: 'Ubuntu-16.04' + match-pattern: '*Ubuntu*16.04*' + default-absent-tool: 'dos2unix' + wsl-version: + - 1 + - 2 + steps: + - id: 'step-0' + name: 'Restore built artifacts from cache' + uses: 'actions/cache/restore@v4' + with: + path: |- + action.yml + build/distributions/ + key: '${{ github.run_id }}' + fail-on-cache-miss: 'true' + - id: 'step-1' + name: 'Execute action' + uses: './' + with: + distribution: '${{ matrix.distribution.user-id }}' + additional-packages: |- + ${{ (matrix.distribution.user-id == 'Alpine') + && 'bash' + || '' }} + wsl-version: '${{ matrix.wsl-version }}' + - id: 'step-2' + name: 'Test - distribution should be running on WSLv${{ matrix.wsl-version }}' + shell: 'wsl-bash {0}' + run: |- + cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) + [[ "$(cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}*\ ${{ matrix.wsl-version }}* ]] if: |- always() && (steps.step-1.outcome == 'success') + test_switching_wsl_version_for_different_distributions: + name: 'Test switching WSL version for different distributions on ${{ matrix.environment }}' + runs-on: '${{ matrix.environment }}' + needs: + - 'build' + - 'check_yaml_consistency' + strategy: + fail-fast: false + matrix: + environment: + - 'windows-2022' + - 'windows-latest' + steps: + - id: 'step-0' + name: 'Restore built artifacts from cache' + uses: 'actions/cache/restore@v4' + with: + path: |- + action.yml + build/distributions/ + key: '${{ github.run_id }}' + fail-on-cache-miss: 'true' + - id: 'step-1' + name: 'Execute action' + uses: './' + with: + distribution: 'Debian' + wsl-version: '1' + - id: 'step-2' + name: 'Execute action' + uses: './' + with: + distribution: 'Ubuntu-16.04' + wsl-version: '2' + - id: 'step-3' + name: 'Execute action' + uses: './' + with: + distribution: 'Ubuntu-18.04' + wsl-version: '1' + - id: 'step-4' + name: 'Test - distributions should be running on their respective WSL version' + shell: 'wsl-bash {0}' + run: |- + cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) | sort -u + [[ "$(cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) | sort -u)" == *Debian*\ 1*Ubuntu-16.04*\ 2*Ubuntu-18.04*\ 1* ]] + if: |- + always() + && (steps.step-3.outcome == 'success') + test_default_wsl_version: + name: 'Test default WSL version for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }}' + runs-on: '${{ matrix.environment }}' + needs: + - 'build' + - 'check_yaml_consistency' + strategy: + fail-fast: false + matrix: + environment: + - 'windows-2019' + - 'windows-2022' + - 'windows-latest' + distribution: + - wsl-id: 'Debian' + user-id: 'Debian' + match-pattern: '*Debian*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Alpine' + user-id: 'Alpine' + match-pattern: '*Alpine*' + default-absent-tool: 'dos2unix' + - wsl-id: 'kali-linux' + user-id: 'kali-linux' + match-pattern: '*Kali*' + default-absent-tool: 'dos2unix' + - wsl-id: 'openSUSE-Leap-15.2' + user-id: 'openSUSE-Leap-15.2' + match-pattern: '*openSUSE*Leap*15.2*' + default-absent-tool: 'which' + - wsl-id: 'Ubuntu-24.04' + user-id: 'Ubuntu-24.04' + match-pattern: '*Ubuntu*24.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu' + user-id: 'Ubuntu-22.04' + match-pattern: '*Ubuntu*22.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu' + user-id: 'Ubuntu-20.04' + match-pattern: '*Ubuntu*20.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu-18.04' + user-id: 'Ubuntu-18.04' + match-pattern: '*Ubuntu*18.04*' + default-absent-tool: 'dos2unix' + - wsl-id: 'Ubuntu-16.04' + user-id: 'Ubuntu-16.04' + match-pattern: '*Ubuntu*16.04*' + default-absent-tool: 'dos2unix' + steps: + - id: 'step-0' + name: 'Restore built artifacts from cache' + uses: 'actions/cache/restore@v4' + with: + path: |- + action.yml + build/distributions/ + key: '${{ github.run_id }}' + fail-on-cache-miss: 'true' + - id: 'step-1' + name: 'Execute action' + uses: './' + with: + distribution: '${{ matrix.distribution.user-id }}' + additional-packages: |- + ${{ (matrix.distribution.user-id == 'Alpine') + && 'bash' + || '' }} + - id: 'step-2' + name: 'Test - default WSL version should be WSLv2' + shell: 'wsl-bash {0}' + run: |- + cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8) + [[ "$(cat <(wsl.exe --list --verbose || true) <(wsl.exe --list --verbose || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}*\ 2* ]] + if: |- + ( + always() + && (steps.step-1.outcome == 'success') + ) + && (matrix.environment != 'windows-2019') test_multiple_usage_with_different_distributions: name: 'Test multiple usage with different distributions ("${{ matrix.distributions.distribution1.user-id }}" / "${{ matrix.distributions.distribution2.user-id }}" / "${{ matrix.distributions.distribution3.user-id }}") on ${{ matrix.environment }}' runs-on: '${{ matrix.environment }}' @@ -1254,17 +1645,20 @@ jobs: uses: './' with: distribution: '${{ matrix.distributions.distribution1.user-id }}' + wsl-version: '1' - id: 'step-2' name: 'Execute action for ${{ matrix.distributions.distribution2.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution2.user-id }}' + wsl-version: '1' - id: 'step-3' name: 'Execute action for ${{ matrix.distributions.distribution3.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution3.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-4' name: 'Execute action for ${{ matrix.distributions.distribution1.user-id }} again' uses: './' @@ -1426,47 +1820,112 @@ jobs: uses: './' with: distribution: '${{ matrix.distribution.user-id }}' - additional-packages: 'bash' - if: 'matrix.distribution.user-id != ''kali-linux''' + additional-packages: |- + ${{ ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) + && 'bash' + || '' }} + wsl-version: |- + ${{ ( + ( + (matrix.distribution.user-id == 'kali-linux') + || (matrix.distribution.user-id == 'Ubuntu-24.04') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' }} - id: 'step-2' - name: 'Execute action' - uses: './' - with: - distribution: '${{ matrix.distribution.user-id }}' - if: 'matrix.distribution.user-id == ''kali-linux''' - - id: 'step-3' name: 'Update distribution' uses: './' with: distribution: '${{ matrix.distribution.user-id }}' update: 'true' if: |- - (matrix.distribution.user-id != 'kali-linux') - && (matrix.distribution.user-id != 'Ubuntu-24.04') - - id: 'step-4' + ( + (matrix.distribution.user-id != 'kali-linux') + && (matrix.distribution.user-id != 'Ubuntu-24.04') + ) + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + || (matrix.distribution.user-id == 'Ubuntu-24.04') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + - id: 'step-3' name: 'Install default absent tool' uses: './' with: distribution: '${{ matrix.distribution.user-id }}' additional-packages: '${{ matrix.distribution.default-absent-tool }}' - if: 'matrix.distribution.user-id != ''kali-linux''' - - id: 'step-5' + if: |- + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + - id: 'step-4' name: 'Test - ${{ matrix.distribution.default-absent-tool }} should be installed' shell: 'wsl-bash {0}' run: '${{ matrix.distribution.default-absent-tool }} --version' if: |- - always() - && (steps.step-4.outcome == 'success') - && (matrix.distribution.user-id != 'kali-linux') - - id: 'step-6' + ( + always() + && (steps.step-3.outcome == 'success') + ) + && ( + (matrix.distribution.user-id != 'kali-linux') + || ( + ( + ( + ( + (matrix.distribution.user-id == 'kali-linux') + ) + && (matrix.environment != 'windows-2019') + ) + && '2' + || '1' + ) == '2' + ) + ) + - id: 'step-5' name: 'Execute action for ${{ matrix.distribution2.user-id }}' uses: './' with: distribution: '${{ matrix.distribution2.user-id }}' + wsl-version: '1' if: |- always() - && (steps.step-4.outcome == 'success') - - id: 'step-7' + && (steps.step-3.outcome == 'success') + - id: 'step-6' name: 'Test - "${{ matrix.distribution2.user-id }}" should be the default distribution after installation' shell: 'wsl-bash {0}' run: |- @@ -1474,16 +1933,16 @@ jobs: [[ "$(cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true))" == ${{ matrix.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-6.outcome == 'success') - - id: 'step-8' + && (steps.step-5.outcome == 'success') + - id: 'step-7' name: 'Re-execute action' uses: './' with: distribution: '${{ matrix.distribution.user-id }}' if: |- always() - && (steps.step-6.outcome == 'success') - - id: 'step-9' + && (steps.step-5.outcome == 'success') + - id: 'step-8' name: 'Test - "${{ matrix.distribution2.user-id }}" should still be the default distribution after re-running for "${{ matrix.distribution.user-id }}"' shell: 'wsl-bash {0}' run: |- @@ -1491,8 +1950,8 @@ jobs: [[ "$(cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true))" == ${{ matrix.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-8.outcome == 'success') - - id: 'step-10' + && (steps.step-7.outcome == 'success') + - id: 'step-9' name: 'Set as default' uses: './' with: @@ -1500,8 +1959,8 @@ jobs: set-as-default: 'true' if: |- always() - && (steps.step-8.outcome == 'success') - - id: 'step-11' + && (steps.step-7.outcome == 'success') + - id: 'step-10' name: 'Test - "${{ matrix.distribution.user-id }}" should be the default distribution after re-running with set-as-default true' shell: 'wsl-bash {0}' run: |- @@ -1509,7 +1968,7 @@ jobs: [[ "$(cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true))" == ${{ matrix.distribution.match-pattern }} ]] if: |- always() - && (steps.step-10.outcome == 'success') + && (steps.step-9.outcome == 'success') test_distribution_specific_wsl_bash_scripts: name: 'Test distribution specific wsl-bash scripts on ${{ matrix.environment }} (without ${{ matrix.distributions.incompatibleUbuntu }})' runs-on: '${{ matrix.environment }}' @@ -1621,48 +2080,56 @@ jobs: uses: './' with: distribution: '${{ matrix.distributions.distribution1.user-id }}' + wsl-version: '1' - id: 'step-2' name: 'Execute action for ${{ matrix.distributions.distribution2.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution2.user-id }}' additional-packages: 'bash' + wsl-version: '1' - id: 'step-3' name: 'Execute action for ${{ matrix.distributions.distribution3.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution3.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-4' name: 'Execute action for ${{ matrix.distributions.distribution4.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution4.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-5' name: 'Execute action for ${{ matrix.distributions.distribution5.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution5.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-6' name: 'Execute action for ${{ matrix.distributions.distribution6.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution6.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-7' name: 'Execute action for ${{ matrix.distributions.distribution7.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution7.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-8' name: 'Execute action for ${{ matrix.distributions.distribution8.user-id }}' uses: './' with: distribution: '${{ matrix.distributions.distribution8.user-id }}' set-as-default: 'false' + wsl-version: '1' - id: 'step-9' name: 'Test - wsl-bash_${{ matrix.distributions.distribution1.user-id }} should use the correct distribution' shell: 'wsl-bash_Debian {0}' @@ -1715,8 +2182,10 @@ jobs: cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true) [[ "$(cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true))" == ${{ matrix.distributions.distribution6.match-pattern }} ]] if: |- - always() - && (steps.step-6.outcome == 'success') + ( + always() + && (steps.step-6.outcome == 'success') + ) && (matrix.distributions.distribution6.user-id != 'Ubuntu-20.04') - id: 'step-15' name: 'Test - wsl-bash_${{ matrix.distributions.distribution6.user-id }} should use the correct distribution' @@ -1725,8 +2194,10 @@ jobs: cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true) [[ "$(cat <(lsb_release -a || true) <(uname -a || true) <([ -d /etc ] && find /etc -maxdepth 1 -type f \( -name '*release' -or -name 'issue*' \) -exec cat {} + || true) <([ -d /etc/products.d ] && find /etc/products.d -maxdepth 1 -type f -name '*.prod' -exec cat {} + || true) <([ -f /proc/version ] && cat /proc/version || true))" == ${{ matrix.distributions.distribution6.match-pattern }} ]] if: |- - always() - && (steps.step-6.outcome == 'success') + ( + always() + && (steps.step-6.outcome == 'success') + ) && (matrix.distributions.distribution6.user-id != 'Ubuntu-22.04') - id: 'step-16' name: 'Test - wsl-bash_${{ matrix.distributions.distribution7.user-id }} should use the correct distribution' diff --git a/action-types.yml b/action-types.yml index 751abf411..3ae49220e 100644 --- a/action-types.yml +++ b/action-types.yml @@ -51,6 +51,9 @@ inputs: wsl-shell-command: type: string + wsl-version: + type: integer + outputs: wsl-shell-wrapper-path: type: string diff --git a/action.yml b/action.yml index 2e993c039..691d74cee 100644 --- a/action.yml +++ b/action.yml @@ -94,6 +94,17 @@ inputs: additional ones for other shells. required: false + wsl-version: + description: | + The WSL version that should be used. This can be set to any positive integer. Using an untested one might + work or break, so issues a warning for the action run. Currently, WSLv1 and WSLv2 are tested and do not + issue a warning. If a new WSL version is available and your workflow works with it, please report an issue + so that proper tests can be added and the warning for that version removed. + Default is '1' if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2. + Default is '2' if not running on 'windows-2019' virtual environment. + required: false + default: 1 | 2 + outputs: wsl-shell-wrapper-path: description: | diff --git a/readme/README_template.md b/readme/README_template.md index a2e3cd792..4739e9bb8 100644 --- a/readme/README_template.md +++ b/readme/README_template.md @@ -7,6 +7,7 @@ Setup WSL A GitHub action to install and setup a Linux distribution for the Windows Subsystem for Linux (WSL). Beginning with `windows-2019` virtual environment for GitHub actions, WSLv1 is enabled. +Beginning with later `windows-2022` virtual environment version for GitHub actions, WSLv2 is also available. However, there is no Linux distribution installed by default and there is also no easy shell for `run` steps that executes commands within a WSL distribution. @@ -14,14 +15,6 @@ This action provides an easy way to install Linux distributions for WSL, update install additional packages in them. It also provides a comfortable shell for `run` steps that uses the default WSL distribution and distribution-specific shells if you set up multiple distributions. -WSLv2 is not explicitly supported, because as of this writing neither the Windows version running on GitHub hosted -runners supports WSLv2, nor is Hyper-V enabled which is also necessary to enable WSLv2. If you use a self-hosted -runner on a Windows OS that is new enough with enabled Hyper-V and default WSL version set to 2, this action will -probably run just fine, but this setup is untested and not explicitly supported. If you want to provide a self-hosted -runner with a sufficient setup for this action to use or need changes for supporting WSLv2 I will happily accept this. -With a proper test environment (self-hosted runner) that will stay available, I would also add proper official support -where you can select the WSL version in your workflow files. - Thanks to the provided [typings](action-types.yml), it is possible to use this action in a type-safe way using https://github.com/typesafegithub/github-workflows-kt which allows writing workflow files using a type-safe Kotlin DSL. @@ -333,6 +326,26 @@ _**Examples:**_ run: DEL /F "\${{ steps.execute_action.outputs.wsl-shell-wrapper-path }}" ``` +#### wsl-version + +The WSL version that should be used. This can be set to any positive integer. Using an untested one might +work or break, so issues a warning for the action run. Currently, WSLv1 and WSLv2 are tested and do not +issue a warning. If a new WSL version is available and your workflow works with it, please report an issue +so that proper tests can be added and the warning for that version removed. +Default is '1' if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2. +Default is '2' if not running on 'windows-2019' virtual environment. + +**Default value:** +* `1` if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2 +* `2` if not running on 'windows-2019' virtual environment + +_**Example:**_ +```yaml +- uses: Vampire/setup-wsl@v3 + with: + wsl-version: 1 +``` + ### Outputs diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index 1b252b116..e2b22f243 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -45,10 +45,13 @@ import kotlinx.coroutines.CoroutineStart.LAZY import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart import node.buffer.Buffer import node.buffer.BufferEncoding import node.fs.exists @@ -61,16 +64,17 @@ import node.process.Platform import node.process.process import nullwritable.NullWritable import org.w3c.dom.url.URL +import kotlin.time.Duration.Companion.seconds import actions.tool.cache.extractZip as toolCacheExtractZip -val wslHelp = GlobalScope.async(start = LAZY) { +suspend fun wslOutput(vararg args: String): String { val stdoutBuilder = StringBuilder() val stdoutBuilderUtf16Le = StringBuilder() val stderrBuilder = StringBuilder() val stderrBuilderUtf16Le = StringBuilder() exec( commandLine = "wsl", - args = arrayOf("--help"), + args = args, options = ExecOptions( ignoreReturnCode = true, outStream = NullWritable(), @@ -90,7 +94,15 @@ val wslHelp = GlobalScope.async(start = LAZY) { stdoutBuilder.append(stdoutBuilderUtf16Le) stdoutBuilder.append(stderrBuilder) stdoutBuilder.append(stderrBuilderUtf16Le) - stdoutBuilder.toString() + return stdoutBuilder.toString() +} + +val wslHelp = GlobalScope.async(start = LAZY) { + wslOutput("--help") +} + +val wslStatus = GlobalScope.async(start = LAZY) { + wslOutput("--status") } val distribution by lazy { @@ -230,6 +242,28 @@ val wslShellCommand by lazy { getInput("wsl-shell-command") } +val wslVersion = GlobalScope.async(start = LAZY) { + when (val input = getInput("wsl-version", InputOptions(required = true))) { + "1 | 2" -> if (wslHelp().contains("--set-default-version")) 2u else 1u + else -> { + input.toUIntOrNull().also { wslVersion -> + when (wslVersion) { + null, 0u -> error("'$input' is not a valid positive integer for 'wsl-version'.") + 1u -> Unit + else -> { + check(wslHelp().contains("--set-default-version")) { + "This Windows environment only has WSLv1 available but WSLv$wslVersion was requested, please verify your 'runs-on' and 'wsl-version' settings" + } + if (wslVersion > 2u) { + warning("WSLv$wslVersion is untested, if it works with your workflow please open an issue to get the version tested and this warning removed") + } + } + } + } + } + } +} + val wslShellName by lazy { wslShellCommand .takeIf { it.isNotEmpty() } @@ -338,8 +372,20 @@ suspend fun verifyWindowsEnvironment() { suspend fun installDistribution() { executeWslCommand( - wslArguments = arrayOf("--set-default-version", "1") + wslArguments = arrayOf("--set-default-version", "${wslVersion()}") ) + if (wslVersion() != 1u) { + executeWslCommand( + wslArguments = arrayOf("--update") + ) + + (2..30) + .asFlow() + .onEach { delay(1.seconds) } + .onStart { emit(1) } + .map { wslStatus() } + .firstOrNull { !it.contains("WSL is finishing an upgrade...") } + } exec( commandLine = """"${path.join(distributionDirectory(), distribution.installerFile)}"""", args = arrayOf("install", "--root"), From ed92ae3c77c3b588f44a6a4b39d83bb4e9c4781e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 4 Dec 2024 14:57:59 +0100 Subject: [PATCH 03/21] Correct README ToC and default value formatting --- README.md | 7 +++---- readme/README.md.sha256 | 2 +- readme/README_template.md | 7 +++---- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 5928033ea..ad4ccde4a 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Table of Contents * [additional-packages](#additional-packages) * [wsl-shell-user](#wsl-shell-user) * [wsl-shell-command](#wsl-shell-command) + * [wsl-version](#wsl-version) * [Outputs](#outputs) * [wsl-shell-wrapper-path](#wsl-shell-wrapper-path) * [wsl-shell-distribution-wrapper-path](#wsl-shell-distribution-wrapper-path) @@ -332,12 +333,10 @@ The WSL version that should be used. This can be set to any positive integer. Us work or break, so issues a warning for the action run. Currently, WSLv1 and WSLv2 are tested and do not issue a warning. If a new WSL version is available and your workflow works with it, please report an issue so that proper tests can be added and the warning for that version removed. -Default is '1' if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2. -Default is '2' if not running on 'windows-2019' virtual environment. **Default value:** -* `1` if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2 -* `2` if not running on 'windows-2019' virtual environment +* `1` if running on `windows-2019` virtual environment as this is not yet supporting WSLv2 +* `2` if not running on `windows-2019` virtual environment _**Example:**_ ```yaml diff --git a/readme/README.md.sha256 b/readme/README.md.sha256 index 040d13756..b68f9a024 100644 --- a/readme/README.md.sha256 +++ b/readme/README.md.sha256 @@ -1 +1 @@ -ce427b3e65e8881e22af3e7eb40d94b47cb6e0f35202af007cf8bc2a71420b3e \ No newline at end of file +a4a08994b4084d8276b16c93ffb0aa463b123749334a22ae5ff39dbb461300e0 \ No newline at end of file diff --git a/readme/README_template.md b/readme/README_template.md index 4739e9bb8..f4e47695c 100644 --- a/readme/README_template.md +++ b/readme/README_template.md @@ -33,6 +33,7 @@ Table of Contents * [additional-packages](#additional-packages) * [wsl-shell-user](#wsl-shell-user) * [wsl-shell-command](#wsl-shell-command) + * [wsl-version](#wsl-version) * [Outputs](#outputs) * [wsl-shell-wrapper-path](#wsl-shell-wrapper-path) * [wsl-shell-distribution-wrapper-path](#wsl-shell-distribution-wrapper-path) @@ -332,12 +333,10 @@ The WSL version that should be used. This can be set to any positive integer. Us work or break, so issues a warning for the action run. Currently, WSLv1 and WSLv2 are tested and do not issue a warning. If a new WSL version is available and your workflow works with it, please report an issue so that proper tests can be added and the warning for that version removed. -Default is '1' if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2. -Default is '2' if not running on 'windows-2019' virtual environment. **Default value:** -* `1` if running on 'windows-2019' virtual environment as this is not yet supporting WSLv2 -* `2` if not running on 'windows-2019' virtual environment +* `1` if running on `windows-2019` virtual environment as this is not yet supporting WSLv2 +* `2` if not running on `windows-2019` virtual environment _**Example:**_ ```yaml From 3d42bb08fcd4729645bee8273cb0ee23cb4353d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 5 Dec 2024 10:18:52 +0100 Subject: [PATCH 04/21] Use permanent short-link again for Ubuntu 16.04 --- .../net/kautler/github/action/setup_wsl/Distribution.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 22928145a..670b19ca8 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -293,9 +293,7 @@ object Ubuntu1604 : AptGetBasedDistribution( wslId = "Ubuntu-16.04", distributionName = "Ubuntu", version = SemVer("16.4.0"), - // work-around for https://github.com/microsoft/WSL/issues/12336 - //downloadUrl = URL("https://aka.ms/wsl-ubuntu-1604"), - downloadUrl = URL("https://wslstorestorage.blob.core.windows.net/wslblob/Ubuntu_1604.2019.523.0_x64.appx"), + downloadUrl = URL("https://aka.ms/wsl-ubuntu-1604"), installerFile = "ubuntu1604.exe" ) From 10b7b9a787f6a4b01cec7941ddac1d50d0b0f13e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 30 Dec 2024 18:59:37 +0100 Subject: [PATCH 05/21] Retry WSLv2 update up to 5 times due to unreliable download server (#66) --- .../github/action/setup_wsl/Distribution.kt | 14 -------------- .../kautler/github/action/setup_wsl/Retry.kt | 17 +++++++++++++++++ .../kautler/github/action/setup_wsl/SetupWsl.kt | 8 +++++--- 3 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 670b19ca8..06fb3765f 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -17,7 +17,6 @@ package net.kautler.github.action.setup_wsl import actions.core.debug -import actions.core.info import actions.core.isDebug import actions.exec.ExecOptions import actions.exec.exec @@ -487,16 +486,3 @@ object Alpine : ApkBasedDistribution( productId = "9p804crf0395", installerFile = "Alpine.exe" ) - -private suspend inline fun retry(amount: Int, crossinline block: suspend () -> T): T { - (1..amount).map { i -> - runCatching { - return block() - }.onFailure { - if (i != 5) { - debug(it.stackTraceToString()) - info("Failure happened, retrying (${it.message ?: it})") - } - } - }.last().getOrThrow() -} diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt new file mode 100644 index 000000000..bff236b74 --- /dev/null +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt @@ -0,0 +1,17 @@ +package net.kautler.github.action.setup_wsl + +import actions.core.debug +import actions.core.info + +internal suspend inline fun retry(amount: Int, crossinline block: suspend () -> T): T { + (1..amount).map { i -> + runCatching { + return block() + }.onFailure { + if (i != 5) { + debug(it.stackTraceToString()) + info("Failure happened, retrying (${it.message ?: it})") + } + } + }.last().getOrThrow() +} diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index e2b22f243..b89a785d6 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -375,9 +375,11 @@ suspend fun installDistribution() { wslArguments = arrayOf("--set-default-version", "${wslVersion()}") ) if (wslVersion() != 1u) { - executeWslCommand( - wslArguments = arrayOf("--update") - ) + retry(5) { + executeWslCommand( + wslArguments = arrayOf("--update") + ) + } (2..30) .asFlow() From b2fcdb982014a75f098b9cce0eb510a006ef98fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Jan 2025 10:52:18 +0100 Subject: [PATCH 06/21] Increase version to 4.1.0 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 1e00ef559..32eaabae5 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,7 +13,7 @@ # limitations under the License. group = net.kautler -version = 4.0.1-SNAPSHOT +version = 4.1.0-SNAPSHOT description = A GitHub action to install and setup a Linux distribution for the Windows Subsystem for Linux (WSL) org.gradle.caching = true From c82592e3ccf0514d639951ceafb4c5a393340c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 30 Dec 2024 19:17:57 +0100 Subject: [PATCH 07/21] Add support for windows-2025 runner images (#65) --- .github/workflows/test.main.kts | 1 + .github/workflows/test.yaml | 35 +++++++ .../github/action/setup_wsl/SetupWsl.kt | 97 ++++++++++++++++--- 3 files changed, 122 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 7ad32ef86..09ccae623 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -56,6 +56,7 @@ import kotlin.math.min val environments = listOf( "windows-2019", "windows-2022", + "windows-2025", "windows-latest" ) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 7742c65a2..d7e22c145 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -86,6 +86,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - user-id: 'invalid' @@ -127,6 +128,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' wsl-version: - '-1' @@ -167,6 +169,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -372,6 +375,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -936,6 +940,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1045,6 +1050,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1190,6 +1196,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1326,6 +1333,7 @@ jobs: matrix: environment: - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1407,6 +1415,7 @@ jobs: matrix: environment: - 'windows-2022' + - 'windows-2025' - 'windows-latest' steps: - id: 'step-0' @@ -1457,6 +1466,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1538,6 +1548,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distributions: - distribution1: @@ -1694,6 +1705,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distribution: - wsl-id: 'Debian' @@ -1760,6 +1772,17 @@ jobs: user-id: 'Debian' match-pattern: '*Debian*' default-absent-tool: 'dos2unix' + - environment: 'windows-2025' + distribution: + wsl-id: 'Debian' + user-id: 'Debian' + match-pattern: '*Debian*' + default-absent-tool: 'dos2unix' + distribution2: + wsl-id: 'Debian' + user-id: 'Debian' + match-pattern: '*Debian*' + default-absent-tool: 'dos2unix' - environment: 'windows-latest' distribution: wsl-id: 'Debian' @@ -1794,6 +1817,17 @@ jobs: user-id: 'Ubuntu-20.04' match-pattern: '*Ubuntu*20.04*' default-absent-tool: 'dos2unix' + - environment: 'windows-2025' + distribution: + wsl-id: 'Debian' + user-id: 'Debian' + match-pattern: '*Debian*' + default-absent-tool: 'dos2unix' + distribution2: + wsl-id: 'Ubuntu' + user-id: 'Ubuntu-20.04' + match-pattern: '*Ubuntu*20.04*' + default-absent-tool: 'dos2unix' - environment: 'windows-latest' distribution: wsl-id: 'Debian' @@ -1981,6 +2015,7 @@ jobs: environment: - 'windows-2019' - 'windows-2022' + - 'windows-2025' - 'windows-latest' distributions: - incompatibleUbuntu: 'Ubuntu-22.04' diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index b89a785d6..67c88996f 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -37,6 +37,7 @@ import actions.exec.ExecOptions import actions.exec.exec import actions.io.mkdirP import actions.io.mv +import actions.io.rmRF import actions.io.which import actions.tool.cache.cacheDir import actions.tool.cache.downloadTool @@ -57,6 +58,7 @@ import node.buffer.BufferEncoding import node.fs.exists import node.fs.mkdtemp import node.fs.readdir +import node.fs.stat import node.fs.writeFile import node.os.tmpdir import node.path.path @@ -64,9 +66,17 @@ import node.process.Platform import node.process.process import nullwritable.NullWritable import org.w3c.dom.url.URL +import kotlin.time.Duration +import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds import actions.tool.cache.extractZip as toolCacheExtractZip +private const val BAD_WSL_EXE_PATH = + "C:\\Users\\runneradmin\\AppData\\Local\\Microsoft\\WindowsApps\\wsl.exe" + +private const val BAD_WSLCONFIG_EXE_PATH = + "C:\\Users\\runneradmin\\AppData\\Local\\Microsoft\\WindowsApps\\wslconfig.exe" + suspend fun wslOutput(vararg args: String): String { val stdoutBuilder = StringBuilder() val stdoutBuilderUtf16Le = StringBuilder() @@ -101,10 +111,6 @@ val wslHelp = GlobalScope.async(start = LAZY) { wslOutput("--help") } -val wslStatus = GlobalScope.async(start = LAZY) { - wslOutput("--status") -} - val distribution by lazy { val distributionId = getInput("distribution", InputOptions(required = true)) @@ -125,6 +131,10 @@ val wslId = GlobalScope.async(start = LAZY) { distribution.wslId } +val wslInstallationNeeded = GlobalScope.async(start = LAZY) { + wslOutput("--status").contains("is not installed") +} + val installationNeeded = GlobalScope.async(start = LAZY) { exec( commandLine = "wsl", @@ -292,6 +302,12 @@ suspend fun main() { if (getInput("only safe actions").isEmpty() || !getBooleanInput("only safe actions") ) { + // on windows-2025 WSL is not installed at all currently, so install it without distribution + // work-around for https://github.com/actions/runner-images/issues/11265 + if (wslInstallationNeeded()) { + group("Install WSL", ::installWsl) + } + if (installationNeeded()) { group("Install Distribution", ::installDistribution) } @@ -370,24 +386,67 @@ suspend fun verifyWindowsEnvironment() { } } +suspend fun installWsl() { + // part of work-around for https://github.com/actions/toolkit/issues/1925 + val deleteWslExe = + runCatching { stat(BAD_WSL_EXE_PATH).isFile() } + .getOrDefault(false) + .not() + val deleteWslConfigExe = + runCatching { stat(BAD_WSLCONFIG_EXE_PATH).isFile() } + .getOrDefault(false) + .not() + + exec( + commandLine = "pwsh", + args = arrayOf("-Command", """Start-Process wsl "--install --no-distribution""""), + options = ExecOptions(ignoreReturnCode = true) + ) + + waitForWslStatusNotContaining("is not installed", 5.minutes) { + // part of work-around for https://github.com/actions/toolkit/issues/1925 + if (deleteWslExe) { + rmRF(BAD_WSL_EXE_PATH) + } + if (deleteWslConfigExe) { + rmRF(BAD_WSLCONFIG_EXE_PATH) + } + } +} + suspend fun installDistribution() { executeWslCommand( wslArguments = arrayOf("--set-default-version", "${wslVersion()}") ) + if (wslVersion() != 1u) { - retry(5) { + // part of work-around for https://github.com/actions/toolkit/issues/1925 + val deleteWslExe = + runCatching { stat(BAD_WSL_EXE_PATH).isFile() } + .getOrDefault(false) + .not() + val deleteWslConfigExe = + runCatching { stat(BAD_WSLCONFIG_EXE_PATH).isFile() } + .getOrDefault(false) + .not() + + retry(10) { executeWslCommand( wslArguments = arrayOf("--update") ) } - (2..30) - .asFlow() - .onEach { delay(1.seconds) } - .onStart { emit(1) } - .map { wslStatus() } - .firstOrNull { !it.contains("WSL is finishing an upgrade...") } + // part of work-around for https://github.com/actions/toolkit/issues/1925 + waitForWslStatusNotContaining("WSL is finishing an upgrade...") { + if (deleteWslExe) { + rmRF(BAD_WSL_EXE_PATH) + } + if (deleteWslConfigExe) { + rmRF(BAD_WSLCONFIG_EXE_PATH) + } + } } + exec( commandLine = """"${path.join(distributionDirectory(), distribution.installerFile)}"""", args = arrayOf("install", "--root"), @@ -395,6 +454,22 @@ suspend fun installDistribution() { ) } +suspend fun waitForWslStatusNotContaining( + text: String, + duration: Duration = 30.seconds, + preAction: suspend () -> Unit = {} +) { + (2..duration.inWholeSeconds) + .asFlow() + .onEach { delay(1.seconds) } + .onStart { emit(1) } + .map { + preAction() + wslOutput("--status") + } + .firstOrNull { !it.contains(text) } +} + suspend fun adjustWslConf() { exec( commandLine = "wsl", From 560a7ce76986a9dcfe9c36de0029bef16f513a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Jan 2025 14:50:46 +0100 Subject: [PATCH 08/21] Update copyright dates --- .github/workflows/check-action-typing.yaml | 2 +- .github/workflows/check-dependency-versions.yaml | 2 +- .github/workflows/test.main.kts | 2 +- .github/workflows/test.yaml | 2 +- .github/workflows/validate-gradle-wrapper.yaml | 2 +- .github/workflows/workflow-with-copyright.main.kts | 4 ++-- gradle.properties | 2 +- .../kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/check-action-typing.yaml b/.github/workflows/check-action-typing.yaml index 34ae96cd2..bfadd12c0 100644 --- a/.github/workflows/check-action-typing.yaml +++ b/.github/workflows/check-action-typing.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Björn Kautler +# Copyright 2020-2025 Björn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 081ed42f3..2f7b48858 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Björn Kautler +# Copyright 2020-2025 Björn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 09ccae623..3a5364a76 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -1,7 +1,7 @@ #!/usr/bin/env kotlin /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index d7e22c145..83570e587 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Björn Kautler +# Copyright 2020-2025 Björn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.github/workflows/validate-gradle-wrapper.yaml b/.github/workflows/validate-gradle-wrapper.yaml index 50eb0e94f..cd422bcc4 100644 --- a/.github/workflows/validate-gradle-wrapper.yaml +++ b/.github/workflows/validate-gradle-wrapper.yaml @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Björn Kautler +# Copyright 2020-2025 Björn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/.github/workflows/workflow-with-copyright.main.kts b/.github/workflows/workflow-with-copyright.main.kts index 8b550b0c6..588549022 100644 --- a/.github/workflows/workflow-with-copyright.main.kts +++ b/.github/workflows/workflow-with-copyright.main.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,7 +40,7 @@ fun workflowWithCopyright( concurrency = concurrency, preamble = WithOriginalAfter( """ - Copyright 2020-2024 Björn Kautler + Copyright 2020-2025 Björn Kautler Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/gradle.properties b/gradle.properties index a55c66612..c110d5b2b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -# Copyright 2020-2023 Bj�rn Kautler +# Copyright 2020-2025 Bj�rn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index 67c88996f..d5fbfdceb 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From e5226c2f8b7cbdd8865af8874eb3806de068e17c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Jan 2025 13:32:08 +0100 Subject: [PATCH 09/21] Add a workflow that verifies all workflow YAMLs for consistency --- ...eck-all-workflow-yaml-consistency.main.kts | 61 +++++++++++++++++++ .../check-all-workflow-yaml-consistency.yaml | 56 +++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100755 .github/workflows/check-all-workflow-yaml-consistency.main.kts create mode 100644 .github/workflows/check-all-workflow-yaml-consistency.yaml diff --git a/.github/workflows/check-all-workflow-yaml-consistency.main.kts b/.github/workflows/check-all-workflow-yaml-consistency.main.kts new file mode 100755 index 000000000..b8632e004 --- /dev/null +++ b/.github/workflows/check-all-workflow-yaml-consistency.main.kts @@ -0,0 +1,61 @@ +#!/usr/bin/env kotlin + +/* + * Copyright 2020-2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Import("workflow-with-copyright.main.kts") +@file:Repository("https://bindings.krzeminski.it/") +@file:DependsOn("actions:checkout:v4") + +import io.github.typesafegithub.workflows.actions.actions.Checkout +import io.github.typesafegithub.workflows.domain.RunnerType.UbuntuLatest +import io.github.typesafegithub.workflows.domain.triggers.PullRequest +import io.github.typesafegithub.workflows.domain.triggers.Push + +workflowWithCopyright( + name = "Check all Workflow YAML Consistency", + on = listOf( + Push(), + PullRequest() + ), + sourceFile = __FILE__ +) { + job( + id = "check_all_workflow_yaml_consistency", + name = "Check all Workflow YAML Consistency", + runsOn = UbuntuLatest + ) { + run( + name = "Configure Git", + command = "git config --global core.autocrlf input" + ) + uses( + name = "Checkout", + action = Checkout() + ) + run( + name = "Regenerate all Workflow YAMLs", + command = """find .github/workflows -mindepth 1 -maxdepth 1 -name '*.main.kts' -exec {} \;""" + ) + run( + name = "Check for Modifications", + command = """ + git add --intent-to-add . + git diff --exit-code + """.trimIndent() + ) + } +} diff --git a/.github/workflows/check-all-workflow-yaml-consistency.yaml b/.github/workflows/check-all-workflow-yaml-consistency.yaml new file mode 100644 index 000000000..d357171c3 --- /dev/null +++ b/.github/workflows/check-all-workflow-yaml-consistency.yaml @@ -0,0 +1,56 @@ +# Copyright 2020-2025 Björn Kautler +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file was generated using Kotlin DSL (.github/workflows/check-all-workflow-yaml-consistency.main.kts). +# If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. +# Generated with https://github.com/typesafegithub/github-workflows-kt + +name: 'Check all Workflow YAML Consistency' +on: + push: {} + pull_request: {} +jobs: + check_yaml_consistency: + name: 'Check YAML consistency' + runs-on: 'ubuntu-latest' + steps: + - id: 'step-0' + name: 'Check out' + uses: 'actions/checkout@v4' + - id: 'step-1' + name: 'Execute script' + run: 'rm ''.github/workflows/check-all-workflow-yaml-consistency.yaml'' && ''.github/workflows/check-all-workflow-yaml-consistency.main.kts''' + - id: 'step-2' + name: 'Consistency check' + run: 'git diff --exit-code ''.github/workflows/check-all-workflow-yaml-consistency.yaml''' + check_all_workflow_yaml_consistency: + name: 'Check all Workflow YAML Consistency' + runs-on: 'ubuntu-latest' + needs: + - 'check_yaml_consistency' + steps: + - id: 'step-0' + name: 'Configure Git' + run: 'git config --global core.autocrlf input' + - id: 'step-1' + name: 'Checkout' + uses: 'actions/checkout@v4' + - id: 'step-2' + name: 'Regenerate all Workflow YAMLs' + run: 'find .github/workflows -mindepth 1 -maxdepth 1 -name ''*.main.kts'' -exec {} \;' + - id: 'step-3' + name: 'Check for Modifications' + run: |- + git add --intent-to-add . + git diff --exit-code From 37c005c630b93c4be29000d932b7d528c62e5715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Jan 2025 13:33:22 +0100 Subject: [PATCH 10/21] Add a workflow that verifies a freshly released version for basic functioning --- .github/workflows/verify-release.main.kts | 46 ++++++++++++++++++++++ .github/workflows/verify-release.yaml | 47 +++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100755 .github/workflows/verify-release.main.kts create mode 100644 .github/workflows/verify-release.yaml diff --git a/.github/workflows/verify-release.main.kts b/.github/workflows/verify-release.main.kts new file mode 100755 index 000000000..3bebe2b9e --- /dev/null +++ b/.github/workflows/verify-release.main.kts @@ -0,0 +1,46 @@ +#!/usr/bin/env kotlin + +/* + * Copyright 2020-2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:Import("workflow-with-copyright.main.kts") +@file:Repository("https://bindings.krzeminski.it/") +@file:DependsOn("Vampire:setup-wsl:RELEASE") + +import io.github.typesafegithub.workflows.actions.vampire.SetupWsl +import io.github.typesafegithub.workflows.domain.RunnerType.WindowsLatest +import io.github.typesafegithub.workflows.domain.triggers.Push +import io.github.typesafegithub.workflows.domain.triggers.WorkflowDispatch + +workflowWithCopyright( + name = "Verify Release", + on = listOf( + Push(tags = listOf("v*")), + WorkflowDispatch() + ), + sourceFile = __FILE__ +) { + job( + id = "verify_release", + name = "Verify Release", + runsOn = WindowsLatest + ) { + uses( + name = "Check for Modifications", + action = SetupWsl() + ) + } +} diff --git a/.github/workflows/verify-release.yaml b/.github/workflows/verify-release.yaml new file mode 100644 index 000000000..aa8df8f87 --- /dev/null +++ b/.github/workflows/verify-release.yaml @@ -0,0 +1,47 @@ +# Copyright 2020-2025 Björn Kautler +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# This file was generated using Kotlin DSL (.github/workflows/verify-release.main.kts). +# If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. +# Generated with https://github.com/typesafegithub/github-workflows-kt + +name: 'Verify Release' +on: + push: + tags: + - 'v*' + workflow_dispatch: {} +jobs: + check_yaml_consistency: + name: 'Check YAML consistency' + runs-on: 'ubuntu-latest' + steps: + - id: 'step-0' + name: 'Check out' + uses: 'actions/checkout@v4' + - id: 'step-1' + name: 'Execute script' + run: 'rm ''.github/workflows/verify-release.yaml'' && ''.github/workflows/verify-release.main.kts''' + - id: 'step-2' + name: 'Consistency check' + run: 'git diff --exit-code ''.github/workflows/verify-release.yaml''' + verify_release: + name: 'Verify Release' + runs-on: 'windows-latest' + needs: + - 'check_yaml_consistency' + steps: + - id: 'step-0' + name: 'Check for Modifications' + uses: 'Vampire/setup-wsl@v4' From 233ed8bce22b17aab736ba96580ef4b5d5257463 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Jan 2025 14:00:05 +0100 Subject: [PATCH 11/21] Use latest action API in test workflow --- .github/workflows/test.main.kts | 111 +++++++++++++------------------- 1 file changed, 43 insertions(+), 68 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 3a5364a76..fd9ed1ae6 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -23,7 +23,7 @@ @file:DependsOn("actions:checkout:v4") @file:DependsOn("actions:setup-java:v4") @file:DependsOn("burrunan:gradle-cache-action:v1") -@file:DependsOn("Vampire:setup-wsl:v3") +@file:DependsOn("Vampire:setup-wsl:RELEASE") import io.github.typesafegithub.workflows.actions.actions.CacheRestore import io.github.typesafegithub.workflows.actions.actions.CacheSave @@ -157,9 +157,7 @@ workflowWithCopyright( val executeAction = SetupWsl( distribution = SetupWsl.Distribution.Custom(expr("matrix.distribution.user-id")), - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) val build = job( @@ -289,9 +287,8 @@ workflowWithCopyright( executeActionStep = usesSelf( action = executeAction.copy( distribution = Debian, - _customInputs = mapOf( - "wsl-version" to expr("matrix.wsl-version") - ) + wslVersion = null, + wslVersion_Untyped = expr("matrix.wsl-version") ), continueOnError = true ) @@ -318,9 +315,7 @@ workflowWithCopyright( executeActionStep = usesSelf( action = SetupWsl( update = true, - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) commonTests() @@ -362,10 +357,9 @@ workflowWithCopyright( executeActionStep = usesSelf( action = executeAction.copy( useCache = false, - _customInputs = mapOf( - // part of work-around for https://bugs.kali.org/view.php?id=8921 - "wsl-version" to expr(getWslVersionExpression(kali)) - ) + // part of work-around for https://bugs.kali.org/view.php?id=8921 + wslVersion = null, + wslVersion_Untyped = expr(getWslVersionExpression(kali)) ) ) verifyFailure( @@ -381,7 +375,7 @@ workflowWithCopyright( name = "Install Bash on Alpine", action = executeAction.copy( additionalPackages = listOf("bash"), - _customInputs = emptyMap() + wslVersion = null ), condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) @@ -407,7 +401,7 @@ workflowWithCopyright( name = "Add wsl-sh wrapper", action = executeAction.copy( wslShellCommand = "sh -eu", - _customInputs = emptyMap() + wslVersion = null ) ) runAfterSuccess( @@ -442,7 +436,7 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Re-add wsl-bash wrapper", action = executeAction.copy( - _customInputs = emptyMap() + wslVersion = null ) ) runAfterSuccess( @@ -485,7 +479,7 @@ workflowWithCopyright( action = executeAction.copy( additionalPackages = listOf("sudo"), wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\""", - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -529,7 +523,7 @@ workflowWithCopyright( }, action = executeAction.copy( wslShellCommand = """bash -c "sudo -u test bash --noprofile --norc -euo pipefail '{0}'"""", - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -541,7 +535,7 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Set wsl-bash wrapper to use default user by default", action = executeAction.copy( - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -558,7 +552,7 @@ workflowWithCopyright( name = "Set wsl-bash wrapper to use existing user test by default with extra parameter", action = executeAction.copy( wslShellUser = "test", - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -575,7 +569,7 @@ workflowWithCopyright( name = "Set wsl-bash wrapper to use non-existing user test2 by default with extra parameter", action = executeAction.copy( wslShellUser = "test2", - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -598,7 +592,7 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Make a no-op execution of the action", action = executeAction.copy( - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -634,7 +628,7 @@ workflowWithCopyright( name = "Install Bash on Alpine", action = executeAction.copy( additionalPackages = listOf("bash"), - _customInputs = emptyMap() + wslVersion = null ), condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) @@ -675,7 +669,7 @@ workflowWithCopyright( name = "Install Bash on Alpine", action = executeAction.copy( additionalPackages = listOf("bash"), - _customInputs = emptyMap() + wslVersion = null ), condition = executeActionStep.getSuccessOnDistributionCondition(alpine) ) @@ -704,7 +698,7 @@ workflowWithCopyright( [automount] root = / """.trimIndent(), - _customInputs = emptyMap() + wslVersion = null ) ) runAfterSuccess( @@ -742,10 +736,9 @@ workflowWithCopyright( expr("matrix.distribution.default-absent-tool"), "bash" ), - _customInputs = mapOf( - // part of work-around for https://bugs.kali.org/view.php?id=8921 - "wsl-version" to expr(getWslVersionExpression(kali)) - ) + // part of work-around for https://bugs.kali.org/view.php?id=8921 + wslVersion = null, + wslVersion_Untyped = expr(getWslVersionExpression(kali)) ), // part of work-around for https://bugs.kali.org/view.php?id=8921 condition = """ @@ -824,9 +817,8 @@ workflowWithCopyright( """.trimIndent() ) ), - _customInputs = mapOf( - "wsl-version" to expr("matrix.wsl-version") - ) + wslVersion = null, + wslVersion_Untyped = expr("matrix.wsl-version") ) ) verifyCommandResult( @@ -855,25 +847,19 @@ workflowWithCopyright( usesSelf( action = executeAction.copy( distribution = Debian, - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) usesSelf( action = executeAction.copy( distribution = Ubuntu1604, - _customInputs = mapOf( - "wsl-version" to "2" - ) + wslVersion = 2 ) ) executeActionStep = usesSelf( action = executeAction.copy( distribution = Ubuntu1804, - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) verifyCommandResult( @@ -912,7 +898,7 @@ workflowWithCopyright( """.trimIndent() ) ), - _customInputs = emptyMap() + wslVersion = null ) ) verifyCommandResult( @@ -992,18 +978,14 @@ workflowWithCopyright( name = "Execute action for ${expr("matrix.distributions.distribution1.user-id")}", action = SetupWsl( distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution1.user-id")), - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution2.user-id")}", action = SetupWsl( distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution2.user-id")), - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) usesSelf( @@ -1011,9 +993,7 @@ workflowWithCopyright( action = SetupWsl( distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution3.user-id")), setAsDefault = false, - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) executeActionStep = usesSelf( @@ -1087,19 +1067,18 @@ workflowWithCopyright( """.trimMargin() ) ), - _customInputs = mapOf( - // part of work-around for https://bugs.kali.org/view.php?id=8921 - // and https://bugs.kali.org/view.php?id=6672 - // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 - "wsl-version" to expr(getWslVersionExpression(kali, ubuntu2404)) - ) + // part of work-around for https://bugs.kali.org/view.php?id=8921 + // and https://bugs.kali.org/view.php?id=6672 + // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 + wslVersion = null, + wslVersion_Untyped = expr(getWslVersionExpression(kali, ubuntu2404)) ) ) usesSelf( name = "Update distribution", action = executeAction.copy( update = true, - _customInputs = emptyMap() + wslVersion = null ), // part of work-around for https://bugs.kali.org/view.php?id=6672 // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 @@ -1119,7 +1098,7 @@ workflowWithCopyright( name = "Install default absent tool", action = executeAction.copy( additionalPackages = listOf(expr("matrix.distribution.default-absent-tool")), - _customInputs = emptyMap() + wslVersion = null ), // part of work-around for https://bugs.kali.org/view.php?id=8921 condition = """ @@ -1155,9 +1134,7 @@ workflowWithCopyright( name = "Execute action for ${expr("matrix.distribution2.user-id")}", action = SetupWsl( distribution = SetupWsl.Distribution.Custom(expr("matrix.distribution2.user-id")), - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) verifyInstalledDistribution( @@ -1167,7 +1144,7 @@ workflowWithCopyright( executeActionStep = usesSelfAfterSuccess( name = "Re-execute action", action = executeAction.copy( - _customInputs = emptyMap() + wslVersion = null ) ) verifyInstalledDistribution( @@ -1178,7 +1155,7 @@ workflowWithCopyright( name = "Set as default", action = executeAction.copy( setAsDefault = true, - _customInputs = emptyMap() + wslVersion = null ) ) verifyInstalledDistribution( @@ -1222,9 +1199,7 @@ workflowWithCopyright( distribution = SetupWsl.Distribution.Custom(expr("matrix.distributions.distribution$it.user-id")), additionalPackages = if (it == 2) listOf("bash") else null, setAsDefault = if (it >= 3) false else null, - _customInputs = mapOf( - "wsl-version" to "1" - ) + wslVersion = 1 ) ) } From f6fe12ca25444b921c5a51961b16492a51b717ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 6 Jan 2025 17:08:06 +0100 Subject: [PATCH 12/21] Fix step name in GHA workflow --- .github/workflows/verify-release.main.kts | 2 +- .github/workflows/verify-release.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/verify-release.main.kts b/.github/workflows/verify-release.main.kts index 3bebe2b9e..efc046faf 100755 --- a/.github/workflows/verify-release.main.kts +++ b/.github/workflows/verify-release.main.kts @@ -39,7 +39,7 @@ workflowWithCopyright( runsOn = WindowsLatest ) { uses( - name = "Check for Modifications", + name = "Execute action", action = SetupWsl() ) } diff --git a/.github/workflows/verify-release.yaml b/.github/workflows/verify-release.yaml index aa8df8f87..78a89454c 100644 --- a/.github/workflows/verify-release.yaml +++ b/.github/workflows/verify-release.yaml @@ -43,5 +43,5 @@ jobs: - 'check_yaml_consistency' steps: - id: 'step-0' - name: 'Check for Modifications' + name: 'Execute action' uses: 'Vampire/setup-wsl@v4' From a6b8abba45a1fe245e901db185273bbfa87cba7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 31 Jan 2025 00:39:14 +0100 Subject: [PATCH 13/21] Update github-workflows-kt to 3.2.0 --- .github/workflows/check-action-typing.main.kts | 7 ++++++- .../workflows/check-all-workflow-yaml-consistency.main.kts | 5 +++++ .github/workflows/check-dependency-versions.main.kts | 7 ++++++- .github/workflows/test.main.kts | 5 +++++ .github/workflows/validate-gradle-wrapper.main.kts | 7 ++++++- .github/workflows/verify-release.main.kts | 5 +++++ .github/workflows/workflow-with-copyright.main.kts | 2 +- 7 files changed, 34 insertions(+), 4 deletions(-) diff --git a/.github/workflows/check-action-typing.main.kts b/.github/workflows/check-action-typing.main.kts index f9c0bdd8c..ce7caeb81 100755 --- a/.github/workflows/check-action-typing.main.kts +++ b/.github/workflows/check-action-typing.main.kts @@ -1,7 +1,7 @@ #!/usr/bin/env kotlin /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,11 @@ @file:Import("workflow-with-copyright.main.kts") @file:Repository("https://bindings.krzeminski.it/") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:DependsOn("actions:checkout:v4") @file:DependsOn("typesafegithub:github-actions-typing:v1") diff --git a/.github/workflows/check-all-workflow-yaml-consistency.main.kts b/.github/workflows/check-all-workflow-yaml-consistency.main.kts index b8632e004..38f73c37f 100755 --- a/.github/workflows/check-all-workflow-yaml-consistency.main.kts +++ b/.github/workflows/check-all-workflow-yaml-consistency.main.kts @@ -17,6 +17,11 @@ */ @file:Import("workflow-with-copyright.main.kts") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:Repository("https://bindings.krzeminski.it/") @file:DependsOn("actions:checkout:v4") diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index d915b01a7..cb5b43aae 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -1,7 +1,7 @@ #!/usr/bin/env kotlin /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,11 @@ */ @file:Import("workflow-with-copyright.main.kts") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:Repository("https://bindings.krzeminski.it/") @file:DependsOn("actions:checkout:v4") @file:DependsOn("actions:setup-java:v4") diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index fd9ed1ae6..e9218cca7 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -17,6 +17,11 @@ */ @file:Import("workflow-with-copyright.main.kts") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:Repository("https://bindings.krzeminski.it/") @file:DependsOn("actions:cache__restore:v4") @file:DependsOn("actions:cache__save:v4") diff --git a/.github/workflows/validate-gradle-wrapper.main.kts b/.github/workflows/validate-gradle-wrapper.main.kts index 19862fc4a..462511f3c 100755 --- a/.github/workflows/validate-gradle-wrapper.main.kts +++ b/.github/workflows/validate-gradle-wrapper.main.kts @@ -1,7 +1,7 @@ #!/usr/bin/env kotlin /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,6 +17,11 @@ */ @file:Import("workflow-with-copyright.main.kts") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:Repository("https://bindings.krzeminski.it/") @file:DependsOn("actions:checkout:v4") @file:DependsOn("gradle:wrapper-validation-action:v1") diff --git a/.github/workflows/verify-release.main.kts b/.github/workflows/verify-release.main.kts index efc046faf..e023a43e1 100755 --- a/.github/workflows/verify-release.main.kts +++ b/.github/workflows/verify-release.main.kts @@ -17,6 +17,11 @@ */ @file:Import("workflow-with-copyright.main.kts") + +@file:Repository("https://repo.maven.apache.org/maven2/") +// work-around for https://youtrack.jetbrains.com/issue/KT-69145 +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") + @file:Repository("https://bindings.krzeminski.it/") @file:DependsOn("Vampire:setup-wsl:RELEASE") diff --git a/.github/workflows/workflow-with-copyright.main.kts b/.github/workflows/workflow-with-copyright.main.kts index 588549022..45a906beb 100644 --- a/.github/workflows/workflow-with-copyright.main.kts +++ b/.github/workflows/workflow-with-copyright.main.kts @@ -15,7 +15,7 @@ */ @file:Repository("https://repo.maven.apache.org/maven2/") -@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.0.0") +@file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") import io.github.typesafegithub.workflows.domain.Concurrency import io.github.typesafegithub.workflows.domain.triggers.Trigger From c3895736a158ab9f6b327ab4c12577a85c8e669c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 31 Jan 2025 00:39:41 +0100 Subject: [PATCH 14/21] Fix logging on more than 5 retries --- .../kautler/github/action/setup_wsl/Retry.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt index bff236b74..92dd53df6 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Retry.kt @@ -1,3 +1,19 @@ +/* + * Copyright 2024-2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package net.kautler.github.action.setup_wsl import actions.core.debug @@ -8,7 +24,7 @@ internal suspend inline fun retry(amount: Int, crossinline block: suspend () runCatching { return block() }.onFailure { - if (i != 5) { + if (i != amount) { debug(it.stackTraceToString()) info("Failure happened, retrying (${it.message ?: it})") } From a408856faaf69b82a0241e3ee6ae0796b5aec855 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 31 Jan 2025 01:46:11 +0100 Subject: [PATCH 15/21] Make workflow generation via Gradle able to run in parallel --- .../net/kautler/github_actions.gradle.kts | 104 ++++-------------- .../githubactions/DetermineImportedFiles.kt | 59 ++++++++++ .../DetermineImportedFilesWorkAction.kt | 90 +++++++++++++++ .../githubactions/PreprocessGithubWorkflow.kt | 73 ++++++++++++ .../PreprocessGithubWorkflowWorkAction.kt | 56 ++++++++++ gradle/libs.versions.toml | 5 +- 6 files changed, 305 insertions(+), 82 deletions(-) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFiles.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFilesWorkAction.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflow.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflowWorkAction.kt diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts index eec2ae15e..ef4a4f468 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2024 Björn Kautler + * Copyright 2020-2025 Björn Kautler * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,26 +16,18 @@ package net.kautler +import net.kautler.githubactions.DetermineImportedFiles +import net.kautler.githubactions.PreprocessGithubWorkflow import org.gradle.accessors.dm.LibrariesForLibs -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY -import org.jetbrains.kotlin.cli.common.messages.MessageCollector.Companion.NONE -import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles.JVM_CONFIG_FILES -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer -import org.jetbrains.kotlin.com.intellij.openapi.vfs.local.CoreLocalFileSystem -import org.jetbrains.kotlin.com.intellij.openapi.vfs.local.CoreLocalVirtualFile -import org.jetbrains.kotlin.com.intellij.psi.PsiManager -import org.jetbrains.kotlin.config.CompilerConfiguration -import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry -import org.jetbrains.kotlin.psi.KtStringTemplateExpression -import java.nio.file.Path plugins { `java-base` } +val compilerEmbeddableClasspath by configurations.creating { + isCanBeConsumed = false +} + val compilerClasspath by configurations.creating { isCanBeConsumed = false } @@ -47,6 +39,7 @@ val scriptClasspath by configurations.creating { val libs = the() dependencies { + compilerEmbeddableClasspath(libs.workflows.kotlin.compiler.embeddable) compilerClasspath(libs.workflows.kotlin.compiler) compilerClasspath(libs.workflows.kotlin.scripting.compiler) scriptClasspath(libs.workflows.kotlin.main.kts) { @@ -64,72 +57,23 @@ file(".github/workflows") val pascalCasedWorkflowName = workflowName.replace("""-\w""".toRegex()) { it.value.substring(1).replaceFirstChar(Char::uppercaseChar) }.replaceFirstChar(Char::uppercaseChar) - val preprocessWorkflow = tasks.register("preprocess${pascalCasedWorkflowName}Workflow") { - group = "github actions" - - inputs - .file(workflowScript) - .withPropertyName("workflowScript") - inputs - .files(file(workflowScript).importedFiles) - .withPropertyName("importedFiles") - outputs - .file(workflowScript.resolveSibling("$workflowName.yaml")) - .withPropertyName("workflowFile") - - javaLauncher.set(javaToolchains.launcherFor { - languageVersion.set(JavaLanguageVersion.of(17)) - }) - classpath(compilerClasspath) - mainClass.set(K2JVMCompiler::class.qualifiedName) - args("-no-stdlib", "-no-reflect") - args("-classpath", scriptClasspath.asPath) - args("-script", workflowScript.absolutePath) - - // work-around for https://youtrack.jetbrains.com/issue/KT-42101 - systemProperty("kotlin.main.kts.compiled.scripts.cache.dir", "") - } + val determineImportedFiles = + tasks.register("determineImportedFilesFor${pascalCasedWorkflowName}Workflow") { + mainKtsFile.set(workflowScript) + importedFiles.set(layout.buildDirectory.file("importedFilesFor${pascalCasedWorkflowName}Workflow.txt")) + kotlinCompilerEmbeddableClasspath.from(compilerEmbeddableClasspath) + } + val preprocessWorkflow = + tasks.register("preprocess${pascalCasedWorkflowName}Workflow") { + this.workflowScript.set(workflowScript) + importedFiles.from(determineImportedFiles.flatMap { it.importedFiles }.map { it.asFile.readLines() }) + kotlinCompilerClasspath.from(compilerClasspath) + mainKtsClasspath.from(scriptClasspath) + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(17)) + }) + } preprocessWorkflows { dependsOn(preprocessWorkflow) } } - -val File.importedFiles: List - get() = if (!isFile) { - emptyList() - } else { - PsiManager - .getInstance( - KotlinCoreEnvironment - .createForProduction( - Disposer.newDisposable(), - CompilerConfiguration().apply { - put(MESSAGE_COLLECTOR_KEY, NONE) - }, - JVM_CONFIG_FILES - ) - .project - ) - .findFile( - // work-around for API change between version we compile against and version we run against - // after upgrading Gradle to a version that contains Kotlin 1.9 the embeddable compiler can - // be upgraded to v2 also for compilation and then this can be removed - CoreLocalVirtualFile::class - .java - .getConstructor(CoreLocalFileSystem::class.java, Path::class.java) - .newInstance(CoreLocalFileSystem(), toPath()) - ) - .let { it as KtFile } - .fileAnnotationList - ?.annotationEntries - ?.asSequence() - ?.filter { it.shortName?.asString() == "Import" } - ?.flatMap { it.valueArgumentList?.arguments ?: emptyList() } - ?.mapNotNull { it.getArgumentExpression() as? KtStringTemplateExpression } - ?.map { it.entries.first() } - ?.mapNotNull { it as? KtLiteralStringTemplateEntry } - ?.map { resolveSibling(it.text) } - ?.flatMap { it.importedFiles + it } - ?.toList() - ?: emptyList() - } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFiles.kt b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFiles.kt new file mode 100644 index 000000000..449f53f99 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFiles.kt @@ -0,0 +1,59 @@ +/* + * Copyright 2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.kautler.githubactions + +import org.gradle.api.DefaultTask +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.ProjectLayout +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import org.gradle.api.tasks.UntrackedTask +import org.gradle.kotlin.dsl.submit +import org.gradle.workers.WorkerExecutor +import javax.inject.Inject + +@UntrackedTask(because = "imported files can import other files so inputs are not determinable upfront") +abstract class DetermineImportedFiles : DefaultTask() { + @get:InputFile + abstract val mainKtsFile: RegularFileProperty + + @get:InputFiles + abstract val kotlinCompilerEmbeddableClasspath: ConfigurableFileCollection + + @get:OutputFile + abstract val importedFiles: RegularFileProperty + + @get:Inject + abstract val workerExecutor: WorkerExecutor + + @get:Inject + abstract val layout: ProjectLayout + + @TaskAction + fun determineImportedFiles() { + workerExecutor.classLoaderIsolation { + classpath.from(kotlinCompilerEmbeddableClasspath) + }.submit(DetermineImportedFilesWorkAction::class) { + projectDirectory.set(layout.projectDirectory) + mainKtsFile.set(this@DetermineImportedFiles.mainKtsFile) + importedFiles.set(this@DetermineImportedFiles.importedFiles) + } + } +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFilesWorkAction.kt b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFilesWorkAction.kt new file mode 100644 index 000000000..0418c748a --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/DetermineImportedFilesWorkAction.kt @@ -0,0 +1,90 @@ +/* + * Copyright 2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.kautler.githubactions + +import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty +import org.gradle.workers.WorkAction +import org.gradle.workers.WorkParameters +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY +import org.jetbrains.kotlin.cli.common.messages.MessageCollector.Companion.NONE +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles.JVM_CONFIG_FILES +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.com.intellij.openapi.util.Disposer +import org.jetbrains.kotlin.com.intellij.openapi.vfs.local.CoreLocalFileSystem +import org.jetbrains.kotlin.com.intellij.openapi.vfs.local.CoreLocalVirtualFile +import org.jetbrains.kotlin.com.intellij.psi.PsiManager +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtLiteralStringTemplateEntry +import org.jetbrains.kotlin.psi.KtStringTemplateExpression +import java.io.File +import java.nio.file.Path + +abstract class DetermineImportedFilesWorkAction : WorkAction { + override fun execute() { + val projectDirectory = parameters.projectDirectory.get().asFile + parameters + .mainKtsFile + .get() + .asFile + .importedFiles + .map { it.relativeTo(projectDirectory).invariantSeparatorsPath } + .distinct() + .sorted() + .joinToString("\n") + .also(parameters.importedFiles.get().asFile::writeText) + } + + interface Parameters : WorkParameters { + val projectDirectory: DirectoryProperty + val mainKtsFile: RegularFileProperty + val importedFiles: RegularFileProperty + } +} + +private val File.importedFiles: List + get() = if (!isFile) { + emptyList() + } else { + PsiManager + .getInstance( + KotlinCoreEnvironment + .createForProduction( + Disposer.newDisposable(), + CompilerConfiguration().apply { + put(MESSAGE_COLLECTOR_KEY, NONE) + }, + JVM_CONFIG_FILES + ) + .project + ) + .findFile(CoreLocalVirtualFile::class.java.getConstructor(CoreLocalFileSystem::class.java, Path::class.java).newInstance(CoreLocalFileSystem(), toPath())) + .let { it as KtFile } + .fileAnnotationList + ?.annotationEntries + ?.asSequence() + ?.filter { it.shortName?.asString() == "Import" } + ?.flatMap { it.valueArgumentList?.arguments ?: emptyList() } + ?.mapNotNull { it.getArgumentExpression() as? KtStringTemplateExpression } + ?.map { it.entries.first() } + ?.mapNotNull { it as? KtLiteralStringTemplateEntry } + ?.map { resolveSibling(it.text) } + ?.flatMap { it.importedFiles + it } + ?.toList() + ?: emptyList() + } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflow.kt b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflow.kt new file mode 100644 index 000000000..64ddca06d --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflow.kt @@ -0,0 +1,73 @@ +/* + * Copyright 2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.kautler.githubactions + +import org.gradle.api.DefaultTask +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.provider.Property +import org.gradle.api.provider.Provider +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.InputFiles +import org.gradle.api.tasks.Nested +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import org.gradle.jvm.toolchain.JavaLauncher +import org.gradle.kotlin.dsl.submit +import org.gradle.workers.WorkerExecutor +import java.io.File +import javax.inject.Inject + +abstract class PreprocessGithubWorkflow : DefaultTask() { + @get:InputFile + abstract val workflowScript: RegularFileProperty + + @get:InputFiles + abstract val importedFiles: ConfigurableFileCollection + + @get:InputFiles + abstract val kotlinCompilerClasspath: ConfigurableFileCollection + + @get:InputFiles + abstract val mainKtsClasspath: ConfigurableFileCollection + + @get:Nested + abstract val javaLauncher: Property + + @get:OutputFile + val workflowFile: Provider = workflowScript.map { + val workflowScript = it.asFile + workflowScript.resolveSibling("${workflowScript.name.removeSuffix(".main.kts")}.yaml") + } + + @get:Inject + abstract val workerExecutor: WorkerExecutor + + init { + group = "github workflows" + } + + @TaskAction + fun determineImportedFiles() { + workerExecutor.noIsolation().submit(PreprocessGithubWorkflowWorkAction::class) { + workflowScript.set(this@PreprocessGithubWorkflow.workflowScript) + kotlinCompilerClasspath.from(this@PreprocessGithubWorkflow.kotlinCompilerClasspath) + mainKtsClasspath.from(this@PreprocessGithubWorkflow.mainKtsClasspath) + javaExecutable.set(this@PreprocessGithubWorkflow.javaLauncher.map { it.executablePath }) + } + } +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflowWorkAction.kt b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflowWorkAction.kt new file mode 100644 index 000000000..f3d212c78 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/githubactions/PreprocessGithubWorkflowWorkAction.kt @@ -0,0 +1,56 @@ +/* + * Copyright 2025 Björn Kautler + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.kautler.githubactions + +import org.gradle.api.file.ConfigurableFileCollection +import org.gradle.api.file.RegularFileProperty +import org.gradle.process.ExecOperations +import org.gradle.workers.WorkAction +import org.gradle.workers.WorkParameters +import javax.inject.Inject + +abstract class PreprocessGithubWorkflowWorkAction : WorkAction { + @get:Inject + abstract val execOperations: ExecOperations + + override fun execute() { + // work-around for https://youtrack.jetbrains.com/issue/KT-74830 + (1..5).map { + runCatching { + execOperations.javaexec { + executable = parameters.javaExecutable.get().asFile.absolutePath + classpath(parameters.kotlinCompilerClasspath) + mainClass.set("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler") + args("-no-stdlib", "-no-reflect") + args("-classpath", parameters.mainKtsClasspath.asPath) + args("-script", parameters.workflowScript.get().asFile.absolutePath) + + // work-around for https://youtrack.jetbrains.com/issue/KT-42101 + systemProperty("kotlin.main.kts.compiled.scripts.cache.dir", "") + } + return + } + }.last().getOrThrow() + } + + interface Parameters : WorkParameters { + val workflowScript: RegularFileProperty + val kotlinCompilerClasspath: ConfigurableFileCollection + val mainKtsClasspath: ConfigurableFileCollection + val javaExecutable: RegularFileProperty + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4f32bf89f..8e5447598 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,4 +1,4 @@ -# Copyright 2020-2024 Björn Kautler +# Copyright 2020-2025 Björn Kautler # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ build-snakeyaml = "2.0" kotlin = "2.0.20" kotlinx-coroutines = "1.6.4" ktor = "3.0.0" -workflows-kotlin = "2.0.20" +workflows-kotlin = "2.1.10" [libraries] build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } @@ -40,6 +40,7 @@ kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-c ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" } ktor-client-js = { module = "io.ktor:ktor-client-js", version.ref = "ktor" } workflows-kotlin-compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", version.ref = "workflows-kotlin" } +workflows-kotlin-compiler-embeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "workflows-kotlin" } workflows-kotlin-main-kts = { module = "org.jetbrains.kotlin:kotlin-main-kts", version.ref = "workflows-kotlin" } workflows-kotlin-scripting-compiler = { module = "org.jetbrains.kotlin:kotlin-scripting-compiler", version.ref = "workflows-kotlin" } From ad61c670c86861ee7cb6a2190ed056b0ae5e275b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 3 Feb 2025 14:06:30 +0100 Subject: [PATCH 16/21] Cancel old workflow runs for the same PR or ref --- .github/workflows/check-action-typing.yaml | 3 +++ .../workflows/check-all-workflow-yaml-consistency.yaml | 3 +++ .github/workflows/check-dependency-versions.yaml | 3 +++ .github/workflows/test.yaml | 3 +++ .github/workflows/validate-gradle-wrapper.yaml | 3 +++ .github/workflows/verify-release.yaml | 3 +++ .github/workflows/workflow-with-copyright.main.kts | 8 ++++++-- 7 files changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-action-typing.yaml b/.github/workflows/check-action-typing.yaml index bfadd12c0..140c0552a 100644 --- a/.github/workflows/check-action-typing.yaml +++ b/.github/workflows/check-action-typing.yaml @@ -20,6 +20,9 @@ name: 'Check Action Typing' on: push: {} pull_request: {} +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/check-all-workflow-yaml-consistency.yaml b/.github/workflows/check-all-workflow-yaml-consistency.yaml index d357171c3..aee3f6983 100644 --- a/.github/workflows/check-all-workflow-yaml-consistency.yaml +++ b/.github/workflows/check-all-workflow-yaml-consistency.yaml @@ -20,6 +20,9 @@ name: 'Check all Workflow YAML Consistency' on: push: {} pull_request: {} +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 2f7b48858..957ca10b6 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -20,6 +20,9 @@ name: 'Check Dependency Versions' on: schedule: - cron: '0 0 * * FRI' +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 83570e587..368af7109 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -22,6 +22,9 @@ on: pull_request: {} schedule: - cron: '0 0 * * *' +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/validate-gradle-wrapper.yaml b/.github/workflows/validate-gradle-wrapper.yaml index cd422bcc4..262a7e2cf 100644 --- a/.github/workflows/validate-gradle-wrapper.yaml +++ b/.github/workflows/validate-gradle-wrapper.yaml @@ -20,6 +20,9 @@ name: 'Validate Gradle Wrapper' on: push: {} pull_request: {} +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/verify-release.yaml b/.github/workflows/verify-release.yaml index 78a89454c..fe26db7a8 100644 --- a/.github/workflows/verify-release.yaml +++ b/.github/workflows/verify-release.yaml @@ -22,6 +22,9 @@ on: tags: - 'v*' workflow_dispatch: {} +concurrency: + group: '${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}' + cancel-in-progress: true jobs: check_yaml_consistency: name: 'Check YAML consistency' diff --git a/.github/workflows/workflow-with-copyright.main.kts b/.github/workflows/workflow-with-copyright.main.kts index 45a906beb..8974586d0 100644 --- a/.github/workflows/workflow-with-copyright.main.kts +++ b/.github/workflows/workflow-with-copyright.main.kts @@ -20,6 +20,8 @@ import io.github.typesafegithub.workflows.domain.Concurrency import io.github.typesafegithub.workflows.domain.triggers.Trigger import io.github.typesafegithub.workflows.dsl.WorkflowBuilder +import io.github.typesafegithub.workflows.dsl.expressions.Contexts.github +import io.github.typesafegithub.workflows.dsl.expressions.expr import io.github.typesafegithub.workflows.dsl.workflow import io.github.typesafegithub.workflows.yaml.Preamble.WithOriginalAfter import java.io.File @@ -29,7 +31,6 @@ fun workflowWithCopyright( on: List, env: Map = mapOf(), sourceFile: File, - concurrency: Concurrency? = null, block: WorkflowBuilder.() -> Unit ) { workflow( @@ -37,7 +38,10 @@ fun workflowWithCopyright( on = on, env = env, sourceFile = sourceFile, - concurrency = concurrency, + concurrency = Concurrency( + group = "${expr { github.workflow }}-${expr("${github.eventPullRequest.pull_request.number} || ${github.ref}")}", + cancelInProgress = true + ), preamble = WithOriginalAfter( """ Copyright 2020-2025 Björn Kautler From 0b318e111dfb64f1bc93414fd6e96219923363be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 3 Feb 2025 13:12:43 +0100 Subject: [PATCH 17/21] Adapt to changed kali-linux distribution ID --- .github/workflows/test.main.kts | 101 ++-------- .github/workflows/test.yaml | 180 +++--------------- .../github/action/setup_wsl/Distribution.kt | 28 ++- 3 files changed, 71 insertions(+), 238 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index e9218cca7..e8ba2f303 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -80,7 +80,7 @@ val alpine = Distribution( ) val kali = Distribution( - wslId = "kali-linux", + wslId = "MyDistribution", userId = "kali-linux", matchPattern = "*Kali*", defaultAbsentTool = "dos2unix" @@ -471,14 +471,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() }, action = executeAction.copy( @@ -495,14 +488,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() }, actualCommand = "whoami", @@ -516,14 +502,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() }, action = executeAction.copy( @@ -746,14 +725,7 @@ workflowWithCopyright( wslVersion_Untyped = expr(getWslVersionExpression(kali)) ), // part of work-around for https://bugs.kali.org/view.php?id=8921 - condition = """ - |(matrix.distribution.user-id != '${kali.userId}') - ||| ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - |) - """.trimMargin() + condition = "matrix.distribution.user-id != '${kali.userId}'" ) runAfterSuccess( name = "Test - ${expr("matrix.distribution.default-absent-tool")} should be installed", @@ -764,14 +736,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() } ) @@ -784,14 +749,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() } ) @@ -1059,14 +1017,7 @@ workflowWithCopyright( additionalPackages = listOf( expr( """ - |( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |(matrix.distribution.user-id != '${kali.userId}') |&& 'bash' ||| '' """.trimMargin() @@ -1076,7 +1027,7 @@ workflowWithCopyright( // and https://bugs.kali.org/view.php?id=6672 // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 wslVersion = null, - wslVersion_Untyped = expr(getWslVersionExpression(kali, ubuntu2404)) + wslVersion_Untyped = expr(getWslVersionExpression(ubuntu2404)) ) ) usesSelf( @@ -1088,14 +1039,14 @@ workflowWithCopyright( // part of work-around for https://bugs.kali.org/view.php?id=6672 // and https://bugs.launchpad.net/ubuntu/+source/systemd/+bug/2069555 condition = """ - |( - | (matrix.distribution.user-id != '${kali.userId}') - | && (matrix.distribution.user-id != '${ubuntu2404.userId}') - |) - ||| ( - | ( - ${getWslVersionExpression(kali, ubuntu2404).prependIndent("| ")} - | ) == '2' + |(matrix.distribution.user-id != '${kali.userId}') + |&& ( + | (matrix.distribution.user-id != '${ubuntu2404.userId}') + | || ( + | ( + ${getWslVersionExpression(ubuntu2404).prependIndent("| ")} + | ) == '2' + | ) |) """.trimMargin() ) @@ -1106,14 +1057,7 @@ workflowWithCopyright( wslVersion = null ), // part of work-around for https://bugs.kali.org/view.php?id=8921 - condition = """ - |(matrix.distribution.user-id != '${kali.userId}') - ||| ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - |) - """.trimMargin() + condition = "(matrix.distribution.user-id != '${kali.userId}')" ) runAfterSuccess( name = "Test - ${expr("matrix.distribution.default-absent-tool")} should be installed", @@ -1124,14 +1068,7 @@ workflowWithCopyright( |( ${it.prependIndent("| ")} |) - |&& ( - | (matrix.distribution.user-id != '${kali.userId}') - | || ( - | ( - ${getWslVersionExpression(kali).prependIndent("| ")} - | ) == '2' - | ) - |) + |&& (matrix.distribution.user-id != '${kali.userId}') """.trimMargin() } ) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 368af7109..5a7543872 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -389,7 +389,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -732,21 +732,7 @@ jobs: always() && (steps.step-31.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') - id: 'step-37' name: 'Test - wsl-bash should use test as default user' shell: 'wsl-bash {0}' @@ -758,21 +744,7 @@ jobs: always() && (steps.step-36.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') - id: 'step-38' name: 'Set wsl-bash wrapper to use user test by default with inline script usage' uses: './' @@ -784,21 +756,7 @@ jobs: always() && (steps.step-36.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') - id: 'step-39' name: 'Test - wsl-bash should use test as default user with inline script usage' shell: 'wsl-bash {0}' @@ -954,7 +912,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1064,7 +1022,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1210,7 +1168,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1263,20 +1221,7 @@ jobs: ) && '2' || '1' }} - if: |- - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) + if: 'matrix.distribution.user-id != ''kali-linux''' - id: 'step-2' name: 'Test - ${{ matrix.distribution.default-absent-tool }} should be installed' shell: 'wsl-bash {0}' @@ -1286,21 +1231,7 @@ jobs: always() && (steps.step-1.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') - id: 'step-3' name: 'Test - bash should be installed' shell: 'wsl-bash {0}' @@ -1310,21 +1241,7 @@ jobs: always() && (steps.step-1.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') test_installation_on_wsl_version: name: 'Test installation on WSLv${{ matrix.wsl-version }} for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }}' runs-on: '${{ matrix.environment }}' @@ -1347,7 +1264,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1480,7 +1397,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1719,7 +1636,7 @@ jobs: user-id: 'Alpine' match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' - - wsl-id: 'kali-linux' + - wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -1858,28 +1775,13 @@ jobs: with: distribution: '${{ matrix.distribution.user-id }}' additional-packages: |- - ${{ ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + ${{ (matrix.distribution.user-id != 'kali-linux') && 'bash' || '' }} wsl-version: |- ${{ ( ( - (matrix.distribution.user-id == 'kali-linux') - || (matrix.distribution.user-id == 'Ubuntu-24.04') + (matrix.distribution.user-id == 'Ubuntu-24.04') ) && (matrix.environment != 'windows-2019') ) @@ -1892,22 +1794,21 @@ jobs: distribution: '${{ matrix.distribution.user-id }}' update: 'true' if: |- - ( - (matrix.distribution.user-id != 'kali-linux') - && (matrix.distribution.user-id != 'Ubuntu-24.04') - ) - || ( - ( + (matrix.distribution.user-id != 'kali-linux') + && ( + (matrix.distribution.user-id != 'Ubuntu-24.04') + || ( + ( ( ( - (matrix.distribution.user-id == 'kali-linux') - || (matrix.distribution.user-id == 'Ubuntu-24.04') + (matrix.distribution.user-id == 'Ubuntu-24.04') ) && (matrix.environment != 'windows-2019') ) && '2' || '1' - ) == '2' + ) == '2' + ) ) - id: 'step-3' name: 'Install default absent tool' @@ -1915,20 +1816,7 @@ jobs: with: distribution: '${{ matrix.distribution.user-id }}' additional-packages: '${{ matrix.distribution.default-absent-tool }}' - if: |- - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) + if: '(matrix.distribution.user-id != ''kali-linux'')' - id: 'step-4' name: 'Test - ${{ matrix.distribution.default-absent-tool }} should be installed' shell: 'wsl-bash {0}' @@ -1938,21 +1826,7 @@ jobs: always() && (steps.step-3.outcome == 'success') ) - && ( - (matrix.distribution.user-id != 'kali-linux') - || ( - ( - ( - ( - (matrix.distribution.user-id == 'kali-linux') - ) - && (matrix.environment != 'windows-2019') - ) - && '2' - || '1' - ) == '2' - ) - ) + && (matrix.distribution.user-id != 'kali-linux') - id: 'step-5' name: 'Execute action for ${{ matrix.distribution2.user-id }}' uses: './' @@ -2033,7 +1907,7 @@ jobs: match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' distribution3: - wsl-id: 'kali-linux' + wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' @@ -2074,7 +1948,7 @@ jobs: match-pattern: '*Alpine*' default-absent-tool: 'dos2unix' distribution3: - wsl-id: 'kali-linux' + wsl-id: 'MyDistribution' user-id: 'kali-linux' match-pattern: '*Kali*' default-absent-tool: 'dos2unix' diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 06fb3765f..f4e29601c 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -191,7 +191,7 @@ abstract class AptGetBasedDistribution : Distribution { installerFile: String ) : super(wslId, userId, distributionName, version, productId, installerFile) - private suspend fun refresh() { + protected open suspend fun refresh() { exec( commandLine = "wsl", args = arrayOf( @@ -305,12 +305,34 @@ object Debian : AptGetBasedDistribution( ) object Kali : AptGetBasedDistribution( - wslId = "kali-linux", + wslId = "MyDistribution", + userId = "kali-linux", distributionName = "Kali", version = SemVer("1.0.0"), downloadUrl = URL("https://aka.ms/wsl-kali-linux-new"), installerFile = "kali.exe" -) +) { + override suspend fun refresh() { + exec( + commandLine = "wsl", + args = arrayOf( + "--distribution", + wslId, + "wget", + "https://archive.kali.org/archive-key.asc", + "-O", + "/etc/apt/trusted.gpg.d/kali-archive-keyring.asc" + ), + options = ExecOptions( + env = recordOf( + "DEBIAN_FRONTEND" to "noninteractive", + "WSLENV" to "DEBIAN_FRONTEND/u" + ) + ) + ) + super.refresh() + } +} abstract class ZypperBasedDistribution : Distribution { constructor( From ee2e26280f8df8bb58d3e840f73454a5a41fcd6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Krzemi=C5=84ski?= <3110813+krzema12@users.noreply.github.com> Date: Mon, 3 Feb 2025 09:25:20 +0100 Subject: [PATCH 18/21] Update typesafegithub/github-actions-typing to v2 --- .github/workflows/check-action-typing.main.kts | 2 +- .github/workflows/check-action-typing.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-action-typing.main.kts b/.github/workflows/check-action-typing.main.kts index ce7caeb81..d9aa3bc1e 100755 --- a/.github/workflows/check-action-typing.main.kts +++ b/.github/workflows/check-action-typing.main.kts @@ -24,7 +24,7 @@ @file:DependsOn("io.github.typesafegithub:github-workflows-kt:3.2.0") @file:DependsOn("actions:checkout:v4") -@file:DependsOn("typesafegithub:github-actions-typing:v1") +@file:DependsOn("typesafegithub:github-actions-typing:v2") import io.github.typesafegithub.workflows.actions.actions.Checkout import io.github.typesafegithub.workflows.actions.typesafegithub.GithubActionsTyping diff --git a/.github/workflows/check-action-typing.yaml b/.github/workflows/check-action-typing.yaml index 140c0552a..fcd182d4c 100644 --- a/.github/workflows/check-action-typing.yaml +++ b/.github/workflows/check-action-typing.yaml @@ -51,4 +51,4 @@ jobs: uses: 'actions/checkout@v4' - id: 'step-2' name: 'Check Action Typing' - uses: 'typesafegithub/github-actions-typing@v1' + uses: 'typesafegithub/github-actions-typing@v2' From eb74a666aff602f86a2d7cbb872dfa5bac7340ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sun, 23 Feb 2025 23:40:39 +0100 Subject: [PATCH 19/21] Let Kotlin/JS inject main function arguments --- .../src/main/kotlin/net/kautler/ncc_packer.gradle.kts | 3 +++ .../src/jsMain/kotlin/net/kautler/nccpacker/NccPacker.kt | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts index 37290b80c..019cfbbef 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts @@ -18,6 +18,7 @@ package net.kautler import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.accessors.dm.LibrariesForKotlinWrappers +import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalMainFunctionArgumentsDsl import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec import org.jetbrains.kotlin.gradle.tasks.IncrementalSyncTask @@ -33,6 +34,8 @@ kotlin { useEsModules() binaries.executable() nodejs() + @OptIn(ExperimentalMainFunctionArgumentsDsl::class) + passAsArgumentToMainFunction("process.argv.slice(2)") } sourceSets { diff --git a/ncc-packer/src/jsMain/kotlin/net/kautler/nccpacker/NccPacker.kt b/ncc-packer/src/jsMain/kotlin/net/kautler/nccpacker/NccPacker.kt index a60f3cbdb..5be77cee2 100644 --- a/ncc-packer/src/jsMain/kotlin/net/kautler/nccpacker/NccPacker.kt +++ b/ncc-packer/src/jsMain/kotlin/net/kautler/nccpacker/NccPacker.kt @@ -28,9 +28,9 @@ import node.process.process import vercel.ncc.NccBuildOptions import vercel.ncc.ncc -suspend fun main() { +suspend fun main(vararg args: String) { runCatching { - val (input, output) = process.argv.filterIndexed { i, _ -> i > 1 } + val (input, output) = args val result = ncc( input, NccBuildOptions( From 00f1a06378e7495f9a4c2f7f8b65230e3eeaf299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sun, 23 Feb 2025 23:40:56 +0100 Subject: [PATCH 20/21] Ignore .kotlin directory --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fbdc97f66..5fc8f34de 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ /.idea/ /.gradle/ +/.kotlin/ /build/ /gradle/build-logic/.gradle/ /gradle/build-logic/build/ From 75ccefa0c3a7dd7abd9c0d97d1fb95febe9a69a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 24 Feb 2025 02:48:26 +0100 Subject: [PATCH 21/21] Work around actions/toolkit#1925 better and more completely --- .../main/kotlin/net/kautler/node.gradle.kts | 7 ++- .../github/action/setup_wsl/SetupWsl.kt | 58 ++----------------- 2 files changed, 10 insertions(+), 55 deletions(-) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts index 86208211c..60ff8fe46 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts @@ -17,7 +17,6 @@ package net.kautler import net.kautler.dao.action.GitHubAction -import net.kautler.util.npm import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.accessors.dm.LibrariesForKotlinWrappers import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec @@ -156,6 +155,12 @@ dependencies { val syncDistribution by tasks.registering(Sync::class) { from(setupWslDistributionFiles) into(layout.buildDirectory.dir("distributions")) + // work-around for https://github.com/actions/toolkit/issues/1925 + filesMatching("index.mjs") { + filter { + it.replace("stats = yield exports.stat", "stats = yield exports.lstat") + } + } } tasks.assemble { diff --git a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index d5fbfdceb..8a579af10 100644 --- a/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/jsMain/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -37,7 +37,6 @@ import actions.exec.ExecOptions import actions.exec.exec import actions.io.mkdirP import actions.io.mv -import actions.io.rmRF import actions.io.which import actions.tool.cache.cacheDir import actions.tool.cache.downloadTool @@ -58,7 +57,6 @@ import node.buffer.BufferEncoding import node.fs.exists import node.fs.mkdtemp import node.fs.readdir -import node.fs.stat import node.fs.writeFile import node.os.tmpdir import node.path.path @@ -71,12 +69,6 @@ import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.seconds import actions.tool.cache.extractZip as toolCacheExtractZip -private const val BAD_WSL_EXE_PATH = - "C:\\Users\\runneradmin\\AppData\\Local\\Microsoft\\WindowsApps\\wsl.exe" - -private const val BAD_WSLCONFIG_EXE_PATH = - "C:\\Users\\runneradmin\\AppData\\Local\\Microsoft\\WindowsApps\\wslconfig.exe" - suspend fun wslOutput(vararg args: String): String { val stdoutBuilder = StringBuilder() val stdoutBuilderUtf16Le = StringBuilder() @@ -387,31 +379,12 @@ suspend fun verifyWindowsEnvironment() { } suspend fun installWsl() { - // part of work-around for https://github.com/actions/toolkit/issues/1925 - val deleteWslExe = - runCatching { stat(BAD_WSL_EXE_PATH).isFile() } - .getOrDefault(false) - .not() - val deleteWslConfigExe = - runCatching { stat(BAD_WSLCONFIG_EXE_PATH).isFile() } - .getOrDefault(false) - .not() - exec( commandLine = "pwsh", args = arrayOf("-Command", """Start-Process wsl "--install --no-distribution""""), options = ExecOptions(ignoreReturnCode = true) ) - - waitForWslStatusNotContaining("is not installed", 5.minutes) { - // part of work-around for https://github.com/actions/toolkit/issues/1925 - if (deleteWslExe) { - rmRF(BAD_WSL_EXE_PATH) - } - if (deleteWslConfigExe) { - rmRF(BAD_WSLCONFIG_EXE_PATH) - } - } + waitForWslStatusNotContaining("is not installed", 5.minutes) } suspend fun installDistribution() { @@ -420,31 +393,12 @@ suspend fun installDistribution() { ) if (wslVersion() != 1u) { - // part of work-around for https://github.com/actions/toolkit/issues/1925 - val deleteWslExe = - runCatching { stat(BAD_WSL_EXE_PATH).isFile() } - .getOrDefault(false) - .not() - val deleteWslConfigExe = - runCatching { stat(BAD_WSLCONFIG_EXE_PATH).isFile() } - .getOrDefault(false) - .not() - retry(10) { executeWslCommand( wslArguments = arrayOf("--update") ) } - - // part of work-around for https://github.com/actions/toolkit/issues/1925 - waitForWslStatusNotContaining("WSL is finishing an upgrade...") { - if (deleteWslExe) { - rmRF(BAD_WSL_EXE_PATH) - } - if (deleteWslConfigExe) { - rmRF(BAD_WSLCONFIG_EXE_PATH) - } - } + waitForWslStatusNotContaining("WSL is finishing an upgrade...") } exec( @@ -456,17 +410,13 @@ suspend fun installDistribution() { suspend fun waitForWslStatusNotContaining( text: String, - duration: Duration = 30.seconds, - preAction: suspend () -> Unit = {} + duration: Duration = 30.seconds ) { (2..duration.inWholeSeconds) .asFlow() .onEach { delay(1.seconds) } .onStart { emit(1) } - .map { - preAction() - wslOutput("--status") - } + .map { wslOutput("--status") } .firstOrNull { !it.contains(text) } }