diff --git a/.ado/build.yml b/.ado/build.yml new file mode 100644 index 0000000..eb85d47 --- /dev/null +++ b/.ado/build.yml @@ -0,0 +1,51 @@ +name: $(Rev:r) + +trigger: + branches: + include: + - '*' + exclude: + - master + +pr: + branches: + include: + - '*' + +jobs: +- job: 'Build' + displayName: 'Build for testing' + + pool: 'MC-Build-1ES-Azure-Pipeline-Linux' + container: adoptopenjdk/openjdk8:latest + + workspace: + clean: all + + steps: + - task: Gradle@2 + displayName: Build and Test + inputs: + workingDirectory: '' + gradleWrapperFile: 'gradlew' + gradleOptions: '-Xmx3072m' + options: '-PbuildNumber=0' + javaHomeOption: 'JDKVersion' + jdkUserInputPath: '/usr/java/openjdk-8' + testResultsFiles: '**/TEST-*.xml' + tasks: 'build test publish' + + # This is a workaround for ComponentGovernanceComponentDetection@0 not recognizing the generated `.pom` file(s) + - task: Bash@3 + displayName: Copy pom for component governance + inputs: + targetType: 'inline' + script: | + pompath=`find build/repo -name *.pom` + cp "${pompath}" build/pom.xml + + - task: ComponentGovernanceComponentDetection@0 + inputs: + scanType: 'Register' + verbosity: 'Verbose' + alertWarningLevel: 'High' diff --git a/.ado/release.yml b/.ado/release.yml new file mode 100644 index 0000000..b4c334a --- /dev/null +++ b/.ado/release.yml @@ -0,0 +1,87 @@ +name: $(Rev:r) + +trigger: + branches: + include: + - master + +pr: none + +variables: + rConnection: 'mc-java-sc' + storageAccount: 'librariesminecraftnet' + storageAccountContainer: 'librariesminecraftnet' + keyVault: 'mc-java-vault' + +jobs: +- job: 'Build' + displayName: 'Build for release' + + pool: 'MC-Build-1ES-Azure-Pipeline-Linux' + container: adoptopenjdk/openjdk8:latest + + workspace: + clean: all + + steps: + - task: Gradle@2 + displayName: Build and Test + inputs: + workingDirectory: '' + gradleWrapperFile: 'gradlew' + gradleOptions: '-Xmx3072m' + options: '-PbuildNumber=$(Build.BuildNumber)' + javaHomeOption: 'JDKVersion' + jdkUserInputPath: '/usr/java/openjdk-8' + testResultsFiles: '**/TEST-*.xml' + tasks: 'build test publish report' + + # This is a workaround for ComponentGovernanceComponentDetection@0 not recognizing the generated `.pom` file(s) + - task: Bash@3 + displayName: Copy pom for component governance + inputs: + targetType: 'inline' + script: | + pompath=`find build/repo -name *.pom` + cp "${pompath}" build/pom.xml + + - task: ComponentGovernanceComponentDetection@0 + inputs: + scanType: 'Register' + verbosity: 'Verbose' + alertWarningLevel: 'High' + + - publish: 'build/repo/' + artifact: repo + +- job: 'Publish' + displayName: 'Publish release' + dependsOn: Build + condition: eq(variables['Build.SourceBranch'], 'refs/heads/master') + + pool: 'MC-Build-1ES-Azure-Pipeline-Linux' + + workspace: + clean: all + + steps: + - download: current + artifact: repo + + - task: AzureKeyVault@1 + displayName: 'Fetching secrets' + name: secrets + inputs: + azureSubscription: '$(rConnection)' + KeyVaultName: '$(keyVault)' + SecretsFilter: 'access-key-prod-librariesminecraftnet' + RunAsPreJob: false + + - task: AzureCLI@2 + displayName: Azure CLI + inputs: + azureSubscription: '$(rConnection)' + scriptType: 'bash' + scriptLocation: 'inlineScript' + inlineScript: | + az storage blob upload-batch -s '$(Pipeline.Workspace)/repo' -d $(storageAccountContainer) --account-name $(storageAccount) --account-key $(access-key-prod-librariesminecraftnet) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml new file mode 100644 index 0000000..de2dee6 --- /dev/null +++ b/.github/workflows/pr-check.yml @@ -0,0 +1,22 @@ +name: pr-check + +on: [ pull_request ] + +jobs: + build: + name: Build and test + runs-on: ubuntu-latest + container: + image: adoptopenjdk/openjdk8:latest + + steps: + - uses: actions/checkout@v3 + - name: Build with Gradle + uses: gradle/gradle-build-action@v2 + with: + arguments: build test + - name: Publish Test Report + uses: mikepenz/action-junit-report@v3 + if: always() + with: + report_paths: '**/build/test-results/test/TEST-*.xml' diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e71a43f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,17 +0,0 @@ -sudo: false -dist: trusty -language: java - -before_cache: - - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock - - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ -cache: - directories: - - $HOME/.gradle/caches/ - - $HOME/.gradle/wrapper/ - -jdk: - - oraclejdk8 - -script: - - ./gradlew check --info -S --parallel \ No newline at end of file diff --git a/build.gradle b/build.gradle index 1b63485..67ccb2c 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,4 @@ import groovy.io.FileType -import com.amazonaws.auth.STSAssumeRoleSessionCredentialsProvider -import com.amazonaws.services.s3.AmazonS3Client apply plugin: 'java-library' apply plugin: 'maven-publish' @@ -15,10 +13,6 @@ buildscript { url "https://libraries.minecraft.net" } } - - dependencies { - classpath 'com.amazonaws:aws-java-sdk:1.11.33' - } } repositories { @@ -86,18 +80,12 @@ publishing { task report { doLast { - println "##teamcity[buildNumber '${project.version}']" + println "##vso[build.updatebuildnumber]${project.version}" } } def publishDir = file("$buildDir/repo") - -def uploadFile(s3, bucket, path, filename) { - println "Uploading $filename to $bucket as $path" - s3.putObject(bucket, path, filename) -} - clean.doLast { delete publishDir } @@ -114,14 +102,13 @@ if (version.endsWith("SNAPSHOT")) { } publish.doLast { - def AWSRoleARN = (System.getenv("AWS_ROLE_ARN") != null && System.getenv("AWS_ROLE_ARN") != "" ? System.getenv("AWS_ROLE_ARN") : null) - if (AWSRoleARN == null) throw new GradleException("AWS Role has not been configured, use the `AWS_ROLE_ARN` environment variable") - def auth = new STSAssumeRoleSessionCredentialsProvider.Builder(AWSRoleARN, "JavaBrigadierPublish").build() - def s3 = new AmazonS3Client(auth) publishDir.eachFileRecurse { - if (!it.name.contains(".xml") && !it.name.contains(".md5") && it.isFile()) { - def relPath = publishDir.toPath().relativize(it.toPath()).toFile().toString().replaceAll('\\\\', '/') - uploadFile(s3, "minecraft-libraries", relPath, it) + if (!it.isFile()) { + return + } + // Remove junk files + if (it.name.contains(".xml") || it.name.contains(".md5")) { + it.delete() } } } diff --git a/gradle.properties b/gradle.properties index 8dee0e0..7b2a236 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1 +1 @@ -majorMinor: 1.0 \ No newline at end of file +majorMinor: 1.1 diff --git a/src/main/java/com/mojang/brigadier/CommandDispatcher.java b/src/main/java/com/mojang/brigadier/CommandDispatcher.java index 586c80b..dfc3dc4 100644 --- a/src/main/java/com/mojang/brigadier/CommandDispatcher.java +++ b/src/main/java/com/mojang/brigadier/CommandDispatcher.java @@ -249,7 +249,6 @@ public class CommandDispatcher { if (child != null) { forked |= context.isForked(); if (child.hasNodes()) { - foundCommand = true; final RedirectModifier modifier = context.getRedirectModifier(); if (modifier == null) { if (next == null) { @@ -266,6 +265,8 @@ public class CommandDispatcher { for (final S source : results) { next.add(child.copyFor(source)); } + } else { + foundCommand = true; } } catch (final CommandSyntaxException ex) { consumer.onCommandComplete(context, false, 0); diff --git a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java index f2bab4a..b69184b 100644 --- a/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java +++ b/src/test/java/com/mojang/brigadier/CommandDispatcherTest.java @@ -4,6 +4,7 @@ package com.mojang.brigadier; import com.google.common.collect.Lists; +import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.context.CommandContextBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; @@ -14,6 +15,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + import static com.mojang.brigadier.arguments.IntegerArgumentType.integer; import static com.mojang.brigadier.builder.LiteralArgumentBuilder.literal; import static com.mojang.brigadier.builder.RequiredArgumentBuilder.argument; @@ -326,6 +330,37 @@ public class CommandDispatcherTest { verify(command).run(argThat(hasProperty("source", is(source2)))); } + @Test + public void testIncompleteRedirectShouldThrow() { + final LiteralCommandNode foo = subject.register(literal("foo") + .then(literal("bar") + .then(argument("value", integer()).executes(context -> IntegerArgumentType.getInteger(context, "value")))) + .then(literal("awa").executes(context -> 2))); + final LiteralCommandNode baz = subject.register(literal("baz").redirect(foo)); + try { + int result = subject.execute("baz bar", source); + fail("Should have thrown an exception"); + } catch (CommandSyntaxException e) { + assertThat(e.getType(), is(CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownCommand())); + } + } + + @Test + public void testRedirectModifierEmptyResult() { + final LiteralCommandNode foo = subject.register(literal("foo") + .then(literal("bar") + .then(argument("value", integer()).executes(context -> IntegerArgumentType.getInteger(context, "value")))) + .then(literal("awa").executes(context -> 2))); + final RedirectModifier emptyModifier = context -> Collections.emptyList(); + final LiteralCommandNode baz = subject.register(literal("baz").fork(foo, emptyModifier)); + try { + int result = subject.execute("baz bar 100", source); + assertThat(result, is(0)); // No commands executed, so result is 0 + } catch (CommandSyntaxException e) { + fail("Should not throw an exception"); + } + } + @Test public void testExecuteOrphanedSubcommand() throws Exception { subject.register(literal("foo").then(