From 43068d5bd2807ed2c7936cba610c96a51d16a538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 26 Jan 2023 11:20:31 +0100 Subject: [PATCH 01/23] Use new action versions in workflows --- .../check-dependency-versions.main.kts | 4 ++-- .../workflows/check-dependency-versions.yaml | 2 +- .github/workflows/test.main.kts | 12 +++++----- .github/workflows/test.yaml | 22 +++++++++---------- .../validate-gradle-wrapper.main.kts | 4 ++-- .../workflows/validate-gradle-wrapper.yaml | 2 +- 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index 96e8bba2..c24a0cc2 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -19,7 +19,7 @@ @file:Import("workflow-with-copyright.main.kts") import it.krzeminski.githubactions.actions.CustomAction -import it.krzeminski.githubactions.actions.actions.CheckoutV2 +import it.krzeminski.githubactions.actions.actions.CheckoutV3 import it.krzeminski.githubactions.domain.RunnerType.WindowsLatest import it.krzeminski.githubactions.domain.triggers.Cron import it.krzeminski.githubactions.domain.triggers.Schedule @@ -52,7 +52,7 @@ workflowWithCopyright( ) uses( name = "Checkout", - action = CheckoutV2() + action = CheckoutV3() ) uses( name = "Check Dependency Versions", diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 3d36e9d3..90ef59cb 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -51,7 +51,7 @@ jobs: run: git config --global core.autocrlf input - id: step-1 name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - id: step-2 name: Check Dependency Versions uses: burrunan/gradle-cache-action@v1 diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index af10355b..42c476af 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -19,8 +19,8 @@ @file:Import("workflow-with-copyright.main.kts") import it.krzeminski.githubactions.actions.CustomAction -import it.krzeminski.githubactions.actions.actions.CacheV2 -import it.krzeminski.githubactions.actions.actions.CheckoutV2 +import it.krzeminski.githubactions.actions.actions.CacheV3 +import it.krzeminski.githubactions.actions.actions.CheckoutV3 import it.krzeminski.githubactions.actions.vampire.SetupWslV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1.Distribution import it.krzeminski.githubactions.domain.CommandStep @@ -36,8 +36,6 @@ import it.krzeminski.githubactions.domain.triggers.Push import it.krzeminski.githubactions.domain.triggers.Schedule import it.krzeminski.githubactions.dsl.JobBuilder import it.krzeminski.githubactions.dsl.expressions.expr -import it.krzeminski.githubactions.dsl.workflow -import it.krzeminski.githubactions.yaml.writeToFile val environments = listOf( "windows-2019", @@ -127,7 +125,7 @@ workflowWithCopyright( ), sourceFile = __FILE__ ) { - val builtArtifactsCache = CacheV2( + val builtArtifactsCache = CacheV3( path = listOf( "action.yml", "build/distributions/" @@ -150,7 +148,7 @@ workflowWithCopyright( ) uses( name = "Checkout", - action = CheckoutV2() + action = CheckoutV3() ) uses( name = "Build", @@ -1094,7 +1092,7 @@ val Step.outcome get() = "steps.$id.outcome" // work-around for https://github.com/krzema12/github-workflows-kt/issues/640 fun SetupWslV1.copy( - distribution: SetupWslV1.Distribution? = null, + distribution: Distribution? = null, useCache: Boolean? = null, wslConf: String? = null, setAsDefault: Boolean? = null, diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 412734f6..c904f992 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -53,7 +53,7 @@ jobs: run: git config --global core.autocrlf input - id: step-1 name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - id: step-2 name: Build uses: burrunan/gradle-cache-action@v1 @@ -64,7 +64,7 @@ jobs: gradle-dependencies-cache-key: buildSrc/**/Versions.kt - id: step-3 name: Save built artifacts to cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -93,7 +93,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -130,7 +130,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -361,7 +361,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -852,7 +852,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -951,7 +951,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -1083,7 +1083,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -1216,7 +1216,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -1383,7 +1383,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml @@ -1554,7 +1554,7 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: |- action.yml diff --git a/.github/workflows/validate-gradle-wrapper.main.kts b/.github/workflows/validate-gradle-wrapper.main.kts index ee684bec..46e7a58d 100755 --- a/.github/workflows/validate-gradle-wrapper.main.kts +++ b/.github/workflows/validate-gradle-wrapper.main.kts @@ -18,7 +18,7 @@ @file:Import("workflow-with-copyright.main.kts") -import it.krzeminski.githubactions.actions.actions.CheckoutV2 +import it.krzeminski.githubactions.actions.actions.CheckoutV3 import it.krzeminski.githubactions.actions.gradle.WrapperValidationActionV1 import it.krzeminski.githubactions.domain.RunnerType.UbuntuLatest import it.krzeminski.githubactions.domain.triggers.PullRequest @@ -43,7 +43,7 @@ workflowWithCopyright( ) uses( name = "Checkout", - action = CheckoutV2() + action = CheckoutV3() ) uses( name = "Validate Gradle Wrapper", diff --git a/.github/workflows/validate-gradle-wrapper.yaml b/.github/workflows/validate-gradle-wrapper.yaml index 6070267f..a7ac3189 100644 --- a/.github/workflows/validate-gradle-wrapper.yaml +++ b/.github/workflows/validate-gradle-wrapper.yaml @@ -51,7 +51,7 @@ jobs: run: git config --global core.autocrlf input - id: step-1 name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - id: step-2 name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 From 1833593203dcef4f5be5fc2a27cc91a85904b4d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 26 Jan 2023 15:15:50 +0100 Subject: [PATCH 02/23] Only run test jobs if the cache restore was successful --- .github/workflows/test.main.kts | 99 ++-- .github/workflows/test.yaml | 543 ++++++++++-------- .../net/kautler/github_actions.gradle.kts | 4 +- 3 files changed, 332 insertions(+), 314 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 42c476af..79016a7f 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -25,6 +25,7 @@ import it.krzeminski.githubactions.actions.vampire.SetupWslV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1.Distribution import it.krzeminski.githubactions.domain.CommandStep import it.krzeminski.githubactions.domain.ExternalActionStepWithOutputs +import it.krzeminski.githubactions.domain.JobOutputs.EMPTY import it.krzeminski.githubactions.domain.RunnerType import it.krzeminski.githubactions.domain.RunnerType.WindowsLatest import it.krzeminski.githubactions.domain.Shell @@ -35,6 +36,7 @@ import it.krzeminski.githubactions.domain.triggers.PullRequest import it.krzeminski.githubactions.domain.triggers.Push import it.krzeminski.githubactions.domain.triggers.Schedule import it.krzeminski.githubactions.dsl.JobBuilder +import it.krzeminski.githubactions.dsl.WorkflowBuilder import it.krzeminski.githubactions.dsl.expressions.expr val environments = listOf( @@ -170,11 +172,34 @@ workflowWithCopyright( ) } - job( - id = "test_invalid_distribution", - name = """Test "${expr("matrix.distribution.label")}" distribution on ${expr("matrix.environment")}""", + fun WorkflowBuilder.testJob( + id: String, + name: String, + _customArguments: Map = mapOf(), + block: JobBuilder.() -> Unit, + ) = job( + id = id, + name = name, needs = listOf(build), runsOn = RunnerType.Custom(expr("matrix.environment")), + _customArguments = _customArguments + ) { + val restoreBuildArtifacts = uses( + name = "Restore built artifacts from cache", + action = builtArtifactsCache + ) + run( + name = "Fail if cache could not be restored", + condition = "${restoreBuildArtifacts.outputs.cacheHit} == false", + shell = Cmd, + command = "exit 1" + ) + block() + } + + testJob( + id = "test_invalid_distribution", + name = """Test "${expr("matrix.distribution.label")}" distribution on ${expr("matrix.environment")}""", _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -198,10 +223,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = executeAction, continueOnError = true @@ -213,11 +234,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_default_distribution", name = "Test default distribution on ${expr("matrix.environment")}", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -228,10 +247,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = SetupWslV1( update = true @@ -260,11 +275,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test", name = """Test "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -275,10 +288,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = executeAction.copy( useCache = false @@ -464,11 +473,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_wsl-conf_on_initial_execution", name = """Test /etc/wsl.conf handling on initial execution for "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -479,10 +486,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = executeAction.copy( wslConf = """ @@ -515,11 +518,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_wsl-conf_on_subsequent_execution", name = """Test /etc/wsl.conf handling on subsequent execution for "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -530,10 +531,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = executeAction ) @@ -587,11 +584,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_additional_packages", name = """Test additional packages for "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -602,10 +597,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) executeActionStep = usesSelf( action = executeAction.copy( additionalPackages = listOf( @@ -624,7 +615,7 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_multiple_usage_with_different_distributions", name = """ Test multiple usage with different distributions @@ -633,8 +624,6 @@ workflowWithCopyright( / "${expr("matrix.distributions.distribution3.user-id")}") on ${expr("matrix.environment")} """.trimIndent().replace("\n", " "), - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -676,10 +665,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) usesSelf( name = "Execute action for ${expr("matrix.distributions.distribution1.user-id")}", action = SetupWslV1( @@ -722,11 +707,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_multiple_usage_with_same_distribution", name = """Test multiple usage with "${expr("matrix.distribution.user-id")}" distribution on ${expr("matrix.environment")}""", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -752,10 +735,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) usesSelf( action = executeAction.copy( additionalPackages = listOf("bash") @@ -808,11 +787,9 @@ workflowWithCopyright( ) } - job( + testJob( id = "test_distribution_specific_wsl_bash_scripts", name = "Test distribution specific wsl-bash scripts on ${expr("matrix.environment")}", - needs = listOf(build), - runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = mapOf( "strategy" to mapOf( "fail-fast" to false, @@ -834,10 +811,6 @@ workflowWithCopyright( ) ) ) { - uses( - name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) (1 until distributions.size) .associateWith { usesSelf( diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index c904f992..f2e73eb8 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -100,15 +100,20 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action continue-on-error: true uses: ./ with: distribution: ${{ matrix.distribution.user-id }} - - id: step-2 + - id: step-3 name: Test - action should fail if an invalid distribution is given shell: cmd - run: if '${{ steps.step-1.outcome }}' NEQ 'failure' exit 1 + run: if '${{ steps.step-2.outcome }}' NEQ 'failure' exit 1 test_default_distribution: name: Test default distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -137,33 +142,38 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: update: true - - id: step-2 + - id: step-3 name: Test - wsl-bash should be available as custom shell shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-3 + && (steps.step-2.outcome == 'success') + - id: step-4 name: Test - wsl-bash should fail if the script fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-4 + && (steps.step-2.outcome == 'success') + - id: step-5 name: Test - wsl-bash should fail if the script fails (verification) shell: cmd - run: IF '${{ steps.step-3.outcome }}' NEQ 'failure' EXIT /B 1 + run: IF '${{ steps.step-4.outcome }}' NEQ 'failure' EXIT /B 1 if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-5 + && (steps.step-2.outcome == 'success') + - id: step-6 name: Test - wsl-bash should fail if one of the commands fails (provocation) continue-on-error: true shell: wsl-bash {0} @@ -172,45 +182,45 @@ jobs: : if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-6 + && (steps.step-2.outcome == 'success') + - id: step-7 name: Test - wsl-bash should fail if one of the commands fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-5.outcome }}'' == ''failure'' ] || exit 1' + run: '[ ''${{ steps.step-6.outcome }}'' == ''failure'' ] || exit 1' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-7 + && (steps.step-2.outcome == 'success') + - id: step-8 name: Test - wsl-bash should fail if an undefined variable is used (provocation) continue-on-error: true shell: wsl-bash {0} run: $foo if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-8 + && (steps.step-2.outcome == 'success') + - id: step-9 name: Test - wsl-bash should fail if an undefined variable is used (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-7.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-8.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-9 + && (steps.step-2.outcome == 'success') + - id: step-10 name: Test - wsl-bash should fail if any command in a pipe fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false | true if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-10 + && (steps.step-2.outcome == 'success') + - id: step-11 name: Test - wsl-bash should fail if any command in a pipe fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-9.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-10.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-11 + && (steps.step-2.outcome == 'success') + - id: step-12 name: Test - the default distribution should be correct shell: wsl-bash {0} run: |- @@ -218,8 +228,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-12 + && (steps.step-2.outcome == 'success') + - id: step-13 name: Test - wsl-bash should use the correct distribution shell: wsl-bash {0} run: |- @@ -227,8 +237,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.distribution.match-pattern }} ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-13 + && (steps.step-2.outcome == 'success') + - id: step-14 name: Test - multi-line commands should not be disturbed by CRLF line endings shell: wsl-bash {0} run: |- @@ -236,82 +246,82 @@ jobs: ! grep -q $'\r' "$0" # this comment catches the CR if present if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-14 + && (steps.step-2.outcome == 'success') + - id: step-15 name: Test - wsl-bash should fail if no script file is given (provocation) continue-on-error: true shell: wsl-bash run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-15 + && (steps.step-2.outcome == 'success') + - id: step-16 name: Test - wsl-bash should fail if no script file is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-14.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-15.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-16 + && (steps.step-2.outcome == 'success') + - id: step-17 name: Test - wsl-bash should fail if more than one parameter is given and first is not -u (provocation) continue-on-error: true shell: wsl-bash user {0} run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-17 + && (steps.step-2.outcome == 'success') + - id: step-18 name: Test - wsl-bash should fail if more than one parameter is given and first is not -u (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-16.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-17.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-18 + && (steps.step-2.outcome == 'success') + - id: step-19 name: Test - wsl-bash should fail if only user is given (provocation) continue-on-error: true shell: wsl-bash -u {0} run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-19 + && (steps.step-2.outcome == 'success') + - id: step-20 name: Test - wsl-bash should fail if only user is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-18.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-19.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-20 + && (steps.step-2.outcome == 'success') + - id: step-21 name: Test - wsl-bash should fail if excess argument is given (provocation) continue-on-error: true shell: wsl-bash -u user {0} foo run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-21 + && (steps.step-2.outcome == 'success') + - id: step-22 name: Test - wsl-bash should fail if excess argument is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-20.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-21.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-22 + && (steps.step-2.outcome == 'success') + - id: step-23 name: Test - wsl-bash should fail if given script file does not exist (provocation) continue-on-error: true shell: wsl-bash -u user {0}foo run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-23 + && (steps.step-2.outcome == 'success') + - id: step-24 name: Test - wsl-bash should fail if given script file does not exist (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-22.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-23.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') test: name: Test "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -368,36 +378,41 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} use-cache: false - - id: step-2 + - id: step-3 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') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-3 + - id: step-4 name: Test - wsl-bash should fail if bash is not present by default (verification) - run: wsl sh -euc "[ '${{ steps.step-2.outcome }}' = 'failure' ]" + run: wsl sh -euc "[ '${{ steps.step-3.outcome }}' = 'failure' ]" if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-5 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-5 + - id: step-6 name: Install Bash on Alpine uses: ./ with: @@ -405,31 +420,31 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-6 + - id: step-7 name: Test - wsl-bash should be available as custom shell shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-7 + && (steps.step-2.outcome == 'success') + - id: step-8 name: Test - wsl-bash should fail if the script fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-8 + && (steps.step-2.outcome == 'success') + - id: step-9 name: Test - wsl-bash should fail if the script fails (verification) shell: cmd - run: IF '${{ steps.step-7.outcome }}' NEQ 'failure' EXIT /B 1 + run: IF '${{ steps.step-8.outcome }}' NEQ 'failure' EXIT /B 1 if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-9 + && (steps.step-2.outcome == 'success') + - id: step-10 name: Test - wsl-bash should fail if one of the commands fails (provocation) continue-on-error: true shell: wsl-bash {0} @@ -438,45 +453,45 @@ jobs: : if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-10 + && (steps.step-2.outcome == 'success') + - id: step-11 name: Test - wsl-bash should fail if one of the commands fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-9.outcome }}'' == ''failure'' ] || exit 1' + run: '[ ''${{ steps.step-10.outcome }}'' == ''failure'' ] || exit 1' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-11 + && (steps.step-2.outcome == 'success') + - id: step-12 name: Test - wsl-bash should fail if an undefined variable is used (provocation) continue-on-error: true shell: wsl-bash {0} run: $foo if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-12 + && (steps.step-2.outcome == 'success') + - id: step-13 name: Test - wsl-bash should fail if an undefined variable is used (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-11.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-12.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-13 + && (steps.step-2.outcome == 'success') + - id: step-14 name: Test - wsl-bash should fail if any command in a pipe fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false | true if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-14 + && (steps.step-2.outcome == 'success') + - id: step-15 name: Test - wsl-bash should fail if any command in a pipe fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-13.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-14.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-15 + && (steps.step-2.outcome == 'success') + - id: step-16 name: Test - the default distribution should be correct shell: wsl-bash {0} run: |- @@ -484,8 +499,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-16 + && (steps.step-2.outcome == 'success') + - id: step-17 name: Test - wsl-bash should use the correct distribution shell: wsl-bash {0} run: |- @@ -493,8 +508,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.distribution.match-pattern }} ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-17 + && (steps.step-2.outcome == 'success') + - id: step-18 name: Test - multi-line commands should not be disturbed by CRLF line endings shell: wsl-bash {0} run: |- @@ -502,52 +517,52 @@ jobs: ! grep -q $'\r' "$0" # this comment catches the CR if present if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-18 + && (steps.step-2.outcome == 'success') + - id: step-19 name: Test - ${{ matrix.distribution.default-absent-tool }} should not be installed by default (provocation) continue-on-error: true shell: wsl-bash {0} run: ${{ matrix.distribution.default-absent-tool }} --version if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-19 + && (steps.step-2.outcome == 'success') + - id: step-20 name: Test - ${{ matrix.distribution.default-absent-tool }} should not be installed by default (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-18.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-19.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-20 + && (steps.step-2.outcome == 'success') + - id: step-21 name: Test - bash should be installed by default shell: wsl-bash {0} run: bash -c true if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-21 + && (steps.step-2.outcome == 'success') + - id: step-22 name: Test - sh should be installed by default shell: wsl-bash {0} run: sh -c true if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-22 + && (steps.step-2.outcome == 'success') + - id: step-23 name: Test - wsl-sh should not be present (provocation) continue-on-error: true shell: wsl-sh {0} run: ':' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-23 + && (steps.step-2.outcome == 'success') + - id: step-24 name: Test - wsl-sh should not be present (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-22.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-23.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-24 + && (steps.step-2.outcome == 'success') + - id: step-25 name: Add wsl-sh wrapper uses: ./ with: @@ -555,15 +570,15 @@ jobs: wsl-shell-command: sh -eu if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-25 + && (steps.step-2.outcome == 'success') + - id: step-26 name: Test - wsl-sh should be present shell: wsl-sh {0} run: ':' if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-26 + && (steps.step-25.outcome == 'success') + - id: step-27 name: Test - wsl-bash should use bash shell: wsl-bash {0} run: |- @@ -571,8 +586,8 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" == 'bash' ] if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-27 + && (steps.step-25.outcome == 'success') + - id: step-28 name: Test - wsl-sh should use sh shell: wsl-sh {0} run: |- @@ -580,45 +595,45 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" = 'sh' ] if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-28 + && (steps.step-25.outcome == 'success') + - id: step-29 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-29 + && (steps.step-25.outcome == 'success') + - id: step-30 name: Test - wsl-bash should not be present (provocation) continue-on-error: true shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-30 + && (steps.step-25.outcome == 'success') + - id: step-31 name: Test - wsl-bash should not be present (verification) shell: wsl-sh {0} - run: '[ ''${{ steps.step-29.outcome }}'' = ''failure'' ]' + run: '[ ''${{ steps.step-30.outcome }}'' = ''failure'' ]' if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-31 + && (steps.step-25.outcome == 'success') + - id: step-32 name: Re-add wsl-bash wrapper uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-24.outcome == 'success') - - id: step-32 + && (steps.step-25.outcome == 'success') + - id: step-33 name: Test - wsl-bash should be present shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-31.outcome == 'success') - - id: step-33 + && (steps.step-32.outcome == 'success') + - id: step-34 name: Test - wsl-bash should use bash shell: wsl-bash {0} run: |- @@ -626,8 +641,8 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" == 'bash' ] if: |- always() - && (steps.step-31.outcome == 'success') - - id: step-34 + && (steps.step-32.outcome == 'success') + - id: step-35 name: Test - wsl-bash should use root as default user shell: wsl-bash {0} run: |- @@ -635,15 +650,15 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-31.outcome == 'success') - - id: step-35 + && (steps.step-32.outcome == 'success') + - id: step-36 name: Add user test shell: wsl-bash {0} run: useradd -m -p 4qBD5NWD3IkbU test if: |- always() - && (steps.step-31.outcome == 'success') - - id: step-36 + && (steps.step-32.outcome == 'success') + - id: step-37 name: Set wsl-bash wrapper to use user test by default uses: ./ with: @@ -652,8 +667,8 @@ jobs: wsl-shell-command: bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\ if: |- always() - && (steps.step-31.outcome == 'success') - - id: step-37 + && (steps.step-32.outcome == 'success') + - id: step-38 name: Test - wsl-bash should use test as default user shell: wsl-bash {0} run: |- @@ -661,8 +676,8 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-36.outcome == 'success') - - id: step-38 + && (steps.step-37.outcome == 'success') + - id: step-39 name: Set wsl-bash wrapper to use user test by default with inline script usage uses: ./ with: @@ -670,8 +685,8 @@ jobs: wsl-shell-command: bash -c "sudo -u test bash --noprofile --norc -euo pipefail '{0}'" if: |- always() - && (steps.step-36.outcome == 'success') - - id: step-39 + && (steps.step-37.outcome == 'success') + - id: step-40 name: Test - wsl-bash should use test as default user with inline script usage shell: wsl-bash {0} run: |- @@ -679,23 +694,23 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-38.outcome == 'success') - - id: step-40 + && (steps.step-39.outcome == 'success') + - id: step-41 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-38.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-39.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-38.outcome == 'success') - - id: step-41 + && (steps.step-39.outcome == 'success') + - id: step-42 name: Set wsl-bash wrapper to use default user by default uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-38.outcome == 'success') - - id: step-42 + && (steps.step-39.outcome == 'success') + - id: step-43 name: Test - wsl-bash should use root as default user shell: wsl-bash {0} run: |- @@ -703,22 +718,22 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-41.outcome == 'success') - - id: step-43 + && (steps.step-42.outcome == 'success') + - id: step-44 name: Test - test user does already exist shell: wsl-bash {0} run: id -u test if: |- always() - && (steps.step-41.outcome == 'success') - - id: step-44 + && (steps.step-42.outcome == 'success') + - id: step-45 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-41.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-42.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-41.outcome == 'success') - - id: step-45 + && (steps.step-42.outcome == 'success') + - id: step-46 name: Set wsl-bash wrapper to use existing user test by default with extra parameter uses: ./ with: @@ -726,8 +741,8 @@ jobs: wsl-shell-user: test if: |- always() - && (steps.step-41.outcome == 'success') - - id: step-46 + && (steps.step-42.outcome == 'success') + - id: step-47 name: Test - wsl-bash should use existing user test as default user with extra parameter shell: wsl-bash {0} run: |- @@ -735,22 +750,22 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-45.outcome == 'success') - - id: step-47 + && (steps.step-46.outcome == 'success') + - id: step-48 name: Test - test2 user does not exist shell: wsl-bash {0} run: '! id -u test2' if: |- always() - && (steps.step-45.outcome == 'success') - - id: step-48 + && (steps.step-46.outcome == 'success') + - id: step-49 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-45.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-46.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-45.outcome == 'success') - - id: step-49 + && (steps.step-46.outcome == 'success') + - id: step-50 name: Set wsl-bash wrapper to use non-existing user test2 by default with extra parameter uses: ./ with: @@ -758,8 +773,8 @@ jobs: wsl-shell-user: test2 if: |- always() - && (steps.step-45.outcome == 'success') - - id: step-50 + && (steps.step-46.outcome == 'success') + - id: step-51 name: Test - wsl-bash should use auto-generated user test2 as default user shell: wsl-bash {0} run: |- @@ -767,8 +782,8 @@ jobs: [ "$(whoami)" == 'test2' ] if: |- always() - && (steps.step-49.outcome == 'success') - - id: step-51 + && (steps.step-50.outcome == 'success') + - id: step-52 name: Test - wsl-bash should use ad-hoc user test shell: wsl-bash -u test {0} run: |- @@ -776,8 +791,8 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-49.outcome == 'success') - - id: step-52 + && (steps.step-50.outcome == 'success') + - id: step-53 name: Test - wsl-bash should use ad-hoc user root shell: wsl-bash -u root {0} run: |- @@ -785,16 +800,16 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-49.outcome == 'success') - - id: step-53 + && (steps.step-50.outcome == 'success') + - id: step-54 name: Make a no-op execution of the action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-49.outcome == 'success') - - id: step-54 + && (steps.step-50.outcome == 'success') + - id: step-55 name: Test - wsl-bash should still use test2 as default user shell: wsl-bash {0} run: |- @@ -802,7 +817,7 @@ jobs: [ "$(whoami)" == 'test2' ] if: |- always() - && (steps.step-53.outcome == 'success') + && (steps.step-54.outcome == 'success') test_wsl-conf_on_initial_execution: name: Test /etc/wsl.conf handling on initial execution for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -859,6 +874,11 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: @@ -866,15 +886,15 @@ jobs: wsl-conf: |- [automount] options = uid=1000 - - id: step-2 + - id: step-3 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-3 + - id: step-4 name: Install Bash on Alpine uses: ./ with: @@ -882,9 +902,9 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-5 name: Test - /etc/wsl.conf should exist shell: wsl-bash {0} run: |- @@ -892,8 +912,8 @@ jobs: cat /etc/wsl.conf if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-5 + && (steps.step-2.outcome == 'success') + - id: step-6 name: Test - /mnt/c should be mounted with uid 1000 shell: wsl-bash {0} run: |- @@ -901,7 +921,7 @@ jobs: [[ "$(stat -c %u /mnt/c)" == 1000 ]] if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') test_wsl-conf_on_subsequent_execution: name: Test /etc/wsl.conf handling on subsequent execution for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -958,19 +978,24 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} - - id: step-2 + - id: step-3 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-3 + - id: step-4 name: Install Bash on Alpine uses: ./ with: @@ -978,16 +1003,16 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-5 name: Test - /etc/wsl.conf should not exist shell: wsl-bash {0} run: '[ ! -f /etc/wsl.conf ]' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-5 + && (steps.step-2.outcome == 'success') + - id: step-6 name: 'Test - C: should be mounted at /mnt/c' shell: wsl-bash {0} run: |- @@ -995,8 +1020,8 @@ jobs: mount | grep 'C:.* on /mnt/c' if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-6 + && (steps.step-2.outcome == 'success') + - id: step-7 name: Test - /mnt/c should be mounted with uid 0 shell: wsl-bash {0} run: |- @@ -1004,8 +1029,8 @@ jobs: [[ "$(stat -c %u /mnt/c)" == 0 ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-7 + && (steps.step-2.outcome == 'success') + - id: step-8 name: Execute action uses: ./ with: @@ -1015,8 +1040,8 @@ jobs: root = / if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-8 + && (steps.step-2.outcome == 'success') + - id: step-9 name: Test - /etc/wsl.conf should exist shell: wsl-bash {0} run: |- @@ -1024,8 +1049,8 @@ jobs: cat /etc/wsl.conf if: |- always() - && (steps.step-7.outcome == 'success') - - id: step-9 + && (steps.step-8.outcome == 'success') + - id: step-10 name: 'Test - C: should be mounted at /c' shell: wsl-bash {0} run: |- @@ -1033,7 +1058,7 @@ jobs: mount | grep 'C:.* on /c' if: |- always() - && (steps.step-7.outcome == 'success') + && (steps.step-8.outcome == 'success') test_additional_packages: name: Test additional packages for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -1090,25 +1115,30 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: ${{ matrix.distribution.default-absent-tool }} bash - - id: step-2 + - id: step-3 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') - - id: step-3 + && (steps.step-2.outcome == 'success') + - id: step-4 name: Test - bash should be installed shell: wsl-bash {0} run: bash -c true if: |- always() - && (steps.step-1.outcome == 'success') + && (steps.step-2.outcome == 'success') 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 }} @@ -1223,27 +1253,32 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-2 + - id: step-3 name: Execute action for ${{ matrix.distributions.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution2.user-id }} - - id: step-3 + - id: step-4 name: Execute action for ${{ matrix.distributions.distribution3.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution3.user-id }} set-as-default: false - - id: step-4 + - id: step-5 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} again uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-5 + - id: step-6 name: Test - the default distribution should be the last installed distribution with set-as-default true shell: wsl-bash {0} run: |- @@ -1251,8 +1286,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distributions.distribution2.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-4.outcome == 'success') - - id: step-6 + && (steps.step-5.outcome == 'success') + - id: step-7 name: Test - wsl-bash should use the last installed distribution with set-as-default true shell: wsl-bash {0} run: |- @@ -1260,7 +1295,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.distributions.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-4.outcome == 'success') + && (steps.step-5.outcome == 'success') test_multiple_usage_with_same_distribution: name: Test multiple usage with "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -1390,40 +1425,45 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: bash - - id: step-2 + - id: step-3 name: Update distribution uses: ./ with: distribution: ${{ matrix.distribution.user-id }} update: true if: matrix.distribution.user-id != 'kali-linux' - - id: step-3 + - id: step-4 name: Install default absent tool uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: ${{ matrix.distribution.default-absent-tool }} - - id: step-4 + - id: step-5 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-3.outcome == 'success') - - id: step-5 + && (steps.step-4.outcome == 'success') + - id: step-6 name: Execute action for ${{ matrix.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distribution2.user-id }} if: |- always() - && (steps.step-3.outcome == 'success') - - id: step-6 + && (steps.step-4.outcome == 'success') + - id: step-7 name: Test - "${{ matrix.distribution2.user-id }}" should be the default distribution after installation shell: wsl-bash {0} run: |- @@ -1431,16 +1471,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-5.outcome == 'success') - - id: step-7 + && (steps.step-6.outcome == 'success') + - id: step-8 name: Re-execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-5.outcome == 'success') - - id: step-8 + && (steps.step-6.outcome == 'success') + - id: step-9 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: |- @@ -1448,8 +1488,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-7.outcome == 'success') - - id: step-9 + && (steps.step-8.outcome == 'success') + - id: step-10 name: Set as default uses: ./ with: @@ -1457,8 +1497,8 @@ jobs: set-as-default: true if: |- always() - && (steps.step-7.outcome == 'success') - - id: step-10 + && (steps.step-8.outcome == 'success') + - id: step-11 name: Test - "${{ matrix.distribution.user-id }}" should be the default distribution after re-running with set-as-default true shell: wsl-bash {0} run: |- @@ -1466,7 +1506,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-9.outcome == 'success') + && (steps.step-10.outcome == 'success') test_distribution_specific_wsl_bash_scripts: name: Test distribution specific wsl-bash scripts on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -1561,47 +1601,52 @@ jobs: build/distributions/ key: ${{ github.run_id }} - id: step-1 + name: Fail if cache could not be restored + shell: cmd + run: exit 1 + if: steps.step-0.outputs.cache-hit == false + - id: step-2 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-2 + - id: step-3 name: Execute action for ${{ matrix.distributions.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution2.user-id }} additional-packages: bash - - id: step-3 + - id: step-4 name: Execute action for ${{ matrix.distributions.distribution3.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution3.user-id }} set-as-default: false - - id: step-4 + - id: step-5 name: Execute action for ${{ matrix.distributions.distribution4.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution4.user-id }} set-as-default: false - - id: step-5 + - id: step-6 name: Execute action for ${{ matrix.distributions.distribution5.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution5.user-id }} set-as-default: false - - id: step-6 + - id: step-7 name: Execute action for ${{ matrix.distributions.distribution6.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution6.user-id }} set-as-default: false - - id: step-7 + - id: step-8 name: Execute action for ${{ matrix.distributions.distribution7.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution7.user-id }} set-as-default: false - - id: step-8 + - id: step-9 name: Test - wsl-bash_${{ matrix.distributions.distribution1.user-id }} should use the correct distribution shell: wsl-bash_Debian {0} run: |- @@ -1609,8 +1654,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.distributions.distribution1.match-pattern }} ]] if: |- always() - && (steps.step-1.outcome == 'success') - - id: step-9 + && (steps.step-2.outcome == 'success') + - id: step-10 name: Test - wsl-bash_${{ matrix.distributions.distribution2.user-id }} should use the correct distribution shell: wsl-bash_Alpine {0} run: |- @@ -1618,8 +1663,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.distributions.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-10 + && (steps.step-3.outcome == 'success') + - id: step-11 name: Test - wsl-bash_${{ matrix.distributions.distribution3.user-id }} should use the correct distribution shell: wsl-bash_kali-linux {0} run: |- @@ -1627,8 +1672,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.distributions.distribution3.match-pattern }} ]] if: |- always() - && (steps.step-3.outcome == 'success') - - id: step-11 + && (steps.step-4.outcome == 'success') + - id: step-12 name: Test - wsl-bash_${{ matrix.distributions.distribution4.user-id }} should use the correct distribution shell: wsl-bash_openSUSE-Leap-15.2 {0} run: |- @@ -1636,8 +1681,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.distributions.distribution4.match-pattern }} ]] if: |- always() - && (steps.step-4.outcome == 'success') - - id: step-12 + && (steps.step-5.outcome == 'success') + - id: step-13 name: Test - wsl-bash_${{ matrix.distributions.distribution5.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-22.04 {0} run: |- @@ -1645,9 +1690,9 @@ 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.distributions.distribution5.match-pattern }} ]] if: |- always() - && (steps.step-5.outcome == 'success') + && (steps.step-6.outcome == 'success') && (matrix.distributions.distribution5.user-id != 'Ubuntu-20.04') - - id: step-13 + - id: step-14 name: Test - wsl-bash_${{ matrix.distributions.distribution5.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-20.04 {0} run: |- @@ -1655,9 +1700,9 @@ 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.distributions.distribution5.match-pattern }} ]] if: |- always() - && (steps.step-5.outcome == 'success') + && (steps.step-6.outcome == 'success') && (matrix.distributions.distribution5.user-id != 'Ubuntu-22.04') - - id: step-14 + - id: step-15 name: Test - wsl-bash_${{ matrix.distributions.distribution6.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-18.04 {0} run: |- @@ -1665,8 +1710,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.distributions.distribution6.match-pattern }} ]] if: |- always() - && (steps.step-6.outcome == 'success') - - id: step-15 + && (steps.step-7.outcome == 'success') + - id: step-16 name: Test - wsl-bash_${{ matrix.distributions.distribution7.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-16.04 {0} run: |- @@ -1674,4 +1719,4 @@ 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.distributions.distribution7.match-pattern }} ]] if: |- always() - && (steps.step-7.outcome == 'success') + && (steps.step-8.outcome == 'success') diff --git a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts b/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts index acc6a4bb..0d2a4cbf 100644 --- a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts +++ b/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts @@ -46,7 +46,7 @@ file(".github/workflows") val camelCasedWorkflowName = workflowName.replace("""-\w""".toRegex()) { it.value.substring(1).capitalize() }.capitalize() - val preProcessWorkflow = tasks.register("preProcess${camelCasedWorkflowName}Workflow") { + val preprocessWorkflow = tasks.register("preprocess${camelCasedWorkflowName}Workflow") { inputs.file(workflowScript) outputs.file(workflowScript.resolveSibling("$workflowName.yaml")) javaLauncher.set(javaToolchains.launcherFor { @@ -59,6 +59,6 @@ file(".github/workflows") args("-script", workflowScript.absolutePath) } preprocessWorkflows { - dependsOn(preProcessWorkflow) + dependsOn(preprocessWorkflow) } } From 372b80fe0dcc74e9575cf5e764665a3a31ac48ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 26 Jan 2023 22:47:23 +0100 Subject: [PATCH 03/23] Consider imported files in workflow scripts as task inputs --- buildSrc/build.gradle.kts | 1 + .../net/kautler/github_actions.gradle.kts | 59 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 2846d1d7..62307439 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -68,6 +68,7 @@ dependencies { implementation("org.kohsuke:github-api".withVersion) implementation("com.charleskorn.kaml:kaml".withVersion) implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime".withVersion) + implementation(embeddedKotlin("compiler-embeddable")) } kotlinDslPluginOptions { diff --git a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts b/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts index 0d2a4cbf..ef4f89e1 100644 --- a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts +++ b/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts @@ -17,6 +17,18 @@ package net.kautler import groovy.lang.Closure +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +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 plugins { `java-base` @@ -47,8 +59,16 @@ file(".github/workflows") it.value.substring(1).capitalize() }.capitalize() val preprocessWorkflow = tasks.register("preprocess${camelCasedWorkflowName}Workflow") { - inputs.file(workflowScript) - outputs.file(workflowScript.resolveSibling("$workflowName.yaml")) + 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)) }) @@ -62,3 +82,38 @@ file(".github/workflows") dependsOn(preprocessWorkflow) } } + +val File.importedFiles: List + get() = if (!isFile) { + emptyList() + } else { + PsiManager + .getInstance( + KotlinCoreEnvironment + .createForProduction( + Disposer.newDisposable(), + CompilerConfiguration().apply { + put(MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) + }, + JVM_CONFIG_FILES + ) + .project + ) + .findFile( + CoreLocalVirtualFile( + CoreLocalFileSystem(), + this + ) + ) + .let { it as KtFile } + .fileAnnotationList + ?.annotationEntries + ?.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 } + ?: emptyList() + } From 67768d612bea9330f1ede421dfb43920e30c7264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sun, 29 Jan 2023 22:19:43 +0100 Subject: [PATCH 04/23] Update @vercel/ncc to 0.36.1 --- buildSrc/src/main/kotlin/net/kautler/Versions.kt | 2 +- ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/net/kautler/Versions.kt b/buildSrc/src/main/kotlin/net/kautler/Versions.kt index 99d25cce..78b0a2cc 100644 --- a/buildSrc/src/main/kotlin/net/kautler/Versions.kt +++ b/buildSrc/src/main/kotlin/net/kautler/Versions.kt @@ -38,7 +38,7 @@ val versions = mapOf( "node" to "16.18.1", // build NPM dependencies - "@vercel/ncc" to "0.25.1", + "@vercel/ncc" to "0.36.1", // build Java dependencies "com.github.ben-manes.versions" to "0.36.0", diff --git a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt index f9b652e8..40370558 100644 --- a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt +++ b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt @@ -29,6 +29,7 @@ external interface NccOptions { var filterAssetBase: String var minify: Boolean var sourceMap: Boolean + var assetBuilds: Boolean var sourceMapBasePrefix: String var sourceMapRegister: Boolean var license: String @@ -63,5 +64,5 @@ inline fun AssetMap.forEach(action: (Pair) -> Unit) { external interface Asset { val source: Buffer - val permissions: Number? + val permissions: Int? } From f8c232835cfd0e364b5ac4c1bfcce9e67af7a110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 2 Feb 2023 18:11:51 +0100 Subject: [PATCH 05/23] Fix tests, failing due to the wrong error --- .github/workflows/test.main.kts | 6 +++--- .github/workflows/test.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 79016a7f..78802ae2 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -207,15 +207,15 @@ workflowWithCopyright( "environment" to environments, "distribution" to listOf( mapOf( - "id" to "invalid", + "user-id" to "invalid", "label" to "invalid" ), mapOf( - "id" to "", + "user-id" to "", "label" to "" ), mapOf( - "id" to null, + "user-id" to null, "label" to "null" ) ) diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f2e73eb8..1c18a8ed 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -84,11 +84,11 @@ jobs: - windows-2022 - windows-latest distribution: - - id: invalid + - user-id: invalid label: invalid - - id: '' + - user-id: '' label: '' - - id: null + - user-id: null label: 'null' steps: - id: step-0 From c6f569ddafbe86058d552dd1da777dd2ae24fb06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Feb 2023 16:01:11 +0100 Subject: [PATCH 06/23] Update to github-actions-kotlin-dsl 0.36.0 and use newly available action wrappers --- .../workflows/check-action-typing.main.kts | 4 +- .github/workflows/check-action-typing.yaml | 20 +- .../check-dependency-versions.main.kts | 17 +- .../workflows/check-dependency-versions.yaml | 22 +- .github/workflows/test.main.kts | 53 +- .github/workflows/test.yaml | 598 ++++++++---------- .../workflows/validate-gradle-wrapper.yaml | 18 +- .../workflow-with-copyright.main.kts | 51 +- 8 files changed, 360 insertions(+), 423 deletions(-) diff --git a/.github/workflows/check-action-typing.main.kts b/.github/workflows/check-action-typing.main.kts index bd151e00..8fd3788d 100755 --- a/.github/workflows/check-action-typing.main.kts +++ b/.github/workflows/check-action-typing.main.kts @@ -19,7 +19,7 @@ @file:Import("workflow-with-copyright.main.kts") import it.krzeminski.githubactions.actions.actions.CheckoutV3 -import it.krzeminski.githubactions.actions.krzema12.GithubActionsTypingV0 +import it.krzeminski.githubactions.actions.krzema12.GithubActionsTypingV1 import it.krzeminski.githubactions.domain.RunnerType.UbuntuLatest import it.krzeminski.githubactions.domain.triggers.PullRequest import it.krzeminski.githubactions.domain.triggers.Push @@ -47,7 +47,7 @@ workflowWithCopyright( ) uses( name = "Check Action Typing", - action = GithubActionsTypingV0() + action = GithubActionsTypingV1() ) } } diff --git a/.github/workflows/check-action-typing.yaml b/.github/workflows/check-action-typing.yaml index b8e62ee0..851e19e7 100644 --- a/.github/workflows/check-action-typing.yaml +++ b/.github/workflows/check-action-typing.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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-action-typing.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt @@ -22,22 +22,16 @@ on: pull_request: {} jobs: check_yaml_consistency: + name: Check YAML consistency runs-on: ubuntu-latest steps: - id: step-0 name: Check out uses: actions/checkout@v3 - id: step-1 - name: Set up Java in proper version - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: zulu - cache: gradle - - id: step-2 name: Execute script run: rm '.github/workflows/check-action-typing.yaml' && '.github/workflows/check-action-typing.main.kts' - - id: step-3 + - id: step-2 name: Consistency check run: git diff --exit-code '.github/workflows/check-action-typing.yaml' check_action_typing: @@ -54,4 +48,4 @@ jobs: uses: actions/checkout@v3 - id: step-2 name: Check Action Typing - uses: krzema12/github-actions-typing@v0 + uses: krzema12/github-actions-typing@v1 diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index c24a0cc2..c932f97d 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -18,8 +18,8 @@ @file:Import("workflow-with-copyright.main.kts") -import it.krzeminski.githubactions.actions.CustomAction import it.krzeminski.githubactions.actions.actions.CheckoutV3 +import it.krzeminski.githubactions.actions.burrunan.GradleCacheActionV1 import it.krzeminski.githubactions.domain.RunnerType.WindowsLatest import it.krzeminski.githubactions.domain.triggers.Cron import it.krzeminski.githubactions.domain.triggers.Schedule @@ -56,16 +56,11 @@ workflowWithCopyright( ) uses( name = "Check Dependency Versions", - action = CustomAction( - actionOwner = "burrunan", - actionName = "gradle-cache-action", - actionVersion = "v1", - inputs = mapOf( - "arguments" to "dependencyUpdates", - "debug" to "false", - "concurrent" to "true", - "gradle-dependencies-cache-key" to "buildSrc/**/Versions.kt" - ) + action = GradleCacheActionV1( + arguments = listOf("dependencyUpdates"), + debug = false, + concurrent = true, + gradleDependenciesCacheKey = listOf("buildSrc/**/Versions.kt") ) ) } diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 90ef59cb..53f91fb4 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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-dependency-versions.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt @@ -22,22 +22,16 @@ on: - cron: 0 0 * * 5 jobs: check_yaml_consistency: + name: Check YAML consistency runs-on: ubuntu-latest steps: - id: step-0 name: Check out uses: actions/checkout@v3 - id: step-1 - name: Set up Java in proper version - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: zulu - cache: gradle - - id: step-2 name: Execute script run: rm '.github/workflows/check-dependency-versions.yaml' && '.github/workflows/check-dependency-versions.main.kts' - - id: step-3 + - id: step-2 name: Consistency check run: git diff --exit-code '.github/workflows/check-dependency-versions.yaml' check_dependency_versions: @@ -56,7 +50,7 @@ jobs: name: Check Dependency Versions uses: burrunan/gradle-cache-action@v1 with: - arguments: dependencyUpdates + gradle-dependencies-cache-key: buildSrc/**/Versions.kt debug: false concurrent: true - gradle-dependencies-cache-key: buildSrc/**/Versions.kt + arguments: dependencyUpdates diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 78802ae2..c8d9e254 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -18,9 +18,10 @@ @file:Import("workflow-with-copyright.main.kts") -import it.krzeminski.githubactions.actions.CustomAction -import it.krzeminski.githubactions.actions.actions.CacheV3 +import it.krzeminski.githubactions.actions.actions.CacheRestoreV3 +import it.krzeminski.githubactions.actions.actions.CacheSaveV3 import it.krzeminski.githubactions.actions.actions.CheckoutV3 +import it.krzeminski.githubactions.actions.burrunan.GradleCacheActionV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1.Distribution import it.krzeminski.githubactions.domain.CommandStep @@ -127,12 +128,9 @@ workflowWithCopyright( ), sourceFile = __FILE__ ) { - val builtArtifactsCache = CacheV3( - path = listOf( - "action.yml", - "build/distributions/" - ), - key = expr { github.run_id } + val builtArtifacts = listOf( + "action.yml", + "build/distributions/" ) val executeAction = SetupWslV1( @@ -154,21 +152,24 @@ workflowWithCopyright( ) uses( name = "Build", - action = CustomAction( - actionOwner = "burrunan", - actionName = "gradle-cache-action", - actionVersion = "v1", - inputs = mapOf( - "arguments" to "build --info --stacktrace --scan", - "debug" to "false", - "concurrent" to "true", - "gradle-dependencies-cache-key" to "buildSrc/**/Versions.kt" - ) + action = GradleCacheActionV1( + arguments = listOf( + "build", + "--info", + "--stacktrace", + "--scan" + ), + debug = false, + concurrent = true, + gradleDependenciesCacheKey = listOf("buildSrc/**/Versions.kt") ) ) uses( name = "Save built artifacts to cache", - action = builtArtifactsCache + action = CacheSaveV3( + path = builtArtifacts, + key = expr { github.run_id } + ) ) } @@ -184,15 +185,13 @@ workflowWithCopyright( runsOn = RunnerType.Custom(expr("matrix.environment")), _customArguments = _customArguments ) { - val restoreBuildArtifacts = uses( + uses( name = "Restore built artifacts from cache", - action = builtArtifactsCache - ) - run( - name = "Fail if cache could not be restored", - condition = "${restoreBuildArtifacts.outputs.cacheHit} == false", - shell = Cmd, - command = "exit 1" + action = CacheRestoreV3( + path = builtArtifacts, + key = expr { github.run_id }, + failOnCacheMiss = true + ) ) block() } diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1c18a8ed..b0cd5c31 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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/test.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt @@ -24,22 +24,16 @@ on: - cron: 0 0 * * * jobs: check_yaml_consistency: + name: Check YAML consistency runs-on: ubuntu-latest steps: - id: step-0 name: Check out uses: actions/checkout@v3 - id: step-1 - name: Set up Java in proper version - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: zulu - cache: gradle - - id: step-2 name: Execute script run: rm '.github/workflows/test.yaml' && '.github/workflows/test.main.kts' - - id: step-3 + - id: step-2 name: Consistency check run: git diff --exit-code '.github/workflows/test.yaml' build: @@ -58,13 +52,17 @@ jobs: name: Build uses: burrunan/gradle-cache-action@v1 with: - arguments: build --info --stacktrace --scan + gradle-dependencies-cache-key: buildSrc/**/Versions.kt debug: false concurrent: true - gradle-dependencies-cache-key: buildSrc/**/Versions.kt + arguments: |- + build + --info + --stacktrace + --scan - id: step-3 name: Save built artifacts to cache - uses: actions/cache@v3 + uses: actions/cache/save@v3 with: path: |- action.yml @@ -93,27 +91,23 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action continue-on-error: true uses: ./ with: distribution: ${{ matrix.distribution.user-id }} - - id: step-3 + - id: step-2 name: Test - action should fail if an invalid distribution is given shell: cmd - run: if '${{ steps.step-2.outcome }}' NEQ 'failure' exit 1 + run: if '${{ steps.step-1.outcome }}' NEQ 'failure' exit 1 test_default_distribution: name: Test default distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -135,45 +129,41 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: update: true - - id: step-3 + - id: step-2 name: Test - wsl-bash should be available as custom shell shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-4 + && (steps.step-1.outcome == 'success') + - id: step-3 name: Test - wsl-bash should fail if the script fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-5 + && (steps.step-1.outcome == 'success') + - id: step-4 name: Test - wsl-bash should fail if the script fails (verification) shell: cmd - run: IF '${{ steps.step-4.outcome }}' NEQ 'failure' EXIT /B 1 + run: IF '${{ steps.step-3.outcome }}' NEQ 'failure' EXIT /B 1 if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-6 + && (steps.step-1.outcome == 'success') + - id: step-5 name: Test - wsl-bash should fail if one of the commands fails (provocation) continue-on-error: true shell: wsl-bash {0} @@ -182,45 +172,45 @@ jobs: : if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-7 + && (steps.step-1.outcome == 'success') + - id: step-6 name: Test - wsl-bash should fail if one of the commands fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-6.outcome }}'' == ''failure'' ] || exit 1' + run: '[ ''${{ steps.step-5.outcome }}'' == ''failure'' ] || exit 1' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-8 + && (steps.step-1.outcome == 'success') + - id: step-7 name: Test - wsl-bash should fail if an undefined variable is used (provocation) continue-on-error: true shell: wsl-bash {0} run: $foo if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-9 + && (steps.step-1.outcome == 'success') + - id: step-8 name: Test - wsl-bash should fail if an undefined variable is used (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-8.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-7.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-10 + && (steps.step-1.outcome == 'success') + - id: step-9 name: Test - wsl-bash should fail if any command in a pipe fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false | true if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-11 + && (steps.step-1.outcome == 'success') + - id: step-10 name: Test - wsl-bash should fail if any command in a pipe fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-10.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-9.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-12 + && (steps.step-1.outcome == 'success') + - id: step-11 name: Test - the default distribution should be correct shell: wsl-bash {0} run: |- @@ -228,8 +218,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-13 + && (steps.step-1.outcome == 'success') + - id: step-12 name: Test - wsl-bash should use the correct distribution shell: wsl-bash {0} run: |- @@ -237,8 +227,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.distribution.match-pattern }} ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-14 + && (steps.step-1.outcome == 'success') + - id: step-13 name: Test - multi-line commands should not be disturbed by CRLF line endings shell: wsl-bash {0} run: |- @@ -246,82 +236,82 @@ jobs: ! grep -q $'\r' "$0" # this comment catches the CR if present if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-15 + && (steps.step-1.outcome == 'success') + - id: step-14 name: Test - wsl-bash should fail if no script file is given (provocation) continue-on-error: true shell: wsl-bash run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-16 + && (steps.step-1.outcome == 'success') + - id: step-15 name: Test - wsl-bash should fail if no script file is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-15.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-14.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-17 + && (steps.step-1.outcome == 'success') + - id: step-16 name: Test - wsl-bash should fail if more than one parameter is given and first is not -u (provocation) continue-on-error: true shell: wsl-bash user {0} run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-18 + && (steps.step-1.outcome == 'success') + - id: step-17 name: Test - wsl-bash should fail if more than one parameter is given and first is not -u (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-17.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-16.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-19 + && (steps.step-1.outcome == 'success') + - id: step-18 name: Test - wsl-bash should fail if only user is given (provocation) continue-on-error: true shell: wsl-bash -u {0} run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-20 + && (steps.step-1.outcome == 'success') + - id: step-19 name: Test - wsl-bash should fail if only user is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-19.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-18.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-21 + && (steps.step-1.outcome == 'success') + - id: step-20 name: Test - wsl-bash should fail if excess argument is given (provocation) continue-on-error: true shell: wsl-bash -u user {0} foo run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-22 + && (steps.step-1.outcome == 'success') + - id: step-21 name: Test - wsl-bash should fail if excess argument is given (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-21.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-20.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-23 + && (steps.step-1.outcome == 'success') + - id: step-22 name: Test - wsl-bash should fail if given script file does not exist (provocation) continue-on-error: true shell: wsl-bash -u user {0}foo run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-24 + && (steps.step-1.outcome == 'success') + - id: step-23 name: Test - wsl-bash should fail if given script file does not exist (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-23.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-22.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') test: name: Test "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -371,48 +361,44 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} use-cache: false - - id: step-3 + - 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-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-3 name: Test - wsl-bash should fail if bash is not present by default (verification) - run: wsl sh -euc "[ '${{ steps.step-3.outcome }}' = 'failure' ]" + run: wsl sh -euc "[ '${{ steps.step-2.outcome }}' = 'failure' ]" if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-5 + - id: step-4 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-6 + - id: step-5 name: Install Bash on Alpine uses: ./ with: @@ -420,31 +406,31 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-7 + - id: step-6 name: Test - wsl-bash should be available as custom shell shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-8 + && (steps.step-1.outcome == 'success') + - id: step-7 name: Test - wsl-bash should fail if the script fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-9 + && (steps.step-1.outcome == 'success') + - id: step-8 name: Test - wsl-bash should fail if the script fails (verification) shell: cmd - run: IF '${{ steps.step-8.outcome }}' NEQ 'failure' EXIT /B 1 + run: IF '${{ steps.step-7.outcome }}' NEQ 'failure' EXIT /B 1 if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-10 + && (steps.step-1.outcome == 'success') + - id: step-9 name: Test - wsl-bash should fail if one of the commands fails (provocation) continue-on-error: true shell: wsl-bash {0} @@ -453,45 +439,45 @@ jobs: : if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-11 + && (steps.step-1.outcome == 'success') + - id: step-10 name: Test - wsl-bash should fail if one of the commands fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-10.outcome }}'' == ''failure'' ] || exit 1' + run: '[ ''${{ steps.step-9.outcome }}'' == ''failure'' ] || exit 1' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-12 + && (steps.step-1.outcome == 'success') + - id: step-11 name: Test - wsl-bash should fail if an undefined variable is used (provocation) continue-on-error: true shell: wsl-bash {0} run: $foo if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-13 + && (steps.step-1.outcome == 'success') + - id: step-12 name: Test - wsl-bash should fail if an undefined variable is used (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-12.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-11.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-14 + && (steps.step-1.outcome == 'success') + - id: step-13 name: Test - wsl-bash should fail if any command in a pipe fails (provocation) continue-on-error: true shell: wsl-bash {0} run: false | true if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-15 + && (steps.step-1.outcome == 'success') + - id: step-14 name: Test - wsl-bash should fail if any command in a pipe fails (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-14.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-13.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-16 + && (steps.step-1.outcome == 'success') + - id: step-15 name: Test - the default distribution should be correct shell: wsl-bash {0} run: |- @@ -499,8 +485,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distribution.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-17 + && (steps.step-1.outcome == 'success') + - id: step-16 name: Test - wsl-bash should use the correct distribution shell: wsl-bash {0} run: |- @@ -508,8 +494,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.distribution.match-pattern }} ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-18 + && (steps.step-1.outcome == 'success') + - id: step-17 name: Test - multi-line commands should not be disturbed by CRLF line endings shell: wsl-bash {0} run: |- @@ -517,52 +503,52 @@ jobs: ! grep -q $'\r' "$0" # this comment catches the CR if present if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-19 + && (steps.step-1.outcome == 'success') + - id: step-18 name: Test - ${{ matrix.distribution.default-absent-tool }} should not be installed by default (provocation) continue-on-error: true shell: wsl-bash {0} run: ${{ matrix.distribution.default-absent-tool }} --version if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-20 + && (steps.step-1.outcome == 'success') + - id: step-19 name: Test - ${{ matrix.distribution.default-absent-tool }} should not be installed by default (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-19.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-18.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-21 + && (steps.step-1.outcome == 'success') + - id: step-20 name: Test - bash should be installed by default shell: wsl-bash {0} run: bash -c true if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-22 + && (steps.step-1.outcome == 'success') + - id: step-21 name: Test - sh should be installed by default shell: wsl-bash {0} run: sh -c true if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-23 + && (steps.step-1.outcome == 'success') + - id: step-22 name: Test - wsl-sh should not be present (provocation) continue-on-error: true shell: wsl-sh {0} run: ':' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-24 + && (steps.step-1.outcome == 'success') + - id: step-23 name: Test - wsl-sh should not be present (verification) shell: wsl-bash {0} - run: '[ ''${{ steps.step-23.outcome }}'' == ''failure'' ]' + run: '[ ''${{ steps.step-22.outcome }}'' == ''failure'' ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-25 + && (steps.step-1.outcome == 'success') + - id: step-24 name: Add wsl-sh wrapper uses: ./ with: @@ -570,15 +556,15 @@ jobs: wsl-shell-command: sh -eu if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-26 + && (steps.step-1.outcome == 'success') + - id: step-25 name: Test - wsl-sh should be present shell: wsl-sh {0} run: ':' if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-27 + && (steps.step-24.outcome == 'success') + - id: step-26 name: Test - wsl-bash should use bash shell: wsl-bash {0} run: |- @@ -586,8 +572,8 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" == 'bash' ] if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-28 + && (steps.step-24.outcome == 'success') + - id: step-27 name: Test - wsl-sh should use sh shell: wsl-sh {0} run: |- @@ -595,45 +581,45 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" = 'sh' ] if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-29 + && (steps.step-24.outcome == 'success') + - id: step-28 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-30 + && (steps.step-24.outcome == 'success') + - id: step-29 name: Test - wsl-bash should not be present (provocation) continue-on-error: true shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-31 + && (steps.step-24.outcome == 'success') + - id: step-30 name: Test - wsl-bash should not be present (verification) shell: wsl-sh {0} - run: '[ ''${{ steps.step-30.outcome }}'' = ''failure'' ]' + run: '[ ''${{ steps.step-29.outcome }}'' = ''failure'' ]' if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-32 + && (steps.step-24.outcome == 'success') + - id: step-31 name: Re-add wsl-bash wrapper uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-25.outcome == 'success') - - id: step-33 + && (steps.step-24.outcome == 'success') + - id: step-32 name: Test - wsl-bash should be present shell: wsl-bash {0} run: ':' if: |- always() - && (steps.step-32.outcome == 'success') - - id: step-34 + && (steps.step-31.outcome == 'success') + - id: step-33 name: Test - wsl-bash should use bash shell: wsl-bash {0} run: |- @@ -641,8 +627,8 @@ jobs: [ "$(ps -o pid='' -o comm='' 2>/dev/null | grep "^\s\+$$\s\+" | grep -o '\S\+$')" == 'bash' ] if: |- always() - && (steps.step-32.outcome == 'success') - - id: step-35 + && (steps.step-31.outcome == 'success') + - id: step-34 name: Test - wsl-bash should use root as default user shell: wsl-bash {0} run: |- @@ -650,15 +636,15 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-32.outcome == 'success') - - id: step-36 + && (steps.step-31.outcome == 'success') + - id: step-35 name: Add user test shell: wsl-bash {0} run: useradd -m -p 4qBD5NWD3IkbU test if: |- always() - && (steps.step-32.outcome == 'success') - - id: step-37 + && (steps.step-31.outcome == 'success') + - id: step-36 name: Set wsl-bash wrapper to use user test by default uses: ./ with: @@ -667,8 +653,8 @@ jobs: wsl-shell-command: bash -c "sudo -u test bash --noprofile --norc -euo pipefail "\ if: |- always() - && (steps.step-32.outcome == 'success') - - id: step-38 + && (steps.step-31.outcome == 'success') + - id: step-37 name: Test - wsl-bash should use test as default user shell: wsl-bash {0} run: |- @@ -676,8 +662,8 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-37.outcome == 'success') - - id: step-39 + && (steps.step-36.outcome == 'success') + - id: step-38 name: Set wsl-bash wrapper to use user test by default with inline script usage uses: ./ with: @@ -685,8 +671,8 @@ jobs: wsl-shell-command: bash -c "sudo -u test bash --noprofile --norc -euo pipefail '{0}'" if: |- always() - && (steps.step-37.outcome == 'success') - - id: step-40 + && (steps.step-36.outcome == 'success') + - id: step-39 name: Test - wsl-bash should use test as default user with inline script usage shell: wsl-bash {0} run: |- @@ -694,23 +680,23 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-39.outcome == 'success') - - id: step-41 + && (steps.step-38.outcome == 'success') + - id: step-40 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-39.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-38.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-39.outcome == 'success') - - id: step-42 + && (steps.step-38.outcome == 'success') + - id: step-41 name: Set wsl-bash wrapper to use default user by default uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-39.outcome == 'success') - - id: step-43 + && (steps.step-38.outcome == 'success') + - id: step-42 name: Test - wsl-bash should use root as default user shell: wsl-bash {0} run: |- @@ -718,22 +704,22 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-42.outcome == 'success') - - id: step-44 + && (steps.step-41.outcome == 'success') + - id: step-43 name: Test - test user does already exist shell: wsl-bash {0} run: id -u test if: |- always() - && (steps.step-42.outcome == 'success') - - id: step-45 + && (steps.step-41.outcome == 'success') + - id: step-44 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-42.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-41.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-42.outcome == 'success') - - id: step-46 + && (steps.step-41.outcome == 'success') + - id: step-45 name: Set wsl-bash wrapper to use existing user test by default with extra parameter uses: ./ with: @@ -741,8 +727,8 @@ jobs: wsl-shell-user: test if: |- always() - && (steps.step-42.outcome == 'success') - - id: step-47 + && (steps.step-41.outcome == 'success') + - id: step-46 name: Test - wsl-bash should use existing user test as default user with extra parameter shell: wsl-bash {0} run: |- @@ -750,22 +736,22 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-46.outcome == 'success') - - id: step-48 + && (steps.step-45.outcome == 'success') + - id: step-47 name: Test - test2 user does not exist shell: wsl-bash {0} run: '! id -u test2' if: |- always() - && (steps.step-46.outcome == 'success') - - id: step-49 + && (steps.step-45.outcome == 'success') + - id: step-48 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-46.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-45.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-46.outcome == 'success') - - id: step-50 + && (steps.step-45.outcome == 'success') + - id: step-49 name: Set wsl-bash wrapper to use non-existing user test2 by default with extra parameter uses: ./ with: @@ -773,8 +759,8 @@ jobs: wsl-shell-user: test2 if: |- always() - && (steps.step-46.outcome == 'success') - - id: step-51 + && (steps.step-45.outcome == 'success') + - id: step-50 name: Test - wsl-bash should use auto-generated user test2 as default user shell: wsl-bash {0} run: |- @@ -782,8 +768,8 @@ jobs: [ "$(whoami)" == 'test2' ] if: |- always() - && (steps.step-50.outcome == 'success') - - id: step-52 + && (steps.step-49.outcome == 'success') + - id: step-51 name: Test - wsl-bash should use ad-hoc user test shell: wsl-bash -u test {0} run: |- @@ -791,8 +777,8 @@ jobs: [ "$(whoami)" == 'test' ] if: |- always() - && (steps.step-50.outcome == 'success') - - id: step-53 + && (steps.step-49.outcome == 'success') + - id: step-52 name: Test - wsl-bash should use ad-hoc user root shell: wsl-bash -u root {0} run: |- @@ -800,16 +786,16 @@ jobs: [ "$(whoami)" == 'root' ] if: |- always() - && (steps.step-50.outcome == 'success') - - id: step-54 + && (steps.step-49.outcome == 'success') + - id: step-53 name: Make a no-op execution of the action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} if: |- always() - && (steps.step-50.outcome == 'success') - - id: step-55 + && (steps.step-49.outcome == 'success') + - id: step-54 name: Test - wsl-bash should still use test2 as default user shell: wsl-bash {0} run: |- @@ -817,7 +803,7 @@ jobs: [ "$(whoami)" == 'test2' ] if: |- always() - && (steps.step-54.outcome == 'success') + && (steps.step-53.outcome == 'success') test_wsl-conf_on_initial_execution: name: Test /etc/wsl.conf handling on initial execution for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -867,18 +853,14 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: @@ -886,15 +868,15 @@ jobs: wsl-conf: |- [automount] options = uid=1000 - - id: step-3 + - id: step-2 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-3 name: Install Bash on Alpine uses: ./ with: @@ -902,9 +884,9 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-5 + - id: step-4 name: Test - /etc/wsl.conf should exist shell: wsl-bash {0} run: |- @@ -912,8 +894,8 @@ jobs: cat /etc/wsl.conf if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-6 + && (steps.step-1.outcome == 'success') + - id: step-5 name: Test - /mnt/c should be mounted with uid 1000 shell: wsl-bash {0} run: |- @@ -921,7 +903,7 @@ jobs: [[ "$(stat -c %u /mnt/c)" == 1000 ]] if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') test_wsl-conf_on_subsequent_execution: name: Test /etc/wsl.conf handling on subsequent execution for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -971,31 +953,27 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} - - id: step-3 + - id: step-2 name: Delete wsl-bash shell: cmd - run: DEL /F "${{ steps.step-2.outputs.wsl-shell-wrapper-path }}" + run: DEL /F "${{ steps.step-1.outputs.wsl-shell-wrapper-path }}" if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-4 + - id: step-3 name: Install Bash on Alpine uses: ./ with: @@ -1003,16 +981,16 @@ jobs: additional-packages: bash if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') && (matrix.distribution.user-id == 'Alpine') - - id: step-5 + - id: step-4 name: Test - /etc/wsl.conf should not exist shell: wsl-bash {0} run: '[ ! -f /etc/wsl.conf ]' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-6 + && (steps.step-1.outcome == 'success') + - id: step-5 name: 'Test - C: should be mounted at /mnt/c' shell: wsl-bash {0} run: |- @@ -1020,8 +998,8 @@ jobs: mount | grep 'C:.* on /mnt/c' if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-7 + && (steps.step-1.outcome == 'success') + - id: step-6 name: Test - /mnt/c should be mounted with uid 0 shell: wsl-bash {0} run: |- @@ -1029,8 +1007,8 @@ jobs: [[ "$(stat -c %u /mnt/c)" == 0 ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-8 + && (steps.step-1.outcome == 'success') + - id: step-7 name: Execute action uses: ./ with: @@ -1040,8 +1018,8 @@ jobs: root = / if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-9 + && (steps.step-1.outcome == 'success') + - id: step-8 name: Test - /etc/wsl.conf should exist shell: wsl-bash {0} run: |- @@ -1049,8 +1027,8 @@ jobs: cat /etc/wsl.conf if: |- always() - && (steps.step-8.outcome == 'success') - - id: step-10 + && (steps.step-7.outcome == 'success') + - id: step-9 name: 'Test - C: should be mounted at /c' shell: wsl-bash {0} run: |- @@ -1058,7 +1036,7 @@ jobs: mount | grep 'C:.* on /c' if: |- always() - && (steps.step-8.outcome == 'success') + && (steps.step-7.outcome == 'success') test_additional_packages: name: Test additional packages for "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -1108,37 +1086,33 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: ${{ matrix.distribution.default-absent-tool }} bash - - id: step-3 + - 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-2.outcome == 'success') - - id: step-4 + && (steps.step-1.outcome == 'success') + - id: step-3 name: Test - bash should be installed shell: wsl-bash {0} run: bash -c true if: |- always() - && (steps.step-2.outcome == 'success') + && (steps.step-1.outcome == 'success') 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 }} @@ -1246,39 +1220,35 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-3 + - id: step-2 name: Execute action for ${{ matrix.distributions.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution2.user-id }} - - id: step-4 + - id: step-3 name: Execute action for ${{ matrix.distributions.distribution3.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution3.user-id }} set-as-default: false - - id: step-5 + - id: step-4 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} again uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-6 + - id: step-5 name: Test - the default distribution should be the last installed distribution with set-as-default true shell: wsl-bash {0} run: |- @@ -1286,8 +1256,8 @@ jobs: [[ "$(cat <(wsl.exe --list || true) <(wsl.exe --list || true | iconv -f UTF-16LE -t UTF-8) <(wslconfig.exe /list || true) <(wslconfig.exe /list || true | iconv -f UTF-16LE -t UTF-8))" == *${{ matrix.distributions.distribution2.wsl-id }}\ \(Default\)* ]] if: |- always() - && (steps.step-5.outcome == 'success') - - id: step-7 + && (steps.step-4.outcome == 'success') + - id: step-6 name: Test - wsl-bash should use the last installed distribution with set-as-default true shell: wsl-bash {0} run: |- @@ -1295,7 +1265,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.distributions.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-5.outcome == 'success') + && (steps.step-4.outcome == 'success') test_multiple_usage_with_same_distribution: name: Test multiple usage with "${{ matrix.distribution.user-id }}" distribution on ${{ matrix.environment }} runs-on: ${{ matrix.environment }} @@ -1418,52 +1388,48 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: bash - - id: step-3 + - id: step-2 name: Update distribution uses: ./ with: distribution: ${{ matrix.distribution.user-id }} update: true if: matrix.distribution.user-id != 'kali-linux' - - id: step-4 + - id: step-3 name: Install default absent tool uses: ./ with: distribution: ${{ matrix.distribution.user-id }} additional-packages: ${{ matrix.distribution.default-absent-tool }} - - id: step-5 + - 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') - - id: step-6 + && (steps.step-3.outcome == 'success') + - id: step-5 name: Execute action for ${{ matrix.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distribution2.user-id }} 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: |- @@ -1471,16 +1437,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: |- @@ -1488,8 +1454,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: @@ -1497,8 +1463,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: |- @@ -1506,7 +1472,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 }} runs-on: ${{ matrix.environment }} @@ -1594,59 +1560,55 @@ jobs: steps: - id: step-0 name: Restore built artifacts from cache - uses: actions/cache@v3 + uses: actions/cache/restore@v3 with: path: |- action.yml build/distributions/ key: ${{ github.run_id }} + fail-on-cache-miss: true - id: step-1 - name: Fail if cache could not be restored - shell: cmd - run: exit 1 - if: steps.step-0.outputs.cache-hit == false - - id: step-2 name: Execute action for ${{ matrix.distributions.distribution1.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution1.user-id }} - - id: step-3 + - id: step-2 name: Execute action for ${{ matrix.distributions.distribution2.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution2.user-id }} additional-packages: bash - - id: step-4 + - id: step-3 name: Execute action for ${{ matrix.distributions.distribution3.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution3.user-id }} set-as-default: false - - id: step-5 + - id: step-4 name: Execute action for ${{ matrix.distributions.distribution4.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution4.user-id }} set-as-default: false - - id: step-6 + - id: step-5 name: Execute action for ${{ matrix.distributions.distribution5.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution5.user-id }} set-as-default: false - - id: step-7 + - id: step-6 name: Execute action for ${{ matrix.distributions.distribution6.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution6.user-id }} set-as-default: false - - id: step-8 + - id: step-7 name: Execute action for ${{ matrix.distributions.distribution7.user-id }} uses: ./ with: distribution: ${{ matrix.distributions.distribution7.user-id }} set-as-default: false - - id: step-9 + - id: step-8 name: Test - wsl-bash_${{ matrix.distributions.distribution1.user-id }} should use the correct distribution shell: wsl-bash_Debian {0} run: |- @@ -1654,8 +1616,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.distributions.distribution1.match-pattern }} ]] if: |- always() - && (steps.step-2.outcome == 'success') - - id: step-10 + && (steps.step-1.outcome == 'success') + - id: step-9 name: Test - wsl-bash_${{ matrix.distributions.distribution2.user-id }} should use the correct distribution shell: wsl-bash_Alpine {0} run: |- @@ -1663,8 +1625,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.distributions.distribution2.match-pattern }} ]] if: |- always() - && (steps.step-3.outcome == 'success') - - id: step-11 + && (steps.step-2.outcome == 'success') + - id: step-10 name: Test - wsl-bash_${{ matrix.distributions.distribution3.user-id }} should use the correct distribution shell: wsl-bash_kali-linux {0} run: |- @@ -1672,8 +1634,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.distributions.distribution3.match-pattern }} ]] if: |- always() - && (steps.step-4.outcome == 'success') - - id: step-12 + && (steps.step-3.outcome == 'success') + - id: step-11 name: Test - wsl-bash_${{ matrix.distributions.distribution4.user-id }} should use the correct distribution shell: wsl-bash_openSUSE-Leap-15.2 {0} run: |- @@ -1681,8 +1643,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.distributions.distribution4.match-pattern }} ]] if: |- always() - && (steps.step-5.outcome == 'success') - - id: step-13 + && (steps.step-4.outcome == 'success') + - id: step-12 name: Test - wsl-bash_${{ matrix.distributions.distribution5.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-22.04 {0} run: |- @@ -1690,9 +1652,9 @@ 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.distributions.distribution5.match-pattern }} ]] if: |- always() - && (steps.step-6.outcome == 'success') + && (steps.step-5.outcome == 'success') && (matrix.distributions.distribution5.user-id != 'Ubuntu-20.04') - - id: step-14 + - id: step-13 name: Test - wsl-bash_${{ matrix.distributions.distribution5.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-20.04 {0} run: |- @@ -1700,9 +1662,9 @@ 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.distributions.distribution5.match-pattern }} ]] if: |- always() - && (steps.step-6.outcome == 'success') + && (steps.step-5.outcome == 'success') && (matrix.distributions.distribution5.user-id != 'Ubuntu-22.04') - - id: step-15 + - id: step-14 name: Test - wsl-bash_${{ matrix.distributions.distribution6.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-18.04 {0} run: |- @@ -1710,8 +1672,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.distributions.distribution6.match-pattern }} ]] if: |- always() - && (steps.step-7.outcome == 'success') - - id: step-16 + && (steps.step-6.outcome == 'success') + - id: step-15 name: Test - wsl-bash_${{ matrix.distributions.distribution7.user-id }} should use the correct distribution shell: wsl-bash_Ubuntu-16.04 {0} run: |- @@ -1719,4 +1681,4 @@ 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.distributions.distribution7.match-pattern }} ]] if: |- always() - && (steps.step-8.outcome == 'success') + && (steps.step-7.outcome == 'success') diff --git a/.github/workflows/validate-gradle-wrapper.yaml b/.github/workflows/validate-gradle-wrapper.yaml index a7ac3189..8f8063e1 100644 --- a/.github/workflows/validate-gradle-wrapper.yaml +++ b/.github/workflows/validate-gradle-wrapper.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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/validate-gradle-wrapper.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt @@ -22,22 +22,16 @@ on: pull_request: {} jobs: check_yaml_consistency: + name: Check YAML consistency runs-on: ubuntu-latest steps: - id: step-0 name: Check out uses: actions/checkout@v3 - id: step-1 - name: Set up Java in proper version - uses: actions/setup-java@v3 - with: - java-version: 17 - distribution: zulu - cache: gradle - - id: step-2 name: Execute script run: rm '.github/workflows/validate-gradle-wrapper.yaml' && '.github/workflows/validate-gradle-wrapper.main.kts' - - id: step-3 + - id: step-2 name: Consistency check run: git diff --exit-code '.github/workflows/validate-gradle-wrapper.yaml' validate_gradle_wrapper: diff --git a/.github/workflows/workflow-with-copyright.main.kts b/.github/workflows/workflow-with-copyright.main.kts index f36ec3dc..4fe8a5c9 100644 --- a/.github/workflows/workflow-with-copyright.main.kts +++ b/.github/workflows/workflow-with-copyright.main.kts @@ -14,7 +14,7 @@ * limitations under the License. */ -@file:DependsOn("it.krzeminski:github-actions-kotlin-dsl:0.35.0") +@file:DependsOn("it.krzeminski:github-actions-kotlin-dsl:0.36.0") import it.krzeminski.githubactions.domain.Concurrency import it.krzeminski.githubactions.domain.triggers.Trigger @@ -22,6 +22,7 @@ import it.krzeminski.githubactions.dsl.WorkflowBuilder import it.krzeminski.githubactions.dsl.workflow import it.krzeminski.githubactions.yaml.writeToFile import java.io.File +import kotlin.io.path.invariantSeparatorsPathString fun workflowWithCopyright( name: String, @@ -31,35 +32,33 @@ fun workflowWithCopyright( concurrency: Concurrency? = null, block: WorkflowBuilder.() -> Unit ) { + val sourceFilePath = sourceFile.toPath() workflow( name = name, on = on, env = env, - sourceFile = sourceFile.toPath(), + sourceFile = sourceFilePath, concurrency = concurrency, block = block - ).apply { - writeToFile() - sourceFile.resolveSibling(targetFileName).apply { - writeText( - """ - |# Copyright 2020-2023 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. - | - ${readText().prependIndent("|")} - """.trimMargin() - ) - } - } + ).writeToFile( + preamble = """ + Copyright 2020-2023 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 (${sourceFilePath.invariantSeparatorsPathString.substringAfter("/setup-wsl/")}). + If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. + Generated with https://github.com/krzema12/github-workflows-kt + """.trimIndent() + ) } From 2238c92433430e256ed436a9d2361bf99969e453 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 2 Feb 2023 17:21:39 +0100 Subject: [PATCH 07/23] Update Kotlin to 1.8.10, Gradle to 8.0, and move buildSrc to included builds --- .../check-dependency-versions.main.kts | 3 +- .../workflows/check-dependency-versions.yaml | 1 - .github/workflows/test.main.kts | 3 +- .github/workflows/test.yaml | 1 - .gitignore | 8 +- build.gradle.kts | 10 +- buildSrc/build.gradle.kts | 216 --- .../src/main/kotlin/net/kautler/Versions.kt | 62 - .../kotlin/net/kautler/dao/GitHubAction.kt | 202 --- .../net/kautler/dao/ResultSerializer.kt | 318 ---- .../kotlin/net/kautler/ncc_packer.gradle.kts | 63 - .../util/DependencyUnresolvedExtension.kt | 27 - .../kotlin/net/kautler/versions.gradle.kts | 151 -- gradle.properties | 3 +- gradle/build-logic/build-logic.gradle.kts | 55 + gradle/build-logic/gradle.properties | 15 + gradle/build-logic/settings.gradle.kts | 45 + .../kotlin/net/kautler/dao/action/Branding.kt | 12 +- .../net/kautler/dao/action/GitHubAction.kt | 44 + .../kotlin/net/kautler/dao/action/Input.kt | 19 +- .../kotlin/net/kautler/dao/action/Output.kt | 25 +- .../kautler/dao/action/OutputMapSerializer.kt | 82 + .../kotlin/net/kautler/dao/action/Runs.kt | 106 ++ .../kotlin/net/kautler/dao/action/Step.kt | 47 + .../net/kautler/github_actions.gradle.kts | 23 +- .../kotlin/net/kautler/ncc_packer.gradle.kts | 88 + .../main/kotlin/net/kautler/node.gradle.kts | 176 +- .../kotlin/net/kautler/publishing.gradle.kts | 41 +- .../main/kotlin/net/kautler/readme.gradle.kts | 4 +- .../util/DependencyHandlerExtension.kt | 35 + .../net/kautler/util/NullOutputStream.kt | 2 +- .../kotlin/net/kautler/util/Properties.kt | 2 +- .../kautler/util/ReleaseExtensionExtension.kt | 65 + .../kotlin/net/kautler/versions.gradle.kts | 78 + ...ency-updates-report-aggregation.gradle.kts | 51 + .../gradle.properties | 15 + .../settings.gradle.kts | 44 + .../dao/result/DependenciesGroupSerializer.kt | 77 + .../dao/result/DependencyLatestSerializer.kt | 88 + .../result/DependencyOutdatedSerializer.kt | 89 + .../dao/result/DependencySerializer.kt | 83 + .../result/DependencyUnresolvedSerializer.kt | 88 + .../kautler/dao/result/ResultSerializer.kt | 92 + .../dao/result/VersionAvailableSerializer.kt | 67 + ...ency-updates-report-aggregation.gradle.kts | 174 ++ .../util/DependencyOutdatedExtension.kt | 9 +- .../net/kautler/util/IgnoredDependency.kt | 50 + .../net/kautler/util/ResultExtension.kt | 2 +- gradle/libs.versions.toml | 78 + gradle/wrapper/gradle-wrapper.jar | Bin 59203 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 7 +- gradlew | 269 +-- gradlew.bat | 15 +- kotlin-js-store/yarn.lock | 1011 +++++++++++ ...build.gradle.kts => ncc-packer.gradle.kts} | 4 +- settings.gradle.kts | 65 +- .../github/action/setup_wsl/Distribution.kt | 11 +- .../github/action/setup_wsl/SetupWsl.kt | 9 +- yarn.lock | 1516 ----------------- 59 files changed, 3112 insertions(+), 2834 deletions(-) delete mode 100644 buildSrc/build.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/net/kautler/Versions.kt delete mode 100644 buildSrc/src/main/kotlin/net/kautler/dao/GitHubAction.kt delete mode 100644 buildSrc/src/main/kotlin/net/kautler/dao/ResultSerializer.kt delete mode 100644 buildSrc/src/main/kotlin/net/kautler/ncc_packer.gradle.kts delete mode 100644 buildSrc/src/main/kotlin/net/kautler/util/DependencyUnresolvedExtension.kt delete mode 100644 buildSrc/src/main/kotlin/net/kautler/versions.gradle.kts create mode 100644 gradle/build-logic/build-logic.gradle.kts create mode 100644 gradle/build-logic/gradle.properties create mode 100644 gradle/build-logic/settings.gradle.kts rename buildSrc/settings.gradle.kts => gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt (73%) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt rename buildSrc/src/main/kotlin/net/kautler/util/YamlMapExtension.kt => gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt (64%) rename buildSrc/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt => gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt (57%) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/github_actions.gradle.kts (87%) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/node.gradle.kts (66%) rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/publishing.gradle.kts (83%) rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/readme.gradle.kts (96%) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/util/NullOutputStream.kt (94%) rename {buildSrc => gradle/build-logic}/src/main/kotlin/net/kautler/util/Properties.kt (99%) create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt create mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts create mode 100644 gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts create mode 100644 gradle/dependency-updates-report-aggregation/gradle.properties create mode 100644 gradle/dependency-updates-report-aggregation/settings.gradle.kts create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts rename {buildSrc => gradle/dependency-updates-report-aggregation}/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt (83%) create mode 100644 gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/IgnoredDependency.kt rename {buildSrc => gradle/dependency-updates-report-aggregation}/src/main/kotlin/net/kautler/util/ResultExtension.kt (95%) create mode 100644 gradle/libs.versions.toml create mode 100644 kotlin-js-store/yarn.lock rename ncc-packer/{build.gradle.kts => ncc-packer.gradle.kts} (85%) delete mode 100644 yarn.lock diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index c932f97d..8a3e36d7 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -59,8 +59,7 @@ workflowWithCopyright( action = GradleCacheActionV1( arguments = listOf("dependencyUpdates"), debug = false, - concurrent = true, - gradleDependenciesCacheKey = listOf("buildSrc/**/Versions.kt") + concurrent = true ) ) } diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 53f91fb4..df51df80 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -50,7 +50,6 @@ jobs: name: Check Dependency Versions uses: burrunan/gradle-cache-action@v1 with: - gradle-dependencies-cache-key: buildSrc/**/Versions.kt debug: false concurrent: true arguments: dependencyUpdates diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index c8d9e254..ab46dd1a 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -160,8 +160,7 @@ workflowWithCopyright( "--scan" ), debug = false, - concurrent = true, - gradleDependenciesCacheKey = listOf("buildSrc/**/Versions.kt") + concurrent = true ) ) uses( diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index b0cd5c31..ba7254b4 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -52,7 +52,6 @@ jobs: name: Build uses: burrunan/gradle-cache-action@v1 with: - gradle-dependencies-cache-key: buildSrc/**/Versions.kt debug: false concurrent: true arguments: |- diff --git a/.gitignore b/.gitignore index f4c53568..d01689f0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# Copyright 2020 Björn Kautler +# Copyright 2020-2023 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. @@ -15,6 +15,8 @@ /.idea/ /.gradle/ /build/ -/buildSrc/.gradle/ -/buildSrc/build/ +/gradle/build-logic/.gradle/ +/gradle/build-logic/build/ +/gradle/dependency-updates-report-aggregation/.gradle/ +/gradle/dependency-updates-report-aggregation/build/ /ncc-packer/build/ diff --git a/build.gradle.kts b/build.gradle.kts index 9f65ea6a..92f82360 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,9 +15,9 @@ */ plugins { - net.kautler.versions - net.kautler.node - net.kautler.github_actions - net.kautler.readme - net.kautler.publishing + id(libs.plugins.convention.versions.get().pluginId) + id(libs.plugins.convention.node.get().pluginId) + id(libs.plugins.convention.github.actions.get().pluginId) + id(libs.plugins.convention.readme.get().pluginId) + id(libs.plugins.convention.publishing.get().pluginId) } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts deleted file mode 100644 index 62307439..00000000 --- a/buildSrc/build.gradle.kts +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2020-2022 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. - */ - -import com.github.benmanes.gradle.versions.reporter.result.Result -import kotlinx.coroutines.runBlocking -import kotlinx.serialization.KSerializer -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration.Companion.Stable -import java.net.URLClassLoader -import kotlin.LazyThreadSafetyMode.NONE -import kotlin.script.experimental.api.ResultValue.Value -import kotlin.script.experimental.api.ScriptCompilationConfiguration -import kotlin.script.experimental.api.onSuccess -import kotlin.script.experimental.api.valueOrThrow -import kotlin.script.experimental.host.toScriptSource -import kotlin.script.experimental.jvm.BasicJvmScriptEvaluator -import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration -import kotlin.script.experimental.jvm.dependenciesFromCurrentContext -import kotlin.script.experimental.jvm.jvm -import kotlin.script.experimental.jvmhost.JvmScriptCompiler - -plugins { - `kotlin-dsl` - kotlin("plugin.serialization") version "1.3.72" - id("com.github.ben-manes.versions") version "0.36.0" -} - -buildscript { - repositories { - mavenCentral() - } - dependencies { - classpath("org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0") - classpath("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2") - classpath(kotlin("scripting-jvm-host", "1.3.72")) - } -} - -repositories { - mavenCentral() - jcenter() - gradlePluginPortal() -} - -val versions by lazy(NONE) { - versionsByClassLoader ?: versionsByScripting -} - -dependencies { - implementation(gradlePlugin("com.github.ben-manes.versions")) - implementation(gradlePlugin("net.researchgate.release")) - implementation(gradlePlugin("net.wooga.github")) - implementation(gradlePlugin("org.ajoberstar.grgit")) - implementation(gradlePlugin("org.jetbrains.kotlin.js")) - implementation("org.kohsuke:github-api".withVersion) - implementation("com.charleskorn.kaml:kaml".withVersion) - implementation("org.jetbrains.kotlinx:kotlinx-serialization-runtime".withVersion) - implementation(embeddedKotlin("compiler-embeddable")) -} - -kotlinDslPluginOptions { - experimentalWarning.set(false) -} - -tasks.dependencyUpdates { - checkForGradleUpdate = false - checkConstraints = true - - rejectVersionIf { - val preliminaryReleaseRegex = Regex( - """(?i)[.-](?:${ - listOf( - "alpha", - "beta", - "dev", - "rc", - "cr", - "m", - "preview", - "test", - "pr", - "pre", - "b", - "ea" - ).joinToString("|") - })[.\d-]*""" - ) - preliminaryReleaseRegex.containsMatchIn(candidate.version) - && !preliminaryReleaseRegex.containsMatchIn(currentVersion) - } - - outputFormatter = closureOf { - gradle = null - file("build/dependencyUpdates/report.json") - .apply { parentFile.mkdirs() } - .also { reportFile -> - Json(Stable.copy(prettyPrint = true)) - .stringify(resultSerializer, this) - .also { reportFile.writeText(it) } - } - } -} - -@Suppress("UNCHECKED_CAST") -val resultSerializerByClassLoader - get() = layout - .buildDirectory - .dir("classes/kotlin/main") - .get() - .let { classesDir -> - if (!classesDir.file("net/kautler/dao/ResultSerializer.class").asFile.isFile) { - return@let null - } - - URLClassLoader( - arrayOf(classesDir.asFile.toURI().toURL()), - buildscript.classLoader - ) - .loadClass("net.kautler.dao.ResultSerializer") - .kotlin - .objectInstance - as KSerializer? - } - -@Suppress("UNCHECKED_CAST") -val resultSerializerByScripting - get() = runBlocking { - JvmScriptCompiler(defaultJvmScriptingHostConfiguration)( - """ - ${file("src/main/kotlin/net/kautler/dao/ResultSerializer.kt").readText()} - ResultSerializer - """.toScriptSource(), - ScriptCompilationConfiguration { - jvm { - dependenciesFromCurrentContext( - "gradle-versions-plugin", - "kotlinx-serialization-runtime", - "groovy-all" - ) - } - } - ).onSuccess { BasicJvmScriptEvaluator()(it) } - } - .valueOrThrow() - .returnValue - .let { it as Value } - .value - as KSerializer - -val resultSerializer by lazy(NONE) { - resultSerializerByClassLoader ?: resultSerializerByScripting -} - -@Suppress("UNCHECKED_CAST") -val versionsByClassLoader - get() = layout - .buildDirectory - .dir("classes/kotlin/main") - .get() - .let { classesDir -> - if (!classesDir.file("net/kautler/VersionsKt.class").asFile.isFile) { - return@let null - } - - URLClassLoader( - arrayOf(classesDir.asFile.toURI().toURL()), - buildscript.classLoader - ) - .loadClass("net.kautler.VersionsKt") - .methods - .find { it.name == "getVersions" } - ?.invoke(null) - as Map? - } - -@Suppress("UNCHECKED_CAST") -val versionsByScripting - get() = runBlocking { - JvmScriptCompiler(defaultJvmScriptingHostConfiguration)( - """val versions = (mapOf\([^)]++\))""" - .toRegex() - .find(file("src/main/kotlin/net/kautler/Versions.kt").readText())!! - .groupValues[1] - .toScriptSource(), - ScriptCompilationConfiguration() - ).onSuccess { BasicJvmScriptEvaluator()(it) } - } - .valueOrThrow() - .returnValue - .let { it as Value } - .value - as Map - -val String.version get() = "${versions[this]}" - -val String.withVersion get() = withVersion(split(":").last()) - -fun String.withVersion(key: String) = "$this:${key.version}" - -fun gradlePlugin(plugin: String): String = plugin.let { - val (id, version) = "$it:".split(":", limit = 3) - "$id:$id.gradle.plugin:${version.ifBlank { id.version }}" -} diff --git a/buildSrc/src/main/kotlin/net/kautler/Versions.kt b/buildSrc/src/main/kotlin/net/kautler/Versions.kt deleted file mode 100644 index 78b0a2cc..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/Versions.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020-2022 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 - -import org.gradle.api.artifacts.dsl.DependencyHandler -import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependencyExtension - -val versions = mapOf( - // project NPM dependencies - "@actions/cache" to "3.0.5", - "@actions/core" to "1.10.0", - "@actions/exec" to "1.1.1", - "@actions/http-client" to "2.0.1", - "@actions/io" to "1.1.2", - "@actions/tool-cache" to "2.0.1", - "@types/semver" to "7.3.12", - "null-writable" to "1.0.5", - "semver" to "7.3.8", - - // project Java dependencies - "kotlin-extensions" to "1.0.1-pre.129-kotlin-1.4.20", - "kotlinx-coroutines-core" to "1.4.2", - "kotlinx-nodejs" to "0.0.7", - "node" to "16.18.1", - - // build NPM dependencies - "@vercel/ncc" to "0.36.1", - - // build Java dependencies - "com.github.ben-manes.versions" to "0.36.0", - "dukat" to "0.5.7", - "github-api" to "1.117", - "kaml" to "0.18.1", - "kotlinx-serialization-runtime" to "0.20.0", - "net.researchgate.release" to "2.8.1", - "net.wooga.github" to "1.4.0", - "org.ajoberstar.grgit" to "4.1.1", - "org.jetbrains.kotlin.js" to "1.4.20" -) - -val String.version get() = "${versions[this]}" - -val String.withVersion get() = withVersion(split(":").last()) - -fun String.withVersion(key: String) = "$this:${key.version}" - -fun DependencyHandler.npm(name: String, generateExternals: Boolean = true) = - (extensions.getByName("npm") as NpmDependencyExtension)(name, name.version, generateExternals) diff --git a/buildSrc/src/main/kotlin/net/kautler/dao/GitHubAction.kt b/buildSrc/src/main/kotlin/net/kautler/dao/GitHubAction.kt deleted file mode 100644 index 35f38df8..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/dao/GitHubAction.kt +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright 2020-2022 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.dao - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlScalar -import kotlinx.serialization.Decoder -import kotlinx.serialization.Encoder -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialDescriptor -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.Serializer -import kotlinx.serialization.UnionKind.CONTEXTUAL -import kotlinx.serialization.builtins.MapSerializer -import net.kautler.dao.GitHubAction.Output.OutputMapSerializer -import net.kautler.util.get - -@Serializable -data class GitHubAction( - val name: String, - val author: String? = null, - val description: String, - val inputs: Map? = null, - @Serializable(with = OutputMapSerializer::class) - val outputs: Map? = null, - val runs: Runs, - val branding: Branding -) { - @Serializable - data class Input( - val description: String, - val required: Boolean, - val default: String? = null - ) - - @Serializable - sealed class Output { - abstract val description: String - - @Serializable - data class NormalOutput( - override val description: String - ) : Output() - - @Serializable - data class CompositeOutput( - override val description: String, - val value: String - ) : Output() - - @Serializer(forClass = Map::class) - class OutputMapSerializer( - private val keySerializer: KSerializer, - private val valueSerializer: KSerializer - ) : KSerializer> { - override val descriptor = - SerialDescriptor("net.kautler.dao.GitHubAction.outputs", CONTEXTUAL) - - override fun deserialize(decoder: Decoder): Map { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val compositeAction = context - .get("runs") - ?.get("using") - ?.content == "composite" - - val valueSerializer = - if (compositeAction) CompositeOutput.serializer() - else NormalOutput.serializer() - - return decoder.decodeSerializableValue(MapSerializer(keySerializer, valueSerializer)) - } - - override fun serialize(encoder: Encoder, value: Map) { - @Suppress("UNCHECKED_CAST") - when (value.values.asSequence().map { it::class }.distinct().count()) { - 0 -> encoder.encodeSerializableValue(MapSerializer(keySerializer, valueSerializer), value) - - 1 -> when (value.values.first()) { - is NormalOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, NormalOutput.serializer()), - value as Map - ) - - is CompositeOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, CompositeOutput.serializer()), - value as Map - ) - } - - else -> error("Output map must not contain normal and composite outputs at the same time") - } - } - } - } - - sealed class Runs { - abstract val using: String - - @Serializable - data class JavaScriptRuns( - override val using: String, - val main: String, - val pre: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val post: String? = null, - @SerialName("post-if") - val postIf: String? = null - ) : Runs() - - @Serializable - data class CompositeRuns( - override val using: String, - val steps: List - ) : Runs() - - @Serializable - data class DockerRuns( - override val using: String, - @SerialName("pre-entrypoint") - val preEntrypoint: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val image: String, - val env: Map? = null, - val entrypoint: String? = null, - @SerialName("post-entrypoint") - val postEntrypoint: String? = null, - @SerialName("post-if") - val postIf: String? = null, - val args: List? = null - ) : Runs() - - @Serializer(forClass = Runs::class) - companion object : KSerializer { - override fun deserialize(decoder: Decoder): Runs { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val actionType = context - .get("runs") - ?.get("using") - ?.content - - val valueSerializer = when (actionType) { - "composite" -> CompositeRuns.serializer() - "docker" -> DockerRuns.serializer() - else -> JavaScriptRuns.serializer() - } - - return decoder.decodeSerializableValue(valueSerializer) - } - - override fun serialize(encoder: Encoder, value: Runs) { - when (value) { - is JavaScriptRuns -> encoder.encodeSerializableValue(JavaScriptRuns.serializer(), value) - is CompositeRuns -> encoder.encodeSerializableValue(CompositeRuns.serializer(), value) - is DockerRuns -> encoder.encodeSerializableValue(DockerRuns.serializer(), value) - } - } - } - } - - @Serializable - data class Step( - val run: String, - val shell: String, - val name: String? = null, - val id: String? = null, - val env: Map? = null, - @SerialName("working-directory") - val workingDirectory: String? = null - ) - - @Serializable - data class Branding( - val color: String, - val icon: String - ) -} diff --git a/buildSrc/src/main/kotlin/net/kautler/dao/ResultSerializer.kt b/buildSrc/src/main/kotlin/net/kautler/dao/ResultSerializer.kt deleted file mode 100644 index 24dc2351..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/dao/ResultSerializer.kt +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2020-2022 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.dao - -import com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup -import com.github.benmanes.gradle.versions.reporter.result.Dependency -import com.github.benmanes.gradle.versions.reporter.result.DependencyLatest -import com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated -import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved -import com.github.benmanes.gradle.versions.reporter.result.Result -import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable -import kotlinx.serialization.CompositeDecoder.Companion.READ_DONE -import kotlinx.serialization.Decoder -import kotlinx.serialization.Encoder -import kotlinx.serialization.KSerializer -import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.SerialDescriptor -import kotlinx.serialization.SerializationException -import kotlinx.serialization.Serializer -import kotlinx.serialization.builtins.nullable -import kotlinx.serialization.builtins.serializer -import kotlinx.serialization.builtins.set -import kotlinx.serialization.decodeStructure -import kotlinx.serialization.encodeStructure -import java.util.SortedSet - -@Serializer(forClass = Result::class) -object ResultSerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Result") { - element("count", Int.serializer().descriptor) - element("current", DependenciesGroupSerializer(DependencySerializer).descriptor) - element("outdated", DependenciesGroupSerializer(DependencyOutdatedSerializer).descriptor) - element("exceeded", DependenciesGroupSerializer(DependencyLatestSerializer).descriptor) - element("unresolved", DependenciesGroupSerializer(DependencyUnresolvedSerializer).descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var count: Int? = null - var current: DependenciesGroup? = null - var outdated: DependenciesGroup? = null - var exceeded: DependenciesGroup? = null - var unresolved: DependenciesGroup? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> count = decodeIntElement(descriptor, i) - 1 -> current = decodeSerializableElement(descriptor, i, DependenciesGroupSerializer(DependencySerializer)) - 2 -> outdated = decodeSerializableElement(descriptor, i, DependenciesGroupSerializer(DependencyOutdatedSerializer)) - 3 -> exceeded = decodeSerializableElement(descriptor, i, DependenciesGroupSerializer(DependencyLatestSerializer)) - 4 -> unresolved = decodeSerializableElement(descriptor, i, DependenciesGroupSerializer(DependencyUnresolvedSerializer)) - else -> throw SerializationException("Unknown index $i") - } - } - - Result(count ?: throw MissingFieldException("count"), current, outdated, exceeded, unresolved) - } - - override fun serialize(encoder: Encoder, value: Result) { - encoder.encodeStructure(descriptor) { - encodeIntElement(descriptor, 0, value.count) - encodeSerializableElement(descriptor, 1, DependenciesGroupSerializer(DependencySerializer), value.current) - encodeSerializableElement(descriptor, 2, DependenciesGroupSerializer(DependencyOutdatedSerializer), value.outdated) - encodeSerializableElement(descriptor, 3, DependenciesGroupSerializer(DependencyLatestSerializer), value.exceeded) - encodeSerializableElement(descriptor, 4, DependenciesGroupSerializer(DependencyUnresolvedSerializer), value.unresolved) - } - } - - @Serializer(forClass = DependenciesGroup::class) - class DependenciesGroupSerializer( - private val elementSerializer: KSerializer - ) : KSerializer> { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup") { - element("count", Int.serializer().descriptor) - element("dependencies", elementSerializer.set.descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var count: Int? = null - var dependencies: SortedSet? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> count = decodeIntElement(descriptor, i) - 1 -> dependencies = decodeSerializableElement(descriptor, i, elementSerializer.set).toSortedSet() - else -> throw SerializationException("Unknown index $i") - } - } - - DependenciesGroup(count ?: throw MissingFieldException("count"), dependencies) - } - - override fun serialize(encoder: Encoder, value: DependenciesGroup) { - encoder.encodeStructure(descriptor) { - encodeIntElement(descriptor, 0, value.count) - encodeSerializableElement(descriptor, 1, elementSerializer.set, value.dependencies) - } - } - } - - @Serializer(forClass = Dependency::class) - object DependencySerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Dependency") { - element("group", String.serializer().descriptor) - element("name", String.serializer().descriptor) - element("version", String.serializer().descriptor) - element("projectUrl", String.serializer().nullable.descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var group: String? = null - var name: String? = null - var version: String? = null - var projectUrl: String? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> group = decodeStringElement(descriptor, i) - 1 -> name = decodeStringElement(descriptor, i) - 2 -> version = decodeStringElement(descriptor, i) - 3 -> projectUrl = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - else -> throw SerializationException("Unknown index $i") - } - } - - Dependency(group, name, version, projectUrl) - } - - override fun serialize(encoder: Encoder, value: Dependency) { - encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) - encodeNullableSerializableElement(descriptor, 3, String.serializer().nullable, value.projectUrl) - } - } - } - - @Serializer(forClass = DependencyOutdated::class) - object DependencyOutdatedSerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated") { - element("group", String.serializer().descriptor) - element("name", String.serializer().descriptor) - element("version", String.serializer().descriptor) - element("projectUrl", String.serializer().nullable.descriptor) - element("available", VersionAvailableSerializer.descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var group: String? = null - var name: String? = null - var version: String? = null - var projectUrl: String? = null - var available: VersionAvailable? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> group = decodeStringElement(descriptor, i) - 1 -> name = decodeStringElement(descriptor, i) - 2 -> version = decodeStringElement(descriptor, i) - 3 -> projectUrl = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - 4 -> available = decodeSerializableElement(descriptor, i, VersionAvailableSerializer) - else -> throw SerializationException("Unknown index $i") - } - } - - DependencyOutdated(group, name, version, projectUrl, available) - } - - override fun serialize(encoder: Encoder, value: DependencyOutdated) { - encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) - encodeNullableSerializableElement(descriptor, 3, String.serializer().nullable, value.projectUrl) - encodeSerializableElement(descriptor, 4, VersionAvailableSerializer, value.available) - } - } - } - - @Serializer(forClass = DependencyLatest::class) - object DependencyLatestSerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyLatest") { - element("group", String.serializer().descriptor) - element("name", String.serializer().descriptor) - element("version", String.serializer().descriptor) - element("projectUrl", String.serializer().nullable.descriptor) - element("latest", String.serializer().descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var group: String? = null - var name: String? = null - var version: String? = null - var projectUrl: String? = null - var latest: String? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> group = decodeStringElement(descriptor, i) - 1 -> name = decodeStringElement(descriptor, i) - 2 -> version = decodeStringElement(descriptor, i) - 3 -> projectUrl = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - 4 -> latest = decodeStringElement(descriptor, i) - else -> throw SerializationException("Unknown index $i") - } - } - - DependencyLatest(group, name, version, projectUrl, latest) - } - - override fun serialize(encoder: Encoder, value: DependencyLatest) { - encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) - encodeNullableSerializableElement(descriptor, 3, String.serializer().nullable, value.projectUrl) - encodeStringElement(descriptor, 4, value.latest) - } - } - } - - @Serializer(forClass = DependencyUnresolved::class) - object DependencyUnresolvedSerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved") { - element("group", String.serializer().descriptor) - element("name", String.serializer().descriptor) - element("version", String.serializer().descriptor) - element("projectUrl", String.serializer().nullable.descriptor) - element("reason", String.serializer().descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var group: String? = null - var name: String? = null - var version: String? = null - var projectUrl: String? = null - var reason: String? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> group = decodeStringElement(descriptor, i) - 1 -> name = decodeStringElement(descriptor, i) - 2 -> version = decodeStringElement(descriptor, i) - 3 -> projectUrl = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - 4 -> reason = decodeStringElement(descriptor, i) - else -> throw SerializationException("Unknown index $i") - } - } - - DependencyUnresolved(group, name, version, projectUrl, reason) - } - - override fun serialize(encoder: Encoder, value: DependencyUnresolved) { - encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) - encodeNullableSerializableElement(descriptor, 3, String.serializer().nullable, value.projectUrl) - encodeStringElement(descriptor, 4, value.reason) - } - } - } - - @Serializer(forClass = VersionAvailable::class) - object VersionAvailableSerializer : KSerializer { - override val descriptor = SerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.VersionAvailable") { - element("release", String.serializer().nullable.descriptor) - element("milestone", String.serializer().nullable.descriptor) - element("integration", String.serializer().nullable.descriptor) - } - - override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { - var release: String? = null - var milestone: String? = null - var integration: String? = null - - loop@ while (true) { - when (val i = decodeElementIndex(descriptor)) { - READ_DONE -> break@loop - 0 -> release = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - 1 -> milestone = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - 2 -> integration = decodeNullableSerializableElement(descriptor, i, String.serializer().nullable) - else -> throw SerializationException("Unknown index $i") - } - } - - VersionAvailable(release, milestone, integration) - } - - override fun serialize(encoder: Encoder, value: VersionAvailable) { - encoder.encodeStructure(descriptor) { - encodeNullableSerializableElement(descriptor, 0, String.serializer().nullable, value.release) - encodeNullableSerializableElement(descriptor, 1, String.serializer().nullable, value.milestone) - encodeNullableSerializableElement(descriptor, 2, String.serializer().nullable, value.integration) - } - } - } -} diff --git a/buildSrc/src/main/kotlin/net/kautler/ncc_packer.gradle.kts b/buildSrc/src/main/kotlin/net/kautler/ncc_packer.gradle.kts deleted file mode 100644 index c39fd426..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/ncc_packer.gradle.kts +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2020-2022 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 - -import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile - -plugins { - kotlin("js") -} - -kotlin { - js { - useCommonJs() - binaries.executable() - nodejs { - runTask { - inputs - .files(rootProject.tasks.compileKotlinJs) - .skipWhenEmpty() - .withPropertyName("compiled JavaScript files") - - val output = rootProject.layout.buildDirectory.dir("distributions") - outputs - .dir(output) - .withPropertyName("packaged JavaScript files") - - args( - rootProject.tasks.compileKotlinJs.get().outputFile.absolutePath, - output.get().asFile.absolutePath - ) - } - } - } -} - -repositories { - mavenCentral() - jcenter() -} - -dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core".withVersion) - implementation("org.jetbrains:kotlin-extensions".withVersion) - implementation("org.jetbrains.kotlinx:kotlinx-nodejs".withVersion) - implementation(npm("@vercel/ncc", generateExternals = false)) -} - -val TaskContainer.compileKotlinJs - get() = named("compileKotlinJs") diff --git a/buildSrc/src/main/kotlin/net/kautler/util/DependencyUnresolvedExtension.kt b/buildSrc/src/main/kotlin/net/kautler/util/DependencyUnresolvedExtension.kt deleted file mode 100644 index 0bb090b7..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/util/DependencyUnresolvedExtension.kt +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020-2022 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.util - -import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved - -fun DependencyUnresolved.matches( - group: String, - name: String, - version: String? = null -) = (this.group == group) - && (this.name == name) - && version?.let { it == version } ?: true diff --git a/buildSrc/src/main/kotlin/net/kautler/versions.gradle.kts b/buildSrc/src/main/kotlin/net/kautler/versions.gradle.kts deleted file mode 100644 index 875b37bf..00000000 --- a/buildSrc/src/main/kotlin/net/kautler/versions.gradle.kts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2020-2022 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 - -import com.github.benmanes.gradle.versions.reporter.PlainTextReporter -import com.github.benmanes.gradle.versions.reporter.result.Result -import com.github.benmanes.gradle.versions.updates.gradle.GradleReleaseChannel.CURRENT -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration.Companion.Stable -import net.kautler.dao.ResultSerializer -import net.kautler.util.NullOutputStream -import net.kautler.util.matches -import net.kautler.util.updateCounts -import java.net.URL -import java.security.DigestInputStream -import java.security.MessageDigest - -plugins { - id("com.github.ben-manes.versions") -} - -val majorVersion by extra("$version".substringBefore('.')) - -val validateGradleWrapperJar by tasks.registering { - onlyIf { - !gradle.startParameter.isOffline - } - - doLast { - val expectedDigest = URL("https://services.gradle.org/distributions/gradle-${gradle.gradleVersion}-wrapper.jar.sha256").readText() - - val sha256 = MessageDigest.getInstance("SHA-256") - layout - .projectDirectory - .dir("gradle") - .dir("wrapper") - .file("gradle-wrapper.jar") - .asFile - .inputStream() - .let { DigestInputStream(it, sha256) } - .use { it.copyTo(NullOutputStream()) } - val actualDigest = sha256.digest().let { - "%02x".repeat(it.size).format(*it.toTypedArray()) - } - - check(expectedDigest == actualDigest) { - "The wrapper JAR does not match the configured Gradle version, please update the wrapper" - } - } -} - -val buildSrcDependencyUpdates by tasks.registering(GradleBuild::class) { - dir = file("buildSrc") - buildName = "buildSrc-for-dependencyUpdates" - tasks = listOf("dependencyUpdates") -} - -tasks.dependencyUpdates { - dependsOn(validateGradleWrapperJar) - dependsOn(buildSrcDependencyUpdates) - - gradleReleaseChannel = CURRENT.id - checkConstraints = true - - rejectVersionIf { - val preliminaryReleaseRegex = Regex( - """(?i)[.-](?:${ - listOf( - "alpha", - "beta", - "dev", - "rc", - "cr", - "m", - "preview", - "test", - "pr", - "pre", - "b", - "ea" - ).joinToString("|") - })[.\d-]*""" - ) - preliminaryReleaseRegex.containsMatchIn(candidate.version) - && !preliminaryReleaseRegex.containsMatchIn(currentVersion) - } - - outputFormatter = closureOf { - val buildSrcResultFile = file("buildSrc/build/dependencyUpdates/report.json") - if (buildSrcResultFile.isFile) { - val buildSrcResult = Json(Stable).parse(ResultSerializer, buildSrcResultFile.readText()) - current.dependencies.addAll(buildSrcResult.current.dependencies) - outdated.dependencies.addAll(buildSrcResult.outdated.dependencies) - exceeded.dependencies.addAll(buildSrcResult.exceeded.dependencies) - unresolved.dependencies.addAll(buildSrcResult.unresolved.dependencies) - } - - val ignored = outdated.dependencies.filter { - // This plugin should always be used without version as it is tightly - // tied to the Gradle version that is building the precompiled script plugins - it.matches("org.gradle.kotlin.kotlin-dsl", "org.gradle.kotlin.kotlin-dsl.gradle.plugin") - // Not until Gradle is on Kotlin 1.4 - || it.matches("com.charleskorn.kaml", "kaml") - || it.matches("org.jetbrains.kotlin", "kotlin-reflect") - || it.matches("org.jetbrains.kotlin", "kotlin-sam-with-receiver") - || it.matches("org.jetbrains.kotlin", "kotlin-scripting-compiler-embeddable") - || it.matches("org.jetbrains.kotlin", "kotlin-scripting-jvm-host") - || it.matches("org.jetbrains.kotlin", "kotlin-serialization") - || it.matches("org.jetbrains.kotlin", "kotlin-serialization-unshaded") - || it.matches("org.jetbrains.kotlin", "kotlin-stdlib-jdk8") - || it.matches("org.jetbrains.kotlin.plugin.serialization", "org.jetbrains.kotlin.plugin.serialization.gradle.plugin") - || it.matches("org.jetbrains.kotlinx", "kotlinx-serialization-runtime") - } - - outdated.dependencies.removeAll(ignored) - updateCounts() - - PlainTextReporter(project, revisionLevel(), gradleReleaseChannelLevel()) - .write(System.out, this) - - if (ignored.isNotEmpty()) { - println("\nThe following dependencies have later ${revisionLevel()} versions but were ignored:") - ignored.forEach { - println(" - ${it.group}:${it.name} [${it.version} -> ${it.available.getProperty(revisionLevel())}]") - it.projectUrl?.let { println(" $it") } - } - } - - if (gradle.current.isFailure || (unresolved.count != 0)) { - error("Unresolved libraries found") - } - - if (gradle.current.isUpdateAvailable || (outdated.count != 0)) { - error("Outdated libraries found") - } - } -} diff --git a/gradle.properties b/gradle.properties index 50d1096a..deb50f91 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -# Copyright 2020-2022 Björn Kautler +# Copyright 2020-2023 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,3 +17,4 @@ version = 2.0.1-SNAPSHOT description = A GitHub action to install and setup a Linux distribution for the Windows Subsystem for Linux (WSL) org.gradle.caching = true +kotlin.js.ir.output.granularity = whole-program diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts new file mode 100644 index 00000000..4598b047 --- /dev/null +++ b/gradle/build-logic/build-logic.gradle.kts @@ -0,0 +1,55 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` + alias(libs.plugins.kotlin.serialization) + id(libs.plugins.convention.dependency.updates.report.aggregation.get().pluginId) +} + +dependencies { + implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) + implementation(plugin(libs.plugins.versions)) + implementation(plugin(libs.plugins.release)) + implementation(plugin(libs.plugins.grgit)) + implementation(plugin(libs.plugins.github)) + implementation(plugin(libs.plugins.kotlin.js)) + implementation(":dependency-updates-report-aggregation") + implementation(libs.build.github.api) + implementation(platform(libs.build.kotlinx.serialization.bom)) + implementation(libs.build.kotlinx.serialization.core) + implementation(libs.build.kotlinx.serialization.json) + implementation(libs.build.kaml) + implementation(embeddedKotlin("compiler-embeddable")) +} + +tasks.withType().configureEach { + kotlinOptions { + allWarningsAsErrors = true + } +} + +tasks.compileKotlin { + kotlinOptions { + freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn") + } +} + +fun plugin(plugin: Provider) = plugin.map { + "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" +} diff --git a/gradle/build-logic/gradle.properties b/gradle/build-logic/gradle.properties new file mode 100644 index 00000000..c9d9db2c --- /dev/null +++ b/gradle/build-logic/gradle.properties @@ -0,0 +1,15 @@ +# Copyright 2020-2023 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. + +org.gradle.caching = true diff --git a/gradle/build-logic/settings.gradle.kts b/gradle/build-logic/settings.gradle.kts new file mode 100644 index 00000000..cc2ec846 --- /dev/null +++ b/gradle/build-logic/settings.gradle.kts @@ -0,0 +1,45 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS + +pluginManagement { + includeBuild("../dependency-updates-report-aggregation") + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } + repositoriesMode.set(FAIL_ON_PROJECT_REPOS) + + versionCatalogs { + create("libs") { + from(files("../libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" +rootProject.buildFileName = "build-logic.gradle.kts" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") diff --git a/buildSrc/settings.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt similarity index 73% rename from buildSrc/settings.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt index e424c7ae..f5f4c0b4 100644 --- a/buildSrc/settings.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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. @@ -13,3 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +package net.kautler.dao.action + +import kotlinx.serialization.Serializable + +@Serializable +data class Branding( + val color: String, + val icon: String? = null +) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt new file mode 100644 index 00000000..aa65d9e5 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2020-2023 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.dao.action + +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import net.kautler.dao.action.Output.CompositeOutput +import net.kautler.dao.action.Output.NormalOutput + +@ExperimentalSerializationApi +@Serializable +data class GitHubAction( + val name: String, + val author: String? = null, + val description: String, + val inputs: Map? = null, + @Serializable(with = OutputMapSerializer::class) + val outputs: Map? = null, + val runs: Runs, + val branding: Branding? = null +) { + init { + require((runs.using == "composite") || (outputs.orEmpty().values.all { it is NormalOutput })) { + "Non-composite actions must only contain normal outputs" + } + require((runs.using != "composite") || (outputs.orEmpty().values.all { it is CompositeOutput })) { + "Composite actions must only contain composite outputs" + } + } +} diff --git a/buildSrc/src/main/kotlin/net/kautler/util/YamlMapExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt similarity index 64% rename from buildSrc/src/main/kotlin/net/kautler/util/YamlMapExtension.kt rename to gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt index 7b90c5ab..8fffb9b7 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/YamlMapExtension.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt @@ -14,15 +14,14 @@ * limitations under the License. */ -package net.kautler.util +package net.kautler.dao.action -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlNode -import com.charleskorn.kaml.YamlScalar +import kotlinx.serialization.Serializable -@Suppress("UNCHECKED_CAST") -operator fun YamlMap.get(key: String) = - entries - .asSequence() - .find { (it.key as? YamlScalar)?.content == key } - ?.value as T? +@Serializable +data class Input( + val description: String, + val required: Boolean = false, + val deprecationMessage: String? = null, + val default: String? = null +) diff --git a/buildSrc/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt similarity index 57% rename from buildSrc/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt rename to gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt index 383d4851..c4ec5328 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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. @@ -14,13 +14,22 @@ * limitations under the License. */ -package net.kautler.util +package net.kautler.dao.action -import net.researchgate.release.GitAdapter.GitConfig -import net.researchgate.release.ReleaseExtension +import kotlinx.serialization.Serializable -val ReleaseExtension.git - get() = getProperty("git") as GitConfig +@Serializable +sealed class Output { + abstract val description: String -fun ReleaseExtension.git(configure: GitConfig.() -> Unit) = - git.configure() + @Serializable + data class NormalOutput( + override val description: String + ) : Output() + + @Serializable + data class CompositeOutput( + override val description: String, + val value: String + ) : Output() +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt new file mode 100644 index 00000000..9c92f5a0 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt @@ -0,0 +1,82 @@ +/* + * Copyright 2020-2023 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.dao.action + +import com.charleskorn.kaml.YamlInput +import com.charleskorn.kaml.YamlMap +import com.charleskorn.kaml.YamlScalar +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.InternalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.MapSerializer +import kotlinx.serialization.descriptors.SerialKind.CONTEXTUAL +import kotlinx.serialization.descriptors.buildSerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.kautler.dao.action.Output.CompositeOutput +import net.kautler.dao.action.Output.NormalOutput + +@ExperimentalSerializationApi +@Serializer(forClass = Map::class) +class OutputMapSerializer( + private val keySerializer: KSerializer, + private val valueSerializer: KSerializer +) : KSerializer> { + @InternalSerializationApi + override val descriptor = + buildSerialDescriptor("net.kautler.dao.action.GitHubAction.outputs", CONTEXTUAL) + + override fun deserialize(decoder: Decoder): Map { + check(decoder is YamlInput) { "This class can only be loaded using kaml" } + + val context = decoder.node + check(context is YamlMap) { "Expected a YamlMap as current context" } + + val compositeAction = context + .get("runs") + ?.get("using") + ?.content == "composite" + + val valueSerializer = + if (compositeAction) CompositeOutput.serializer() + else NormalOutput.serializer() + + return decoder.decodeSerializableValue(MapSerializer(keySerializer, valueSerializer)) + } + + override fun serialize(encoder: Encoder, value: Map) { + @Suppress("UNCHECKED_CAST") + when (value.values.asSequence().map { it::class }.distinct().count()) { + 0 -> encoder.encodeSerializableValue(MapSerializer(keySerializer, valueSerializer), value) + + 1 -> when (value.values.first()) { + is NormalOutput -> encoder.encodeSerializableValue( + MapSerializer(keySerializer, NormalOutput.serializer()), + value as Map + ) + + is CompositeOutput -> encoder.encodeSerializableValue( + MapSerializer(keySerializer, CompositeOutput.serializer()), + value as Map + ) + } + + else -> error("Output map must not contain normal and composite outputs at the same time") + } + } +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt new file mode 100644 index 00000000..bb8d3546 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt @@ -0,0 +1,106 @@ +/* + * Copyright 2020-2023 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.dao.action + +import com.charleskorn.kaml.YamlInput +import com.charleskorn.kaml.YamlMap +import com.charleskorn.kaml.YamlScalar +import kotlinx.serialization.EncodeDefault +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.Serializer +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +sealed class Runs { + abstract val using: String + + @Serializable + data class JavaScriptRuns( + override val using: String, + val main: String, + val pre: String? = null, + @SerialName("pre-if") + val preIf: String? = null, + val post: String? = null, + @SerialName("post-if") + val postIf: String? = null + ) : Runs() + + @Serializable + data class CompositeRuns( + val steps: List + ) : Runs() { + @ExperimentalSerializationApi + @EncodeDefault + override val using: String = "composite" + } + + @Serializable + data class DockerRuns( + @SerialName("pre-entrypoint") + val preEntrypoint: String? = null, + @SerialName("pre-if") + val preIf: String? = null, + val image: String, + val env: Map? = null, + val entrypoint: String? = null, + @SerialName("post-entrypoint") + val postEntrypoint: String? = null, + @SerialName("post-if") + val postIf: String? = null, + val args: List? = null + ) : Runs() { + @ExperimentalSerializationApi + @EncodeDefault + override val using: String = "docker" + } + + @ExperimentalSerializationApi + @Serializer(forClass = Runs::class) + companion object : KSerializer { + override fun deserialize(decoder: Decoder): Runs { + check(decoder is YamlInput) { "This class can only be loaded using kaml" } + + val context = decoder.node + check(context is YamlMap) { "Expected a YamlMap as current context" } + + val actionType = context + .get("runs") + ?.get("using") + ?.content + + val valueSerializer = when (actionType) { + "composite" -> CompositeRuns.serializer() + "docker" -> DockerRuns.serializer() + else -> JavaScriptRuns.serializer() + } + + return decoder.decodeSerializableValue(valueSerializer) + } + + override fun serialize(encoder: Encoder, value: Runs) { + when (value) { + is JavaScriptRuns -> encoder.encodeSerializableValue(JavaScriptRuns.serializer(), value) + is CompositeRuns -> encoder.encodeSerializableValue(CompositeRuns.serializer(), value) + is DockerRuns -> encoder.encodeSerializableValue(DockerRuns.serializer(), value) + } + } + } +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt new file mode 100644 index 00000000..4f77a4d1 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2020-2023 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.dao.action + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class Step( + val run: String? = null, + val shell: String? = null, + val uses: String? = null, + val with: Map? = null, + val name: String? = null, + val id: String? = null, + @SerialName("if") + val condition: String? = null, + val env: Map? = null, + @SerialName("working-directory") + val workingDirectory: String? = null +) { + init { + require((run == null) || (uses == null)) { + "'run' and 'uses' are mutually exclusive" + } + require((run != null) || (uses != null)) { + "one of 'run' or 'uses' is required" + } + require((run == null) || (shell != null)) { + "'shell' is required if 'run' is set" + } + } +} diff --git a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts similarity index 87% rename from buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts index ef4f89e1..9251f2af 100644 --- a/buildSrc/src/main/kotlin/net/kautler/github_actions.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/github_actions.gradle.kts @@ -16,9 +16,10 @@ package net.kautler -import groovy.lang.Closure +import org.gradle.accessors.dm.LibrariesForLibs import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY -import org.jetbrains.kotlin.cli.common.messages.MessageCollector +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 @@ -42,12 +43,14 @@ val scriptClasspath by configurations.creating { isCanBeConsumed = false } +val libs = the() + dependencies { - compilerClasspath(kotlin("compiler", "1.8.0")) - compilerClasspath(kotlin("scripting-compiler", "1.8.0")) - add(scriptClasspath.name, kotlin("main-kts", "1.8.0"), closureOf { + compilerClasspath(libs.workflows.kotlin.compiler) + compilerClasspath(libs.workflows.kotlin.scripting.compiler) + scriptClasspath(libs.workflows.kotlin.main.kts) { isTransitive = false - } as Closure) + } } val preprocessWorkflows by tasks.registering @@ -56,8 +59,8 @@ file(".github/workflows") .forEach { workflowScript -> val workflowName = workflowScript.name.removeSuffix(".main.kts") val camelCasedWorkflowName = workflowName.replace("""-\w""".toRegex()) { - it.value.substring(1).capitalize() - }.capitalize() + it.value.substring(1).replaceFirstChar(Char::uppercaseChar) + }.replaceFirstChar(Char::uppercaseChar) val preprocessWorkflow = tasks.register("preprocess${camelCasedWorkflowName}Workflow") { inputs .file(workflowScript) @@ -73,7 +76,7 @@ file(".github/workflows") languageVersion.set(JavaLanguageVersion.of(17)) }) classpath(compilerClasspath) - mainClass.set("org.jetbrains.kotlin.cli.jvm.K2JVMCompiler") + mainClass.set(K2JVMCompiler::class.qualifiedName) args("-no-stdlib", "-no-reflect") args("-classpath", scriptClasspath.asPath) args("-script", workflowScript.absolutePath) @@ -93,7 +96,7 @@ val File.importedFiles: List .createForProduction( Disposer.newDisposable(), CompilerConfiguration().apply { - put(MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) + put(MESSAGE_COLLECTOR_KEY, NONE) }, JVM_CONFIG_FILES ) 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 new file mode 100644 index 00000000..d48bbd05 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/ncc_packer.gradle.kts @@ -0,0 +1,88 @@ +/* + * Copyright 2020-2023 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 + +import net.kautler.util.npm +import org.gradle.accessors.dm.LibrariesForLibs +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec + +plugins { + kotlin("js") +} + +kotlin { + js(IR) { + useCommonJs() + binaries.executable() + nodejs() + } +} + +// work-around for https://youtrack.jetbrains.com/issue/KT-56305 +tasks.withType().configureEach { + if (name.endsWith("ExecutableCompileSync")) { + doFirst { + outputs.files.forEach { it.deleteRecursively() } + } + } +} + +// work-around for https://youtrack.jetbrains.com/issue/KT-56305 +tasks.withType().configureEach { + abstract class ArgumentProvider @Inject constructor(rootProject: Project) : CommandLineArgumentProvider { + @get:InputFile + @get:SkipWhenEmpty + abstract val input: RegularFileProperty + + @get:OutputDirectory + abstract val output: DirectoryProperty + + init { + input.fileProvider( + rootProject + .tasks + .named("productionExecutableCompileSync") + .map { + it + .outputs + .files + .asFileTree + .matching { include("${rootProject.name}.js") } + .singleFile + } + ) + + output.set(rootProject.layout.buildDirectory.dir("distributions")) + } + + override fun asArguments(): MutableIterable = + mutableListOf( + input.get().asFile.absolutePath, + output.get().asFile.absolutePath + ) + } + argumentProviders.add(objects.newInstance(rootProject)) +} + +val libs = the() + +dependencies { + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlin.extensions) + implementation(libs.kotlinx.nodejs) + implementation(npm(libs.build.vercel.ncc, generateExternals = false)) +} diff --git a/buildSrc/src/main/kotlin/net/kautler/node.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts similarity index 66% rename from buildSrc/src/main/kotlin/net/kautler/node.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts index 1ea62c19..65f5572c 100644 --- a/buildSrc/src/main/kotlin/net/kautler/node.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/node.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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,8 +17,12 @@ package net.kautler import com.charleskorn.kaml.Yaml -import net.kautler.dao.GitHubAction +import kotlinx.serialization.ExperimentalSerializationApi +import net.kautler.dao.action.GitHubAction +import net.kautler.util.npm +import org.gradle.accessors.dm.LibrariesForLibs import org.jetbrains.kotlin.gradle.targets.js.dukat.IntegratedDukatTask +import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import java.security.MessageDigest import kotlin.text.RegexOption.MULTILINE @@ -28,97 +32,60 @@ plugins { } kotlin { - js { + js(IR) { useCommonJs() binaries.executable() - nodejs { - runTask { - val toolCacheDir = "$temporaryDir/tool-cache" - - environment("RUNNER_TEMP", "$temporaryDir/runner-temp") - environment("RUNNER_TOOL_CACHE", toolCacheDir) - - Yaml - .default - .parse(GitHubAction.serializer(), file("action.yml").readText()) - .inputs - ?.filterValues { it.default != null } - ?.filterKeys { !System.getenv().containsKey("INPUT_${it.toUpperCase()}") } - ?.forEach { name, input -> - environment( - "INPUT_${name.toUpperCase()}", - if (name == "use-cache") "false" else input.default!! - ) - } + nodejs() + } +} - doFirst("Delete tool-cache") { - file(toolCacheDir).deleteRecursively() - } - } +// work-around for https://youtrack.jetbrains.com/issue/KT-56305 +tasks.withType().configureEach { + if (name.endsWith("ExecutableCompileSync")) { + doFirst { + outputs.files.forEach { it.deleteRecursively() } } } } -configure { - nodeVersion = "node".version - versions.dukat.version = "dukat".version - - // work-around for https://youtrack.jetbrains.com/issue/KT-34014 - val copyYarnLock by tasks.registering { - val yarnLock = layout.projectDirectory.file("yarn.lock") +@ExperimentalSerializationApi +val inputDefaultValues by lazy { + Yaml + .default + .decodeFromString(GitHubAction.serializer(), file("action.yml").readText()) + .inputs + ?.filterValues { it.default != null } + ?.filterKeys { !System.getenv().containsKey("INPUT_${it.uppercase()}") } +} - inputs - .file(yarnLock) - .withPropertyName("versioned Yarn lock file") - outputs - .file(rootPackageDir.resolve("yarn.lock")) - .withPropertyName("Yarn lock file") +// work-around for https://youtrack.jetbrains.com/issue/KT-56305 +tasks.withType().configureEach { + val toolCacheDir = "$temporaryDir/tool-cache" - onlyIf { - !gradle.taskGraph.hasTask(":updateYarnLock") - } + environment("RUNNER_TEMP", "$temporaryDir/runner-temp") + environment("RUNNER_TOOL_CACHE", toolCacheDir) - doLast { - copy { - from(yarnLock) - into(rootPackageDir) - } - } - } - npmInstallTaskProvider { - dependsOn(copyYarnLock) - } - val cleanKotlinNpmInstall by tasks - val cleanGenerateExternalsIntegrated by tasks - npmInstallTaskProvider { - shouldRunAfter(cleanKotlinNpmInstall) - shouldRunAfter(cleanGenerateExternalsIntegrated) + @OptIn(ExperimentalSerializationApi::class) + inputDefaultValues?.forEach { (name, input) -> + environment( + "INPUT_${name.uppercase()}", + if (name == "use-cache") "false" else input.default!! + ) } - val updateYarnLock by tasks.registering { - dependsOn(cleanKotlinNpmInstall) - dependsOn(cleanGenerateExternalsIntegrated) - dependsOn(tasks.build) - dependsOn(project(":ncc-packer").tasks.build) - val yarnLock = rootPackageDir.resolve("yarn.lock") + doFirst("Delete tool-cache") { + file(toolCacheDir).deleteRecursively() + } +} - inputs - .file(yarnLock) - .withPropertyName("Yarn lock file") - outputs - .file(layout.projectDirectory.file("yarn.lock")) - .withPropertyName("versioned Yarn lock file") +val libs = the() - doLast { - copy { - from(yarnLock) - into(layout.projectDirectory) - } - } - } +configure { + nodeVersion = libs.versions.build.node.get() + versions.dukat.version = libs.versions.build.dukat.get() // work-around for https://github.com/Kotlin/dukat/issues/103 - npmInstallTaskProvider { + npmInstallTaskProvider!!.configure { val patchedDukat0012CliJs = layout .projectDirectory .file("resources/dukat-cli-0.0.12.js") @@ -161,27 +128,22 @@ configure { } } -repositories { - mavenCentral() - jcenter() -} - dependencies { - implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core".withVersion) - implementation("org.jetbrains:kotlin-extensions".withVersion) - implementation("org.jetbrains.kotlinx:kotlinx-nodejs".withVersion) - implementation(npm("@actions/cache")) - implementation(npm("@actions/core")) - implementation(npm("@actions/exec")) - implementation(npm("@actions/http-client")) - implementation(npm("@actions/io")) - implementation(npm("@actions/tool-cache")) - implementation(npm("@types/semver")) - implementation(npm("semver", generateExternals = false)) - implementation(npm("null-writable")) + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlin.extensions) + implementation(libs.kotlinx.nodejs) + implementation(npm(libs.actions.cache)) + implementation(npm(libs.actions.core)) + implementation(npm(libs.actions.exec)) + implementation(npm(libs.actions.http.client)) + implementation(npm(libs.actions.io)) + implementation(npm(libs.actions.tool.cache)) + implementation(npm(libs.types.semver)) + implementation(npm(libs.semver, generateExternals = false)) + implementation(npm(libs.nullWritable)) } -tasks.withType(IntegratedDukatTask::class) { +tasks.withType(IntegratedDukatTask::class).configureEach { doLast { // work-around for https://github.com/Kotlin/dukat/issues/240 addJsModuleAnnotations( @@ -250,7 +212,7 @@ tasks.withType(IntegratedDukatTask::class) { } tasks.assemble { - dependsOn(project(":ncc-packer").tasks.named("run")) + dependsOn(project(":ncc-packer").tasks.named("nodeProductionRun")) } fun addJsModuleAnnotations(task: Task, vararg pairs: Pair) { @@ -262,7 +224,12 @@ fun addJsModuleAnnotations(task: Task, vararg pairs: Pair) { .matching { include("**/$file") } .singleFile .apply { - writeText("@file:JsModule(\"$module\")\n${readText()}") + writeText( + """ + |@file:JsModule("$module") + ${readText().prependIndent("|")} + """.trimMargin() + ) } } } @@ -289,12 +256,17 @@ fun fixExternalsFiles(task: Task, vararg pairs: Pair pattern.toRegex(MULTILINE) to replacement } - .fold(readText()) { current, (regex, replacement) -> - regex.replace(current, replacement) - } + writeText( + fixups + .map { (pattern, replacement) -> pattern.toRegex(MULTILINE) to replacement } + .fold(readText()) { current, (regex, replacement) -> + regex.replace(current, replacement) + } ) } } } + +fun plugin(plugin: Provider) = plugin.map { + "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" +} diff --git a/buildSrc/src/main/kotlin/net/kautler/publishing.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts similarity index 83% rename from buildSrc/src/main/kotlin/net/kautler/publishing.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts index d221d41a..c939cbb2 100644 --- a/buildSrc/src/main/kotlin/net/kautler/publishing.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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,8 +18,17 @@ package net.kautler import net.kautler.util.Property.Companion.boolean import net.kautler.util.Property.Companion.optionalString +import net.kautler.util.afterReleaseBuild +import net.kautler.util.beforeReleaseBuild +import net.kautler.util.checkoutMergeFromReleaseBranch +import net.kautler.util.createReleaseTag import net.kautler.util.git +import net.kautler.util.preTagCommit +import net.kautler.util.release +import net.kautler.util.runBuildTasks +import net.kautler.util.updateVersion import net.researchgate.release.ReleasePlugin +import org.gradle.tooling.GradleConnector import org.kohsuke.github.GHIssueState.OPEN import org.kohsuke.github.GitHub import wooga.gradle.github.publish.PublishMethod.update @@ -38,11 +47,15 @@ import javax.swing.SwingUtilities import kotlin.LazyThreadSafetyMode.NONE plugins { - id("net.researchgate.release") + // needed for accessing majorVersion + id("net.kautler.versions") id("org.ajoberstar.grgit") id("net.wooga.github") } +// part of work-around for https://github.com/gradle/gradle/issues/23747 +apply(plugin = "net.researchgate.release") + extra["release.useAutomaticVersion"] = boolean(project, "release.useAutomaticVersion").getValue() extra["release.releaseVersion"] = optionalString(project, "release.releaseVersion").getValue() extra["release.newVersion"] = optionalString(project, "release.newVersion").getValue() @@ -165,6 +178,30 @@ tasks.updateVersion { dependsOn(removeDistributionsFromGit) } +configure(listOf(tasks.release, tasks.runBuildTasks)) { + configure { + actions.clear() + doLast { + GradleConnector + .newConnector() + .forProjectDirectory(layout.projectDirectory.asFile) + .connect() + .use { projectConnection -> + val buildLauncher = projectConnection + .newBuild() + .forTasks(*tasks.toTypedArray()) + .setStandardInput(System.`in`) + .setStandardOutput(System.out) + .setStandardError(System.err) + gradle.startParameter.excludedTaskNames.forEach { + buildLauncher.addArguments("-x", it) + } + buildLauncher.run() + } + } + } +} + tasks.withType().configureEach { onlyIf { releaseVersion } repositoryName(githubRepositoryName) diff --git a/buildSrc/src/main/kotlin/net/kautler/readme.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts similarity index 96% rename from buildSrc/src/main/kotlin/net/kautler/readme.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts index 3a366a97..3a496be9 100644 --- a/buildSrc/src/main/kotlin/net/kautler/readme.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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. @@ -19,6 +19,8 @@ package net.kautler import java.security.MessageDigest plugins { + // needed for accessing majorVersion + id("net.kautler.versions") `lifecycle-base` } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt new file mode 100644 index 00000000..6bfc035b --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2020-2023 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.util + +import org.gradle.api.artifacts.MinimalExternalModuleDependency +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency +import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependencyExtension + +fun DependencyHandler.npm( + dependency: Provider, + generateExternals: Boolean = true +): NpmDependency { + val dep = dependency.get() + return (extensions.getByName("npm") as NpmDependencyExtension)( + name = if (dep.group == "") dep.name else "@${dep.group}/${dep.name}", + version = dep.version!!, + generateExternals = generateExternals + ) +} diff --git a/buildSrc/src/main/kotlin/net/kautler/util/NullOutputStream.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/NullOutputStream.kt similarity index 94% rename from buildSrc/src/main/kotlin/net/kautler/util/NullOutputStream.kt rename to gradle/build-logic/src/main/kotlin/net/kautler/util/NullOutputStream.kt index 50f5b31c..30b55003 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/NullOutputStream.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/NullOutputStream.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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/buildSrc/src/main/kotlin/net/kautler/util/Properties.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt similarity index 99% rename from buildSrc/src/main/kotlin/net/kautler/util/Properties.kt rename to gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt index a35d6626..6b0c1933 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/Properties.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt new file mode 100644 index 00000000..edcc537f --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2020-2023 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.util + +import net.researchgate.release.GitAdapter.GitConfig +import net.researchgate.release.ReleaseExtension +import org.gradle.api.Action +import org.gradle.api.Project +import org.gradle.api.Task +import org.gradle.api.tasks.GradleBuild +import org.gradle.api.tasks.TaskContainer +import org.gradle.api.tasks.TaskProvider +import org.gradle.kotlin.dsl.getByName +import org.gradle.kotlin.dsl.named + +val ReleaseExtension.git + get() = getProperty("git") as GitConfig + +fun ReleaseExtension.git(configure: GitConfig.() -> Unit) = + git.configure() + +// part of work-around for https://github.com/gradle/gradle/issues/23747 +val Project.release: ReleaseExtension + get() = extensions.getByName("release") + +fun Project.release(configure: Action): Unit = + extensions.configure("release", configure) + +val TaskContainer.release: TaskProvider + get() = named("release") + +val TaskContainer.runBuildTasks: TaskProvider + get() = named("runBuildTasks") + +val TaskContainer.checkoutMergeFromReleaseBranch: TaskProvider + get() = named("checkoutMergeFromReleaseBranch") + +val TaskContainer.updateVersion: TaskProvider + get() = named("updateVersion") + +val TaskContainer.afterReleaseBuild: TaskProvider + get() = named("afterReleaseBuild") + +val TaskContainer.preTagCommit: TaskProvider + get() = named("preTagCommit") + +val TaskContainer.createReleaseTag: TaskProvider + get() = named("createReleaseTag") + +val TaskContainer.beforeReleaseBuild: TaskProvider + get() = named("beforeReleaseBuild") diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts new file mode 100644 index 00000000..c8bec7b4 --- /dev/null +++ b/gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts @@ -0,0 +1,78 @@ +/* + * Copyright 2020-2023 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 + +import net.kautler.util.NullOutputStream +import net.kautler.util.add +import net.kautler.util.ignoredDependencies +import java.net.URL +import java.security.DigestInputStream +import java.security.MessageDigest + +plugins { + id("net.kautler.dependency-updates-report-aggregation") +} + +val majorVersion by extra("$version".substringBefore('.')) + +val validateGradleWrapperJar by tasks.registering { + onlyIf { + !gradle.startParameter.isOffline + } + + doLast { + val expectedDigest = URL("https://services.gradle.org/distributions/gradle-${gradle.gradleVersion}-wrapper.jar.sha256").readText() + + val sha256 = MessageDigest.getInstance("SHA-256") + layout + .projectDirectory + .dir("gradle") + .dir("wrapper") + .file("gradle-wrapper.jar") + .asFile + .inputStream() + .let { DigestInputStream(it, sha256) } + .use { it.copyTo(NullOutputStream()) } + val actualDigest = sha256.digest().let { + "%02x".repeat(it.size).format(*it.toTypedArray()) + } + + check(expectedDigest == actualDigest) { + "The wrapper JAR does not match the configured Gradle version, please update the wrapper" + } + } +} + +tasks.dependencyUpdates { + dependsOn(validateGradleWrapperJar) + + ignoredDependencies { + // Should match the Kotlin version of Gradle as the serialization is used during the build + add(group = "org.jetbrains.kotlin.plugin.serialization", name = "org.jetbrains.kotlin.plugin.serialization.gradle.plugin") + // This plugin should always be used without version as it is tightly + // tied to the Gradle version that is building the precompiled script plugins + add(group = "org.gradle.kotlin.kotlin-dsl", name = "org.gradle.kotlin.kotlin-dsl.gradle.plugin") + // These dependencies are used in the build logic so should match the + // embedded Kotlin version and not be upgraded independently + add(group = "org.jetbrains.kotlin", name = "kotlin-compiler-embeddable") + add(group = "org.jetbrains.kotlin", name = "kotlin-klib-commonizer-embeddable") + add(group = "org.jetbrains.kotlin", name = "kotlin-reflect") + add(group = "org.jetbrains.kotlin", name = "kotlin-sam-with-receiver") + add(group = "org.jetbrains.kotlin", name = "kotlin-scripting-compiler-embeddable") + add(group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8") + } +} diff --git a/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts b/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts new file mode 100644 index 00000000..ef87f09d --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts @@ -0,0 +1,51 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.versions) +} + +dependencies { + implementation(plugin(libs.plugins.versions)) + implementation(platform(libs.build.kotlinx.serialization.bom)) + implementation(libs.build.kotlinx.serialization.core) + implementation(libs.build.kotlinx.serialization.json) +} + +tasks.withType().configureEach { + kotlinOptions { + allWarningsAsErrors = true + } +} + +tasks.compileKotlin { + kotlinOptions { + freeCompilerArgs = listOf("-opt-in=kotlin.RequiresOptIn") + } +} + +tasks.dependencyUpdates { + checkForGradleUpdate = false + checkConstraints = true +} + +fun plugin(plugin: Provider) = plugin.map { + "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" +} diff --git a/gradle/dependency-updates-report-aggregation/gradle.properties b/gradle/dependency-updates-report-aggregation/gradle.properties new file mode 100644 index 00000000..c9d9db2c --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/gradle.properties @@ -0,0 +1,15 @@ +# Copyright 2020-2023 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. + +org.gradle.caching = true diff --git a/gradle/dependency-updates-report-aggregation/settings.gradle.kts b/gradle/dependency-updates-report-aggregation/settings.gradle.kts new file mode 100644 index 00000000..6a46b6c3 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/settings.gradle.kts @@ -0,0 +1,44 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } + repositoriesMode.set(FAIL_ON_PROJECT_REPOS) + + versionCatalogs { + create("libs") { + from(files("../libs.versions.toml")) + } + } +} + +rootProject.name = "dependency-updates-report-aggregation" +rootProject.buildFileName = "dependency-updates-report-aggregation.gradle.kts" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt new file mode 100644 index 00000000..a06f7b19 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt @@ -0,0 +1,77 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup +import com.github.benmanes.gradle.versions.reporter.result.Dependency +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.SetSerializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure +import java.util.SortedSet + +@ExperimentalSerializationApi +@Serializer(forClass = DependenciesGroup::class) +class DependenciesGroupSerializer( + private val elementSerializer: KSerializer +) : KSerializer> { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup") { + element("count") + element("dependencies", SetSerializer(elementSerializer).descriptor) + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var count: Int? = null + var dependencies: SortedSet? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> count = decodeIntElement(descriptor, index) + 1 -> dependencies = decodeSerializableElement(descriptor, index, SetSerializer(elementSerializer)).toSortedSet() + else -> error("Unexpected index $index") + } + } + + listOf( + "count" to count, + "dependencies" to dependencies + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + DependenciesGroup(count!!, dependencies) + } + + override fun serialize(encoder: Encoder, value: DependenciesGroup) { + encoder.encodeStructure(descriptor) { + encodeIntElement(descriptor, 0, value.count) + encodeSerializableElement(descriptor, 1, SetSerializer(elementSerializer), value.dependencies) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt new file mode 100644 index 00000000..b57bac78 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.DependencyLatest +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = DependencyLatest::class) +object DependencyLatestSerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyLatest") { + element("group") + element("name") + element("version") + element("projectUrl") + element("latest") + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var group: String? = null + var name: String? = null + var version: String? = null + var projectUrl: String? = null + var latest: String? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> group = decodeStringElement(descriptor, index) + 1 -> name = decodeStringElement(descriptor, index) + 2 -> version = decodeStringElement(descriptor, index) + 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 4 -> latest = decodeStringElement(descriptor, index) + else -> error("Unexpected index $index") + } + } + + listOf( + "group" to group, + "name" to name, + "version" to version, + "latest" to latest + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + DependencyLatest(group, name, version, projectUrl, latest) + } + + override fun serialize(encoder: Encoder, value: DependencyLatest) { + encoder.encodeStructure(descriptor) { + encodeStringElement(descriptor, 0, value.group) + encodeStringElement(descriptor, 1, value.name) + encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) + encodeStringElement(descriptor, 4, value.latest) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt new file mode 100644 index 00000000..ea74e9fb --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated +import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = DependencyOutdated::class) +object DependencyOutdatedSerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated") { + element("group") + element("name") + element("version") + element("projectUrl") + element("available", VersionAvailableSerializer.descriptor) + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var group: String? = null + var name: String? = null + var version: String? = null + var projectUrl: String? = null + var available: VersionAvailable? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> group = decodeStringElement(descriptor, index) + 1 -> name = decodeStringElement(descriptor, index) + 2 -> version = decodeStringElement(descriptor, index) + 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 4 -> available = decodeSerializableElement(descriptor, index, VersionAvailableSerializer) + else -> error("Unexpected index $index") + } + } + + listOf( + "group" to group, + "name" to name, + "version" to version, + "available" to available + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + DependencyOutdated(group, name, version, projectUrl, available) + } + + override fun serialize(encoder: Encoder, value: DependencyOutdated) { + encoder.encodeStructure(descriptor) { + encodeStringElement(descriptor, 0, value.group) + encodeStringElement(descriptor, 1, value.name) + encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) + encodeSerializableElement(descriptor, 4, VersionAvailableSerializer, value.available) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt new file mode 100644 index 00000000..cbf46e29 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.Dependency +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = Dependency::class) +object DependencySerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Dependency") { + element("group") + element("name") + element("version") + element("projectUrl") + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var group: String? = null + var name: String? = null + var version: String? = null + var projectUrl: String? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> group = decodeStringElement(descriptor, index) + 1 -> name = decodeStringElement(descriptor, index) + 2 -> version = decodeStringElement(descriptor, index) + 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + else -> error("Unexpected index $index") + } + } + + listOf( + "group" to group, + "name" to name, + "version" to version + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + Dependency(group, name, version, projectUrl) + } + + override fun serialize(encoder: Encoder, value: Dependency) { + encoder.encodeStructure(descriptor) { + encodeStringElement(descriptor, 0, value.group) + encodeStringElement(descriptor, 1, value.name) + encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt new file mode 100644 index 00000000..0bbc0e9e --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt @@ -0,0 +1,88 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = DependencyUnresolved::class) +object DependencyUnresolvedSerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved") { + element("group") + element("name") + element("version") + element("projectUrl") + element("reason") + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var group: String? = null + var name: String? = null + var version: String? = null + var projectUrl: String? = null + var reason: String? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> group = decodeStringElement(descriptor, index) + 1 -> name = decodeStringElement(descriptor, index) + 2 -> version = decodeStringElement(descriptor, index) + 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 4 -> reason = decodeStringElement(descriptor, index) + else -> error("Unexpected index $index") + } + } + + listOf( + "group" to group, + "name" to name, + "version" to version, + "reason" to reason + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + DependencyUnresolved(group, name, version, projectUrl, reason) + } + + override fun serialize(encoder: Encoder, value: DependencyUnresolved) { + encoder.encodeStructure(descriptor) { + encodeStringElement(descriptor, 0, value.group) + encodeStringElement(descriptor, 1, value.name) + encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) + encodeStringElement(descriptor, 4, value.reason) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt new file mode 100644 index 00000000..ab5a20a9 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup +import com.github.benmanes.gradle.versions.reporter.result.Dependency +import com.github.benmanes.gradle.versions.reporter.result.DependencyLatest +import com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated +import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved +import com.github.benmanes.gradle.versions.reporter.result.Result +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.MissingFieldException +import kotlinx.serialization.Serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = Result::class) +object ResultSerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Result") { + element("count") + element("current", DependenciesGroupSerializer(DependencySerializer).descriptor) + element("outdated", DependenciesGroupSerializer(DependencyOutdatedSerializer).descriptor) + element("exceeded", DependenciesGroupSerializer(DependencyLatestSerializer).descriptor) + element("unresolved", DependenciesGroupSerializer(DependencyUnresolvedSerializer).descriptor) + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var count: Int? = null + var current: DependenciesGroup? = null + var outdated: DependenciesGroup? = null + var exceeded: DependenciesGroup? = null + var unresolved: DependenciesGroup? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> count = decodeIntElement(descriptor, index) + 1 -> current = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencySerializer)) + 2 -> outdated = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyOutdatedSerializer)) + 3 -> exceeded = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyLatestSerializer)) + 4 -> unresolved = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyUnresolvedSerializer)) + else -> error("Unexpected index $index") + } + } + + listOf( + "count" to count, + "current" to current, + "outdated" to outdated, + "exceeded" to exceeded, + "unresolved" to unresolved + ) + .filter { it.second == null } + .map { it.first } + .toList() + .takeIf { it.isNotEmpty() } + ?.also { throw MissingFieldException(it, descriptor.serialName) } + + Result(count!!, current, outdated, exceeded, unresolved) + } + + override fun serialize(encoder: Encoder, value: Result) { + encoder.encodeStructure(descriptor) { + encodeIntElement(descriptor, 0, value.count) + encodeSerializableElement(descriptor, 1, DependenciesGroupSerializer(DependencySerializer), value.current) + encodeSerializableElement(descriptor, 2, DependenciesGroupSerializer(DependencyOutdatedSerializer), value.outdated) + encodeSerializableElement(descriptor, 3, DependenciesGroupSerializer(DependencyLatestSerializer), value.exceeded) + encodeSerializableElement(descriptor, 4, DependenciesGroupSerializer(DependencyUnresolvedSerializer), value.unresolved) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt new file mode 100644 index 00000000..131c0cd4 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt @@ -0,0 +1,67 @@ +/* + * Copyright 2020-2023 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.dao.result + +import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializer +import kotlinx.serialization.builtins.nullable +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.buildClassSerialDescriptor +import kotlinx.serialization.descriptors.element +import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import kotlinx.serialization.encoding.decodeStructure +import kotlinx.serialization.encoding.encodeStructure + +@ExperimentalSerializationApi +@Serializer(forClass = VersionAvailable::class) +object VersionAvailableSerializer : KSerializer { + override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.VersionAvailable") { + element("release") + element("milestone") + element("integration") + } + + override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { + var release: String? = null + var milestone: String? = null + var integration: String? = null + + while (true) { + when (val index = decodeElementIndex(descriptor)) { + DECODE_DONE -> break + 0 -> release = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 1 -> milestone = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 2 -> integration = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + else -> error("Unexpected index $index") + } + } + + VersionAvailable(release, milestone, integration) + } + + override fun serialize(encoder: Encoder, value: VersionAvailable) { + encoder.encodeStructure(descriptor) { + encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.release) + encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.milestone) + encodeNullableSerializableElement(descriptor, 2, String.serializer(), value.integration) + } + } +} diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts new file mode 100644 index 00000000..63c45d3e --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts @@ -0,0 +1,174 @@ +/* + * Copyright 2020-2023 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 + +import com.github.benmanes.gradle.versions.reporter.PlainTextReporter +import com.github.benmanes.gradle.versions.reporter.result.Result +import com.github.benmanes.gradle.versions.updates.gradle.GradleReleaseChannel.CURRENT +import com.github.benmanes.gradle.versions.updates.resolutionstrategy.ComponentSelectionWithCurrent +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import kotlinx.serialization.json.encodeToStream +import net.kautler.dao.result.ResultSerializer +import net.kautler.util.IgnoredDependency +import net.kautler.util.matches +import net.kautler.util.updateCounts +import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE +import org.gradle.api.attributes.Category.VERIFICATION +import org.gradle.api.attributes.VerificationType.VERIFICATION_TYPE_ATTRIBUTE + +plugins { + id("com.github.ben-manes.versions") +} + +val isPrelimiaryRelease: ComponentSelectionWithCurrent.() -> Boolean = { + val preliminaryReleaseRegex = Regex( + """(?i)[.-](?:${ + listOf( + "alpha", + "beta", + "dev", + "rc", + "cr", + "m", + "preview", + "test", + "pr", + "pre", + "b", + "ea" + ).joinToString("|") + })[.\d-]*""" + ) + preliminaryReleaseRegex.containsMatchIn(candidate.version) + && !preliminaryReleaseRegex.containsMatchIn(currentVersion) +} + +val json = Json { prettyPrint = true } + +if (gradle.parent == null && parent == null) { + // we are in the root project of the root build + val dependencyUpdatesResults by configurations.creating { + isCanBeConsumed = false + isCanBeResolved = true + attributes { + attribute(CATEGORY_ATTRIBUTE, objects.named(VERIFICATION)) + attribute(VERIFICATION_TYPE_ATTRIBUTE, objects.named("dependency-updates-result")) + } + } + + val includedBuildNames = gradle + .includedBuilds + .map { it.name } + + dependencies { + includedBuildNames + .forEach { dependencyUpdatesResults(":$it") } + } + + tasks.dependencyUpdates { + inputs + .files(dependencyUpdatesResults) + .withPropertyName("dependencyUpdatesResults") + + gradleReleaseChannel = CURRENT.id + checkConstraints = true + rejectVersionIf(isPrelimiaryRelease) + + val ignoredDependencies = objects.domainObjectSet(IgnoredDependency::class) + extensions.add>("ignoredDependencies", ignoredDependencies) + + outputFormatter = closureOf { + dependencyUpdatesResults.files.forEach { dependencyUpdatesResultFile -> + val dependencyUpdatesResult = dependencyUpdatesResultFile.inputStream().use { + @OptIn(ExperimentalSerializationApi::class) + json.decodeFromStream(ResultSerializer, it) + } + current.dependencies.addAll(dependencyUpdatesResult.current.dependencies) + outdated.dependencies.addAll(dependencyUpdatesResult.outdated.dependencies) + exceeded.dependencies.addAll(dependencyUpdatesResult.exceeded.dependencies) + unresolved.dependencies.addAll(dependencyUpdatesResult.unresolved.dependencies) + } + + val ignored = outdated + .dependencies + .filter { ignoredDependencies.any(it::matches) } + + outdated.dependencies.removeAll(ignored.toSet()) + + unresolved.dependencies.removeAll { + (it.group == "null") + && ((it.name in includedBuildNames) || (it.name == "dependency-updates-report-aggregation")) + && (it.version == "+") + } + + updateCounts() + + PlainTextReporter(project, revisionLevel(), gradleReleaseChannelLevel()) + .write(System.out, this) + + if (ignored.isNotEmpty()) { + println("\nThe following dependencies have later ${revisionLevel()} versions but were ignored:") + ignored.forEach { + println(" - ${it.group}:${it.name} [${it.version} -> ${it.available.getProperty(revisionLevel())}]") + it.projectUrl?.let { println(" $it") } + } + } + + if (gradle.current.isFailure || (unresolved.count != 0)) { + error("Unresolved libraries found") + } + + if (gradle.current.isUpdateAvailable || (outdated.count != 0)) { + error("Outdated libraries found") + } + } + } +} else { + val dependencyUpdatesResult by configurations.creating { + isCanBeConsumed = true + isCanBeResolved = false + attributes { + attribute(CATEGORY_ATTRIBUTE, objects.named(VERIFICATION)) + attribute(VERIFICATION_TYPE_ATTRIBUTE, objects.named("dependency-updates-result")) + } + } + + tasks.dependencyUpdates { + val reportFile = file("build/dependencyUpdates/dependencyUpdatesReport.json") + outputs.file(reportFile).withPropertyName("reportFile") + + checkForGradleUpdate = false + checkConstraints = true + rejectVersionIf(isPrelimiaryRelease) + + outputFormatter = closureOf { + reportFile + .apply { parentFile.mkdirs() } + .outputStream() + .use { reportFileStream -> + @OptIn(ExperimentalSerializationApi::class) + json.encodeToStream(ResultSerializer, this, reportFileStream) + } + } + } + + artifacts { + add(dependencyUpdatesResult.name, tasks.dependencyUpdates) + } +} diff --git a/buildSrc/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt similarity index 83% rename from buildSrc/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt rename to gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt index 525fa1c0..6721dc5b 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/DependencyOutdatedExtension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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,3 +27,10 @@ fun DependencyOutdated.matches( && (this.name == name) && oldVersion?.let { it == version } ?: true && newVersion?.let { it == available.milestone } ?: true + +fun DependencyOutdated.matches(ignored: IgnoredDependency) = matches( + ignored.group, + ignored.name, + ignored.oldVersion, + ignored.newVersion +) diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/IgnoredDependency.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/IgnoredDependency.kt new file mode 100644 index 00000000..edf01d45 --- /dev/null +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/IgnoredDependency.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2020-2023 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.util + +import com.github.benmanes.gradle.versions.updates.DependencyUpdatesTask +import org.gradle.api.Action +import org.gradle.api.DomainObjectCollection +import org.gradle.api.DomainObjectSet +import org.gradle.kotlin.dsl.getByName + +data class IgnoredDependency( + val group: String, + val name: String, + val oldVersion: String? = null, + val newVersion: String? = null +) + +val DependencyUpdatesTask.ignoredDependencies: DomainObjectCollection + get() = extensions.getByName>("ignoredDependencies") + +fun DependencyUpdatesTask.ignoredDependencies(configure: Action>): Unit = + extensions.configure("ignoredDependencies", configure) + +fun DomainObjectCollection.add( + group: String, + name: String, + oldVersion: String? = null, + newVersion: String? = null +) = add( + IgnoredDependency( + group = group, + name = name, + oldVersion = oldVersion, + newVersion = newVersion + ) +) diff --git a/buildSrc/src/main/kotlin/net/kautler/util/ResultExtension.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt similarity index 95% rename from buildSrc/src/main/kotlin/net/kautler/util/ResultExtension.kt rename to gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt index 5bedc11a..07d6285e 100644 --- a/buildSrc/src/main/kotlin/net/kautler/util/ResultExtension.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 00000000..b97c9dc8 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,78 @@ +# Copyright 2020-2023 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. + +[versions] +actions-cache = "3.0.5" +actions-core = "1.10.0" +actions-exec = "1.1.1" +actions-http-client = "2.0.1" +actions-io = "1.1.2" +actions-tool-cache = "2.0.1" +build-dukat = "0.5.7" +build-github-api = "1.117" +build-gradle-plugin-github = "1.4.0" +build-gradle-plugin-grgit = "4.1.1" +build-gradle-plugin-release = "2.8.1" +build-gradle-plugin-versions = "0.36.0" +build-kaml = "0.51.0" +build-kotlin = "1.8.10" +build-kotlinx-serialization = "1.4.1" +build-node = "16.18.1" +build-vercel-ncc = "0.36.1" +kotlin = "1.8.10" +kotlin-extensions = "1.0.1-pre.156-kotlin-1.5.0" +kotlinx-coroutines = "1.6.4" +kotlinx-nodejs = "0.0.7" +nullWritable = "1.0.5" +semver = "7.3.8" +types-semver = "7.3.13" +workflows-kotlin = "1.8.10" + +[libraries] +actions-cache = { module = "actions:cache", version.ref = "actions-cache" } +actions-core = { module = "actions:core", version.ref = "actions-core" } +actions-exec = { module = "actions:exec", version.ref = "actions-exec" } +actions-http-client = { module = "actions:http-client", version.ref = "actions-http-client" } +actions-io = { module = "actions:io", version.ref = "actions-io" } +actions-tool-cache = { module = "actions:tool-cache", version.ref = "actions-tool-cache" } +build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } +build-kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "build-kaml" } +build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "build-kotlinx-serialization" } +build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } +build-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } +build-vercel-ncc = { module = "vercel:ncc", version.ref = "build-vercel-ncc" } +kotlin-extensions = { module = "org.jetbrains:kotlin-extensions", version.ref = "kotlin-extensions" } +kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } +kotlinx-nodejs = { module = "org.jetbrains.kotlinx:kotlinx-nodejs", version.ref = "kotlinx-nodejs" } +nullWritable = { module = ":null-writable", version.ref = "nullWritable" } +semver = { module = ":semver", version.ref = "semver" } +types-semver = { module = "types:semver", version.ref = "types-semver" } +workflows-kotlin-compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", 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" } + +[plugins] +convention-dependency-updates-report-aggregation = { id = "net.kautler.dependency-updates-report-aggregation", version = "?" } +convention-github_actions = { id = "net.kautler.github_actions", version = "?" } +convention-ncc-packer = { id = "net.kautler.ncc_packer", version = "?" } +convention-node = { id = "net.kautler.node", version = "?" } +convention-publishing = { id = "net.kautler.publishing", version = "?" } +convention-readme = { id = "net.kautler.readme", version = "?" } +convention-versions = { id = "net.kautler.versions", version = "?" } +github = { id = "net.wooga.github", version.ref = "build-gradle-plugin-github" } +grgit = { id = "org.ajoberstar.grgit", version.ref = "build-gradle-plugin-grgit" } +kotlin-js = { id = "org.jetbrains.kotlin.js", version.ref = "kotlin" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "build-kotlin" } +release = { id = "net.researchgate.release", version.ref = "build-gradle-plugin-release" } +versions = { id = "com.github.ben-manes.versions", version.ref = "build-gradle-plugin-versions" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023ec8b20f512888fe07c5bd3ff77bb8f..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 42019 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 delta 39521 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 R149saZvb8 \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd32..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock new file mode 100644 index 00000000..74378378 --- /dev/null +++ b/kotlin-js-store/yarn.lock @@ -0,0 +1,1011 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@actions/cache@3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@actions/cache/-/cache-3.0.5.tgz#ede622cdb42409698a2d79c3560fa429711dfcfd" + integrity sha512-0WpPmwnRPkn5k5ASmjoX8bY8NrZEPTwN+64nGYJmR/bHjEVgC8svdf5K956wi67tNJBGJky2+UfvNbUOtHmMHg== + dependencies: + "@actions/core" "^1.10.0" + "@actions/exec" "^1.0.1" + "@actions/glob" "^0.1.0" + "@actions/http-client" "^2.0.1" + "@actions/io" "^1.0.1" + "@azure/ms-rest-js" "^2.6.0" + "@azure/storage-blob" "^12.8.0" + semver "^6.1.0" + uuid "^3.3.3" + +"@actions/core@1.10.0", "@actions/core@^1.10.0", "@actions/core@^1.2.6": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" + integrity sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug== + dependencies: + "@actions/http-client" "^2.0.1" + uuid "^8.3.2" + +"@actions/exec@1.1.1", "@actions/exec@^1.0.0", "@actions/exec@^1.0.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" + integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== + dependencies: + "@actions/io" "^1.0.1" + +"@actions/glob@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@actions/glob/-/glob-0.1.2.tgz#9685ed2d6583093479c8f137d067c4329d7d0974" + integrity sha512-SclLR7Ia5sEqjkJTPs7Sd86maMDw43p769YxBOxvPvEWuPEhpAnBsQfENOpXjFYMmhCqd127bmf+YdvJqVqR4A== + dependencies: + "@actions/core" "^1.2.6" + minimatch "^3.0.4" + +"@actions/http-client@2.0.1", "@actions/http-client@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" + integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== + dependencies: + tunnel "^0.0.6" + +"@actions/io@1.1.2", "@actions/io@^1.0.1", "@actions/io@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.2.tgz#766ac09674a289ce0f1550ffe0a6eac9261a8ea9" + integrity sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw== + +"@actions/tool-cache@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@actions/tool-cache/-/tool-cache-2.0.1.tgz#8a649b9c07838d9d750c9864814e66a7660ab720" + integrity sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA== + dependencies: + "@actions/core" "^1.2.6" + "@actions/exec" "^1.0.0" + "@actions/http-client" "^2.0.1" + "@actions/io" "^1.1.1" + semver "^6.1.0" + uuid "^3.3.2" + +"@azure/abort-controller@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" + integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== + dependencies: + tslib "^2.2.0" + +"@azure/core-auth@^1.1.4", "@azure/core-auth@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.4.0.tgz#6fa9661c1705857820dbc216df5ba5665ac36a9e" + integrity sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-http@^2.0.0": + version "2.2.7" + resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-2.2.7.tgz#f4f52b3b7b8adb5387acf11102e751358a31fa6f" + integrity sha512-TyGMeDm90mkRS8XzSQbSMD+TqnWL1XKGCh0x0QVGMD8COH2yU0q5SaHm/IBEBkzcq0u73NhS/p57T3KVSgUFqQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.3.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/core-util" "^1.1.0" + "@azure/logger" "^1.0.0" + "@types/node-fetch" "^2.5.0" + "@types/tunnel" "^0.0.3" + form-data "^4.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + tough-cookie "^4.0.0" + tslib "^2.2.0" + tunnel "^0.0.6" + uuid "^8.3.0" + xml2js "^0.4.19" + +"@azure/core-lro@^2.2.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.4.0.tgz#e3fdff797b045ee753aab25c3d2ecc0aa3e0a539" + integrity sha512-F65+rYkll1dpw3RGm8/SSiSj+/QkMeYDanzS/QKlM1dmuneVyXbO46C88V1MRHluLGdMP6qfD3vDRYALn0z0tQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/logger" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-paging@^1.1.1": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.3.0.tgz#ebf6520a931be7d5ff1cf58bc4fe6c14d6a3080d" + integrity sha512-H6Tg9eBm0brHqLy0OSAGzxIh1t4UL8eZVrSUMJ60Ra9cwq2pOskFqVpz2pYoHDsBY1jZ4V/P8LRGb5D5pmC6rg== + dependencies: + tslib "^2.2.0" + +"@azure/core-tracing@1.0.0-preview.13": + version "1.0.0-preview.13" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" + integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== + dependencies: + "@opentelemetry/api" "^1.0.1" + tslib "^2.2.0" + +"@azure/core-util@^1.1.0": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" + integrity sha512-A4TBYVQCtHOigFb2ETiiKFDocBoI1Zk2Ui1KpI42aJSIDexF7DHQFpnjonltXAIU/ceH+1fsZAWWgvX6/AKzog== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/logger@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" + integrity sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g== + dependencies: + tslib "^2.2.0" + +"@azure/ms-rest-js@^2.6.0": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-2.6.2.tgz#185a9d643ea55c696134af76a5c6026c94e26217" + integrity sha512-0/8rOxAoR9M3qKUdbGOIYtHtQkm4m5jdoDNdxTU0DkOr84KwyAdJuW/RfjJinGyig4h73DNF0rdCl6XowgCYcg== + dependencies: + "@azure/core-auth" "^1.1.4" + abort-controller "^3.0.0" + form-data "^2.5.0" + node-fetch "^2.6.7" + tough-cookie "^3.0.1" + tslib "^1.10.0" + tunnel "0.0.6" + uuid "^8.3.2" + xml2js "^0.4.19" + +"@azure/storage-blob@^12.8.0": + version "12.11.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.11.0.tgz#2e27902ab293715411ab1f7c8fae422ad0b4b827" + integrity sha512-na+FisoARuaOWaHWpmdtk3FeuTWf2VWamdJ9/TJJzj5ZdXPLC3juoDgFs6XVuJIoK30yuBpyFBEDXVRK4pB7Tg== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-http" "^2.0.0" + "@azure/core-lro" "^2.2.0" + "@azure/core-paging" "^1.1.1" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + events "^3.0.0" + tslib "^2.2.0" + +"@opentelemetry/api@^1.0.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" + integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== + +"@types/node-fetch@^2.5.0": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "18.11.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.0.tgz#f38c7139247a1d619f6cc6f27b072606af7c289d" + integrity sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w== + +"@types/semver@7.3.13": + version "7.3.13" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" + integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== + +"@types/tunnel@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" + integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== + dependencies: + "@types/node" "*" + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +"@vercel/ncc@0.36.1": + version "0.36.1" + resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.36.1.tgz#d4c01fdbbe909d128d1bf11c7f8b5431654c5b95" + integrity sha512-S4cL7Taa9yb5qbv+6wLgiKVZ03Qfkc4jGRuiUQMQ8HGBD5pcNRnHeYM33zBvJE4/zJGjJJ8GScB+WmTsn9mORw== + +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" + integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +combined-stream@^1.0.6, combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +debug@4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + +dukat@0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.7.tgz#4b3981f3fbde993546cc6f674b9027923f7293c6" + integrity sha512-PBM+B1oIE/aHbcrtdqX8yHfwdfdJ5ejJzkbU2LOW7bbAC3r1EcEyrS9ytFdHMPv06gVkF2QO77zGcMbGcsmXaA== + dependencies: + google-protobuf "3.12.2" + typescript "3.9.5" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +format-util@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/format-util/-/format-util-1.0.5.tgz#1ffb450c8a03e7bccffe40643180918cc297d271" + integrity sha512-varLbTj0e0yVyRpqQhuWV+8hlePAgaoFRhNFj50BNjEIrw1/DphHSObtqwskVCPWNgzwPoQrZAbfa/SBiicNeg== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +google-protobuf@3.12.2: + version "3.12.2" + resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" + integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + +minimatch@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.0.1.tgz#fb9022f7528125187c92bd9e9b6366be1cf3415b" + integrity sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +mocha@10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.0.0.tgz#205447d8993ec755335c4b13deba3d3a13c4def9" + integrity sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.4" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "5.0.1" + ms "2.1.3" + nanoid "3.3.3" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + workerpool "6.2.1" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +node-fetch@^2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +null-writable@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/null-writable/-/null-writable-1.0.5.tgz#0c619bf6a63f59c4f78b2b6d3acb00843a03710d" + integrity sha512-eLk4j1viNDfDCceYNSxUsfbIhnNTOTADss5Hc9f/zxhooegSlyWfyAzdQHsliniIF8j42+S0iroenyxRyA2pBA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + +psl@^1.1.28, psl@^1.1.33: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +querystringify@^2.1.1: + version "2.2.0" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" + integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +sax@>=0.6.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +semver@7.3.8: + version "7.3.8" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" + integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== + dependencies: + lru-cache "^6.0.0" + +semver@^6.1.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + +source-map-support@0.5.21: + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + +tough-cookie@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" + integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== + dependencies: + psl "^1.1.33" + punycode "^2.1.1" + universalify "^0.2.0" + url-parse "^1.5.3" + +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + +tslib@^1.10.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.2.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +tunnel@0.0.6, tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + +typescript@3.9.5: + version "3.9.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" + integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== + +typescript@4.7.4: + version "4.7.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" + integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== + +universalify@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" + integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== + +url-parse@^1.5.3: + version "1.5.10" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" + integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +uuid@^3.3.2, uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.0, uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + +workerpool@6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" + integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +xml2js@^0.4.19: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== diff --git a/ncc-packer/build.gradle.kts b/ncc-packer/ncc-packer.gradle.kts similarity index 85% rename from ncc-packer/build.gradle.kts rename to ncc-packer/ncc-packer.gradle.kts index 09e4f8d5..ef8ceea5 100644 --- a/ncc-packer/build.gradle.kts +++ b/ncc-packer/ncc-packer.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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. @@ -15,5 +15,5 @@ */ plugins { - net.kautler.ncc_packer + id(libs.plugins.convention.ncc.packer.get().pluginId) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 751e3356..83a75d47 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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. @@ -14,10 +14,65 @@ * limitations under the License. */ +import org.gradle.api.initialization.resolve.RepositoriesMode.PREFER_SETTINGS + +pluginManagement { + includeBuild("gradle/build-logic") + repositories { + mavenCentral() + gradlePluginPortal() + } +} + plugins { id("com.gradle.enterprise") version "3.6.1" } +dependencyResolutionManagement { + repositories { + ivy("https://nodejs.org/dist/") { + name = "Node.js Distributions" + patternLayout { + artifact("v[revision]/[artifact](-v[revision]-[classifier]).[ext]") + } + metadataSources { + artifact() + } + content { + includeModule("org.nodejs", "node") + } + } + ivy("https://github.com/yarnpkg/yarn/releases/download/") { + name = "Yarn Distributions" + patternLayout { + artifact("v[revision]/[artifact](-v[revision]).[ext]") + } + metadataSources { + artifact() + } + content { + includeModule("com.yarnpkg", "yarn") + } + } + mavenCentral() + //TODO: Remove after getting rid of kotlin-extensions + maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers/") { + content { + includeModule("org.jetbrains", "kotlin-extensions") + } + } + //TODO: Remove after getting rid of kotlinx-nodejs + jcenter { + content { + includeModule("org.jetbrains.kotlinx", "kotlinx-nodejs") + } + } + } + // work-around for https://youtrack.jetbrains.com/issue/KT-56300 + //repositoriesMode.set(FAIL_ON_PROJECT_REPOS) + repositoriesMode.set(PREFER_SETTINGS) +} + gradleEnterprise { buildScan { termsOfServiceUrl = "https://gradle.com/terms-of-service" @@ -25,5 +80,11 @@ gradleEnterprise { } } -rootProject.name = "setup-wsl" +includeBuild("gradle/build-logic") include("ncc-packer") +project(":ncc-packer").buildFileName = "ncc-packer.gradle.kts" + +rootProject.name = "setup-wsl" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 6c7c1637..3fe7414e 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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,18 +17,18 @@ package net.kautler.github.action.setup_wsl import HttpClient -import RangeOptions as SemVerRangeOptions import SemVer -import debug as coreDebug import exec -import http.OutgoingHttpHeaders -import info as coreInfo import kotlinext.js.jsObject import kotlinx.coroutines.CoroutineStart.LAZY +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.await import org.w3c.dom.url.URL +import RangeOptions as SemVerRangeOptions +import debug as coreDebug +import info as coreInfo val distributions = listOf( Alpine, @@ -50,6 +50,7 @@ sealed class Distribution( val installerFile: String, val userId: String = wslId ) { + @DelicateCoroutinesApi val downloadUrl = GlobalScope.async(start = LAZY) { if (_downloadUrl != null) { return@async _downloadUrl diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index d4ec38ea..8e948d64 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020-2022 Björn Kautler + * Copyright 2020-2023 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. @@ -14,6 +14,8 @@ * limitations under the License. */ +@file:OptIn(DelicateCoroutinesApi::class) + package net.kautler.github.action.setup_wsl import Buffer @@ -29,6 +31,7 @@ import fs.readdirSync import fs.writeFileSync import kotlinext.js.jsObject import kotlinx.coroutines.CoroutineStart.LAZY +import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async import kotlinx.coroutines.await @@ -148,7 +151,7 @@ val useCache by lazy { if (result && !cacheIsFeatureAvailable()) { val ghUrl = URL(process.env["GITHUB_SERVER_URL"] ?: "https://github.com", "") - if (ghUrl.hostname.toUpperCase() != "GITHUB.COM") { + if (ghUrl.hostname.uppercase() != "GITHUB.COM") { coreWarning("Caching is only supported on GHES version >= 3.5. If you are on version >= 3.5 please check with GHES admin if Actions cache service is enabled or not.") } else { coreWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.") @@ -162,7 +165,7 @@ val useCache by lazy { val distributionDirectory = GlobalScope.async(start = LAZY) { var cacheDirectory = toolCacheFind(distribution.distributionName, "${distribution.version}") - if (!cacheDirectory.isBlank()) { + if (cacheDirectory.isNotBlank()) { return@async cacheDirectory } diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index f79332a2..00000000 --- a/yarn.lock +++ /dev/null @@ -1,1516 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"17def1782b5ee417-kotlinx-nodejs-jsLegacy@file:packages_imported/17def1782b5ee417-kotlinx-nodejs-jsLegacy/0.0.7": - version "0.0.7" - -"@actions/cache@3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@actions/cache/-/cache-3.0.5.tgz#ede622cdb42409698a2d79c3560fa429711dfcfd" - integrity sha512-0WpPmwnRPkn5k5ASmjoX8bY8NrZEPTwN+64nGYJmR/bHjEVgC8svdf5K956wi67tNJBGJky2+UfvNbUOtHmMHg== - dependencies: - "@actions/core" "^1.10.0" - "@actions/exec" "^1.0.1" - "@actions/glob" "^0.1.0" - "@actions/http-client" "^2.0.1" - "@actions/io" "^1.0.1" - "@azure/ms-rest-js" "^2.6.0" - "@azure/storage-blob" "^12.8.0" - semver "^6.1.0" - uuid "^3.3.3" - -"@actions/core@1.10.0", "@actions/core@^1.10.0", "@actions/core@^1.2.6": - version "1.10.0" - resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" - integrity sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug== - dependencies: - "@actions/http-client" "^2.0.1" - uuid "^8.3.2" - -"@actions/exec@1.1.1", "@actions/exec@^1.0.0", "@actions/exec@^1.0.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" - integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== - dependencies: - "@actions/io" "^1.0.1" - -"@actions/glob@^0.1.0": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@actions/glob/-/glob-0.1.2.tgz#9685ed2d6583093479c8f137d067c4329d7d0974" - integrity sha512-SclLR7Ia5sEqjkJTPs7Sd86maMDw43p769YxBOxvPvEWuPEhpAnBsQfENOpXjFYMmhCqd127bmf+YdvJqVqR4A== - dependencies: - "@actions/core" "^1.2.6" - minimatch "^3.0.4" - -"@actions/http-client@2.0.1", "@actions/http-client@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" - integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== - dependencies: - tunnel "^0.0.6" - -"@actions/io@1.1.2", "@actions/io@^1.0.1", "@actions/io@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.2.tgz#766ac09674a289ce0f1550ffe0a6eac9261a8ea9" - integrity sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw== - -"@actions/tool-cache@2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@actions/tool-cache/-/tool-cache-2.0.1.tgz#8a649b9c07838d9d750c9864814e66a7660ab720" - integrity sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA== - dependencies: - "@actions/core" "^1.2.6" - "@actions/exec" "^1.0.0" - "@actions/http-client" "^2.0.1" - "@actions/io" "^1.1.1" - semver "^6.1.0" - uuid "^3.3.2" - -"@azure/abort-controller@^1.0.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" - integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== - dependencies: - tslib "^2.2.0" - -"@azure/core-auth@^1.1.4", "@azure/core-auth@^1.3.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.4.0.tgz#6fa9661c1705857820dbc216df5ba5665ac36a9e" - integrity sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ== - dependencies: - "@azure/abort-controller" "^1.0.0" - tslib "^2.2.0" - -"@azure/core-http@^2.0.0": - version "2.2.7" - resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-2.2.7.tgz#f4f52b3b7b8adb5387acf11102e751358a31fa6f" - integrity sha512-TyGMeDm90mkRS8XzSQbSMD+TqnWL1XKGCh0x0QVGMD8COH2yU0q5SaHm/IBEBkzcq0u73NhS/p57T3KVSgUFqQ== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-auth" "^1.3.0" - "@azure/core-tracing" "1.0.0-preview.13" - "@azure/core-util" "^1.1.0" - "@azure/logger" "^1.0.0" - "@types/node-fetch" "^2.5.0" - "@types/tunnel" "^0.0.3" - form-data "^4.0.0" - node-fetch "^2.6.7" - process "^0.11.10" - tough-cookie "^4.0.0" - tslib "^2.2.0" - tunnel "^0.0.6" - uuid "^8.3.0" - xml2js "^0.4.19" - -"@azure/core-lro@^2.2.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.4.0.tgz#e3fdff797b045ee753aab25c3d2ecc0aa3e0a539" - integrity sha512-F65+rYkll1dpw3RGm8/SSiSj+/QkMeYDanzS/QKlM1dmuneVyXbO46C88V1MRHluLGdMP6qfD3vDRYALn0z0tQ== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/logger" "^1.0.0" - tslib "^2.2.0" - -"@azure/core-paging@^1.1.1": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.3.0.tgz#ebf6520a931be7d5ff1cf58bc4fe6c14d6a3080d" - integrity sha512-H6Tg9eBm0brHqLy0OSAGzxIh1t4UL8eZVrSUMJ60Ra9cwq2pOskFqVpz2pYoHDsBY1jZ4V/P8LRGb5D5pmC6rg== - dependencies: - tslib "^2.2.0" - -"@azure/core-tracing@1.0.0-preview.13": - version "1.0.0-preview.13" - resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" - integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== - dependencies: - "@opentelemetry/api" "^1.0.1" - tslib "^2.2.0" - -"@azure/core-util@^1.1.0": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" - integrity sha512-A4TBYVQCtHOigFb2ETiiKFDocBoI1Zk2Ui1KpI42aJSIDexF7DHQFpnjonltXAIU/ceH+1fsZAWWgvX6/AKzog== - dependencies: - "@azure/abort-controller" "^1.0.0" - tslib "^2.2.0" - -"@azure/logger@^1.0.0": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" - integrity sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g== - dependencies: - tslib "^2.2.0" - -"@azure/ms-rest-js@^2.6.0": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-2.6.2.tgz#185a9d643ea55c696134af76a5c6026c94e26217" - integrity sha512-0/8rOxAoR9M3qKUdbGOIYtHtQkm4m5jdoDNdxTU0DkOr84KwyAdJuW/RfjJinGyig4h73DNF0rdCl6XowgCYcg== - dependencies: - "@azure/core-auth" "^1.1.4" - abort-controller "^3.0.0" - form-data "^2.5.0" - node-fetch "^2.6.7" - tough-cookie "^3.0.1" - tslib "^1.10.0" - tunnel "0.0.6" - uuid "^8.3.2" - xml2js "^0.4.19" - -"@azure/storage-blob@^12.8.0": - version "12.11.0" - resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.11.0.tgz#2e27902ab293715411ab1f7c8fae422ad0b4b827" - integrity sha512-na+FisoARuaOWaHWpmdtk3FeuTWf2VWamdJ9/TJJzj5ZdXPLC3juoDgFs6XVuJIoK30yuBpyFBEDXVRK4pB7Tg== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-http" "^2.0.0" - "@azure/core-lro" "^2.2.0" - "@azure/core-paging" "^1.1.1" - "@azure/core-tracing" "1.0.0-preview.13" - "@azure/logger" "^1.0.0" - events "^3.0.0" - tslib "^2.2.0" - -"@opentelemetry/api@^1.0.1": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" - integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== - -"@types/node-fetch@^2.5.0": - version "2.6.2" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" - integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== - dependencies: - "@types/node" "*" - form-data "^3.0.0" - -"@types/node@*": - version "18.11.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.0.tgz#f38c7139247a1d619f6cc6f27b072606af7c289d" - integrity sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w== - -"@types/semver@7.3.12": - version "7.3.12" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.12.tgz#920447fdd78d76b19de0438b7f60df3c4a80bf1c" - integrity sha512-WwA1MW0++RfXmCr12xeYOOC5baSC9mSb0ZqCquFzKhcoF4TvHu5MKOuXsncgZcpVFhB1pXd5hZmM0ryAoCp12A== - -"@types/tunnel@^0.0.3": - version "0.0.3" - resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" - integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== - dependencies: - "@types/node" "*" - -"@vercel/ncc@0.25.1": - version "0.25.1" - resolved "https://registry.yarnpkg.com/@vercel/ncc/-/ncc-0.25.1.tgz#a4aacdb508ac496fc0c63a3c3203d700a619cc0e" - integrity sha512-dGecC5+1wLof1MQpey4+6i2KZv4Sfs6WfXkl9KfO32GED4ZPiKxRfvtGPjbjZv0IbqMl6CxtcV1RotXYfd5SSA== - -abort-controller@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" - integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== - dependencies: - event-target-shim "^5.0.0" - -ansi-colors@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" - integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== - -ansi-regex@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" - integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== - -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -anymatch@~3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -array.prototype.map@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array.prototype.map/-/array.prototype.map-1.0.4.tgz#0d97b640cfdd036c1b41cfe706a5e699aa0711f2" - integrity sha512-Qds9QnX7A0qISY7JT5WuJO0NJPE9CMlC6JzHQfhpqAAQQzufVRoeH7EzUY5GcPTx72voG8LV/5eo+b8Qi8hmhA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== - -balanced-match@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" - integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== - -binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" - integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== - -call-bind@^1.0.0, call-bind@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" - integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== - dependencies: - function-bind "^1.1.1" - get-intrinsic "^1.0.2" - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chokidar@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" - integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.3.0" - optionalDependencies: - fsevents "~2.1.2" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== - -combined-stream@^1.0.6, combined-stream@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== - -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - -define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" - integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== - dependencies: - has-property-descriptors "^1.0.0" - object-keys "^1.1.1" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== - -diff@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" - integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== - -dukat@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.7.tgz#4b3981f3fbde993546cc6f674b9027923f7293c6" - integrity sha512-PBM+B1oIE/aHbcrtdqX8yHfwdfdJ5ejJzkbU2LOW7bbAC3r1EcEyrS9ytFdHMPv06gVkF2QO77zGcMbGcsmXaA== - dependencies: - google-protobuf "3.12.2" - typescript "3.9.5" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -es-abstract@^1.17.0-next.1, es-abstract@^1.19.0, es-abstract@^1.19.5: - version "1.20.4" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.4.tgz#1d103f9f8d78d4cf0713edcd6d0ed1a46eed5861" - integrity sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.1.3" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-symbols "^1.0.3" - internal-slot "^1.0.3" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-weakref "^1.0.2" - object-inspect "^1.12.2" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trimend "^1.0.5" - string.prototype.trimstart "^1.0.5" - unbox-primitive "^1.0.2" - -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - -es-get-iterator@^1.0.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" - integrity sha512-+DTO8GYwbMCwbywjimwZMHp8AuYXOS2JZFWoi2AlPOS3ebnII9w/NLpNZtA7A0YLaVDw+O7KFCeoIV7OPvM7hQ== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.0" - has-symbols "^1.0.1" - is-arguments "^1.1.0" - is-map "^2.0.2" - is-set "^2.0.2" - is-string "^1.0.5" - isarray "^2.0.5" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -event-target-shim@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" - integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== - -events@^3.0.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" - integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -find-up@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -flat@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" - integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== - dependencies: - is-buffer "~2.0.3" - -form-data@^2.5.0: - version "2.5.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" - integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -form-data@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" - integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.8" - mime-types "^2.1.12" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -function.prototype.name@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.5.tgz#cce0505fe1ffb80503e6f9e46cc64e46a12a9621" - integrity sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.0" - functions-have-names "^1.2.2" - -functions-have-names@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" - integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" - integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== - dependencies: - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.3" - -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -glob-parent@~5.1.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" - integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== - dependencies: - is-glob "^4.0.1" - -glob@7.1.6: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -google-protobuf@3.12.2: - version "3.12.2" - resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" - integrity sha512-4CZhpuRr1d6HjlyrxoXoocoGFnRYgKULgMtikMddA9ztRyYR59Aondv2FioyxWVamRo0rF2XpYawkTCBEQOSkA== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-property-descriptors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" - integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== - dependencies: - get-intrinsic "^1.1.1" - -has-symbols@^1.0.0, has-symbols@^1.0.1, has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== - -has-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - -ip-regex@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" - integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== - -is-arguments@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-buffer@~2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" - integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== - -is-callable@^1.1.4, is-callable@^1.2.7: - version "1.2.7" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" - integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== - -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w== - -is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.3" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" - integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== - dependencies: - is-extglob "^2.1.1" - -is-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" - integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== - -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== - dependencies: - has-tostringtag "^1.0.0" - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== - -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - -is-set@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" - integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== - -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== - dependencies: - call-bind "^1.0.2" - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== - dependencies: - call-bind "^1.0.2" - -isarray@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" - integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== - -iterate-iterator@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/iterate-iterator/-/iterate-iterator-1.0.2.tgz#551b804c9eaa15b847ea6a7cdc2f5bf1ec150f91" - integrity sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw== - -iterate-value@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/iterate-value/-/iterate-value-1.0.2.tgz#935115bd37d006a52046535ebc8d07e9c9337f57" - integrity sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ== - dependencies: - es-get-iterator "^1.0.2" - iterate-iterator "^1.0.1" - -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -"kotlin-test-js-runner@file:packages_imported/kotlin-test-js-runner/1.4.20": - version "1.4.20" - -"kotlin-test@file:packages_imported/kotlin-test/1.4.20": - version "1.4.20" - -"kotlin-wrappers-kotlin-extensions-jsLegacy@file:packages_imported/kotlin-wrappers-kotlin-extensions-jsLegacy/1.0.1-pre.129-kotlin-1.4.20": - version "1.0.1-pre.129-kotlin-1.4.20" - -"kotlin@file:packages_imported/kotlin/1.4.20": - version "1.4.20" - -"kotlinx-atomicfu@file:packages_imported/kotlinx-atomicfu/0.14.4": - version "0.14.4" - -"kotlinx-coroutines-core@file:packages_imported/kotlinx-coroutines-core/1.4.2": - version "1.4.2" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - -log-symbols@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" - integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== - dependencies: - chalk "^2.4.2" - -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - -mime-db@1.52.0: - version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" - integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== - -mime-types@^2.1.12: - version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" - integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== - dependencies: - mime-db "1.52.0" - -minimatch@3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimatch@^3.0.4: - version "3.1.2" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" - integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== - dependencies: - brace-expansion "^1.1.7" - -mocha@8.1.1: - version "8.1.1" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.1.1.tgz#1de1ba4e9a2c955d96b84e469d7540848223592d" - integrity sha512-p7FuGlYH8t7gaiodlFreseLxEmxTgvyG9RgPHODFPySNhwUehu8NIb0vdSt3WFckSneswZ0Un5typYcWElk7HQ== - dependencies: - ansi-colors "4.1.1" - browser-stdout "1.3.1" - chokidar "3.3.1" - debug "3.2.6" - diff "4.0.2" - escape-string-regexp "1.0.5" - find-up "4.1.0" - glob "7.1.6" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "3.0.0" - minimatch "3.0.4" - ms "2.1.2" - object.assign "4.1.0" - promise.allsettled "1.0.2" - serialize-javascript "4.0.0" - strip-json-comments "3.0.1" - supports-color "7.1.0" - which "2.0.2" - wide-align "1.1.3" - workerpool "6.0.0" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.1" - -ms@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -ms@^2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" - integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== - -node-fetch@^2.6.7: - version "2.6.7" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" - integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== - dependencies: - whatwg-url "^5.0.0" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -null-writable@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/null-writable/-/null-writable-1.0.5.tgz#0c619bf6a63f59c4f78b2b6d3acb00843a03710d" - integrity sha512-eLk4j1viNDfDCceYNSxUsfbIhnNTOTADss5Hc9f/zxhooegSlyWfyAzdQHsliniIF8j42+S0iroenyxRyA2pBA== - -object-inspect@^1.12.2, object-inspect@^1.9.0: - version "1.12.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" - integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== - -object-keys@^1.0.11, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.assign@^4.1.4: - version "4.1.4" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" - integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - has-symbols "^1.0.3" - object-keys "^1.1.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== - dependencies: - wrappy "1" - -p-limit@^2.0.0, p-limit@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" - integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== - dependencies: - p-try "^2.0.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== - -path-exists@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" - integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== - -picomatch@^2.0.4, picomatch@^2.0.7: - version "2.3.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" - integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== - -promise.allsettled@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/promise.allsettled/-/promise.allsettled-1.0.2.tgz#d66f78fbb600e83e863d893e98b3d4376a9c47c9" - integrity sha512-UpcYW5S1RaNKT6pd+s9jp9K9rlQge1UXKskec0j6Mmuq7UJCvlS2J2/s/yuPN8ehftf9HXMxWlKiPbGGUzpoRg== - dependencies: - array.prototype.map "^1.0.1" - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - iterate-value "^1.0.0" - -psl@^1.1.28, psl@^1.1.33: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== - -punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -querystringify@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6" - integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ== - -randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -readdirp@~3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" - integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== - dependencies: - picomatch "^2.0.7" - -regexp.prototype.flags@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz#87cab30f80f66660181a3bb7bf5981a872b367ac" - integrity sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - functions-have-names "^1.2.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -requires-port@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== - -safe-buffer@^5.1.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -safe-regex-test@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" - integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.3" - is-regex "^1.1.4" - -sax@>=0.6.0: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -semver@7.3.8: - version "7.3.8" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" - integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== - dependencies: - lru-cache "^6.0.0" - -semver@^6.1.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -serialize-javascript@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - -side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== - dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" - -source-map-support@0.5.19: - version "0.5.19" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" - integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== - -"string-width@^1.0.2 || 2": - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string.prototype.trimend@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" - integrity sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -string.prototype.trimstart@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.5.tgz#5466d93ba58cfa2134839f81d7f42437e8c01fef" - integrity sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.19.5" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow== - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-json-comments@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -supports-color@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -tough-cookie@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" - integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== - dependencies: - ip-regex "^2.1.0" - psl "^1.1.28" - punycode "^2.1.1" - -tough-cookie@^4.0.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874" - integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ== - dependencies: - psl "^1.1.33" - punycode "^2.1.1" - universalify "^0.2.0" - url-parse "^1.5.3" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== - -tslib@^1.10.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" - integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== - -tslib@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -tunnel@0.0.6, tunnel@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" - integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== - -typescript@3.9.5: - version "3.9.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.5.tgz#586f0dba300cde8be52dd1ac4f7e1009c1b13f36" - integrity sha512-hSAifV3k+i6lEoCJ2k6R2Z/rp/H3+8sdmcn5NrS3/3kE7+RyZXm9aqvxWqjEXHAd8b0pShatpcdMTvEdvAJltQ== - -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== - dependencies: - call-bind "^1.0.2" - has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" - -universalify@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0" - integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg== - -url-parse@^1.5.3: - version "1.5.10" - resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1" - integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ== - dependencies: - querystringify "^2.1.1" - requires-port "^1.0.0" - -uuid@^3.3.2, uuid@^3.3.3: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -uuid@^8.3.0, uuid@^8.3.2: - version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" - integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== - dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== - -which@2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" - integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== - dependencies: - isexe "^2.0.0" - -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -workerpool@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.0.tgz#85aad67fa1a2c8ef9386a1b43539900f61d03d58" - integrity sha512-fU2OcNA/GVAJLLyKUoHkAgIhKb0JoCpSjLC/G2vYKxUjVmQwGbRVeoPJ1a8U4pnVofz4AQV5Y/NEw8oKqxEBtA== - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== - -xml2js@^0.4.19: - version "0.4.23" - resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" - integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== - dependencies: - sax ">=0.6.0" - xmlbuilder "~11.0.0" - -xmlbuilder@~11.0.0: - version "11.0.1" - resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" - integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== - -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - -yallist@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" - integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== - -yargs-parser@13.1.2, yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^15.0.1: - version "15.0.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.3.tgz#316e263d5febe8b38eef61ac092b33dfcc9b1115" - integrity sha512-/MVEVjTXy/cGAjdtQf8dW3V9b97bPN7rNn8ETj6BmAQL7ibC7O1Q9SPJbGjgh3SlwoBNXMzj/ZGIj8mBgl12YA== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-unparser@1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.1.tgz#bd4b0ee05b4c94d058929c32cb09e3fce71d3c5f" - integrity sha512-qZV14lK9MWsGCmcr7u5oXGH0dbGqZAIxTDrWXZDo5zUr6b6iUmelNKO6x6R1dQT24AH3LgRxJpr8meWy2unolA== - dependencies: - camelcase "^5.3.1" - decamelize "^1.2.0" - flat "^4.1.0" - is-plain-obj "^1.1.0" - yargs "^14.2.3" - -yargs@13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@^14.2.3: - version "14.2.3" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" - integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== - dependencies: - cliui "^5.0.0" - decamelize "^1.2.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^15.0.1" From a1aeb4c3e331291d02c4824016d5cd2e18345857 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 3 Feb 2023 01:46:11 +0100 Subject: [PATCH 08/23] Replace kotlin-extensions and kotlinx-nodejs by kotlin-wrappers --- .../kotlin/net/kautler/ncc_packer.gradle.kts | 5 +- .../main/kotlin/net/kautler/node.gradle.kts | 83 ++++++++++------- gradle/libs.versions.toml | 8 +- kotlin-js-store/yarn.lock | 13 +++ .../kotlin/net/kautler/nccpacker/NccPacker.kt | 28 +++--- .../main/kotlin/net/kautler/nccpacker/ncc.kt | 6 +- settings.gradle.kts | 12 --- .../github/action/setup_wsl/Distribution.kt | 41 ++++----- .../github/action/setup_wsl/MapExtension.kt | 31 ------- .../github/action/setup_wsl/SetupWsl.kt | 88 ++++++++++--------- 10 files changed, 155 insertions(+), 160 deletions(-) delete mode 100644 src/main/kotlin/net/kautler/github/action/setup_wsl/MapExtension.kt 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 d48bbd05..c2b14553 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 @@ -82,7 +82,8 @@ val libs = the() dependencies { implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlin.extensions) - implementation(libs.kotlinx.nodejs) + implementation(platform(libs.kotlin.wrappers.bom)) + implementation(libs.kotlin.wrapper.js) + implementation(libs.kotlin.wrapper.node) implementation(npm(libs.build.vercel.ncc, generateExternals = false)) } 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 65f5572c..002322c4 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 @@ -130,8 +130,9 @@ configure { dependencies { implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlin.extensions) - implementation(libs.kotlinx.nodejs) + implementation(platform(libs.kotlin.wrappers.bom)) + implementation(libs.kotlin.wrapper.js) + implementation(libs.kotlin.wrapper.node) implementation(npm(libs.actions.cache)) implementation(npm(libs.actions.core)) implementation(npm(libs.actions.exec)) @@ -163,22 +164,55 @@ tasks.withType(IntegratedDukatTask::class).configureEach { ) fixExternalsFiles( this, + "index.module_@actions_http-client.kt" to listOf( + """\Qimport http.IncomingMessage\E$""" to "import node.http.IncomingMessage", + """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", + """\Qimport NodeJS.ReadableStream\E$""" to "import node.ReadableStream", + """\Qimport http.Agent\E$""" to "import node.http.Agent", + """\Qtypealias HttpClientError = Error\E$""" to "external class HttpClientError : Throwable" + ), + "interfaces.module_@actions_exec.kt" to listOf( + """\Qimport stream.internal.Writable\E$""" to "import node.stream.Writable", + """\Qimport buffer.global.Buffer\E$""" to "import node.buffer.Buffer", + """\Qvar env: `T$2`?\E\r?\n\Q get() = definedExternally\E\r?\n\Q set(value) = definedExternally\E""" to "var env: js.core.ReadonlyRecord?" + ), + "interfaces.module_@actions_http-client.kt" to listOf( + """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", + """\Qimport NodeJS.ReadableStream\E$""" to "import node.ReadableStream", + """\Qimport http.IncomingHttpHeaders\E$""" to "import node.http.IncomingHttpHeaders", + """\Qexternal interface HttpClient {\E$""" to "external interface HttpClient2 {", + """\Qoptions: http.RequestOptions\E(\))?$""" to "options: node.http.RequestOptions$1" + ), "lib.dom.kt" to listOf( - """\Qoverride fun addEventListener(type: String, listener: EventListenerObject\E""" to """fun addEventListener(type: String, listener: EventListenerObject""", - """\Qoverride fun removeEventListener(type: String, callback: EventListenerObject\E""" to """fun removeEventListener(type: String, callback: EventListenerObject""", - """\Q`T${'$'}16`\E""" to """`T\${'$'}16`""" + """\Qimport url.URL as _URL\E$""" to "import node.url.URL as _URL", + """\Qimport url.URLSearchParams as _URLSearchParams\E$""" to "import node.url.URLSearchParams as _URLSearchParams", + """\Qoverride fun addEventListener(type: String, listener: EventListenerObject\E""" to "fun addEventListener(type: String, listener: EventListenerObject", + """\Qoverride fun removeEventListener(type: String, callback: EventListenerObject\E""" to "fun removeEventListener(type: String, callback: EventListenerObject", + """\Q`T$16`\E""" to """`T\$16`""" ), // work-around for https://github.com/Kotlin/dukat/issues/402 "lib.es2018.asynciterable.module_dukat.kt" to listOf( """\Qval `return`: ((value: TReturn) -> Promise | IteratorReturnResult */>)?\E$""" to "val `return`: ((value: dynamic) -> Promise | IteratorReturnResult */>)?", - """^*\Qval `return`: ((value: PromiseLike) -> Promise | IteratorReturnResult */>)?\E\r?\n\Q get() = definedExternally\E\r?\n""" to "" + """\Qval `return`: ((value: PromiseLike) -> Promise | IteratorReturnResult */>)?\E\r?\n\Q get() = definedExternally\E\r?\n""" to "" + ), + "lib.es2020.bigint.module_dukat.kt" to listOf( + """\Q : RelativeIndexable\E""" to "" + ), + "lib.es5.kt" to listOf( + """\Qimport NodeJS.CallSite\E$""" to "import node.CallSite", + """\Qval resolve: ((specified: String, parent: URL) -> Promise)?\E$""" to "val resolve2: ((specified: String, parent: URL) -> Promise)?" ), // work-around for https://github.com/Kotlin/dukat/issues/401 "null-writable.module_null-writable.kt" to listOf( - """\Q`T$13`\E""" to """`T\$10`""" + """\Qimport stream.internal.`T$13`\E$""" to "", + """\Qimport stream.internal.Writable\E$""" to "import node.stream.Writable", + """\Qoverride fun _write(_chunk: Any, _encoding: String, callback: (error: Error?) -> Unit)\E$""" to "override fun _write(chunk: Any, encoding: node.buffer.BufferEncoding, callback: (error: Error?) -> Unit)", + """\Qopen fun _writev(_chunks: Array<`T$88`>, callback: (error: Error?) -> Unit)\E$""" to "", + """\Qoverride fun _writev(chunks: Array<`T$13`>, callback: (error: Error?) -> Unit)\E$""" to "" ), // work-around for https://github.com/Kotlin/dukat/issues/399 "tool-cache.module_@actions_tool-cache.kt" to listOf( + """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", """\Qtypealias HTTPError = Error\E$""" to "external class HTTPError : Throwable", """\Qtypealias IToolRelease = IToolRelease\E$""" to "", """\Qtypealias IToolReleaseFile = IToolReleaseFile\E$""" to "" @@ -188,24 +222,9 @@ tasks.withType(IntegratedDukatTask::class).configureEach { """\Qtypealias ValidationError = Error\E$""" to "external class ValidationError : Throwable", """\Qtypealias ReserveCacheError = Error\E$""" to "external class ReserveCacheError : Throwable" ), - "index.module_@actions_http-client.kt" to listOf( - """\Qtypealias HttpClientError = Error\E$""" to "external class HttpClientError : Throwable" - ), - "interfaces.module_@actions_http-client.kt" to listOf( - """\Qexternal interface HttpClient {\E$""" to "external interface HttpClient2 {" - ), // work-around for https://github.com/Kotlin/dukat/issues/400 "semver.module_semver.kt" to listOf( """\Q@JsModule("semver")\E$""" to """@JsModule("semver/classes/semver")""" - ), - "interfaces.module_@actions_exec.kt" to listOf( - """\Qimport buffer.global.Buffer\E$""" to """import Buffer""" - ), - "lib.es5.kt" to listOf( - """\Qval resolve: ((specified: String, parent: URL) -> Promise)?\E$""" to """val resolve2: ((specified: String, parent: URL) -> Promise)?""" - ), - "lib.es2020.bigint.module_dukat.kt" to listOf( - """\Q : RelativeIndexable\E""" to """""" ) ) } @@ -235,16 +254,18 @@ fun addJsModuleAnnotations(task: Task, vararg pairs: Pair) { } fun deleteExternalsFiles(task: Task, vararg files: String) { - task - .outputs - .files - .asFileTree - .matching { - for (file in files) { - include("**/$file") + if (files.isNotEmpty()) { + task + .outputs + .files + .asFileTree + .matching { + for (file in files) { + include("**/$file") + } } - } - .forEach { it.delete() } + .forEach { it.delete() } + } } fun fixExternalsFiles(task: Task, vararg pairs: Pair>>) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b97c9dc8..3b7a9528 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,9 +31,8 @@ build-kotlinx-serialization = "1.4.1" build-node = "16.18.1" build-vercel-ncc = "0.36.1" kotlin = "1.8.10" -kotlin-extensions = "1.0.1-pre.156-kotlin-1.5.0" +kotlin-wrappers = "1.0.0-pre.491" kotlinx-coroutines = "1.6.4" -kotlinx-nodejs = "0.0.7" nullWritable = "1.0.5" semver = "7.3.8" types-semver = "7.3.13" @@ -52,9 +51,10 @@ build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-seri build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } build-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } build-vercel-ncc = { module = "vercel:ncc", version.ref = "build-vercel-ncc" } -kotlin-extensions = { module = "org.jetbrains:kotlin-extensions", version.ref = "kotlin-extensions" } +kotlin-wrapper-js = { module = "org.jetbrains.kotlin-wrappers:kotlin-js" } +kotlin-wrapper-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node" } +kotlin-wrappers-bom = { module = "org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom", version.ref = "kotlin-wrappers" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } -kotlinx-nodejs = { module = "org.jetbrains.kotlinx:kotlinx-nodejs", version.ref = "kotlinx-nodejs" } nullWritable = { module = ":null-writable", version.ref = "nullWritable" } semver = { module = ":semver", version.ref = "semver" } types-semver = { module = "types:semver", version.ref = "types-semver" } diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 74378378..c2acc167 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -186,6 +186,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.0.tgz#f38c7139247a1d619f6cc6f27b072606af7c289d" integrity sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w== +"@types/node@^18.11.18": + version "18.11.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" + integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== + "@types/semver@7.3.13": version "7.3.13" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" @@ -383,6 +388,14 @@ dukat@0.5.7: google-protobuf "3.12.2" typescript "3.9.5" +dukat@0.5.8-rc.4: + version "0.5.8-rc.4" + resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" + integrity sha512-ZnMt6DGBjlVgK2uQamXfd7uP/AxH7RqI0BL9GLrrJb2gKdDxvJChWy+M9AQEaL+7/6TmxzJxFOsRiInY9oGWTA== + dependencies: + google-protobuf "3.12.2" + typescript "3.9.5" + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" diff --git a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/NccPacker.kt b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/NccPacker.kt index c573c6ca..c3e2bbf8 100644 --- a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/NccPacker.kt +++ b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/NccPacker.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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,35 +16,35 @@ package net.kautler.nccpacker -import fs.MakeDirectoryOptions -import fs.`T$45` -import fs.mkdirSync -import fs.writeFileSync -import kotlinext.js.jsObject +import js.core.jso import kotlinx.coroutines.await -import path.path -import process +import node.fs.MakeDirectoryOptions +import node.fs.WriteFileOptions +import node.fs.mkdir +import node.fs.writeFile +import node.path.path +import node.process.process suspend fun main() { runCatching { val (input, output) = process.argv.filterIndexed { i, _ -> i > 1 } - val result = ncc(input, jsObject { + val result = ncc(input, jso { sourceMap = true license = "LICENSES" }).await() - mkdirSync(output, jsObject { + mkdir(output, jso { recursive = true }) - writeFileSync(path.join(output, "index.js"), result.code, jsObject<`T$45`>()) - result.map?.also { writeFileSync(path.join(output, "index.js.map"), it, jsObject<`T$45`>()) } + writeFile(path.join(output, "index.js"), result.code) + result.map?.also { writeFile(path.join(output, "index.js.map"), it) } result.assets?.forEach { (assetFileName, asset) -> val assetFilePath = path.join(output, assetFileName) - mkdirSync(path.dirname(assetFilePath), jsObject { + mkdir(path.dirname(assetFilePath), jso { recursive = true }) - writeFileSync(assetFilePath, asset.source, jsObject<`T$45`> { + writeFile(assetFilePath, asset.source, jso { mode = asset.permissions }) } diff --git a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt index 40370558..ae976e72 100644 --- a/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt +++ b/ncc-packer/src/main/kotlin/net/kautler/nccpacker/ncc.kt @@ -1,5 +1,5 @@ /* - * Copyright 2020 Björn Kautler + * Copyright 2020-2023 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,8 +16,8 @@ package net.kautler.nccpacker -import Buffer -import kotlinext.js.Object +import js.core.Object +import node.buffer.Buffer import kotlin.js.Promise @JsModule("@vercel/ncc") diff --git a/settings.gradle.kts b/settings.gradle.kts index 83a75d47..1f675ba5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -55,18 +55,6 @@ dependencyResolutionManagement { } } mavenCentral() - //TODO: Remove after getting rid of kotlin-extensions - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-js-wrappers/") { - content { - includeModule("org.jetbrains", "kotlin-extensions") - } - } - //TODO: Remove after getting rid of kotlinx-nodejs - jcenter { - content { - includeModule("org.jetbrains.kotlinx", "kotlinx-nodejs") - } - } } // work-around for https://youtrack.jetbrains.com/issue/KT-56300 //repositoriesMode.set(FAIL_ON_PROJECT_REPOS) diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 3fe7414e..605a8c98 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -19,7 +19,8 @@ package net.kautler.github.action.setup_wsl import HttpClient import SemVer import exec -import kotlinext.js.jsObject +import js.core.jso +import js.core.recordOf import kotlinx.coroutines.CoroutineStart.LAZY import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope @@ -60,9 +61,9 @@ sealed class Distribution( val response = HttpClient().post( requestUrl = "https://store.rg-adguard.net/api/GetFiles", data = "type=ProductId&url=$productId", - additionalHeaders = mapOf( + additionalHeaders = recordOf( "Content-Type" to "application/x-www-form-urlencoded" - ).asOutgoingHttpHeaders() + ) ).await() if (response.message.statusCode != 200) { @@ -161,11 +162,11 @@ abstract class AptGetBasedDistribution : Distribution { "apt-get", "update" ), - options = jsObject { - env = mapOf( + options = jso { + env = recordOf( "DEBIAN_FRONTEND" to "noninteractive", "WSLENV" to "DEBIAN_FRONTEND/u" - ).`asT$2`() + ) } ).await() } @@ -181,11 +182,11 @@ abstract class AptGetBasedDistribution : Distribution { "upgrade", "--yes" ), - options = jsObject { - env = mapOf( + options = jso { + env = recordOf( "DEBIAN_FRONTEND" to "noninteractive", "WSLENV" to "DEBIAN_FRONTEND/u" - ).`asT$2`() + ) } ).await() } @@ -203,11 +204,11 @@ abstract class AptGetBasedDistribution : Distribution { "--no-install-recommends", *packages ), - options = jsObject { - env = mapOf( + options = jso { + env = recordOf( "DEBIAN_FRONTEND" to "noninteractive", "WSLENV" to "DEBIAN_FRONTEND/u" - ).`asT$2`() + ) } ).await() } @@ -217,7 +218,7 @@ object Ubuntu2204 : AptGetBasedDistribution( wslId = "Ubuntu", userId = "Ubuntu-22.04", distributionName = "Ubuntu", - version = SemVer("22.4.0", jsObject()), + version = SemVer("22.4.0", jso()), downloadUrl = URL("https://aka.ms/wslubuntu2204"), installerFile = "ubuntu.exe" ) @@ -226,7 +227,7 @@ object Ubuntu2004 : AptGetBasedDistribution( wslId = "Ubuntu", userId = "Ubuntu-20.04", distributionName = "Ubuntu", - version = SemVer("20.4.0", jsObject()), + version = SemVer("20.4.0", jso()), downloadUrl = URL("https://aka.ms/wslubuntu2004"), installerFile = "ubuntu.exe" ) @@ -234,7 +235,7 @@ object Ubuntu2004 : AptGetBasedDistribution( object Ubuntu1804 : AptGetBasedDistribution( wslId = "Ubuntu-18.04", distributionName = "Ubuntu", - version = SemVer("18.4.0", jsObject()), + version = SemVer("18.4.0", jso()), downloadUrl = URL("https://aka.ms/wsl-ubuntu-1804"), installerFile = "ubuntu1804.exe" ) @@ -242,7 +243,7 @@ object Ubuntu1804 : AptGetBasedDistribution( object Ubuntu1604 : AptGetBasedDistribution( wslId = "Ubuntu-16.04", distributionName = "Ubuntu", - version = SemVer("16.4.0", jsObject()), + version = SemVer("16.4.0", jso()), downloadUrl = URL("https://aka.ms/wsl-ubuntu-1604"), installerFile = "ubuntu1604.exe" ) @@ -250,7 +251,7 @@ object Ubuntu1604 : AptGetBasedDistribution( object Debian : AptGetBasedDistribution( wslId = "Debian", distributionName = "Debian", - version = SemVer("1.0.0", jsObject()), + version = SemVer("1.0.0", jso()), downloadUrl = URL("https://aka.ms/wsl-debian-gnulinux"), installerFile = "debian.exe" ) @@ -258,7 +259,7 @@ object Debian : AptGetBasedDistribution( object Kali : AptGetBasedDistribution( wslId = "kali-linux", distributionName = "Kali", - version = SemVer("1.0.0", jsObject()), + version = SemVer("1.0.0", jso()), productId = "9pkr34tncv07", installerFile = "kali.exe" ) @@ -344,7 +345,7 @@ abstract class ZypperBasedDistribution : Distribution { object OpenSuseLeap15_2 : ZypperBasedDistribution( wslId = "openSUSE-Leap-15.2", distributionName = "openSUSE Leap", - version = SemVer("15.2.0", jsObject()), + version = SemVer("15.2.0", jso()), productId = "9mzd0n9z4m4h", installerFile = "openSUSE-Leap-15.2.exe" ) { @@ -433,7 +434,7 @@ abstract class ApkBasedDistribution : Distribution { object Alpine : ApkBasedDistribution( wslId = "Alpine", distributionName = "Alpine", - version = SemVer("1.0.3", jsObject()), + version = SemVer("1.0.3", jso()), productId = "9p804crf0395", installerFile = "Alpine.exe" ) diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/MapExtension.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/MapExtension.kt deleted file mode 100644 index 17329249..00000000 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/MapExtension.kt +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2020 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 http.OutgoingHttpHeaders -import kotlinext.js.jsObject -import tsstdlib.`T$2` - -fun Map.asOutgoingHttpHeaders() = asDynamic().unsafeCast() - -fun Map.`asT$2`() = asDynamic().unsafeCast<`T$2`>() - -fun Map.asDynamic() = jsObject { - for ((name, value) in this@asDynamic) { - this[name] = value - } -} diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index 8e948d64..71584d68 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -18,18 +18,10 @@ package net.kautler.github.action.setup_wsl -import Buffer -import NodeJS.get import NullWritable import exec -import fs.`T$32` -import fs.`T$35` -import fs.`T$45` -import fs.existsSync -import fs.mkdtempSync -import fs.readdirSync -import fs.writeFileSync -import kotlinext.js.jsObject +import js.core.get +import js.core.jso import kotlinx.coroutines.CoroutineStart.LAZY import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope @@ -39,10 +31,18 @@ import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map -import os.tmpdir -import path.path -import process -import url.URL +import node.buffer.Buffer +import node.buffer.BufferEncoding.utf16le +import node.fs.PathLike +import node.fs.accessAsync +import node.fs.mkdtemp +import node.fs.readdir +import node.fs.writeFile +import node.os.tmpdir +import node.path.path +import node.process.Platform.win32 +import node.process.process +import node.url.URL import addPath as coreAddPath import cacheDir as toolCacheCacheDir import debug as coreDebug @@ -72,18 +72,18 @@ val wslHelp = GlobalScope.async(start = LAZY) { exec( commandLine = "wsl", args = arrayOf("--help"), - options = jsObject { + options = jso { ignoreReturnCode = true outStream = NullWritable() errStream = NullWritable() - listeners = jsObject { + listeners = jso { stdout = { stdoutBuilder.append(it) - stdoutBuilderUtf16Le.append(it.toString("UTF-16LE")) + stdoutBuilderUtf16Le.append(it.toString(utf16le)) } stderr = { stderrBuilder.append(it) - stderrBuilderUtf16Le.append(it.toString("UTF-16LE")) + stderrBuilderUtf16Le.append(it.toString(utf16le)) } } } @@ -95,7 +95,7 @@ val wslHelp = GlobalScope.async(start = LAZY) { } val distribution by lazy { - val distributionId = coreGetInput("distribution", jsObject { + val distributionId = coreGetInput("distribution", jso { required = true }) @@ -124,7 +124,7 @@ val installationNeeded = GlobalScope.async(start = LAZY) { distribution.wslId, "true" ), - options = jsObject { + options = jso { ignoreReturnCode = true outStream = NullWritable() errStream = NullWritable() @@ -133,12 +133,12 @@ val installationNeeded = GlobalScope.async(start = LAZY) { } val toolCacheDir = GlobalScope.async(start = LAZY) { - val fakeDir = mkdtempSync(path.join(tmpdir(), "setup_wsl_fake_dir_"), jsObject<`T$32`>()) + val fakeDir = mkdtemp(path.join(tmpdir(), "setup_wsl_fake_dir_")) toolCacheCacheDir(fakeDir, distribution.distributionName, "${distribution.version}").await() } val useCache by lazy { - val input = coreGetInput("use-cache", jsObject { + val input = coreGetInput("use-cache", jso { required = true }) @@ -175,7 +175,7 @@ val distributionDirectory = GlobalScope.async(start = LAZY) { val restoredKey = if (useCache) cacheRestoreCache(arrayOf(cacheDirectory), cacheKey).await() else null if (restoredKey != null) { - if (existsSync(path.join(cacheDirectory, distribution.installerFile))) { + if (exists(path.join(cacheDirectory, distribution.installerFile))) { return@async cacheDirectory } } @@ -183,12 +183,12 @@ val distributionDirectory = GlobalScope.async(start = LAZY) { val distributionDownload = toolCacheDownloadTool("${distribution.downloadUrl()}").await() var extractedDistributionDirectory = extractZip(distributionDownload) - if (!existsSync(path.join(extractedDistributionDirectory, distribution.installerFile))) { - extractedDistributionDirectory = readdirSync(extractedDistributionDirectory, jsObject<`T$35`>()) + if (!exists(path.join(extractedDistributionDirectory, distribution.installerFile))) { + extractedDistributionDirectory = readdir(extractedDistributionDirectory) .asFlow() .filter { it.contains("""(? group(name: String, fn: suspend () -> T): T { } suspend fun verifyWindowsEnvironment() { - check(process.platform == "win32") { + check(process.platform == win32) { "platform '${process.platform}' is not supported by this action, please verify your 'runs-on' setting" } check(ioWhich("wsl").await().isNotBlank() || ioWhich("wslconfig").await().isNotBlank()) { @@ -349,7 +349,7 @@ suspend fun installDistribution() { exec( commandLine = """"${path.join(distributionDirectory(), distribution.installerFile)}"""", args = arrayOf("install", "--root"), - options = jsObject { + options = jso { input = Buffer.from("") } ).await() @@ -389,7 +389,7 @@ suspend fun writeWslShellWrapper() { "-c", "true" ), - options = jsObject { + options = jso { ignoreReturnCode = true } ).await() != 0) @@ -404,7 +404,7 @@ suspend fun writeWslShellWrapper() { "-u", wslShellUser ), - options = jsObject { + options = jso { ignoreReturnCode = true } ).await() == 0 @@ -491,22 +491,24 @@ suspend fun writeWslShellWrapper() { } """).trimIndent().lines().joinToString("\r\n") - if (wslShellCommand.isNotEmpty() || !existsSync(wslShellWrapperPath)) { - writeFileSync( + if (wslShellCommand.isNotEmpty() || !exists(wslShellWrapperPath)) { + writeFile( wslShellWrapperPath, - scriptContent.replace(" ", ""), - jsObject<`T$45`>() + scriptContent.replace(" ", "") ) } - - if (wslShellCommand.isNotEmpty() || !existsSync(wslShellDistributionWrapperPath)) { - writeFileSync( + if (wslShellCommand.isNotEmpty() || !exists(wslShellDistributionWrapperPath)) { + writeFile( wslShellDistributionWrapperPath, - scriptContent.replace("", "--distribution ${wslId()}"), - jsObject<`T$45`>() + scriptContent.replace("", "--distribution ${wslId()}") ) } coreAddPath(wslShellWrapperDirectory) } + +suspend fun exists(path: PathLike) = accessAsync(path) + .then { true } + .catch { false } + .await() From 0ea19237d9ca07fe77dcaa46c7a85466e64bdf8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 6 Feb 2023 00:52:56 +0100 Subject: [PATCH 09/23] Apply dependency analysis plugin --- .../check-dependency-versions.main.kts | 9 ++++ .../workflows/check-dependency-versions.yaml | 6 +++ .github/workflows/test.main.kts | 9 ++++ .github/workflows/test.yaml | 8 ++- build.gradle.kts | 2 +- gradle.properties | 2 + gradle/build-logic/build-logic.gradle.kts | 53 ++++++++++++++++++- gradle/build-logic/gradle.properties | 2 + ...ons.gradle.kts => dependencies.gradle.kts} | 17 ++++++ .../kotlin/net/kautler/publishing.gradle.kts | 4 +- .../main/kotlin/net/kautler/readme.gradle.kts | 2 +- ...ency-updates-report-aggregation.gradle.kts | 17 ++++++ .../gradle.properties | 2 + gradle/libs.versions.toml | 6 ++- settings.gradle.kts | 4 ++ 15 files changed, 136 insertions(+), 7 deletions(-) rename gradle/build-logic/src/main/kotlin/net/kautler/{versions.gradle.kts => dependencies.gradle.kts} (90%) diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index 8a3e36d7..faa98c3d 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -19,6 +19,8 @@ @file:Import("workflow-with-copyright.main.kts") import it.krzeminski.githubactions.actions.actions.CheckoutV3 +import it.krzeminski.githubactions.actions.actions.SetupJavaV3 +import it.krzeminski.githubactions.actions.actions.SetupJavaV3.Distribution.Temurin import it.krzeminski.githubactions.actions.burrunan.GradleCacheActionV1 import it.krzeminski.githubactions.domain.RunnerType.WindowsLatest import it.krzeminski.githubactions.domain.triggers.Cron @@ -54,6 +56,13 @@ workflowWithCopyright( name = "Checkout", action = CheckoutV3() ) + uses( + name = "Setup Java 11", + action = SetupJavaV3( + javaVersion = "11", + distribution = Temurin + ) + ) uses( name = "Check Dependency Versions", action = GradleCacheActionV1( diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index df51df80..e7752791 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -47,6 +47,12 @@ jobs: name: Checkout uses: actions/checkout@v3 - id: step-2 + name: Setup Java 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: temurin + - id: step-3 name: Check Dependency Versions uses: burrunan/gradle-cache-action@v1 with: diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index ab46dd1a..f076a97f 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -21,6 +21,8 @@ import it.krzeminski.githubactions.actions.actions.CacheRestoreV3 import it.krzeminski.githubactions.actions.actions.CacheSaveV3 import it.krzeminski.githubactions.actions.actions.CheckoutV3 +import it.krzeminski.githubactions.actions.actions.SetupJavaV3 +import it.krzeminski.githubactions.actions.actions.SetupJavaV3.Distribution.Temurin import it.krzeminski.githubactions.actions.burrunan.GradleCacheActionV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1.Distribution @@ -150,6 +152,13 @@ workflowWithCopyright( name = "Checkout", action = CheckoutV3() ) + uses( + name = "Setup Java 11", + action = SetupJavaV3( + javaVersion = "11", + distribution = Temurin + ) + ) uses( name = "Build", action = GradleCacheActionV1( diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index ba7254b4..58c7944e 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -49,6 +49,12 @@ jobs: name: Checkout uses: actions/checkout@v3 - id: step-2 + name: Setup Java 11 + uses: actions/setup-java@v3 + with: + java-version: 11 + distribution: temurin + - id: step-3 name: Build uses: burrunan/gradle-cache-action@v1 with: @@ -59,7 +65,7 @@ jobs: --info --stacktrace --scan - - id: step-3 + - id: step-4 name: Save built artifacts to cache uses: actions/cache/save@v3 with: diff --git a/build.gradle.kts b/build.gradle.kts index 92f82360..cd6dd735 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -15,7 +15,7 @@ */ plugins { - id(libs.plugins.convention.versions.get().pluginId) + id(libs.plugins.convention.dependencies.get().pluginId) id(libs.plugins.convention.node.get().pluginId) id(libs.plugins.convention.github.actions.get().pluginId) id(libs.plugins.convention.readme.get().pluginId) diff --git a/gradle.properties b/gradle.properties index deb50f91..71d09ca6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,4 +17,6 @@ version = 2.0.1-SNAPSHOT description = A GitHub action to install and setup a Linux distribution for the Windows Subsystem for Linux (WSL) org.gradle.caching = true + +dependency.analysis.print.build.health = true kotlin.js.ir.output.granularity = whole-program diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts index 4598b047..c43ff91b 100644 --- a/gradle/build-logic/build-logic.gradle.kts +++ b/gradle/build-logic/build-logic.gradle.kts @@ -20,20 +20,22 @@ plugins { `kotlin-dsl` alias(libs.plugins.kotlin.serialization) id(libs.plugins.convention.dependency.updates.report.aggregation.get().pluginId) + alias(libs.plugins.dependency.analysis) } dependencies { implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) implementation(plugin(libs.plugins.versions)) + implementation(plugin(libs.plugins.dependency.analysis)) implementation(plugin(libs.plugins.release)) implementation(plugin(libs.plugins.grgit)) implementation(plugin(libs.plugins.github)) implementation(plugin(libs.plugins.kotlin.js)) implementation(":dependency-updates-report-aggregation") + implementation(libs.build.inject) implementation(libs.build.github.api) implementation(platform(libs.build.kotlinx.serialization.bom)) implementation(libs.build.kotlinx.serialization.core) - implementation(libs.build.kotlinx.serialization.json) implementation(libs.build.kaml) implementation(embeddedKotlin("compiler-embeddable")) } @@ -50,6 +52,55 @@ tasks.compileKotlin { } } +dependencyAnalysis { + dependencies { + bundle("com.autonomousapps.dependency-analysis.gradle.plugin") { + includeDependency("com.autonomousapps.dependency-analysis:com.autonomousapps.dependency-analysis.gradle.plugin") + includeDependency("com.autonomousapps:dependency-analysis-gradle-plugin") + } + bundle("com.github.ben-manes.versions.gradle.plugin") { + includeDependency("com.github.ben-manes.versions:com.github.ben-manes.versions.gradle.plugin") + includeDependency("com.github.ben-manes:gradle-versions-plugin") + } + bundle("net.researchgate.release.gradle.plugin") { + includeDependency("net.researchgate.release:net.researchgate.release.gradle.plugin") + includeDependency("net.researchgate:gradle-release") + } + bundle("net.wooga.github.gradle.plugin") { + includeDependency("net.wooga.github:net.wooga.github.gradle.plugin") + includeDependency("gradle.plugin.net.wooga.gradle:atlas-github") + } + bundle("org.ajoberstar.grgit.gradle.plugin") { + includeDependency("org.ajoberstar.grgit:org.ajoberstar.grgit.gradle.plugin") + includeDependency("org.ajoberstar.grgit:grgit-core") + } + bundle("org.jetbrains.kotlin.js.gradle.plugin") { + includeDependency("org.jetbrains.kotlin.js:org.jetbrains.kotlin.js.gradle.plugin") + includeDependency("org.jetbrains.kotlin:kotlin-gradle-plugin-api") + includeDependency("org.jetbrains.kotlin:kotlin-gradle-plugin") + } + } + issues { + all { + onAny { + // the "implementation(files(...)) is reported as false-positive unused + // and cannot be suppressed, so we cannot let the task fail currently + //severity("fail") + } + onUsedTransitiveDependencies { + // false positive + exclude(":dependency-updates-report-aggregation") + } + } + } +} + +tasks.configureEach { + if (name == "buildHealth") { + dependsOn(gradle.includedBuilds.map { it.task(":buildHealth") }) + } +} + fun plugin(plugin: Provider) = plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" } diff --git a/gradle/build-logic/gradle.properties b/gradle/build-logic/gradle.properties index c9d9db2c..f5c5b07c 100644 --- a/gradle/build-logic/gradle.properties +++ b/gradle/build-logic/gradle.properties @@ -13,3 +13,5 @@ # limitations under the License. org.gradle.caching = true + +dependency.analysis.print.build.health = true diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts similarity index 90% rename from gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts rename to gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts index c8bec7b4..3fa56646 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/versions.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts @@ -25,6 +25,7 @@ import java.security.MessageDigest plugins { id("net.kautler.dependency-updates-report-aggregation") + id("com.autonomousapps.dependency-analysis") } val majorVersion by extra("$version".substringBefore('.')) @@ -76,3 +77,19 @@ tasks.dependencyUpdates { add(group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8") } } + +dependencyAnalysis { + issues { + all { + onAny { + severity("fail") + } + } + } +} + +tasks.configureEach { + if (name == "buildHealth") { + dependsOn(gradle.includedBuilds.map { it.task(":buildHealth") }) + } +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts index c939cbb2..ae69eaf9 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts @@ -48,7 +48,7 @@ import kotlin.LazyThreadSafetyMode.NONE plugins { // needed for accessing majorVersion - id("net.kautler.versions") + id("net.kautler.dependencies") id("org.ajoberstar.grgit") id("net.wooga.github") } @@ -100,7 +100,7 @@ val releaseTagName by lazy(NONE) { releasePlugin.tagName()!! } -val github by lazy(NONE) { +internal val github by lazy(NONE) { GitHub.connectUsingOAuth(extra["github.token"] as String)!! } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts index 3a496be9..da77fc32 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/readme.gradle.kts @@ -20,7 +20,7 @@ import java.security.MessageDigest plugins { // needed for accessing majorVersion - id("net.kautler.versions") + id("net.kautler.dependencies") `lifecycle-base` } diff --git a/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts b/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts index ef87f09d..17690ce9 100644 --- a/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts +++ b/gradle/dependency-updates-report-aggregation/dependency-updates-report-aggregation.gradle.kts @@ -20,6 +20,7 @@ plugins { `kotlin-dsl` alias(libs.plugins.kotlin.serialization) alias(libs.plugins.versions) + alias(libs.plugins.dependency.analysis) } dependencies { @@ -29,6 +30,22 @@ dependencies { implementation(libs.build.kotlinx.serialization.json) } +dependencyAnalysis { + dependencies { + bundle("com.github.ben-manes.versions.gradle.plugin") { + includeDependency("com.github.ben-manes.versions:com.github.ben-manes.versions.gradle.plugin") + includeDependency("com.github.ben-manes:gradle-versions-plugin") + } + } + issues { + all { + onAny { + severity("fail") + } + } + } +} + tasks.withType().configureEach { kotlinOptions { allWarningsAsErrors = true diff --git a/gradle/dependency-updates-report-aggregation/gradle.properties b/gradle/dependency-updates-report-aggregation/gradle.properties index c9d9db2c..f5c5b07c 100644 --- a/gradle/dependency-updates-report-aggregation/gradle.properties +++ b/gradle/dependency-updates-report-aggregation/gradle.properties @@ -13,3 +13,5 @@ # limitations under the License. org.gradle.caching = true + +dependency.analysis.print.build.health = true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3b7a9528..103c5fcd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,10 +21,12 @@ actions-io = "1.1.2" actions-tool-cache = "2.0.1" build-dukat = "0.5.7" build-github-api = "1.117" +build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" build-gradle-plugin-grgit = "4.1.1" build-gradle-plugin-release = "2.8.1" build-gradle-plugin-versions = "0.36.0" +build-inject = "1" build-kaml = "0.51.0" build-kotlin = "1.8.10" build-kotlinx-serialization = "1.4.1" @@ -46,6 +48,7 @@ actions-http-client = { module = "actions:http-client", version.ref = "actions-h actions-io = { module = "actions:io", version.ref = "actions-io" } actions-tool-cache = { module = "actions:tool-cache", version.ref = "actions-tool-cache" } build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } +build-inject = { module = "javax.inject:javax.inject", version.ref = "build-inject" } build-kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "build-kaml" } build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "build-kotlinx-serialization" } build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } @@ -63,13 +66,14 @@ workflows-kotlin-main-kts = { module = "org.jetbrains.kotlin:kotlin-main-kts", v workflows-kotlin-scripting-compiler = { module = "org.jetbrains.kotlin:kotlin-scripting-compiler", version.ref = "workflows-kotlin" } [plugins] +convention-dependencies = { id = "net.kautler.dependencies", version = "?" } convention-dependency-updates-report-aggregation = { id = "net.kautler.dependency-updates-report-aggregation", version = "?" } convention-github_actions = { id = "net.kautler.github_actions", version = "?" } convention-ncc-packer = { id = "net.kautler.ncc_packer", version = "?" } convention-node = { id = "net.kautler.node", version = "?" } convention-publishing = { id = "net.kautler.publishing", version = "?" } convention-readme = { id = "net.kautler.readme", version = "?" } -convention-versions = { id = "net.kautler.versions", version = "?" } +dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "build-gradle-plugin-dependency-analysis" } github = { id = "net.wooga.github", version.ref = "build-gradle-plugin-github" } grgit = { id = "org.ajoberstar.grgit", version.ref = "build-gradle-plugin-grgit" } kotlin-js = { id = "org.jetbrains.kotlin.js", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 1f675ba5..91830d44 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -17,6 +17,10 @@ import org.gradle.api.initialization.resolve.RepositoriesMode.PREFER_SETTINGS pluginManagement { + require(JavaVersion.current().isJava11Compatible) { + "This build requires Gradle to be run with at least Java 11" + } + includeBuild("gradle/build-logic") repositories { mavenCentral() From 4e9937fb47480ec1a5c0e30c4adaf90bffb9a46d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 6 Feb 2023 04:06:16 +0100 Subject: [PATCH 10/23] Apply refreshVersions plugin --- gradle/build-logic/settings.gradle.kts | 48 +++++++++++++++++++ .../settings.gradle.kts | 48 +++++++++++++++++++ settings.gradle.kts | 33 +++++++++++++ 3 files changed, 129 insertions(+) diff --git a/gradle/build-logic/settings.gradle.kts b/gradle/build-logic/settings.gradle.kts index cc2ec846..b8eb9c95 100644 --- a/gradle/build-logic/settings.gradle.kts +++ b/gradle/build-logic/settings.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS pluginManagement { @@ -24,6 +25,53 @@ pluginManagement { } } +plugins { + id("de.fayard.refreshVersions") version "0.51.0" +} + +refreshVersions { + featureFlags { + disable(GRADLE_UPDATES) + } + rejectVersionIf { + candidate.stabilityLevel.isLessStableThan(current.stabilityLevel) + } + // work-around for https://github.com/jmfayard/refreshVersions/issues/662 + file("build/tmp/refreshVersions").mkdirs() + // work-around for https://github.com/jmfayard/refreshVersions/issues/640 + versionsPropertiesFile = file("build/tmp/refreshVersions/versions.properties") +} + +// work-around for https://github.com/jmfayard/refreshVersions/issues/596 +gradle.rootProject { + tasks.configureEach { + if (name == "refreshVersions") { + doFirst { + copy { + from(gradle.parent!!.rootProject.file("gradle/libs.versions.toml")) + into("gradle") + } + } + doLast { + // work-around for https://github.com/jmfayard/refreshVersions/issues/661 + // and https://github.com/jmfayard/refreshVersions/issues/663 + file("gradle/libs.versions.toml").apply { + readText() + .replace("⬆ =", " ⬆ =") + .replace("]\n\n", "]\n") + .replace("""(?s)^(.*)(\n\Q[plugins]\E[^\[]*)(\n.*)$""".toRegex(), "$1$3$2") + .also { writeText(it) } + } + copy { + from("gradle/libs.versions.toml") + into(gradle.parent!!.rootProject.file("gradle")) + } + delete("gradle") + } + } + } +} + dependencyResolutionManagement { repositories { mavenCentral() diff --git a/gradle/dependency-updates-report-aggregation/settings.gradle.kts b/gradle/dependency-updates-report-aggregation/settings.gradle.kts index 6a46b6c3..23d35d37 100644 --- a/gradle/dependency-updates-report-aggregation/settings.gradle.kts +++ b/gradle/dependency-updates-report-aggregation/settings.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS pluginManagement { @@ -23,6 +24,53 @@ pluginManagement { } } +plugins { + id("de.fayard.refreshVersions") version "0.51.0" +} + +refreshVersions { + featureFlags { + disable(GRADLE_UPDATES) + } + rejectVersionIf { + candidate.stabilityLevel.isLessStableThan(current.stabilityLevel) + } + // work-around for https://github.com/jmfayard/refreshVersions/issues/662 + file("build/tmp/refreshVersions").mkdirs() + // work-around for https://github.com/jmfayard/refreshVersions/issues/640 + versionsPropertiesFile = file("build/tmp/refreshVersions/versions.properties") +} + +// work-around for https://github.com/jmfayard/refreshVersions/issues/596 +gradle.rootProject { + tasks.configureEach { + if (name == "refreshVersions") { + doFirst { + copy { + from(gradle.parent!!.rootProject.file("gradle/libs.versions.toml")) + into("gradle") + } + } + doLast { + // work-around for https://github.com/jmfayard/refreshVersions/issues/661 + // and https://github.com/jmfayard/refreshVersions/issues/663 + file("gradle/libs.versions.toml").apply { + readText() + .replace("⬆ =", " ⬆ =") + .replace("]\n\n", "]\n") + .replace("""(?s)^(.*)(\n\Q[plugins]\E[^\[]*)(\n.*)$""".toRegex(), "$1$3$2") + .also { writeText(it) } + } + copy { + from("gradle/libs.versions.toml") + into(gradle.parent!!.rootProject.file("gradle")) + } + delete("gradle") + } + } + } +} + dependencyResolutionManagement { repositories { mavenCentral() diff --git a/settings.gradle.kts b/settings.gradle.kts index 91830d44..c748dd9e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -14,6 +14,7 @@ * limitations under the License. */ +import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES import org.gradle.api.initialization.resolve.RepositoriesMode.PREFER_SETTINGS pluginManagement { @@ -29,9 +30,41 @@ pluginManagement { } plugins { + id("de.fayard.refreshVersions") version "0.51.0" id("com.gradle.enterprise") version "3.6.1" } +refreshVersions { + featureFlags { + disable(GRADLE_UPDATES) + } + rejectVersionIf { + candidate.stabilityLevel.isLessStableThan(current.stabilityLevel) + } + // work-around for https://github.com/jmfayard/refreshVersions/issues/662 + file("build/tmp/refreshVersions").mkdirs() + // work-around for https://github.com/jmfayard/refreshVersions/issues/640 + versionsPropertiesFile = file("build/tmp/refreshVersions/versions.properties") +} + +gradle.rootProject { + tasks.configureEach { + if (name == "refreshVersions") { + doLast { + // work-around for https://github.com/jmfayard/refreshVersions/issues/661 + // and https://github.com/jmfayard/refreshVersions/issues/663 + file("gradle/libs.versions.toml").apply { + readText() + .replace("⬆ =", " ⬆ =") + .replace("]\n\n", "]\n") + .replace("""(?s)^(.*)(\n\Q[plugins]\E[^\[]*)(\n.*)$""".toRegex(), "$1$3$2") + .also { writeText(it) } + } + } + } + } +} + dependencyResolutionManagement { repositories { ivy("https://nodejs.org/dist/") { From d59723544f2e1c813e75e756dbedac519e487b75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 6 Feb 2023 04:09:24 +0100 Subject: [PATCH 11/23] Update Gradle enterprise plugin to 3.12.3 --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index c748dd9e..4a17bca9 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -31,7 +31,7 @@ pluginManagement { plugins { id("de.fayard.refreshVersions") version "0.51.0" - id("com.gradle.enterprise") version "3.6.1" + id("com.gradle.enterprise") version "3.12.3" } refreshVersions { From c15c4a67c492d21b28f20a66bffc32a467b42e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Mon, 6 Feb 2023 11:29:58 +0100 Subject: [PATCH 12/23] Update Gradle versions plugin to 0.45.0 --- .../dao/result/DependenciesGroupSerializer.kt | 10 ++--- .../dao/result/DependencyLatestSerializer.kt | 42 ++++++++++--------- .../result/DependencyOutdatedSerializer.kt | 41 +++++++++--------- .../dao/result/DependencySerializer.kt | 41 +++++++----------- .../result/DependencyUnresolvedSerializer.kt | 41 +++++++++--------- .../kautler/dao/result/ResultSerializer.kt | 35 ++++++++++++---- .../dao/result/VersionAvailableSerializer.kt | 5 +-- ...ency-updates-report-aggregation.gradle.kts | 17 ++++---- .../net/kautler/util/ResultExtension.kt | 18 ++++---- gradle/libs.versions.toml | 2 +- 10 files changed, 139 insertions(+), 113 deletions(-) diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt index a06f7b19..7cb6d7b1 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependenciesGroupSerializer.kt @@ -21,7 +21,6 @@ import com.github.benmanes.gradle.versions.reporter.result.Dependency import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.SetSerializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor import kotlinx.serialization.descriptors.element @@ -32,8 +31,6 @@ import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure import java.util.SortedSet -@ExperimentalSerializationApi -@Serializer(forClass = DependenciesGroup::class) class DependenciesGroupSerializer( private val elementSerializer: KSerializer ) : KSerializer> { @@ -63,9 +60,12 @@ class DependenciesGroupSerializer( .map { it.first } .toList() .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } + ?.also { + @OptIn(ExperimentalSerializationApi::class) + throw MissingFieldException(it, descriptor.serialName) + } - DependenciesGroup(count!!, dependencies) + DependenciesGroup(count!!, dependencies!!.toMutableSet()) } override fun serialize(encoder: Encoder, value: DependenciesGroup) { diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt index b57bac78..12948d6b 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyLatestSerializer.kt @@ -20,7 +20,6 @@ import com.github.benmanes.gradle.versions.reporter.result.DependencyLatest import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor @@ -31,14 +30,14 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = DependencyLatest::class) +//@ExperimentalSerializationApi object DependencyLatestSerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyLatest") { - element("group") - element("name") - element("version") + element("group") + element("name") + element("version") element("projectUrl") + element("userReason") element("latest") } @@ -47,42 +46,47 @@ object DependencyLatestSerializer : KSerializer { var name: String? = null var version: String? = null var projectUrl: String? = null + var userReason: String? = null var latest: String? = null while (true) { + @OptIn(ExperimentalSerializationApi::class) when (val index = decodeElementIndex(descriptor)) { DECODE_DONE -> break - 0 -> group = decodeStringElement(descriptor, index) - 1 -> name = decodeStringElement(descriptor, index) - 2 -> version = decodeStringElement(descriptor, index) + 0 -> group = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 1 -> name = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 2 -> version = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) - 4 -> latest = decodeStringElement(descriptor, index) + 4 -> userReason = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 5 -> latest = decodeStringElement(descriptor, index) else -> error("Unexpected index $index") } } listOf( - "group" to group, - "name" to name, - "version" to version, "latest" to latest ) .filter { it.second == null } .map { it.first } .toList() .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } + ?.also { + @OptIn(ExperimentalSerializationApi::class) + throw MissingFieldException(it, descriptor.serialName) + } - DependencyLatest(group, name, version, projectUrl, latest) + DependencyLatest(group, name, version, projectUrl, userReason, latest!!) } override fun serialize(encoder: Encoder, value: DependencyLatest) { + @OptIn(ExperimentalSerializationApi::class) encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.group) + encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.name) + encodeNullableSerializableElement(descriptor, 2, String.serializer(), value.version) encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) - encodeStringElement(descriptor, 4, value.latest) + encodeNullableSerializableElement(descriptor, 4, String.serializer(), value.userReason) + encodeStringElement(descriptor, 5, value.latest) } } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt index ea74e9fb..d652107a 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyOutdatedSerializer.kt @@ -21,7 +21,6 @@ import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor @@ -32,14 +31,13 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = DependencyOutdated::class) object DependencyOutdatedSerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated") { - element("group") - element("name") - element("version") + element("group") + element("name") + element("version") element("projectUrl") + element("userReason") element("available", VersionAvailableSerializer.descriptor) } @@ -48,42 +46,47 @@ object DependencyOutdatedSerializer : KSerializer { var name: String? = null var version: String? = null var projectUrl: String? = null + var userReason: String? = null var available: VersionAvailable? = null while (true) { + @OptIn(ExperimentalSerializationApi::class) when (val index = decodeElementIndex(descriptor)) { DECODE_DONE -> break - 0 -> group = decodeStringElement(descriptor, index) - 1 -> name = decodeStringElement(descriptor, index) - 2 -> version = decodeStringElement(descriptor, index) + 0 -> group = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 1 -> name = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 2 -> version = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) - 4 -> available = decodeSerializableElement(descriptor, index, VersionAvailableSerializer) + 4 -> userReason = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 5 -> available = decodeSerializableElement(descriptor, index, VersionAvailableSerializer) else -> error("Unexpected index $index") } } listOf( - "group" to group, - "name" to name, - "version" to version, "available" to available ) .filter { it.second == null } .map { it.first } .toList() .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } + ?.also { + @OptIn(ExperimentalSerializationApi::class) + throw MissingFieldException(it, descriptor.serialName) + } - DependencyOutdated(group, name, version, projectUrl, available) + DependencyOutdated(group, name, version, projectUrl, userReason, available!!) } override fun serialize(encoder: Encoder, value: DependencyOutdated) { + @OptIn(ExperimentalSerializationApi::class) encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.group) + encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.name) + encodeNullableSerializableElement(descriptor, 2, String.serializer(), value.version) encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) - encodeSerializableElement(descriptor, 4, VersionAvailableSerializer, value.available) + encodeNullableSerializableElement(descriptor, 4, String.serializer(), value.userReason) + encodeSerializableElement(descriptor, 5, VersionAvailableSerializer, value.available) } } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt index cbf46e29..7cbf76ac 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencySerializer.kt @@ -19,8 +19,6 @@ package net.kautler.dao.result import com.github.benmanes.gradle.versions.reporter.result.Dependency import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor @@ -31,14 +29,13 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = Dependency::class) object DependencySerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Dependency") { - element("group") - element("name") - element("version") + element("group") + element("name") + element("version") element("projectUrl") + element("userReason") } override fun deserialize(decoder: Decoder) = decoder.decodeStructure(descriptor) { @@ -46,38 +43,32 @@ object DependencySerializer : KSerializer { var name: String? = null var version: String? = null var projectUrl: String? = null + var userReason: String? = null while (true) { + @OptIn(ExperimentalSerializationApi::class) when (val index = decodeElementIndex(descriptor)) { DECODE_DONE -> break - 0 -> group = decodeStringElement(descriptor, index) - 1 -> name = decodeStringElement(descriptor, index) - 2 -> version = decodeStringElement(descriptor, index) + 0 -> group = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 1 -> name = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 2 -> version = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 4 -> userReason = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) else -> error("Unexpected index $index") } } - listOf( - "group" to group, - "name" to name, - "version" to version - ) - .filter { it.second == null } - .map { it.first } - .toList() - .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } - - Dependency(group, name, version, projectUrl) + Dependency(group, name, version, projectUrl, userReason) } override fun serialize(encoder: Encoder, value: Dependency) { + @OptIn(ExperimentalSerializationApi::class) encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.group) + encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.name) + encodeNullableSerializableElement(descriptor, 2, String.serializer(), value.version) encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) + encodeNullableSerializableElement(descriptor, 4, String.serializer(), value.userReason) } } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt index 0bbc0e9e..a015d8e7 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/DependencyUnresolvedSerializer.kt @@ -20,7 +20,6 @@ import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor @@ -31,14 +30,13 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = DependencyUnresolved::class) object DependencyUnresolvedSerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved") { - element("group") - element("name") - element("version") + element("group") + element("name") + element("version") element("projectUrl") + element("userReason") element("reason") } @@ -47,42 +45,47 @@ object DependencyUnresolvedSerializer : KSerializer { var name: String? = null var version: String? = null var projectUrl: String? = null + var userReason: String? = null var reason: String? = null while (true) { + @OptIn(ExperimentalSerializationApi::class) when (val index = decodeElementIndex(descriptor)) { DECODE_DONE -> break - 0 -> group = decodeStringElement(descriptor, index) - 1 -> name = decodeStringElement(descriptor, index) - 2 -> version = decodeStringElement(descriptor, index) + 0 -> group = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 1 -> name = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 2 -> version = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) 3 -> projectUrl = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) - 4 -> reason = decodeStringElement(descriptor, index) + 4 -> userReason = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) + 5 -> reason = decodeStringElement(descriptor, index) else -> error("Unexpected index $index") } } listOf( - "group" to group, - "name" to name, - "version" to version, "reason" to reason ) .filter { it.second == null } .map { it.first } .toList() .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } + ?.also { + @OptIn(ExperimentalSerializationApi::class) + throw MissingFieldException(it, descriptor.serialName) + } - DependencyUnresolved(group, name, version, projectUrl, reason) + DependencyUnresolved(group, name, version, projectUrl, userReason, reason!!) } override fun serialize(encoder: Encoder, value: DependencyUnresolved) { + @OptIn(ExperimentalSerializationApi::class) encoder.encodeStructure(descriptor) { - encodeStringElement(descriptor, 0, value.group) - encodeStringElement(descriptor, 1, value.name) - encodeStringElement(descriptor, 2, value.version) + encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.group) + encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.name) + encodeNullableSerializableElement(descriptor, 2, String.serializer(), value.version) encodeNullableSerializableElement(descriptor, 3, String.serializer(), value.projectUrl) - encodeStringElement(descriptor, 4, value.reason) + encodeNullableSerializableElement(descriptor, 4, String.serializer(), value.userReason) + encodeStringElement(descriptor, 5, value.reason) } } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt index ab5a20a9..73e8626b 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/ResultSerializer.kt @@ -22,10 +22,11 @@ import com.github.benmanes.gradle.versions.reporter.result.DependencyLatest import com.github.benmanes.gradle.versions.reporter.result.DependencyOutdated import com.github.benmanes.gradle.versions.reporter.result.DependencyUnresolved import com.github.benmanes.gradle.versions.reporter.result.Result +import com.github.benmanes.gradle.versions.updates.gradle.GradleUpdateResult +import com.github.benmanes.gradle.versions.updates.gradle.GradleUpdateResults import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.MissingFieldException -import kotlinx.serialization.Serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor import kotlinx.serialization.descriptors.element import kotlinx.serialization.encoding.CompositeDecoder.Companion.DECODE_DONE @@ -34,14 +35,13 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = Result::class) object ResultSerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.Result") { element("count") element("current", DependenciesGroupSerializer(DependencySerializer).descriptor) element("outdated", DependenciesGroupSerializer(DependencyOutdatedSerializer).descriptor) element("exceeded", DependenciesGroupSerializer(DependencyLatestSerializer).descriptor) + element("undeclared", DependenciesGroupSerializer(DependencySerializer).descriptor) element("unresolved", DependenciesGroupSerializer(DependencyUnresolvedSerializer).descriptor) } @@ -50,6 +50,7 @@ object ResultSerializer : KSerializer { var current: DependenciesGroup? = null var outdated: DependenciesGroup? = null var exceeded: DependenciesGroup? = null + var undeclared: DependenciesGroup? = null var unresolved: DependenciesGroup? = null while (true) { @@ -59,7 +60,8 @@ object ResultSerializer : KSerializer { 1 -> current = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencySerializer)) 2 -> outdated = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyOutdatedSerializer)) 3 -> exceeded = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyLatestSerializer)) - 4 -> unresolved = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyUnresolvedSerializer)) + 4 -> undeclared = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencySerializer)) + 5 -> unresolved = decodeSerializableElement(descriptor, index, DependenciesGroupSerializer(DependencyUnresolvedSerializer)) else -> error("Unexpected index $index") } } @@ -69,15 +71,33 @@ object ResultSerializer : KSerializer { "current" to current, "outdated" to outdated, "exceeded" to exceeded, + "undeclared" to undeclared, "unresolved" to unresolved ) .filter { it.second == null } .map { it.first } .toList() .takeIf { it.isNotEmpty() } - ?.also { throw MissingFieldException(it, descriptor.serialName) } + ?.also { + @OptIn(ExperimentalSerializationApi::class) + throw MissingFieldException(it, descriptor.serialName) + } - Result(count!!, current, outdated, exceeded, unresolved) + Result( + count!!, + current!!, + outdated!!, + exceeded!!, + undeclared!!, + unresolved!!, + GradleUpdateResults( + true, + GradleUpdateResult(), + GradleUpdateResult(), + GradleUpdateResult(), + GradleUpdateResult() + ) + ) } override fun serialize(encoder: Encoder, value: Result) { @@ -86,7 +106,8 @@ object ResultSerializer : KSerializer { encodeSerializableElement(descriptor, 1, DependenciesGroupSerializer(DependencySerializer), value.current) encodeSerializableElement(descriptor, 2, DependenciesGroupSerializer(DependencyOutdatedSerializer), value.outdated) encodeSerializableElement(descriptor, 3, DependenciesGroupSerializer(DependencyLatestSerializer), value.exceeded) - encodeSerializableElement(descriptor, 4, DependenciesGroupSerializer(DependencyUnresolvedSerializer), value.unresolved) + encodeSerializableElement(descriptor, 4, DependenciesGroupSerializer(DependencySerializer), value.undeclared) + encodeSerializableElement(descriptor, 5, DependenciesGroupSerializer(DependencyUnresolvedSerializer), value.unresolved) } } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt index 131c0cd4..043c9bd1 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dao/result/VersionAvailableSerializer.kt @@ -19,7 +19,6 @@ package net.kautler.dao.result import com.github.benmanes.gradle.versions.reporter.result.VersionAvailable import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.nullable import kotlinx.serialization.builtins.serializer import kotlinx.serialization.descriptors.buildClassSerialDescriptor @@ -30,8 +29,6 @@ import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.encoding.decodeStructure import kotlinx.serialization.encoding.encodeStructure -@ExperimentalSerializationApi -@Serializer(forClass = VersionAvailable::class) object VersionAvailableSerializer : KSerializer { override val descriptor = buildClassSerialDescriptor("com.github.benmanes.gradle.versions.reporter.result.VersionAvailable") { element("release") @@ -45,6 +42,7 @@ object VersionAvailableSerializer : KSerializer { var integration: String? = null while (true) { + @OptIn(ExperimentalSerializationApi::class) when (val index = decodeElementIndex(descriptor)) { DECODE_DONE -> break 0 -> release = decodeNullableSerializableElement(descriptor, index, String.serializer().nullable) @@ -58,6 +56,7 @@ object VersionAvailableSerializer : KSerializer { } override fun serialize(encoder: Encoder, value: VersionAvailable) { + @OptIn(ExperimentalSerializationApi::class) encoder.encodeStructure(descriptor) { encodeNullableSerializableElement(descriptor, 0, String.serializer(), value.release) encodeNullableSerializableElement(descriptor, 1, String.serializer(), value.milestone) diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts index 63c45d3e..eec50677 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts @@ -27,7 +27,7 @@ import kotlinx.serialization.json.encodeToStream import net.kautler.dao.result.ResultSerializer import net.kautler.util.IgnoredDependency import net.kautler.util.matches -import net.kautler.util.updateCounts +import net.kautler.util.withUpdatedCounts import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE import org.gradle.api.attributes.Category.VERIFICATION import org.gradle.api.attributes.VerificationType.VERIFICATION_TYPE_ATTRIBUTE @@ -102,6 +102,7 @@ if (gradle.parent == null && parent == null) { current.dependencies.addAll(dependencyUpdatesResult.current.dependencies) outdated.dependencies.addAll(dependencyUpdatesResult.outdated.dependencies) exceeded.dependencies.addAll(dependencyUpdatesResult.exceeded.dependencies) + undeclared.dependencies.addAll(dependencyUpdatesResult.undeclared.dependencies) unresolved.dependencies.addAll(dependencyUpdatesResult.unresolved.dependencies) } @@ -117,24 +118,24 @@ if (gradle.parent == null && parent == null) { && (it.version == "+") } - updateCounts() + val result = withUpdatedCounts - PlainTextReporter(project, revisionLevel(), gradleReleaseChannelLevel()) - .write(System.out, this) + PlainTextReporter(project, revision, gradleReleaseChannel) + .write(System.out, result) if (ignored.isNotEmpty()) { - println("\nThe following dependencies have later ${revisionLevel()} versions but were ignored:") + println("\nThe following dependencies have later $revision versions but were ignored:") ignored.forEach { - println(" - ${it.group}:${it.name} [${it.version} -> ${it.available.getProperty(revisionLevel())}]") + println(" - ${it.group}:${it.name} [${it.version} -> ${it.available[revision]}]") it.projectUrl?.let { println(" $it") } } } - if (gradle.current.isFailure || (unresolved.count != 0)) { + if (gradle.current.isFailure || (result.unresolved.count != 0)) { error("Unresolved libraries found") } - if (gradle.current.isUpdateAvailable || (outdated.count != 0)) { + if (gradle.current.isUpdateAvailable || (result.outdated.count != 0)) { error("Outdated libraries found") } } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt index 07d6285e..2e232f65 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/util/ResultExtension.kt @@ -16,12 +16,16 @@ package net.kautler.util +import com.github.benmanes.gradle.versions.reporter.result.DependenciesGroup import com.github.benmanes.gradle.versions.reporter.result.Result -fun Result.updateCounts() { - val dependencyGroups = listOf(current, outdated, exceeded, unresolved) - dependencyGroups.forEach { - it.count = it.dependencies.size - } - count = dependencyGroups.map { it.count }.sum() -} +val Result.withUpdatedCounts: Result + get() = Result( + listOf(current, outdated, exceeded, undeclared, unresolved).sumOf { it.dependencies.size }, + DependenciesGroup(current.dependencies.size, current.dependencies), + DependenciesGroup(outdated.dependencies.size, outdated.dependencies), + DependenciesGroup(exceeded.dependencies.size, exceeded.dependencies), + DependenciesGroup(undeclared.dependencies.size, undeclared.dependencies), + DependenciesGroup(unresolved.dependencies.size, unresolved.dependencies), + gradle + ) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 103c5fcd..59abd7f6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -25,7 +25,7 @@ build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" build-gradle-plugin-grgit = "4.1.1" build-gradle-plugin-release = "2.8.1" -build-gradle-plugin-versions = "0.36.0" +build-gradle-plugin-versions = "0.45.0" build-inject = "1" build-kaml = "0.51.0" build-kotlin = "1.8.10" From d7655c1556c5225c713362beaeed7900d450ac67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Tue, 7 Feb 2023 03:12:55 +0100 Subject: [PATCH 13/23] Replace Dukat generated actions toolkit packages by kotlin-wrappers --- .../main/kotlin/net/kautler/node.gradle.kts | 76 +--------- gradle/libs.versions.toml | 15 +- kotlin-js-store/yarn.lock | 82 +++++++++-- .../github/action/setup_wsl/Distribution.kt | 30 ++-- .../github/action/setup_wsl/SetupWsl.kt | 135 +++++++++--------- 5 files changed, 153 insertions(+), 185 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 002322c4..e64f1c48 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 @@ -131,14 +131,9 @@ configure { dependencies { implementation(libs.kotlinx.coroutines.core) implementation(platform(libs.kotlin.wrappers.bom)) + implementation(libs.kotlin.wrapper.actions.toolkit) implementation(libs.kotlin.wrapper.js) implementation(libs.kotlin.wrapper.node) - implementation(npm(libs.actions.cache)) - implementation(npm(libs.actions.core)) - implementation(npm(libs.actions.exec)) - implementation(npm(libs.actions.http.client)) - implementation(npm(libs.actions.io)) - implementation(npm(libs.actions.tool.cache)) implementation(npm(libs.types.semver)) implementation(npm(libs.semver, generateExternals = false)) implementation(npm(libs.nullWritable)) @@ -146,16 +141,6 @@ dependencies { tasks.withType(IntegratedDukatTask::class).configureEach { doLast { - // work-around for https://github.com/Kotlin/dukat/issues/240 - addJsModuleAnnotations( - this, - "core.module_@actions_core.kt" to "@actions/core", - "io.module_@actions_io.kt" to "@actions/io", - "exec.module_@actions_exec.kt" to "@actions/exec", - "index.module_@actions_http-client.kt" to "@actions/http-client", - "tool-cache.module_@actions_tool-cache.kt" to "@actions/tool-cache", - "cache.module_@actions_cache.kt" to "@actions/cache" - ) // work-around for https://github.com/Kotlin/dukat/issues/397 deleteExternalsFiles( this, @@ -164,31 +149,12 @@ tasks.withType(IntegratedDukatTask::class).configureEach { ) fixExternalsFiles( this, - "index.module_@actions_http-client.kt" to listOf( - """\Qimport http.IncomingMessage\E$""" to "import node.http.IncomingMessage", - """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", - """\Qimport NodeJS.ReadableStream\E$""" to "import node.ReadableStream", - """\Qimport http.Agent\E$""" to "import node.http.Agent", - """\Qtypealias HttpClientError = Error\E$""" to "external class HttpClientError : Throwable" - ), - "interfaces.module_@actions_exec.kt" to listOf( - """\Qimport stream.internal.Writable\E$""" to "import node.stream.Writable", - """\Qimport buffer.global.Buffer\E$""" to "import node.buffer.Buffer", - """\Qvar env: `T$2`?\E\r?\n\Q get() = definedExternally\E\r?\n\Q set(value) = definedExternally\E""" to "var env: js.core.ReadonlyRecord?" - ), - "interfaces.module_@actions_http-client.kt" to listOf( - """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", - """\Qimport NodeJS.ReadableStream\E$""" to "import node.ReadableStream", - """\Qimport http.IncomingHttpHeaders\E$""" to "import node.http.IncomingHttpHeaders", - """\Qexternal interface HttpClient {\E$""" to "external interface HttpClient2 {", - """\Qoptions: http.RequestOptions\E(\))?$""" to "options: node.http.RequestOptions$1" - ), "lib.dom.kt" to listOf( """\Qimport url.URL as _URL\E$""" to "import node.url.URL as _URL", """\Qimport url.URLSearchParams as _URLSearchParams\E$""" to "import node.url.URLSearchParams as _URLSearchParams", """\Qoverride fun addEventListener(type: String, listener: EventListenerObject\E""" to "fun addEventListener(type: String, listener: EventListenerObject", """\Qoverride fun removeEventListener(type: String, callback: EventListenerObject\E""" to "fun removeEventListener(type: String, callback: EventListenerObject", - """\Q`T$16`\E""" to """`T\$16`""" + """\Q`T$19`\E""" to """`T\$19`""" ), // work-around for https://github.com/Kotlin/dukat/issues/402 "lib.es2018.asynciterable.module_dukat.kt" to listOf( @@ -204,25 +170,12 @@ tasks.withType(IntegratedDukatTask::class).configureEach { ), // work-around for https://github.com/Kotlin/dukat/issues/401 "null-writable.module_null-writable.kt" to listOf( - """\Qimport stream.internal.`T$13`\E$""" to "", + """\Qimport stream.internal.`T$17`\E$""" to "", """\Qimport stream.internal.Writable\E$""" to "import node.stream.Writable", """\Qoverride fun _write(_chunk: Any, _encoding: String, callback: (error: Error?) -> Unit)\E$""" to "override fun _write(chunk: Any, encoding: node.buffer.BufferEncoding, callback: (error: Error?) -> Unit)", - """\Qopen fun _writev(_chunks: Array<`T$88`>, callback: (error: Error?) -> Unit)\E$""" to "", - """\Qoverride fun _writev(chunks: Array<`T$13`>, callback: (error: Error?) -> Unit)\E$""" to "" + """\Qopen fun _writev(_chunks: Array<`T$3`>, callback: (error: Error?) -> Unit)\E$""" to "", + """\Qoverride fun _writev(chunks: Array<`T$17`>, callback: (error: Error?) -> Unit)\E$""" to "" ), - // work-around for https://github.com/Kotlin/dukat/issues/399 - "tool-cache.module_@actions_tool-cache.kt" to listOf( - """\Qimport http.OutgoingHttpHeaders\E$""" to "import node.http.OutgoingHttpHeaders", - """\Qtypealias HTTPError = Error\E$""" to "external class HTTPError : Throwable", - """\Qtypealias IToolRelease = IToolRelease\E$""" to "", - """\Qtypealias IToolReleaseFile = IToolReleaseFile\E$""" to "" - ), - // work-around for https://github.com/Kotlin/dukat/issues/398 - "cache.module_@actions_cache.kt" to listOf( - """\Qtypealias ValidationError = Error\E$""" to "external class ValidationError : Throwable", - """\Qtypealias ReserveCacheError = Error\E$""" to "external class ReserveCacheError : Throwable" - ), - // work-around for https://github.com/Kotlin/dukat/issues/400 "semver.module_semver.kt" to listOf( """\Q@JsModule("semver")\E$""" to """@JsModule("semver/classes/semver")""" ) @@ -234,25 +187,6 @@ tasks.assemble { dependsOn(project(":ncc-packer").tasks.named("nodeProductionRun")) } -fun addJsModuleAnnotations(task: Task, vararg pairs: Pair) { - for ((file, module) in pairs) { - task - .outputs - .files - .asFileTree - .matching { include("**/$file") } - .singleFile - .apply { - writeText( - """ - |@file:JsModule("$module") - ${readText().prependIndent("|")} - """.trimMargin() - ) - } - } -} - fun deleteExternalsFiles(task: Task, vararg files: String) { if (files.isNotEmpty()) { task diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 59abd7f6..6deba750 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,12 +13,6 @@ # limitations under the License. [versions] -actions-cache = "3.0.5" -actions-core = "1.10.0" -actions-exec = "1.1.1" -actions-http-client = "2.0.1" -actions-io = "1.1.2" -actions-tool-cache = "2.0.1" build-dukat = "0.5.7" build-github-api = "1.117" build-gradle-plugin-dependency-analysis = "1.19.0" @@ -33,7 +27,7 @@ build-kotlinx-serialization = "1.4.1" build-node = "16.18.1" build-vercel-ncc = "0.36.1" kotlin = "1.8.10" -kotlin-wrappers = "1.0.0-pre.491" +kotlin-wrappers = "1.0.0-pre.498" kotlinx-coroutines = "1.6.4" nullWritable = "1.0.5" semver = "7.3.8" @@ -41,12 +35,6 @@ types-semver = "7.3.13" workflows-kotlin = "1.8.10" [libraries] -actions-cache = { module = "actions:cache", version.ref = "actions-cache" } -actions-core = { module = "actions:core", version.ref = "actions-core" } -actions-exec = { module = "actions:exec", version.ref = "actions-exec" } -actions-http-client = { module = "actions:http-client", version.ref = "actions-http-client" } -actions-io = { module = "actions:io", version.ref = "actions-io" } -actions-tool-cache = { module = "actions:tool-cache", version.ref = "actions-tool-cache" } build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } build-inject = { module = "javax.inject:javax.inject", version.ref = "build-inject" } build-kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "build-kaml" } @@ -54,6 +42,7 @@ build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-seri build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } build-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } build-vercel-ncc = { module = "vercel:ncc", version.ref = "build-vercel-ncc" } +kotlin-wrapper-actions-toolkit = { module = "org.jetbrains.kotlin-wrappers:kotlin-actions-toolkit" } kotlin-wrapper-js = { module = "org.jetbrains.kotlin-wrappers:kotlin-js" } kotlin-wrapper-node = { module = "org.jetbrains.kotlin-wrappers:kotlin-node" } kotlin-wrappers-bom = { module = "org.jetbrains.kotlin-wrappers:kotlin-wrappers-bom", version.ref = "kotlin-wrappers" } diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index c2acc167..11819f76 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -2,22 +2,33 @@ # yarn lockfile v1 -"@actions/cache@3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@actions/cache/-/cache-3.0.5.tgz#ede622cdb42409698a2d79c3560fa429711dfcfd" - integrity sha512-0WpPmwnRPkn5k5ASmjoX8bY8NrZEPTwN+64nGYJmR/bHjEVgC8svdf5K956wi67tNJBGJky2+UfvNbUOtHmMHg== +"@actions/artifact@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@actions/artifact/-/artifact-1.1.1.tgz#b920bf2e67a5aeda49f10107673b0805690704eb" + integrity sha512-Vv4y0EW0ptEkU+Pjs5RGS/0EryTvI6s79LjSV9Gg/h+O3H/ddpjhuX/Bi/HZE4pbNPyjGtQjbdFWphkZhmgabA== + dependencies: + "@actions/core" "^1.9.1" + "@actions/http-client" "^2.0.1" + tmp "^0.2.1" + tmp-promise "^3.0.2" + +"@actions/cache@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@actions/cache/-/cache-3.1.3.tgz#6521648a259dab2ce981cdaadf98bf192293b569" + integrity sha512-5YbATJUS6nVs9EkpK7JaliC3G5koKdJT99NLreL0gJlznudzZzXGNIheW5+HUT9C2DBvubOxYIyfX4v2UpZWrA== dependencies: "@actions/core" "^1.10.0" "@actions/exec" "^1.0.1" "@actions/glob" "^0.1.0" "@actions/http-client" "^2.0.1" "@actions/io" "^1.0.1" + "@azure/abort-controller" "^1.1.0" "@azure/ms-rest-js" "^2.6.0" "@azure/storage-blob" "^12.8.0" semver "^6.1.0" uuid "^3.3.3" -"@actions/core@1.10.0", "@actions/core@^1.10.0", "@actions/core@^1.2.6": +"@actions/core@^1.10.0", "@actions/core@^1.2.6", "@actions/core@^1.9.1": version "1.10.0" resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" integrity sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug== @@ -25,7 +36,7 @@ "@actions/http-client" "^2.0.1" uuid "^8.3.2" -"@actions/exec@1.1.1", "@actions/exec@^1.0.0", "@actions/exec@^1.0.1": +"@actions/exec@^1.0.0", "@actions/exec@^1.0.1", "@actions/exec@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== @@ -40,19 +51,27 @@ "@actions/core" "^1.2.6" minimatch "^3.0.4" -"@actions/http-client@2.0.1", "@actions/http-client@^2.0.1": +"@actions/glob@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@actions/glob/-/glob-0.4.0.tgz#b169b1c1c72f41e5df7b3d9349539c88fa68403c" + integrity sha512-+eKIGFhsFa4EBwaf/GMyzCdWrXWymGXfFmZU3FHQvYS8mPcHtTtZONbkcqqUMzw9mJ/pImEBFET1JNifhqGsAQ== + dependencies: + "@actions/core" "^1.9.1" + minimatch "^3.0.4" + +"@actions/http-client@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== dependencies: tunnel "^0.0.6" -"@actions/io@1.1.2", "@actions/io@^1.0.1", "@actions/io@^1.1.1": +"@actions/io@^1.0.1", "@actions/io@^1.1.1", "@actions/io@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.2.tgz#766ac09674a289ce0f1550ffe0a6eac9261a8ea9" integrity sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw== -"@actions/tool-cache@2.0.1": +"@actions/tool-cache@^2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@actions/tool-cache/-/tool-cache-2.0.1.tgz#8a649b9c07838d9d750c9864814e66a7660ab720" integrity sha512-iPU+mNwrbA8jodY8eyo/0S/QqCKDajiR8OxWTnSk/SnYg0sj8Hp4QcUEVC1YFpHWXtrfbQrE13Jz4k4HXJQKcA== @@ -64,7 +83,7 @@ semver "^6.1.0" uuid "^3.3.2" -"@azure/abort-controller@^1.0.0": +"@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== @@ -186,10 +205,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.0.tgz#f38c7139247a1d619f6cc6f27b072606af7c289d" integrity sha512-IOXCvVRToe7e0ny7HpT/X9Rb2RYtElG1a+VshjwT00HxrM2dWBApHQoqsI6WiY7Q03vdf2bCrIGzVrkF/5t10w== -"@types/node@^18.11.18": - version "18.11.18" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" - integrity sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA== +"@types/node@^18.13.0": + version "18.13.0" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" + integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== "@types/semver@7.3.13": version "7.3.13" @@ -507,6 +526,18 @@ glob@7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + google-protobuf@3.12.2: version "3.12.2" resolved "https://registry.yarnpkg.com/google-protobuf/-/google-protobuf-3.12.2.tgz#50ce9f9b6281235724eb243d6a83e969a2176e53" @@ -627,7 +658,7 @@ minimatch@5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^3.0.4: +minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -774,6 +805,13 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + safe-buffer@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -851,6 +889,20 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +tmp-promise@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/tmp-promise/-/tmp-promise-3.0.3.tgz#60a1a1cc98c988674fcbfd23b6e3367bdeac4ce7" + integrity sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ== + dependencies: + tmp "^0.2.0" + +tmp@^0.2.0, tmp@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" + integrity sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ== + dependencies: + rimraf "^3.0.0" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt index 605a8c98..fefc7cc9 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/Distribution.kt @@ -16,9 +16,11 @@ package net.kautler.github.action.setup_wsl -import HttpClient import SemVer -import exec +import actions.core.debug +import actions.core.info +import actions.exec.exec +import actions.http.client.HttpClient import js.core.jso import js.core.recordOf import kotlinx.coroutines.CoroutineStart.LAZY @@ -28,8 +30,6 @@ import kotlinx.coroutines.async import kotlinx.coroutines.await import org.w3c.dom.url.URL import RangeOptions as SemVerRangeOptions -import debug as coreDebug -import info as coreInfo val distributions = listOf( Alpine, @@ -168,7 +168,7 @@ abstract class AptGetBasedDistribution : Distribution { "WSLENV" to "DEBIAN_FRONTEND/u" ) } - ).await() + ) } override suspend fun update() { @@ -188,7 +188,7 @@ abstract class AptGetBasedDistribution : Distribution { "WSLENV" to "DEBIAN_FRONTEND/u" ) } - ).await() + ) } override suspend fun install(vararg packages: String) { @@ -210,7 +210,7 @@ abstract class AptGetBasedDistribution : Distribution { "WSLENV" to "DEBIAN_FRONTEND/u" ) } - ).await() + ) } } @@ -309,7 +309,7 @@ abstract class ZypperBasedDistribution : Distribution { "--non-interactive", "refresh" ) - ).await() + ) } override suspend fun update() { @@ -323,7 +323,7 @@ abstract class ZypperBasedDistribution : Distribution { "--non-interactive", "update" ) - ).await() + ) } override suspend fun install(vararg packages: String) { @@ -338,7 +338,7 @@ abstract class ZypperBasedDistribution : Distribution { "install", *packages ) - ).await() + ) } } @@ -400,7 +400,7 @@ abstract class ApkBasedDistribution : Distribution { "apk", "update" ) - ).await() + ) } override suspend fun update() { @@ -413,7 +413,7 @@ abstract class ApkBasedDistribution : Distribution { "apk", "upgrade" ) - ).await() + ) } override suspend fun install(vararg packages: String) { @@ -427,7 +427,7 @@ abstract class ApkBasedDistribution : Distribution { "add", *packages ) - ).await() + ) } } @@ -445,8 +445,8 @@ private suspend inline fun retry(amount: Int, crossinline block: suspend () return block() }.onFailure { if (i != 5) { - coreDebug(it.stackTraceToString()) - coreInfo("Failure happened, retrying (${it.message ?: it})") + debug(it.stackTraceToString()) + info("Failure happened, retrying (${it.message ?: it})") } } }.last().getOrThrow() diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index 71584d68..ca8f4418 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -19,22 +19,39 @@ package net.kautler.github.action.setup_wsl import NullWritable -import exec +import actions.cache.isFeatureAvailable +import actions.cache.restoreCache +import actions.cache.saveCache +import actions.core.addPath +import actions.core.debug +import actions.core.endGroup +import actions.core.getBooleanInput +import actions.core.getInput +import actions.core.isDebug +import actions.core.setFailed +import actions.core.setOutput +import actions.core.startGroup +import actions.core.warning +import actions.exec.exec +import actions.io.mkdirP +import actions.io.mv +import actions.io.which +import actions.tool.cache.cacheDir +import actions.tool.cache.downloadTool +import actions.tool.cache.find import js.core.get import js.core.jso import kotlinx.coroutines.CoroutineStart.LAZY import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.async -import kotlinx.coroutines.await import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.map import node.buffer.Buffer import node.buffer.BufferEncoding.utf16le -import node.fs.PathLike -import node.fs.accessAsync +import node.fs.exists import node.fs.mkdtemp import node.fs.readdir import node.fs.writeFile @@ -43,26 +60,7 @@ import node.path.path import node.process.Platform.win32 import node.process.process import node.url.URL -import addPath as coreAddPath -import cacheDir as toolCacheCacheDir -import debug as coreDebug -import downloadTool as toolCacheDownloadTool -import endGroup as coreEndGroup -import extractZip as toolCacheExtractZip -import find as toolCacheFind -import getBooleanInput as coreGetBooleanInput -import getInput as coreGetInput -import isDebug as coreIsDebug -import isFeatureAvailable as cacheIsFeatureAvailable -import mkdirP as ioMkdirP -import mv as ioMv -import restoreCache as cacheRestoreCache -import saveCache as cacheSaveCache -import setFailed as coreSetFailed -import setOutput as coreSetOutput -import startGroup as coreStartGroup -import warning as coreWarning -import which as ioWhich +import actions.tool.cache.extractZip as toolCacheExtractZip val wslHelp = GlobalScope.async(start = LAZY) { val stdoutBuilder = StringBuilder() @@ -87,7 +85,7 @@ val wslHelp = GlobalScope.async(start = LAZY) { } } } - ).await() + ) stdoutBuilder.append(stdoutBuilderUtf16Le) stdoutBuilder.append(stderrBuilder) stdoutBuilder.append(stderrBuilderUtf16Le) @@ -95,7 +93,7 @@ val wslHelp = GlobalScope.async(start = LAZY) { } val distribution by lazy { - val distributionId = coreGetInput("distribution", jso { + val distributionId = getInput("distribution", jso { required = true }) @@ -107,7 +105,7 @@ val distribution by lazy { } val wslId = GlobalScope.async(start = LAZY) { - if (coreIsDebug()) { + if (isDebug()) { executeWslCommand( wslArguments = arrayOf("--list"), wslconfigArguments = arrayOf("/list") @@ -129,32 +127,32 @@ val installationNeeded = GlobalScope.async(start = LAZY) { outStream = NullWritable() errStream = NullWritable() } - ).await() != 0 + ) != 0 } val toolCacheDir = GlobalScope.async(start = LAZY) { val fakeDir = mkdtemp(path.join(tmpdir(), "setup_wsl_fake_dir_")) - toolCacheCacheDir(fakeDir, distribution.distributionName, "${distribution.version}").await() + cacheDir(fakeDir, distribution.distributionName, "${distribution.version}") } val useCache by lazy { - val input = coreGetInput("use-cache", jso { + val input = getInput("use-cache", jso { required = true }) val result = when (input) { "true" -> true "false" -> false - "true | false" -> cacheIsFeatureAvailable() + "true | false" -> isFeatureAvailable() else -> error("'$input' is not a valid boolean for 'use-cache'. Valid values: true, false") } - if (result && !cacheIsFeatureAvailable()) { + if (result && !isFeatureAvailable()) { val ghUrl = URL(process.env["GITHUB_SERVER_URL"] ?: "https://github.com", "") if (ghUrl.hostname.uppercase() != "GITHUB.COM") { - coreWarning("Caching is only supported on GHES version >= 3.5. If you are on version >= 3.5 please check with GHES admin if Actions cache service is enabled or not.") + warning("Caching is only supported on GHES version >= 3.5. If you are on version >= 3.5 please check with GHES admin if Actions cache service is enabled or not.") } else { - coreWarning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.") + warning("An internal error has occurred in cache backend. Please check https://www.githubstatus.com/ for any ongoing issue in actions.") } return@lazy false } @@ -163,7 +161,7 @@ val useCache by lazy { } val distributionDirectory = GlobalScope.async(start = LAZY) { - var cacheDirectory = toolCacheFind(distribution.distributionName, "${distribution.version}") + var cacheDirectory = find(distribution.distributionName, "${distribution.version}") if (cacheDirectory.isNotBlank()) { return@async cacheDirectory @@ -173,14 +171,14 @@ val distributionDirectory = GlobalScope.async(start = LAZY) { val cacheKey = "2:distributionDirectory_${distribution.distributionName}_${distribution.version}" - val restoredKey = if (useCache) cacheRestoreCache(arrayOf(cacheDirectory), cacheKey).await() else null + val restoredKey = if (useCache) restoreCache(arrayOf(cacheDirectory), cacheKey) else null if (restoredKey != null) { if (exists(path.join(cacheDirectory, distribution.installerFile))) { return@async cacheDirectory } } - val distributionDownload = toolCacheDownloadTool("${distribution.downloadUrl()}").await() + val distributionDownload = downloadTool("${distribution.downloadUrl()}") var extractedDistributionDirectory = extractZip(distributionDownload) if (!exists(path.join(extractedDistributionDirectory, distribution.installerFile))) { @@ -192,25 +190,25 @@ val distributionDirectory = GlobalScope.async(start = LAZY) { ?: error("'${distribution.installerFile}' not found for distribution '${distribution.userId}'") } - cacheDirectory = toolCacheCacheDir( + cacheDirectory = cacheDir( extractedDistributionDirectory, distribution.distributionName, "${distribution.version}" - ).await() + ) if (useCache) { - cacheSaveCache(arrayOf(cacheDirectory), cacheKey).await() + saveCache(arrayOf(cacheDirectory), cacheKey) } return@async cacheDirectory } val wslConf by lazy { - coreGetInput("wsl-conf") + getInput("wsl-conf") } val setAsDefault = GlobalScope.async(start = LAZY) { - val input = coreGetInput("set-as-default", jso { + val input = getInput("set-as-default", jso { required = true }) @@ -223,24 +221,24 @@ val setAsDefault = GlobalScope.async(start = LAZY) { } val update by lazy { - coreGetBooleanInput("update", jso { + getBooleanInput("update", jso { required = true }) } val additionalPackages by lazy { - coreGetInput("additional-packages") + getInput("additional-packages") .split("""\s+""".toRegex()) .filterNot { it.isBlank() } .toTypedArray() } val wslShellUser by lazy { - coreGetInput("wsl-shell-user") + getInput("wsl-shell-user") } val wslShellCommand by lazy { - coreGetInput("wsl-shell-command") + getInput("wsl-shell-command") } val wslShellName by lazy { @@ -292,19 +290,19 @@ suspend fun main() { group("Write WSL Shell Wrapper", ::writeWslShellWrapper) } - coreSetOutput("wsl-shell-wrapper-path", wslShellWrapperPath) - coreSetOutput("wsl-shell-distribution-wrapper-path", wslShellDistributionWrapperPath) + setOutput("wsl-shell-wrapper-path", wslShellWrapperPath) + setOutput("wsl-shell-distribution-wrapper-path", wslShellDistributionWrapperPath) }.onFailure { - coreDebug(it.stackTraceToString()) - coreSetFailed(it.message ?: "$it") + debug(it.stackTraceToString()) + setFailed(it.message ?: "$it") } } suspend fun extractZip(archive: String): String { // work-around for https://github.com/actions/toolkit/issues/1319 val archiveZip = "$archive.zip" - ioMv(archive, archiveZip).await() - return toolCacheExtractZip(archiveZip).await() + mv(archive, archiveZip) + return toolCacheExtractZip(archiveZip) } suspend fun executeWslCommand( @@ -315,21 +313,21 @@ suspend fun executeWslCommand( exec( commandLine = "wsl", args = wslArguments - ).await() + ) } else if (wslconfigArguments != null) { exec( commandLine = "wslconfig", args = wslconfigArguments - ).await() + ) } } suspend fun group(name: String, fn: suspend () -> T): T { - coreStartGroup(name) + startGroup(name) try { return fn() } finally { - coreEndGroup() + endGroup() } } @@ -337,7 +335,7 @@ suspend fun verifyWindowsEnvironment() { check(process.platform == win32) { "platform '${process.platform}' is not supported by this action, please verify your 'runs-on' setting" } - check(ioWhich("wsl").await().isNotBlank() || ioWhich("wslconfig").await().isNotBlank()) { + check(which("wsl").isNotBlank() || which("wslconfig").isNotBlank()) { "This Windows environment does not have WSL enabled, please verify your 'runs-on' setting" } } @@ -352,7 +350,7 @@ suspend fun installDistribution() { options = jso { input = Buffer.from("") } - ).await() + ) } suspend fun createWslConf() { @@ -362,7 +360,7 @@ suspend fun createWslConf() { "--distribution", wslId(), "sh", "-c", "echo '$wslConf' >/etc/wsl.conf" ) - ).await() + ) executeWslCommand( wslArguments = arrayOf("--terminate", wslId()), wslconfigArguments = arrayOf("/terminate", wslId()) @@ -377,7 +375,7 @@ suspend fun setDistributionAsDefault() { } suspend fun writeWslShellWrapper() { - ioMkdirP(wslShellWrapperDirectory).await() + mkdirP(wslShellWrapperDirectory) val bashMissing = wslShellCommand.isEmpty() && (exec( @@ -392,7 +390,7 @@ suspend fun writeWslShellWrapper() { options = jso { ignoreReturnCode = true } - ).await() != 0) + ) != 0) if (wslShellUser.isNotEmpty()) { val wslShellUserExists = exec( @@ -407,7 +405,7 @@ suspend fun writeWslShellWrapper() { options = jso { ignoreReturnCode = true } - ).await() == 0 + ) == 0 if (!wslShellUserExists) { exec( commandLine = "wsl", @@ -420,17 +418,17 @@ suspend fun writeWslShellWrapper() { "4qBD5NWD3IkbU", wslShellUser ) - ).await() + ) } } val scriptContent = (if (bashMissing) """ - @ECHO ${if (coreIsDebug()) "ON" else "OFF"} + @ECHO ${if (isDebug()) "ON" else "OFF"} ECHO Bash is not available by default in '${distribution.userId}', please either add it to 'additional-packages' input or configure a different 'wsl-shell-command' >&2 EXIT /B 1 """ else """ - @ECHO ${if (coreIsDebug()) "ON" else "OFF"} + @ECHO ${if (isDebug()) "ON" else "OFF"} SETLOCAL @@ -505,10 +503,5 @@ suspend fun writeWslShellWrapper() { ) } - coreAddPath(wslShellWrapperDirectory) + addPath(wslShellWrapperDirectory) } - -suspend fun exists(path: PathLike) = accessAsync(path) - .then { true } - .catch { false } - .await() From 32af37a1275723d411409509145bd096e60d3694 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Tue, 7 Feb 2023 11:09:53 +0100 Subject: [PATCH 14/23] Show version when running Gradle builds --- .github/workflows/check-dependency-versions.main.kts | 2 +- .github/workflows/check-dependency-versions.yaml | 4 +++- .github/workflows/test.main.kts | 1 + .github/workflows/test.yaml | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/check-dependency-versions.main.kts b/.github/workflows/check-dependency-versions.main.kts index faa98c3d..0276fe8d 100755 --- a/.github/workflows/check-dependency-versions.main.kts +++ b/.github/workflows/check-dependency-versions.main.kts @@ -66,7 +66,7 @@ workflowWithCopyright( uses( name = "Check Dependency Versions", action = GradleCacheActionV1( - arguments = listOf("dependencyUpdates"), + arguments = listOf("--show-version", "dependencyUpdates"), debug = false, concurrent = true ) diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index e7752791..202d00fa 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -58,4 +58,6 @@ jobs: with: debug: false concurrent: true - arguments: dependencyUpdates + arguments: |- + --show-version + dependencyUpdates diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index f076a97f..9baa1c54 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -163,6 +163,7 @@ workflowWithCopyright( name = "Build", action = GradleCacheActionV1( arguments = listOf( + "--show-version", "build", "--info", "--stacktrace", diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 58c7944e..f8c78de1 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -61,6 +61,7 @@ jobs: debug: false concurrent: true arguments: |- + --show-version build --info --stacktrace From c2e1cac267da3be9e95243b9a3c64233ee051e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Tue, 7 Feb 2023 00:43:40 +0100 Subject: [PATCH 15/23] Apply refreshVersions only when called This is a work-around for https://github.com/jmfayard/refreshVersions/issues/667. --- .gitignore | 2 + gradle/build-logic/settings.gradle.kts | 6 +- .../conditional-refresh-versions.gradle.kts | 59 +++++++++++++++++++ .../gradle.properties | 17 ++++++ .../settings.gradle.kts | 44 ++++++++++++++ .../net/kautler/ExtensionConfiguration.kt | 42 +++++++++++++ ...ional-refresh-versions.settings.gradle.kts | 25 ++++++++ .../settings.gradle.kts | 6 +- ...ency-updates-report-aggregation.gradle.kts | 1 + gradle/libs.versions.toml | 2 + settings.gradle.kts | 6 +- 11 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 gradle/conditional-refresh-versions/conditional-refresh-versions.gradle.kts create mode 100644 gradle/conditional-refresh-versions/gradle.properties create mode 100644 gradle/conditional-refresh-versions/settings.gradle.kts create mode 100644 gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/ExtensionConfiguration.kt create mode 100644 gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/conditional-refresh-versions.settings.gradle.kts diff --git a/.gitignore b/.gitignore index d01689f0..fbdc97f6 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,8 @@ /build/ /gradle/build-logic/.gradle/ /gradle/build-logic/build/ +/gradle/conditional-refresh-versions/.gradle/ +/gradle/conditional-refresh-versions/build/ /gradle/dependency-updates-report-aggregation/.gradle/ /gradle/dependency-updates-report-aggregation/build/ /ncc-packer/build/ diff --git a/gradle/build-logic/settings.gradle.kts b/gradle/build-logic/settings.gradle.kts index b8eb9c95..65795b1c 100644 --- a/gradle/build-logic/settings.gradle.kts +++ b/gradle/build-logic/settings.gradle.kts @@ -15,10 +15,12 @@ */ import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES +import net.kautler.conditionalRefreshVersions import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS pluginManagement { includeBuild("../dependency-updates-report-aggregation") + includeBuild("../conditional-refresh-versions") repositories { mavenCentral() gradlePluginPortal() @@ -26,10 +28,10 @@ pluginManagement { } plugins { - id("de.fayard.refreshVersions") version "0.51.0" + id("net.kautler.conditional-refresh-versions") } -refreshVersions { +conditionalRefreshVersions { featureFlags { disable(GRADLE_UPDATES) } diff --git a/gradle/conditional-refresh-versions/conditional-refresh-versions.gradle.kts b/gradle/conditional-refresh-versions/conditional-refresh-versions.gradle.kts new file mode 100644 index 00000000..4d20a831 --- /dev/null +++ b/gradle/conditional-refresh-versions/conditional-refresh-versions.gradle.kts @@ -0,0 +1,59 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` + alias(libs.plugins.versions) + alias(libs.plugins.dependency.analysis) +} + +dependencies { + implementation(plugin(libs.plugins.refresh.versions)) +} + +dependencyAnalysis { + dependencies { + bundle("de.fayard.refreshVersions.gradle.plugin") { + includeDependency("de.fayard.refreshVersions:de.fayard.refreshVersions.gradle.plugin") + includeDependency("de.fayard.refreshVersions:refreshVersions") + includeDependency("de.fayard.refreshVersions:refreshVersions-core") + } + } + issues { + all { + onAny { + severity("fail") + } + } + } +} + +tasks.withType().configureEach { + kotlinOptions { + allWarningsAsErrors = true + } +} + +tasks.dependencyUpdates { + checkForGradleUpdate = false + checkConstraints = true +} + +fun plugin(plugin: Provider) = plugin.map { + "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" +} diff --git a/gradle/conditional-refresh-versions/gradle.properties b/gradle/conditional-refresh-versions/gradle.properties new file mode 100644 index 00000000..f5c5b07c --- /dev/null +++ b/gradle/conditional-refresh-versions/gradle.properties @@ -0,0 +1,17 @@ +# Copyright 2020-2023 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. + +org.gradle.caching = true + +dependency.analysis.print.build.health = true diff --git a/gradle/conditional-refresh-versions/settings.gradle.kts b/gradle/conditional-refresh-versions/settings.gradle.kts new file mode 100644 index 00000000..f1119042 --- /dev/null +++ b/gradle/conditional-refresh-versions/settings.gradle.kts @@ -0,0 +1,44 @@ +/* + * Copyright 2020-2023 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. + */ + +import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS + +pluginManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } +} + +dependencyResolutionManagement { + repositories { + mavenCentral() + gradlePluginPortal() + } + repositoriesMode.set(FAIL_ON_PROJECT_REPOS) + + versionCatalogs { + create("libs") { + from(files("../libs.versions.toml")) + } + } +} + +rootProject.name = "conditional-refresh-versions" +rootProject.buildFileName = "conditional-refresh-versions.gradle.kts" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") +enableFeaturePreview("STABLE_CONFIGURATION_CACHE") diff --git a/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/ExtensionConfiguration.kt b/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/ExtensionConfiguration.kt new file mode 100644 index 00000000..71d3e9d4 --- /dev/null +++ b/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/ExtensionConfiguration.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2020-2023 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 + +import de.fayard.refreshVersions.RefreshVersionsExtension +import org.gradle.api.initialization.Settings +import org.gradle.api.invocation.Gradle +import org.gradle.kotlin.dsl.refreshVersions + +inline fun Settings.onRefreshVersionsRequested(configure: Settings.() -> Unit) { + val rootBuild = gradle.parent == null + val startTaskNames = gradle.rootBuild.startParameter.taskNames + if ( + (rootBuild && (startTaskNames.contains(":refreshVersions") || startTaskNames.contains("refreshVersions"))) + || (!rootBuild && startTaskNames.contains(":${settings.rootProject.name}:refreshVersions")) + ) { + configure() + } +} + +inline fun Settings.conditionalRefreshVersions(configure: RefreshVersionsExtension.() -> Unit) { + onRefreshVersionsRequested { + refreshVersions(configure) + } +} + +val Gradle.rootBuild: Gradle + get() = if (gradle.parent == null) gradle else gradle.parent!!.rootBuild diff --git a/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/conditional-refresh-versions.settings.gradle.kts b/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/conditional-refresh-versions.settings.gradle.kts new file mode 100644 index 00000000..ea64a853 --- /dev/null +++ b/gradle/conditional-refresh-versions/src/main/kotlin/net/kautler/conditional-refresh-versions.settings.gradle.kts @@ -0,0 +1,25 @@ +/* + * Copyright 2020-2023 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 + +require(gradle.rootBuild.startParameter.taskNames.count { it.endsWith("refreshVersions") } <= 1) { + "Only one refreshVersions task can be executed per Gradle run" +} + +onRefreshVersionsRequested { + apply(plugin = "de.fayard.refreshVersions") +} diff --git a/gradle/dependency-updates-report-aggregation/settings.gradle.kts b/gradle/dependency-updates-report-aggregation/settings.gradle.kts index 23d35d37..d5cc56ab 100644 --- a/gradle/dependency-updates-report-aggregation/settings.gradle.kts +++ b/gradle/dependency-updates-report-aggregation/settings.gradle.kts @@ -15,9 +15,11 @@ */ import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES +import net.kautler.conditionalRefreshVersions import org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS pluginManagement { + includeBuild("../conditional-refresh-versions") repositories { mavenCentral() gradlePluginPortal() @@ -25,10 +27,10 @@ pluginManagement { } plugins { - id("de.fayard.refreshVersions") version "0.51.0" + id("net.kautler.conditional-refresh-versions") } -refreshVersions { +conditionalRefreshVersions { featureFlags { disable(GRADLE_UPDATES) } diff --git a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts index eec50677..e1df0b09 100644 --- a/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts +++ b/gradle/dependency-updates-report-aggregation/src/main/kotlin/net/kautler/dependency-updates-report-aggregation.gradle.kts @@ -78,6 +78,7 @@ if (gradle.parent == null && parent == null) { dependencies { includedBuildNames + .filterNot { it == "conditional-refresh-versions" } .forEach { dependencyUpdatesResults(":$it") } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6deba750..61064c63 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ build-github-api = "1.117" build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" build-gradle-plugin-grgit = "4.1.1" +build-gradle-plugin-refresh-versions = "0.51.0" build-gradle-plugin-release = "2.8.1" build-gradle-plugin-versions = "0.45.0" build-inject = "1" @@ -67,5 +68,6 @@ github = { id = "net.wooga.github", version.ref = "build-gradle-plugin-github" } grgit = { id = "org.ajoberstar.grgit", version.ref = "build-gradle-plugin-grgit" } kotlin-js = { id = "org.jetbrains.kotlin.js", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "build-kotlin" } +refresh-versions = { id = "de.fayard.refreshVersions", version.ref = "build-gradle-plugin-refresh-versions" } release = { id = "net.researchgate.release", version.ref = "build-gradle-plugin-release" } versions = { id = "com.github.ben-manes.versions", version.ref = "build-gradle-plugin-versions" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 4a17bca9..78948dcf 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,6 +15,7 @@ */ import de.fayard.refreshVersions.core.FeatureFlag.GRADLE_UPDATES +import net.kautler.conditionalRefreshVersions import org.gradle.api.initialization.resolve.RepositoriesMode.PREFER_SETTINGS pluginManagement { @@ -23,6 +24,7 @@ pluginManagement { } includeBuild("gradle/build-logic") + includeBuild("gradle/conditional-refresh-versions") repositories { mavenCentral() gradlePluginPortal() @@ -30,11 +32,11 @@ pluginManagement { } plugins { - id("de.fayard.refreshVersions") version "0.51.0" + id("net.kautler.conditional-refresh-versions") id("com.gradle.enterprise") version "3.12.3" } -refreshVersions { +conditionalRefreshVersions { featureFlags { disable(GRADLE_UPDATES) } From dfcd136dd43104d8023e2e2add903eed295b191b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 8 Feb 2023 01:02:51 +0100 Subject: [PATCH 16/23] Replace kotlinx-serialization and kaml by SnakeYAML kaml is very eager for a library when it comes to updating the required Kotlin version. This does not harmonize with the embedded Kotlin runtime in Gradle. Now pure SnakeYAML is used to read the actions file for getting the input defaults. --- gradle/build-logic/build-logic.gradle.kts | 5 +- .../kotlin/net/kautler/dao/action/Branding.kt | 25 ----- .../net/kautler/dao/action/GitHubAction.kt | 33 ++---- .../kotlin/net/kautler/dao/action/Input.kt | 15 +-- .../kotlin/net/kautler/dao/action/Output.kt | 35 ------ .../kautler/dao/action/OutputMapSerializer.kt | 82 -------------- .../kotlin/net/kautler/dao/action/Runs.kt | 106 ------------------ .../kotlin/net/kautler/dao/action/Step.kt | 47 -------- .../net/kautler/dependencies.gradle.kts | 2 - .../main/kotlin/net/kautler/node.gradle.kts | 20 ++-- gradle/libs.versions.toml | 4 +- 11 files changed, 26 insertions(+), 348 deletions(-) delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt delete mode 100644 gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts index c43ff91b..1dfcb6cf 100644 --- a/gradle/build-logic/build-logic.gradle.kts +++ b/gradle/build-logic/build-logic.gradle.kts @@ -18,7 +18,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { `kotlin-dsl` - alias(libs.plugins.kotlin.serialization) id(libs.plugins.convention.dependency.updates.report.aggregation.get().pluginId) alias(libs.plugins.dependency.analysis) } @@ -34,9 +33,7 @@ dependencies { implementation(":dependency-updates-report-aggregation") implementation(libs.build.inject) implementation(libs.build.github.api) - implementation(platform(libs.build.kotlinx.serialization.bom)) - implementation(libs.build.kotlinx.serialization.core) - implementation(libs.build.kaml) + implementation(libs.build.snakeyaml) implementation(embeddedKotlin("compiler-embeddable")) } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt deleted file mode 100644 index f5f4c0b4..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Branding.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020-2023 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.dao.action - -import kotlinx.serialization.Serializable - -@Serializable -data class Branding( - val color: String, - val icon: String? = null -) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt index aa65d9e5..59652530 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/GitHubAction.kt @@ -16,29 +16,12 @@ package net.kautler.dao.action -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.Serializable -import net.kautler.dao.action.Output.CompositeOutput -import net.kautler.dao.action.Output.NormalOutput - -@ExperimentalSerializationApi -@Serializable -data class GitHubAction( - val name: String, - val author: String? = null, - val description: String, - val inputs: Map? = null, - @Serializable(with = OutputMapSerializer::class) - val outputs: Map? = null, - val runs: Runs, - val branding: Branding? = null -) { - init { - require((runs.using == "composite") || (outputs.orEmpty().values.all { it is NormalOutput })) { - "Non-composite actions must only contain normal outputs" - } - require((runs.using != "composite") || (outputs.orEmpty().values.all { it is CompositeOutput })) { - "Composite actions must only contain composite outputs" - } - } +class GitHubAction { + var name: String? = null + var author: String? = null + var description: String? = null + var inputs: Map? = null + var outputs: Map? = null + var runs: Map? = null + var branding: Map? = null } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt index 8fffb9b7..a36f9514 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Input.kt @@ -16,12 +16,9 @@ package net.kautler.dao.action -import kotlinx.serialization.Serializable - -@Serializable -data class Input( - val description: String, - val required: Boolean = false, - val deprecationMessage: String? = null, - val default: String? = null -) +class Input { + var description: String? = null + var required: Boolean = false + var deprecationMessage: String? = null + var default: String? = null +} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt deleted file mode 100644 index c4ec5328..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Output.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2020-2023 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.dao.action - -import kotlinx.serialization.Serializable - -@Serializable -sealed class Output { - abstract val description: String - - @Serializable - data class NormalOutput( - override val description: String - ) : Output() - - @Serializable - data class CompositeOutput( - override val description: String, - val value: String - ) : Output() -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt deleted file mode 100644 index 9c92f5a0..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/OutputMapSerializer.kt +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2020-2023 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.dao.action - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlScalar -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.InternalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializer -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.descriptors.SerialKind.CONTEXTUAL -import kotlinx.serialization.descriptors.buildSerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import net.kautler.dao.action.Output.CompositeOutput -import net.kautler.dao.action.Output.NormalOutput - -@ExperimentalSerializationApi -@Serializer(forClass = Map::class) -class OutputMapSerializer( - private val keySerializer: KSerializer, - private val valueSerializer: KSerializer -) : KSerializer> { - @InternalSerializationApi - override val descriptor = - buildSerialDescriptor("net.kautler.dao.action.GitHubAction.outputs", CONTEXTUAL) - - override fun deserialize(decoder: Decoder): Map { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val compositeAction = context - .get("runs") - ?.get("using") - ?.content == "composite" - - val valueSerializer = - if (compositeAction) CompositeOutput.serializer() - else NormalOutput.serializer() - - return decoder.decodeSerializableValue(MapSerializer(keySerializer, valueSerializer)) - } - - override fun serialize(encoder: Encoder, value: Map) { - @Suppress("UNCHECKED_CAST") - when (value.values.asSequence().map { it::class }.distinct().count()) { - 0 -> encoder.encodeSerializableValue(MapSerializer(keySerializer, valueSerializer), value) - - 1 -> when (value.values.first()) { - is NormalOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, NormalOutput.serializer()), - value as Map - ) - - is CompositeOutput -> encoder.encodeSerializableValue( - MapSerializer(keySerializer, CompositeOutput.serializer()), - value as Map - ) - } - - else -> error("Output map must not contain normal and composite outputs at the same time") - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt deleted file mode 100644 index bb8d3546..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Runs.kt +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2020-2023 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.dao.action - -import com.charleskorn.kaml.YamlInput -import com.charleskorn.kaml.YamlMap -import com.charleskorn.kaml.YamlScalar -import kotlinx.serialization.EncodeDefault -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.KSerializer -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable -import kotlinx.serialization.Serializer -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder - -sealed class Runs { - abstract val using: String - - @Serializable - data class JavaScriptRuns( - override val using: String, - val main: String, - val pre: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val post: String? = null, - @SerialName("post-if") - val postIf: String? = null - ) : Runs() - - @Serializable - data class CompositeRuns( - val steps: List - ) : Runs() { - @ExperimentalSerializationApi - @EncodeDefault - override val using: String = "composite" - } - - @Serializable - data class DockerRuns( - @SerialName("pre-entrypoint") - val preEntrypoint: String? = null, - @SerialName("pre-if") - val preIf: String? = null, - val image: String, - val env: Map? = null, - val entrypoint: String? = null, - @SerialName("post-entrypoint") - val postEntrypoint: String? = null, - @SerialName("post-if") - val postIf: String? = null, - val args: List? = null - ) : Runs() { - @ExperimentalSerializationApi - @EncodeDefault - override val using: String = "docker" - } - - @ExperimentalSerializationApi - @Serializer(forClass = Runs::class) - companion object : KSerializer { - override fun deserialize(decoder: Decoder): Runs { - check(decoder is YamlInput) { "This class can only be loaded using kaml" } - - val context = decoder.node - check(context is YamlMap) { "Expected a YamlMap as current context" } - - val actionType = context - .get("runs") - ?.get("using") - ?.content - - val valueSerializer = when (actionType) { - "composite" -> CompositeRuns.serializer() - "docker" -> DockerRuns.serializer() - else -> JavaScriptRuns.serializer() - } - - return decoder.decodeSerializableValue(valueSerializer) - } - - override fun serialize(encoder: Encoder, value: Runs) { - when (value) { - is JavaScriptRuns -> encoder.encodeSerializableValue(JavaScriptRuns.serializer(), value) - is CompositeRuns -> encoder.encodeSerializableValue(CompositeRuns.serializer(), value) - is DockerRuns -> encoder.encodeSerializableValue(DockerRuns.serializer(), value) - } - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt b/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt deleted file mode 100644 index 4f77a4d1..00000000 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dao/action/Step.kt +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2020-2023 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.dao.action - -import kotlinx.serialization.SerialName -import kotlinx.serialization.Serializable - -@Serializable -data class Step( - val run: String? = null, - val shell: String? = null, - val uses: String? = null, - val with: Map? = null, - val name: String? = null, - val id: String? = null, - @SerialName("if") - val condition: String? = null, - val env: Map? = null, - @SerialName("working-directory") - val workingDirectory: String? = null -) { - init { - require((run == null) || (uses == null)) { - "'run' and 'uses' are mutually exclusive" - } - require((run != null) || (uses != null)) { - "one of 'run' or 'uses' is required" - } - require((run == null) || (shell != null)) { - "'shell' is required if 'run' is set" - } - } -} diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts index 3fa56646..9f39109c 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/dependencies.gradle.kts @@ -62,8 +62,6 @@ tasks.dependencyUpdates { dependsOn(validateGradleWrapperJar) ignoredDependencies { - // Should match the Kotlin version of Gradle as the serialization is used during the build - add(group = "org.jetbrains.kotlin.plugin.serialization", name = "org.jetbrains.kotlin.plugin.serialization.gradle.plugin") // This plugin should always be used without version as it is tightly // tied to the Gradle version that is building the precompiled script plugins add(group = "org.gradle.kotlin.kotlin-dsl", name = "org.gradle.kotlin.kotlin-dsl.gradle.plugin") 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 e64f1c48..cc908e69 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 @@ -16,16 +16,15 @@ package net.kautler -import com.charleskorn.kaml.Yaml -import kotlinx.serialization.ExperimentalSerializationApi +import java.security.MessageDigest +import kotlin.text.RegexOption.MULTILINE import net.kautler.dao.action.GitHubAction import net.kautler.util.npm import org.gradle.accessors.dm.LibrariesForLibs import org.jetbrains.kotlin.gradle.targets.js.dukat.IntegratedDukatTask import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import java.security.MessageDigest -import kotlin.text.RegexOption.MULTILINE +import org.yaml.snakeyaml.Yaml plugins { kotlin("js") @@ -48,13 +47,13 @@ tasks.withType().configureEach { } } -@ExperimentalSerializationApi val inputDefaultValues by lazy { - Yaml - .default - .decodeFromString(GitHubAction.serializer(), file("action.yml").readText()) + file("action.yml") + .inputStream() + .use { Yaml().loadAs(it, GitHubAction::class.java) } .inputs ?.filterValues { it.default != null } + ?.mapValues { it.value.default!! } ?.filterKeys { !System.getenv().containsKey("INPUT_${it.uppercase()}") } } @@ -65,11 +64,10 @@ tasks.withType().configureEach { environment("RUNNER_TEMP", "$temporaryDir/runner-temp") environment("RUNNER_TOOL_CACHE", toolCacheDir) - @OptIn(ExperimentalSerializationApi::class) - inputDefaultValues?.forEach { (name, input) -> + inputDefaultValues?.forEach { (name, default) -> environment( "INPUT_${name.uppercase()}", - if (name == "use-cache") "false" else input.default!! + if (name == "use-cache") "false" else default ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 61064c63..07baeead 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,10 +22,10 @@ build-gradle-plugin-refresh-versions = "0.51.0" build-gradle-plugin-release = "2.8.1" build-gradle-plugin-versions = "0.45.0" build-inject = "1" -build-kaml = "0.51.0" build-kotlin = "1.8.10" build-kotlinx-serialization = "1.4.1" build-node = "16.18.1" +build-snakeyaml = "1.33" build-vercel-ncc = "0.36.1" kotlin = "1.8.10" kotlin-wrappers = "1.0.0-pre.498" @@ -38,10 +38,10 @@ workflows-kotlin = "1.8.10" [libraries] build-github-api = { module = "org.kohsuke:github-api", version.ref = "build-github-api" } build-inject = { module = "javax.inject:javax.inject", version.ref = "build-inject" } -build-kaml = { module = "com.charleskorn.kaml:kaml", version.ref = "build-kaml" } build-kotlinx-serialization-bom = { module = "org.jetbrains.kotlinx:kotlinx-serialization-bom", version.ref = "build-kotlinx-serialization" } build-kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core" } build-kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json" } +build-snakeyaml = { module = "org.yaml:snakeyaml", version.ref = "build-snakeyaml" } build-vercel-ncc = { module = "vercel:ncc", version.ref = "build-vercel-ncc" } kotlin-wrapper-actions-toolkit = { module = "org.jetbrains.kotlin-wrappers:kotlin-actions-toolkit" } kotlin-wrapper-js = { module = "org.jetbrains.kotlin-wrappers:kotlin-js" } From d374368ce9baba8ed19806afe0f4bab5910c9d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Wed, 8 Feb 2023 02:04:48 +0100 Subject: [PATCH 17/23] Only execute safe actions locally --- .../main/kotlin/net/kautler/node.gradle.kts | 3 ++ .../github/action/setup_wsl/SetupWsl.kt | 44 ++++++++++--------- 2 files changed, 27 insertions(+), 20 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 cc908e69..3541d9c1 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 @@ -61,6 +61,9 @@ val inputDefaultValues by lazy { tasks.withType().configureEach { val toolCacheDir = "$temporaryDir/tool-cache" + // only execute safe actions that do not change the execution environment + environment("INPUT_ONLY_SAFE_ACTIONS", true) + environment("RUNNER_TEMP", "$temporaryDir/runner-temp") environment("RUNNER_TOOL_CACHE", toolCacheDir) diff --git a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt index ca8f4418..54439ae0 100644 --- a/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt +++ b/src/main/kotlin/net/kautler/github/action/setup_wsl/SetupWsl.kt @@ -263,31 +263,35 @@ suspend fun main() { runCatching { group("Verify Windows Environment", ::verifyWindowsEnvironment) - if (installationNeeded()) { - group("Install Distribution", ::installDistribution) - } + if (getInput("only safe actions").isEmpty() + || !getBooleanInput("only safe actions") + ) { + if (installationNeeded()) { + group("Install Distribution", ::installDistribution) + } - if (wslConf.isNotEmpty()) { - group("Create /etc/wsl.conf", ::createWslConf) - } + if (wslConf.isNotEmpty()) { + group("Create /etc/wsl.conf", ::createWslConf) + } - if (setAsDefault()) { - group("Set Distribution as Default", ::setDistributionAsDefault) - } + if (setAsDefault()) { + group("Set Distribution as Default", ::setDistributionAsDefault) + } - if (update) { - group("Update Distribution", distribution::update) - } + if (update) { + group("Update Distribution", distribution::update) + } - if (additionalPackages.isNotEmpty()) { - group("Install Additional Packages", suspend { distribution.install(*additionalPackages) }) - } + if (additionalPackages.isNotEmpty()) { + group("Install Additional Packages", suspend { distribution.install(*additionalPackages) }) + } - if (wslShellCommand.isNotEmpty() - || !exists(wslShellWrapperPath) - || !exists(wslShellDistributionWrapperPath) - ) { - group("Write WSL Shell Wrapper", ::writeWslShellWrapper) + if (wslShellCommand.isNotEmpty() + || !exists(wslShellWrapperPath) + || !exists(wslShellDistributionWrapperPath) + ) { + group("Write WSL Shell Wrapper", ::writeWslShellWrapper) + } } setOutput("wsl-shell-wrapper-path", wslShellWrapperPath) From aadcf83883aec4e305dd459d28941841a167b4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Thu, 9 Feb 2023 21:28:58 +0100 Subject: [PATCH 18/23] Remove usage of Dukat Dukat results are still very suboptimal and in Kotlin 1.8.20-Beta it was disabled. As most usages were already replaced by kotlin-wrappers or self-written class, now the last remaining three classes are hand-written too and Dukat is not necessary, including the massive post-processing just to make it compile. This will save the time for running Dukat, for doing the post processing, and for compiling quite some unncessary classes. If Dukat is improved and added back to the Gradle plugin integration, this decision can be reconsidered, but for now it saves much time and is better future proof in the light of 1.8.20-Beta. --- .../kotlin/net/kautler/ncc_packer.gradle.kts | 2 +- .../main/kotlin/net/kautler/node.gradle.kts | 129 +--------- .../util/DependencyHandlerExtension.kt | 6 +- gradle/libs.versions.toml | 3 - kotlin-js-store/yarn.lock | 13 - resources/dukat-cli-0.0.12.js | 203 ---------------- resources/dukat-cli-0.5.7.js | 223 ------------------ src/main/kotlin/NullWritable.kt | 21 ++ src/main/kotlin/SemVer.kt | 19 ++ 9 files changed, 44 insertions(+), 575 deletions(-) delete mode 100644 resources/dukat-cli-0.0.12.js delete mode 100644 resources/dukat-cli-0.5.7.js create mode 100644 src/main/kotlin/NullWritable.kt create mode 100644 src/main/kotlin/SemVer.kt 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 c2b14553..c4d1e9b7 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 @@ -85,5 +85,5 @@ dependencies { implementation(platform(libs.kotlin.wrappers.bom)) implementation(libs.kotlin.wrapper.js) implementation(libs.kotlin.wrapper.node) - implementation(npm(libs.build.vercel.ncc, generateExternals = false)) + implementation(npm(libs.build.vercel.ncc)) } 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 3541d9c1..e1326ea2 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 @@ -16,12 +16,9 @@ package net.kautler -import java.security.MessageDigest -import kotlin.text.RegexOption.MULTILINE import net.kautler.dao.action.GitHubAction import net.kautler.util.npm import org.gradle.accessors.dm.LibrariesForLibs -import org.jetbrains.kotlin.gradle.targets.js.dukat.IntegratedDukatTask import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsExec import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension import org.yaml.snakeyaml.Yaml @@ -83,50 +80,6 @@ val libs = the() configure { nodeVersion = libs.versions.build.node.get() - versions.dukat.version = libs.versions.build.dukat.get() - - // work-around for https://github.com/Kotlin/dukat/issues/103 - npmInstallTaskProvider!!.configure { - val patchedDukat0012CliJs = layout - .projectDirectory - .file("resources/dukat-cli-0.0.12.js") - - val patchedDukat057CliJs = layout - .projectDirectory - .file("resources/dukat-cli-0.5.7.js") - - inputs - .files(patchedDukat0012CliJs, patchedDukat057CliJs) - .withPropertyName("patched dukat-cli.js files") - - doLast { - val dukatCliJs = rootPackageDir.resolve("node_modules/dukat/bin/dukat-cli.js") - - if (dukatCliJs.exists()) { - val sha256 = MessageDigest - .getInstance("SHA-256") - .digest(dukatCliJs.readBytes()) - .joinToString("") { "%02x".format(it) } - - when (sha256) { - // already a patched version - "32b7c91ecf8c94b8f1e554da870a617437e421db07e40d558dbb959bd221cb5e", - "e16d684be9b90c2d5d78f90077dc9690253fd4d7bc6b48f94bbd48b1692bf2d5" -> - return@doLast - - // original 0.0.12 version - "ceebdfbb94d103eb44da265b572e51fb69ff4bb1c524b94f621c6a6e94716ac8" -> - patchedDukat0012CliJs.asFile.copyTo(dukatCliJs, overwrite = true) - - // original 0.5.7 version - "12645e1491b68638d2c1c4146502ae9ed5037baa82cc12e6c55070471d962187" -> - patchedDukat057CliJs.asFile.copyTo(dukatCliJs, overwrite = true) - - else -> throw RuntimeException("dukat-cli.js has unexpected checksum $sha256") - } - } - } - } } dependencies { @@ -135,94 +88,14 @@ dependencies { implementation(libs.kotlin.wrapper.actions.toolkit) implementation(libs.kotlin.wrapper.js) implementation(libs.kotlin.wrapper.node) - implementation(npm(libs.types.semver)) - implementation(npm(libs.semver, generateExternals = false)) + implementation(npm(libs.semver)) implementation(npm(libs.nullWritable)) } -tasks.withType(IntegratedDukatTask::class).configureEach { - doLast { - // work-around for https://github.com/Kotlin/dukat/issues/397 - deleteExternalsFiles( - this, - "*.module_node.kt", - "*.nonDeclarations.kt" - ) - fixExternalsFiles( - this, - "lib.dom.kt" to listOf( - """\Qimport url.URL as _URL\E$""" to "import node.url.URL as _URL", - """\Qimport url.URLSearchParams as _URLSearchParams\E$""" to "import node.url.URLSearchParams as _URLSearchParams", - """\Qoverride fun addEventListener(type: String, listener: EventListenerObject\E""" to "fun addEventListener(type: String, listener: EventListenerObject", - """\Qoverride fun removeEventListener(type: String, callback: EventListenerObject\E""" to "fun removeEventListener(type: String, callback: EventListenerObject", - """\Q`T$19`\E""" to """`T\$19`""" - ), - // work-around for https://github.com/Kotlin/dukat/issues/402 - "lib.es2018.asynciterable.module_dukat.kt" to listOf( - """\Qval `return`: ((value: TReturn) -> Promise | IteratorReturnResult */>)?\E$""" to "val `return`: ((value: dynamic) -> Promise | IteratorReturnResult */>)?", - """\Qval `return`: ((value: PromiseLike) -> Promise | IteratorReturnResult */>)?\E\r?\n\Q get() = definedExternally\E\r?\n""" to "" - ), - "lib.es2020.bigint.module_dukat.kt" to listOf( - """\Q : RelativeIndexable\E""" to "" - ), - "lib.es5.kt" to listOf( - """\Qimport NodeJS.CallSite\E$""" to "import node.CallSite", - """\Qval resolve: ((specified: String, parent: URL) -> Promise)?\E$""" to "val resolve2: ((specified: String, parent: URL) -> Promise)?" - ), - // work-around for https://github.com/Kotlin/dukat/issues/401 - "null-writable.module_null-writable.kt" to listOf( - """\Qimport stream.internal.`T$17`\E$""" to "", - """\Qimport stream.internal.Writable\E$""" to "import node.stream.Writable", - """\Qoverride fun _write(_chunk: Any, _encoding: String, callback: (error: Error?) -> Unit)\E$""" to "override fun _write(chunk: Any, encoding: node.buffer.BufferEncoding, callback: (error: Error?) -> Unit)", - """\Qopen fun _writev(_chunks: Array<`T$3`>, callback: (error: Error?) -> Unit)\E$""" to "", - """\Qoverride fun _writev(chunks: Array<`T$17`>, callback: (error: Error?) -> Unit)\E$""" to "" - ), - "semver.module_semver.kt" to listOf( - """\Q@JsModule("semver")\E$""" to """@JsModule("semver/classes/semver")""" - ) - ) - } -} - tasks.assemble { dependsOn(project(":ncc-packer").tasks.named("nodeProductionRun")) } -fun deleteExternalsFiles(task: Task, vararg files: String) { - if (files.isNotEmpty()) { - task - .outputs - .files - .asFileTree - .matching { - for (file in files) { - include("**/$file") - } - } - .forEach { it.delete() } - } -} - -fun fixExternalsFiles(task: Task, vararg pairs: Pair>>) { - for ((file, fixups) in pairs) { - task - .outputs - .files - .asFileTree - .matching { include("**/$file") } - .singleFile - .apply { - writeText( - fixups - .map { (pattern, replacement) -> pattern.toRegex(MULTILINE) to replacement } - .fold(readText()) { current, (regex, replacement) -> - regex.replace(current, replacement) - } - ) - } - } -} - fun plugin(plugin: Provider) = plugin.map { "${it.pluginId}:${it.pluginId}.gradle.plugin:${it.version.requiredVersion}" } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt index 6bfc035b..c1b6297b 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/DependencyHandlerExtension.kt @@ -23,13 +23,11 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependencyExtension fun DependencyHandler.npm( - dependency: Provider, - generateExternals: Boolean = true + dependency: Provider ): NpmDependency { val dep = dependency.get() return (extensions.getByName("npm") as NpmDependencyExtension)( name = if (dep.group == "") dep.name else "@${dep.group}/${dep.name}", - version = dep.version!!, - generateExternals = generateExternals + version = dep.version!! ) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 07baeead..c7875eff 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,6 @@ # limitations under the License. [versions] -build-dukat = "0.5.7" build-github-api = "1.117" build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" @@ -32,7 +31,6 @@ kotlin-wrappers = "1.0.0-pre.498" kotlinx-coroutines = "1.6.4" nullWritable = "1.0.5" semver = "7.3.8" -types-semver = "7.3.13" workflows-kotlin = "1.8.10" [libraries] @@ -50,7 +48,6 @@ kotlin-wrappers-bom = { module = "org.jetbrains.kotlin-wrappers:kotlin-wrappers- kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines" } nullWritable = { module = ":null-writable", version.ref = "nullWritable" } semver = { module = ":semver", version.ref = "semver" } -types-semver = { module = "types:semver", version.ref = "types-semver" } workflows-kotlin-compiler = { module = "org.jetbrains.kotlin:kotlin-compiler", 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" } diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 11819f76..a94a884f 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -210,11 +210,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.13.0.tgz#0400d1e6ce87e9d3032c19eb6c58205b0d3f7850" integrity sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg== -"@types/semver@7.3.13": - version "7.3.13" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.3.13.tgz#da4bfd73f49bd541d28920ab0e2bf0ee80f71c91" - integrity sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw== - "@types/tunnel@^0.0.3": version "0.0.3" resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" @@ -399,14 +394,6 @@ diff@5.0.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== -dukat@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.7.tgz#4b3981f3fbde993546cc6f674b9027923f7293c6" - integrity sha512-PBM+B1oIE/aHbcrtdqX8yHfwdfdJ5ejJzkbU2LOW7bbAC3r1EcEyrS9ytFdHMPv06gVkF2QO77zGcMbGcsmXaA== - dependencies: - google-protobuf "3.12.2" - typescript "3.9.5" - dukat@0.5.8-rc.4: version "0.5.8-rc.4" resolved "https://registry.yarnpkg.com/dukat/-/dukat-0.5.8-rc.4.tgz#90384dcb50b14c26f0e99dae92b2dea44f5fce21" diff --git a/resources/dukat-cli-0.0.12.js b/resources/dukat-cli-0.0.12.js deleted file mode 100644 index f96e251f..00000000 --- a/resources/dukat-cli-0.0.12.js +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/env node - -var execSync = require('child_process').execSync; -var spawn = require('child_process').spawn; -var path = require('path'); -var fs = require('fs'); - -var createBundle = require("../lib/converter").createBundle; -var Readable = require('stream').Readable; -var EventEmitter = require('events'); - -var printError = function (errorMessage) { - if (typeof errorMessage !== "string") { - console.error("ERROR:"); - console.error(errorMessage) - } else { - console.error("ERROR: " + errorMessage); - } -}; - -function run(command, args) { - var child = spawn(command, args); - process.stdin.pipe(child.stdin); - - child.stdout.pipe(process.stdout); - child.stderr.pipe(process.stderr); - - return child; -} - -function printInvalidJavaHome() { - printError("Your \"JAVA_HOME\" environment variable points to an invalid directory."); - printError("As of now \"dukat\" requires Java Runtime Environment to be installed."); - printError("Either set \"JAVA_HOME\" to a proper Java installation,"); - printError("or make sure \"java\" is callable from commandline and unset \"JAVA_HOME\"."); -} - -function printNoJava() { - printError("\"java\" is not callable from commandline and no \"JAVA_HOME\" environment variable is set."); - printError("As of now \"dukat\" requires Java Runtime Environment to be installed."); - printError("Either set \"JAVA_HOME\" to a proper Java installation,"); - printError("or make sure \"java\" is callable from commandline."); -} - -function findJavaExecutable() { - var javaHome = process.env.JAVA_HOME - var result = javaHome ? path.join(javaHome, "bin", "java") : "java" - try { - execSync('"' + result + "\" -version", { - stdio: ['pipe', 'ignore', 'pipe'] - }); - } catch (error) { - printError(error) - if (javaHome) { - printInvalidJavaHome(); - } else { - printNoJava(); - } - process.exit(1); - } - return result -} - -function createReadable() { - var readable = new Readable(); - readable._read = function(chunk) {}; - - return readable -} - -function getStdLib() { - return path.resolve(__dirname, "..", "d.ts.libs/lib.es6.d.ts"); -} - -function processArgs(args) { - var skip_2args = new Set(["-d", "-p", "-m", "-r"]); - var ordinary_args = new Set(["--descriptors"]); - var count = 0; - - var binaryOutput = null; - var stdlib = getStdLib(); - - while (count < args.length) { - var arg = args[count]; - if(arg == "-b") { - binaryOutput = args[count + 1]; - count += 2; - } else if(arg == "-l") { - stdlib = args[count + 1]; - count += 2; - } else if (skip_2args.has(arg)) { - count += 2; - } else if (ordinary_args.has(arg)) { - count++; - } else { - break; - } - } - - var files = []; - if (count < args.length) { - files = args.slice(count).map(function(arg) { - return path.resolve(arg); - }); - } - - var res = { - stdlib: stdlib, - binaryOutput: binaryOutput, - files: files - }; - - return res; -} - -function endsWith(str, postfix) { - return str.lastIndexOf(postfix) == (str.length - postfix.length); -} - - -function createBinaryStream(stdlib, files, onData, onEnd) { - var bundle = createBundle(stdlib, files); - - var readable = createReadable(); - - if (typeof onData == "function") { - readable.on("data", onData); - } - - if (typeof onEnd == "function") { - readable.on("end", onEnd); - } - - readable.push(bundle.serializeBinary()); - readable.push(null); - - return readable; -} - -function cliMode(args) { - var packageDir = path.resolve(__dirname, ".."); - - if (args[0] == "-v" || args[0] == "version") { - var version = require(path.resolve(packageDir, "package.json")).version; - console.log("dukat version " + version); - return; - } - - var runtimePath = path.resolve(packageDir, "build/runtime"); - var jsPath = path.resolve(runtimePath, "js.jar"); - var cliPath = path.resolve(runtimePath, "dukat-cli.jar"); - var classPath = [jsPath, cliPath].join(path.delimiter); - - var java = findJavaExecutable(); - - var argsProcessed = processArgs(args); - - var files = argsProcessed.files; - var is_ts = files.every(function(file) { return endsWith(file, ".d.ts")}); - var is_idl = files.every(function(file) { return endsWith(file, ".idl") || endsWith(file, ".webidl")}); - - if (is_ts) { - var inputStream = createBinaryStream(argsProcessed.stdlib, files); - - if (typeof argsProcessed.binaryOutput == "string") { - inputStream.pipe(fs.createWriteStream(argsProcessed.binaryOutput)); - return null; - } - - var commandArgs = [ - "-Ddukat.cli.internal.packagedir=" + packageDir, - "-cp", classPath, "org.jetbrains.dukat.cli.CliKt"].concat(args); - - var dukatProcess = run(java, commandArgs); - inputStream.pipe(dukatProcess.stdin); - return dukatProcess; - } else if (is_idl) { - var commandArgs = [ - "-Ddukat.cli.internal.packagedir=" + packageDir, - "-cp", classPath, "org.jetbrains.dukat.cli.CliKt"].concat(args); - - return run(java, commandArgs); - } - - process.exit(1); -} - -var main = function (args) { - var childProcess = cliMode(args); - if (childProcess instanceof EventEmitter) { - childProcess.on("exit", function() { - process.exit(); - }); - } -}; - -if (require.main === module) { - main(process.argv.slice(2)); -} - -exports.translate = main; -exports.createBinaryStream = createBinaryStream; -exports.getStdLib = getStdLib; \ No newline at end of file diff --git a/resources/dukat-cli-0.5.7.js b/resources/dukat-cli-0.5.7.js deleted file mode 100644 index 824f686f..00000000 --- a/resources/dukat-cli-0.5.7.js +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env node - -var execSync = require('child_process').execSync; -var spawn = require('child_process').spawn; -var path = require('path'); -var fs = require('fs'); - -var createSourceSet = require("../lib/converter").createSourceSet; -var Readable = require('stream').Readable; -var EventEmitter = require('events'); - -var printError = function (errorMessage) { - if (typeof errorMessage !== "string") { - console.error("ERROR:"); - console.error(errorMessage) - } else { - console.error("ERROR: " + errorMessage); - } -}; - -function run(command, args) { - var child = spawn(command, args); - process.stdin.pipe(child.stdin); - - child.stdout.pipe(process.stdout); - child.stderr.pipe(process.stderr); - - return child; -} - -function printInvalidJavaHome() { - printError("Your \"JAVA_HOME\" environment variable points to an invalid directory."); - printError("As of now \"dukat\" requires Java Runtime Environment to be installed."); - printError("Either set \"JAVA_HOME\" to a proper Java installation,"); - printError("or make sure \"java\" is callable from commandline and unset \"JAVA_HOME\"."); -} - -function printNoJava() { - printError("\"java\" is not callable from commandline and no \"JAVA_HOME\" environment variable is set."); - printError("As of now \"dukat\" requires Java Runtime Environment to be installed."); - printError("Either set \"JAVA_HOME\" to a proper Java installation,"); - printError("or make sure \"java\" is callable from commandline."); -} - -function findJavaExecutable() { - var javaHome = process.env.JAVA_HOME - var result = javaHome ? path.join(javaHome, "bin", "java") : "java" - try { - execSync('"' + result + "\" -version", { - stdio: ['pipe', 'ignore', 'pipe'] - }); - } catch (error) { - printError(error) - if (javaHome) { - printInvalidJavaHome(); - } else { - printNoJava(); - } - process.exit(1); - } - return result -} - -function createReadable() { - var readable = new Readable(); - readable._read = function(chunk) {}; - - return readable -} - -function getStdLib() { - return path.resolve(__dirname, "..", "d.ts.libs/lib.es6.d.ts"); -} - -function processArgs(args) { - var skip_2args = new Set(["-d", "-p", "-m", "-r"]); - var ordinary_args = new Set(["--descriptors"]); - var count = 0; - - var binaryOutput = null; - var stdlib = getStdLib(); - var tsConfig = null; - - while (count < args.length) { - var arg = args[count]; - if (arg == "-b") { - binaryOutput = args[count + 1]; - count += 2; - } else if (arg == "--ts-config") { - tsConfig = args[count + 1]; - count += 2; - } else if(arg == "-l") { - stdlib = args[count + 1]; - count += 2; - } else if (skip_2args.has(arg)) { - count += 2; - } else if (ordinary_args.has(arg)) { - count++; - } else { - break; - } - } - - var files = []; - if (count < args.length) { - files = args.slice(count).map(function(arg) { - return path.resolve(arg); - }); - } - - return { - stdlib: stdlib, - binaryOutput: binaryOutput, - files: files, - tsConfig: tsConfig - }; -} - -function endsWith(str, postfix) { - return str.lastIndexOf(postfix) == (str.length - postfix.length); -} - - - -function createBinary(tsConfig, stdlib, emitDiagnostics, files) { - return createSourceSet(tsConfig, stdlib, emitDiagnostics, files); -} - -function createReadableStream(binary, onData, onEnd) { - var readable = createReadable(); - - if (typeof onData == "function") { - readable.on("data", onData); - } - - if (typeof onEnd == "function") { - readable.on("end", onEnd); - } - - readable.push(binary.serializeBinary()); - readable.push(null); - - return readable; -} - -function cliMode(args) { - var packageDir = path.resolve(__dirname, ".."); - - if (args[0] == "-v" || args[0] == "version") { - var version = require(path.resolve(packageDir, "package.json")).version; - console.log("dukat version " + version); - return; - } - - var runtimePath = path.resolve(packageDir, "build/runtime"); - var cliPath = path.resolve(runtimePath, "dukat-cli.jar"); - var classPath = [cliPath].join(path.delimiter); - - var java = findJavaExecutable(); - - var argsProcessed = processArgs(args); - - var files = argsProcessed.files; - var is_ts = files.every(function(file) { return endsWith(file, ".d.ts") || endsWith(file, ".ts")}); - var is_idl = files.every(function(file) { return endsWith(file, ".idl") || endsWith(file, ".webidl")}); - var is_js = files.every(function(file) { return endsWith(file, ".js")}); - - if (is_ts || is_js) { - try { - let bundle = createBinary(argsProcessed.tsConfig, argsProcessed.stdlib, false, files); - - var inputStream = createReadableStream(bundle); - - if (typeof argsProcessed.binaryOutput == "string") { - inputStream.pipe(fs.createWriteStream(argsProcessed.binaryOutput)); - return null; - } - - var commandArgs = [ - "-Ddukat.cli.internal.packagedir=" + packageDir, - "-cp", classPath, "org.jetbrains.dukat.cli.CliKt"].concat(args); - - var dukatProcess = run(java, commandArgs); - inputStream.pipe(dukatProcess.stdin); - return dukatProcess; - } catch (e) { - if (e.hasOwnProperty("tsDiagnostic")) { - console.log(`failed to parse tsconfig: ${argsProcessed.tsConfig}`); - } else { - console.log("unresolved exception"); - } - console.log(e); - process.exit(1); - } - - } else if (is_idl) { - var commandArgs = [ - "-Ddukat.cli.internal.packagedir=" + packageDir, - "-cp", classPath, "org.jetbrains.dukat.cli.CliKt"].concat(args); - - return run(java, commandArgs); - } - - process.exit(1); -} - -var main = function (args) { - var childProcess = cliMode(args); - if (childProcess instanceof EventEmitter) { - childProcess.on("exit", function() { - process.exit(); - }); - } -}; - -if (require.main === module) { - main(process.argv.slice(2)); -} - -exports.translate = main; -exports.createBinary = createBinary; -exports.createReadableStream = createReadableStream; -exports.getStdLib = getStdLib; \ No newline at end of file diff --git a/src/main/kotlin/NullWritable.kt b/src/main/kotlin/NullWritable.kt new file mode 100644 index 00000000..98fa7158 --- /dev/null +++ b/src/main/kotlin/NullWritable.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2020-2023 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:JsModule("null-writable") + +import node.stream.Writable + +external class NullWritable : Writable diff --git a/src/main/kotlin/SemVer.kt b/src/main/kotlin/SemVer.kt new file mode 100644 index 00000000..e1406d7b --- /dev/null +++ b/src/main/kotlin/SemVer.kt @@ -0,0 +1,19 @@ +/* + * Copyright 2020-2023 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. + */ + +@JsModule("semver/classes/semver") +external class SemVer(version: String, options: RangeOptions) +external interface RangeOptions From 1f755447444549ba709cf71b7875e252fd9a45d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 10 Feb 2023 17:06:40 +0100 Subject: [PATCH 19/23] Update github-api to 1.313 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c7875eff..279922d5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ # limitations under the License. [versions] -build-github-api = "1.117" +build-github-api = "1.313" build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" build-gradle-plugin-grgit = "4.1.1" From 9d8be63017f36c1427cae02ffd9b75e724b936cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sat, 11 Feb 2023 19:20:42 +0100 Subject: [PATCH 20/23] Update grgit to 5.0.0 and use the new service plugin --- gradle/build-logic/build-logic.gradle.kts | 5 +- .../kotlin/net/kautler/publishing.gradle.kts | 65 ++++++++++++++----- gradle/libs.versions.toml | 4 +- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts index 1dfcb6cf..7e138c5e 100644 --- a/gradle/build-logic/build-logic.gradle.kts +++ b/gradle/build-logic/build-logic.gradle.kts @@ -67,8 +67,9 @@ dependencyAnalysis { includeDependency("net.wooga.github:net.wooga.github.gradle.plugin") includeDependency("gradle.plugin.net.wooga.gradle:atlas-github") } - bundle("org.ajoberstar.grgit.gradle.plugin") { - includeDependency("org.ajoberstar.grgit:org.ajoberstar.grgit.gradle.plugin") + bundle("org.ajoberstar.grgit.service.gradle.plugin") { + includeDependency("org.ajoberstar.grgit.service:org.ajoberstar.grgit.service.gradle.plugin") + includeDependency("org.ajoberstar.grgit:grgit-gradle") includeDependency("org.ajoberstar.grgit:grgit-core") } bundle("org.jetbrains.kotlin.js.gradle.plugin") { diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts index ae69eaf9..5d8ea714 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts @@ -49,7 +49,7 @@ import kotlin.LazyThreadSafetyMode.NONE plugins { // needed for accessing majorVersion id("net.kautler.dependencies") - id("org.ajoberstar.grgit") + id("org.ajoberstar.grgit.service") id("net.wooga.github") } @@ -72,7 +72,10 @@ release { } val githubRepositoryName by lazy(NONE) { - grgit + grgitService + .service + .get() + .grgit .remote .list() .find { it.name == "origin" } @@ -105,14 +108,23 @@ internal val github by lazy(NONE) { } val releaseBody by lazy(NONE) { - val releaseBody = grgit.log { - includes.add(release.git.requireBranch) - github.getRepository(githubRepositoryName).latestRelease?.apply { excludes.add(tagName) } - }.filter { commit -> - !commit.shortMessage.startsWith("[Gradle Release Plugin] ") - }.asReversed().joinToString("\n") { commit -> - "- ${commit.shortMessage} [${commit.id}]" - } + val releaseBody = grgitService + .service + .get() + .grgit + .log { + includes.add(release.git.requireBranch) + github.getRepository(githubRepositoryName).latestRelease?.apply { + excludes.add(tagName) + } + } + .filter { commit -> + !commit.shortMessage.startsWith("[Gradle Release Plugin] ") + } + .asReversed() + .joinToString("\n") { commit -> + "- ${commit.shortMessage} [${commit.id}]" + } if (isHeadless()) { return@lazy releaseBody @@ -166,12 +178,18 @@ val releaseVersion get() = !"$version".endsWith("-SNAPSHOT") val removeDistributionsFromGit by tasks.registering { mustRunAfter(tasks.checkoutMergeFromReleaseBranch) + // work-around for https://github.com/ajoberstar/grgit/pull/382 + //usesService(grgitService.service) doLast("Remove distributions from Git") { - grgit.remove { - cached = true - patterns = setOf("build/distributions") - } + grgitService + .service + .get() + .grgit + .remove { + cached = true + patterns = setOf("build/distributions") + } } } tasks.updateVersion { @@ -210,6 +228,8 @@ tasks.withType().configureEach { } tasks.githubPublish { + // work-around for https://github.com/ajoberstar/grgit/pull/382 + //usesService(grgitService.service) body { releaseBody } draft(true) } @@ -220,6 +240,8 @@ val undraftGithubRelease by tasks.registering(GithubPublish::class) { val finishMilestone by tasks.registering { enabled = releaseVersion + // work-around for https://github.com/ajoberstar/grgit/pull/382 + //usesService(grgitService.service) doLast("finish milestone") { github.getRepository(githubRepositoryName)!!.apply { @@ -237,15 +259,21 @@ val finishMilestone by tasks.registering { val addDistributionsToGit by tasks.registering { dependsOn(tasks.named("assemble")) + // work-around for https://github.com/ajoberstar/grgit/pull/382 + //usesService(grgitService.service) doLast("Add distributions to Git") { val gitIgnore = file(".gitignore") val gitIgnoreBak = file(".gitignore.bak") gitIgnore.renameTo(gitIgnoreBak) try { - grgit.add { - patterns = setOf("build/distributions") - } + grgitService + .service + .get() + .grgit + .add { + patterns = setOf("build/distributions") + } } finally { gitIgnoreBak.renameTo(gitIgnore) } @@ -285,6 +313,9 @@ tasks.updateVersion { } val checkBranchProtectionCompatibility by tasks.registering { + // work-around for https://github.com/ajoberstar/grgit/pull/382 + //usesService(grgitService.service) + doLast { check( !github diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 279922d5..b7af9a72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ build-github-api = "1.313" build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "1.4.0" -build-gradle-plugin-grgit = "4.1.1" +build-gradle-plugin-grgit = "5.0.0" build-gradle-plugin-refresh-versions = "0.51.0" build-gradle-plugin-release = "2.8.1" build-gradle-plugin-versions = "0.45.0" @@ -62,7 +62,7 @@ convention-publishing = { id = "net.kautler.publishing", version = "?" } convention-readme = { id = "net.kautler.readme", version = "?" } dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "build-gradle-plugin-dependency-analysis" } github = { id = "net.wooga.github", version.ref = "build-gradle-plugin-github" } -grgit = { id = "org.ajoberstar.grgit", version.ref = "build-gradle-plugin-grgit" } +grgit = { id = "org.ajoberstar.grgit.service", version.ref = "build-gradle-plugin-grgit" } kotlin-js = { id = "org.jetbrains.kotlin.js", version.ref = "kotlin" } kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "build-kotlin" } refresh-versions = { id = "de.fayard.refreshVersions", version.ref = "build-gradle-plugin-refresh-versions" } From f594319221b1d32ac3181c0a51fe996c797e4078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sun, 12 Feb 2023 20:28:11 +0100 Subject: [PATCH 21/23] Update net.wooga.github plugin to 3.0.0 --- gradle/build-logic/build-logic.gradle.kts | 2 +- .../kotlin/net/kautler/publishing.gradle.kts | 194 ++++++++---------- .../kotlin/net/kautler/util/Properties.kt | 6 +- gradle/libs.versions.toml | 2 +- 4 files changed, 91 insertions(+), 113 deletions(-) diff --git a/gradle/build-logic/build-logic.gradle.kts b/gradle/build-logic/build-logic.gradle.kts index 7e138c5e..4233ac29 100644 --- a/gradle/build-logic/build-logic.gradle.kts +++ b/gradle/build-logic/build-logic.gradle.kts @@ -65,7 +65,7 @@ dependencyAnalysis { } bundle("net.wooga.github.gradle.plugin") { includeDependency("net.wooga.github:net.wooga.github.gradle.plugin") - includeDependency("gradle.plugin.net.wooga.gradle:atlas-github") + includeDependency("net.wooga.gradle:github") } bundle("org.ajoberstar.grgit.service.gradle.plugin") { includeDependency("org.ajoberstar.grgit.service:org.ajoberstar.grgit.service.gradle.plugin") diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts index 5d8ea714..47af399c 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts @@ -30,7 +30,7 @@ import net.kautler.util.updateVersion import net.researchgate.release.ReleasePlugin import org.gradle.tooling.GradleConnector import org.kohsuke.github.GHIssueState.OPEN -import org.kohsuke.github.GitHub +import wooga.gradle.github.base.tasks.Github import wooga.gradle.github.publish.PublishMethod.update import wooga.gradle.github.publish.tasks.GithubPublish import java.awt.GraphicsEnvironment.isHeadless @@ -59,7 +59,6 @@ apply(plugin = "net.researchgate.release") extra["release.useAutomaticVersion"] = boolean(project, "release.useAutomaticVersion").getValue() extra["release.releaseVersion"] = optionalString(project, "release.releaseVersion").getValue() extra["release.newVersion"] = optionalString(project, "release.newVersion").getValue() -extra["github.token"] = optionalString(project, "github.token").getValue() val majorVersion: String by project @@ -71,30 +70,6 @@ release { } } -val githubRepositoryName by lazy(NONE) { - grgitService - .service - .get() - .grgit - .remote - .list() - .find { it.name == "origin" } - ?.let { remote -> - Regex( - """(?x) - (?: - ://([^@]++@)?+github\.com(?::\d++)?+/ | - ([^@]++@)?+github\.com: - ) - (?.*) - \.git - """ - ) - .find(remote.url) - ?.let { it.groups["repositoryName"]!!.value } - } ?: "Vampire/setup-wsl" -} - val releasePlugin by lazy(NONE) { plugins.findPlugin(ReleasePlugin::class)!! } @@ -103,77 +78,6 @@ val releaseTagName by lazy(NONE) { releasePlugin.tagName()!! } -internal val github by lazy(NONE) { - GitHub.connectUsingOAuth(extra["github.token"] as String)!! -} - -val releaseBody by lazy(NONE) { - val releaseBody = grgitService - .service - .get() - .grgit - .log { - includes.add(release.git.requireBranch) - github.getRepository(githubRepositoryName).latestRelease?.apply { - excludes.add(tagName) - } - } - .filter { commit -> - !commit.shortMessage.startsWith("[Gradle Release Plugin] ") - } - .asReversed() - .joinToString("\n") { commit -> - "- ${commit.shortMessage} [${commit.id}]" - } - - if (isHeadless()) { - return@lazy releaseBody - } - - val result = CompletableFuture() - - SwingUtilities.invokeLater { - val initialReleaseBody = """ - # Highlights - - - - # Details - - """.trimIndent() + releaseBody - - val textArea = JTextArea(initialReleaseBody) - - val parentFrame = JFrame().apply { - isUndecorated = true - setLocationRelativeTo(null) - isVisible = true - } - - val resetButton = JButton("Reset").apply { - addActionListener { - textArea.text = initialReleaseBody - } - } - - result.complete( - try { - when (showOptionDialog( - parentFrame, JScrollPane(textArea), "Release Body", - DEFAULT_OPTION, QUESTION_MESSAGE, null, - arrayOf("OK", resetButton), null - )) { - OK_OPTION -> textArea.text!! - else -> releaseBody - } - } finally { - parentFrame.dispose() - } - ) - } - - result.join()!! -} - val releaseVersion get() = !"$version".endsWith("-SNAPSHOT") val removeDistributionsFromGit by tasks.registering { @@ -196,6 +100,12 @@ tasks.updateVersion { dependsOn(removeDistributionsFromGit) } +val gitHubToken by optionalString("github.token", project) + +github { + token.set(provider { gitHubToken }) +} + configure(listOf(tasks.release, tasks.runBuildTasks)) { configure { actions.clear() @@ -222,29 +132,98 @@ configure(listOf(tasks.release, tasks.runBuildTasks)) { tasks.withType().configureEach { onlyIf { releaseVersion } - repositoryName(githubRepositoryName) - tagName(Callable { releaseTagName }) - releaseName(Callable { releaseTagName }) + tagName.set(provider { releaseTagName }) + releaseName.set(provider { releaseTagName }) } tasks.githubPublish { // work-around for https://github.com/ajoberstar/grgit/pull/382 //usesService(grgitService.service) - body { releaseBody } - draft(true) + body.set(provider { + val releaseBody = grgitService + .service + .get() + .grgit + .log { + includes.add(release.git.requireBranch) + github + .clientProvider + .get() + .getRepository(github.repositoryName.get()) + .latestRelease + ?.apply { + excludes.add(tagName) + } + } + .filter { commit -> + !commit.shortMessage.startsWith("[Gradle Release Plugin] ") + } + .asReversed() + .joinToString("\n") { commit -> + "- ${commit.shortMessage} [${commit.id}]" + } + + if (isHeadless()) { + return@provider releaseBody + } + + val result = CompletableFuture() + + SwingUtilities.invokeLater { + val initialReleaseBody = """ + # Highlights + - + + # Details + + """.trimIndent() + releaseBody + + val textArea = JTextArea(initialReleaseBody) + + val parentFrame = JFrame().apply { + isUndecorated = true + setLocationRelativeTo(null) + isVisible = true + } + + val resetButton = JButton("Reset").apply { + addActionListener { + textArea.text = initialReleaseBody + } + } + + result.complete( + try { + when (showOptionDialog( + parentFrame, JScrollPane(textArea), "Release Body", + DEFAULT_OPTION, QUESTION_MESSAGE, null, + arrayOf("OK", resetButton), null + )) { + OK_OPTION -> textArea.text!! + else -> releaseBody + } + } finally { + parentFrame.dispose() + } + ) + } + + return@provider result.join()!! + }) + draft.set(true) } val undraftGithubRelease by tasks.registering(GithubPublish::class) { - publishMethod = update + publishMethod.set(update) } -val finishMilestone by tasks.registering { +val finishMilestone by tasks.registering(Github::class) { enabled = releaseVersion // work-around for https://github.com/ajoberstar/grgit/pull/382 //usesService(grgitService.service) doLast("finish milestone") { - github.getRepository(githubRepositoryName)!!.apply { + repository.apply { listMilestones(OPEN) .find { it.title == "Next Version" }!! .apply { @@ -312,14 +291,13 @@ tasks.updateVersion { dependsOn(undraftGithubRelease) } -val checkBranchProtectionCompatibility by tasks.registering { +val checkBranchProtectionCompatibility by tasks.registering(Github::class) { // work-around for https://github.com/ajoberstar/grgit/pull/382 //usesService(grgitService.service) doLast { check( - !github - .getRepository(githubRepositoryName)!! + !repository .getBranch(release.git.requireBranch) .protection .enforceAdmins diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt index 6b0c1933..2c5d11d9 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/Properties.kt @@ -20,6 +20,7 @@ import org.gradle.api.Project import org.gradle.api.Task import kotlin.properties.ReadOnlyProperty import kotlin.reflect.KProperty +import kotlin.properties.PropertyDelegateProvider as KotlinPropertyDelegateProvider sealed class Property constructor( private val default: () -> T, @@ -137,20 +138,19 @@ sealed class Property constructor( } } -//TODO: ": PropertyDelegateProvider" when Kotlin 1.4 is used in the build scripts class PropertyDelegateProvider( private val default: () -> T, private val propertyName: String? = null, private val project: Project? = null, private val delegateFactory: (() -> T, String, Project) -> Property -) { +) : KotlinPropertyDelegateProvider> { operator fun provideDelegate(thisRef: Project, property: KProperty<*>) = delegateFactory(default, propertyName ?: property.name, project ?: thisRef) operator fun provideDelegate(thisRef: Task, property: KProperty<*>) = provideDelegate(thisRef.project, property) - operator fun provideDelegate(thisRef: Any?, property: KProperty<*>) = + override operator fun provideDelegate(thisRef: Any?, property: KProperty<*>) = project?.let { provideDelegate(it, property) } ?: error( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b7af9a72..a9a84b2e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -15,7 +15,7 @@ [versions] build-github-api = "1.313" build-gradle-plugin-dependency-analysis = "1.19.0" -build-gradle-plugin-github = "1.4.0" +build-gradle-plugin-github = "3.0.0" build-gradle-plugin-grgit = "5.0.0" build-gradle-plugin-refresh-versions = "0.51.0" build-gradle-plugin-release = "2.8.1" From 37324c861a0d1f7c3a96887e5b433f3d07cd3b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Sun, 12 Feb 2023 21:04:49 +0100 Subject: [PATCH 22/23] Update net.researchgate.release plugin to 3.0.2 --- .../main/kotlin/net/kautler/publishing.gradle.kts | 14 +++++++------- .../net/kautler/util/ReleaseExtensionExtension.kt | 7 ------- gradle/libs.versions.toml | 2 +- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts index 47af399c..06205d01 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts +++ b/gradle/build-logic/src/main/kotlin/net/kautler/publishing.gradle.kts @@ -22,7 +22,6 @@ import net.kautler.util.afterReleaseBuild import net.kautler.util.beforeReleaseBuild import net.kautler.util.checkoutMergeFromReleaseBranch import net.kautler.util.createReleaseTag -import net.kautler.util.git import net.kautler.util.preTagCommit import net.kautler.util.release import net.kautler.util.runBuildTasks @@ -63,10 +62,11 @@ extra["release.newVersion"] = optionalString(project, "release.newVersion").getV val majorVersion: String by project release { - pushReleaseVersionBranch = "v$majorVersion" - tagTemplate = "v\$version" + pushReleaseVersionBranch.set("v$majorVersion") + tagTemplate.set("v\$version") git { - signTag = true + requireBranch.set("master") + signTag.set(true) } } @@ -145,7 +145,7 @@ tasks.githubPublish { .get() .grgit .log { - includes.add(release.git.requireBranch) + includes.add(release.git.requireBranch.get()) github .clientProvider .get() @@ -298,7 +298,7 @@ val checkBranchProtectionCompatibility by tasks.registering(Github::class) { doLast { check( !repository - .getBranch(release.git.requireBranch) + .getBranch(release.git.requireBranch.get()) .protection .enforceAdmins .isEnabled @@ -306,7 +306,7 @@ val checkBranchProtectionCompatibility by tasks.registering(Github::class) { """ Please disable branch protection for administrators before triggering a release, for example using - gh api 'repos/{owner}/{repo}/branches/${release.git.requireBranch}/protection/enforce_admins' -X DELETE + gh api 'repos/{owner}/{repo}/branches/${release.git.requireBranch.get()}/protection/enforce_admins' -X DELETE """.trimIndent() } } diff --git a/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt b/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt index edcc537f..a3f2cfee 100644 --- a/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt +++ b/gradle/build-logic/src/main/kotlin/net/kautler/util/ReleaseExtensionExtension.kt @@ -16,7 +16,6 @@ package net.kautler.util -import net.researchgate.release.GitAdapter.GitConfig import net.researchgate.release.ReleaseExtension import org.gradle.api.Action import org.gradle.api.Project @@ -27,12 +26,6 @@ import org.gradle.api.tasks.TaskProvider import org.gradle.kotlin.dsl.getByName import org.gradle.kotlin.dsl.named -val ReleaseExtension.git - get() = getProperty("git") as GitConfig - -fun ReleaseExtension.git(configure: GitConfig.() -> Unit) = - git.configure() - // part of work-around for https://github.com/gradle/gradle/issues/23747 val Project.release: ReleaseExtension get() = extensions.getByName("release") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a9a84b2e..3acbc924 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,7 +18,7 @@ build-gradle-plugin-dependency-analysis = "1.19.0" build-gradle-plugin-github = "3.0.0" build-gradle-plugin-grgit = "5.0.0" build-gradle-plugin-refresh-versions = "0.51.0" -build-gradle-plugin-release = "2.8.1" +build-gradle-plugin-release = "3.0.2" build-gradle-plugin-versions = "0.45.0" build-inject = "1" build-kotlin = "1.8.10" From 5a56cf59b061b6f76b79496c35c79f3383b621b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kautler?= Date: Fri, 17 Feb 2023 12:40:56 +0100 Subject: [PATCH 23/23] Update github-actions-kotlin-dsl to 0.37.0 --- .github/workflows/check-action-typing.yaml | 8 ++--- .../workflows/check-dependency-versions.yaml | 8 ++--- .github/workflows/test.main.kts | 4 +-- .github/workflows/test.yaml | 8 ++--- .../workflows/validate-gradle-wrapper.yaml | 8 ++--- .../workflow-with-copyright.main.kts | 33 +++++++++---------- 6 files changed, 34 insertions(+), 35 deletions(-) diff --git a/.github/workflows/check-action-typing.yaml b/.github/workflows/check-action-typing.yaml index 851e19e7..3801329e 100644 --- a/.github/workflows/check-action-typing.yaml +++ b/.github/workflows/check-action-typing.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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-action-typing.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt diff --git a/.github/workflows/check-dependency-versions.yaml b/.github/workflows/check-dependency-versions.yaml index 202d00fa..b4ce07e7 100644 --- a/.github/workflows/check-dependency-versions.yaml +++ b/.github/workflows/check-dependency-versions.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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-dependency-versions.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt diff --git a/.github/workflows/test.main.kts b/.github/workflows/test.main.kts index 9baa1c54..0740a33c 100755 --- a/.github/workflows/test.main.kts +++ b/.github/workflows/test.main.kts @@ -27,7 +27,7 @@ import it.krzeminski.githubactions.actions.burrunan.GradleCacheActionV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1 import it.krzeminski.githubactions.actions.vampire.SetupWslV1.Distribution import it.krzeminski.githubactions.domain.CommandStep -import it.krzeminski.githubactions.domain.ExternalActionStepWithOutputs +import it.krzeminski.githubactions.domain.ExternalActionStep import it.krzeminski.githubactions.domain.JobOutputs.EMPTY import it.krzeminski.githubactions.domain.RunnerType import it.krzeminski.githubactions.domain.RunnerType.WindowsLatest @@ -119,7 +119,7 @@ val wslBash = Shell.Custom("wsl-bash {0}") val wslSh = Shell.Custom("wsl-sh {0}") -lateinit var executeActionStep: ExternalActionStepWithOutputs +lateinit var executeActionStep: ExternalActionStep workflowWithCopyright( name = "Build and Test", diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index f8c78de1..3a1f3be2 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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/test.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt diff --git a/.github/workflows/validate-gradle-wrapper.yaml b/.github/workflows/validate-gradle-wrapper.yaml index 8f8063e1..f17f20b0 100644 --- a/.github/workflows/validate-gradle-wrapper.yaml +++ b/.github/workflows/validate-gradle-wrapper.yaml @@ -1,17 +1,17 @@ # Copyright 2020-2023 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/validate-gradle-wrapper.main.kts). # If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. # Generated with https://github.com/krzema12/github-workflows-kt diff --git a/.github/workflows/workflow-with-copyright.main.kts b/.github/workflows/workflow-with-copyright.main.kts index 4fe8a5c9..1b90a4d6 100644 --- a/.github/workflows/workflow-with-copyright.main.kts +++ b/.github/workflows/workflow-with-copyright.main.kts @@ -14,12 +14,13 @@ * limitations under the License. */ -@file:DependsOn("it.krzeminski:github-actions-kotlin-dsl:0.36.0") +@file:DependsOn("it.krzeminski:github-actions-kotlin-dsl:0.37.0") import it.krzeminski.githubactions.domain.Concurrency import it.krzeminski.githubactions.domain.triggers.Trigger import it.krzeminski.githubactions.dsl.WorkflowBuilder import it.krzeminski.githubactions.dsl.workflow +import it.krzeminski.githubactions.yaml.Preamble.WithOriginalAfter import it.krzeminski.githubactions.yaml.writeToFile import java.io.File import kotlin.io.path.invariantSeparatorsPathString @@ -41,24 +42,22 @@ fun workflowWithCopyright( concurrency = concurrency, block = block ).writeToFile( - preamble = """ - Copyright 2020-2023 Björn Kautler + preamble = WithOriginalAfter( + """ + Copyright 2020-2023 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 + 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 + 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 (${sourceFilePath.invariantSeparatorsPathString.substringAfter("/setup-wsl/")}). - If you want to modify the workflow, please change the Kotlin file and regenerate this YAML file. - Generated with https://github.com/krzema12/github-workflows-kt - """.trimIndent() + 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. + """.trimIndent() + ) ) }