From 34df45707b47f6fd78c31601e598616f654cc853 Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 13:19:37 -0600 Subject: [PATCH 1/8] chore: Make signing tests more robust Old tests didn't verify the signatures were produced and also assumed that signing config wasn't set up wherever you ran tests. Since I do use signed commits now for my own work, this was a bad assumption and made the tests fail locally. Now we check for either the signature to be present or that signing failed because no secret key was found. For disabling signing, we ensure that no signature was added to the commit. --- .../gradle/git/publish/BaseCompatTest.groovy | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy b/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy index 6210c4c..5f93462 100644 --- a/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy +++ b/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy @@ -8,6 +8,8 @@ import org.gradle.testkit.runner.UnexpectedBuildFailure import spock.lang.Specification import spock.lang.TempDir +import java.rmi.UnexpectedException + class BaseCompatTest extends Specification { @TempDir File tempDir File projectDir @@ -420,10 +422,15 @@ gitPublish { } """ when: - def result = buildAndFail() + def result = buildOrFail() then: - result.output.contains("gpg: signing failed: No secret key") + def newCommit = remote.resolve.toCommit("gh-pages").id + def remoteGitDir = "${remote.repository.rootDir}/.git" + def proc = "git --git-dir ${remoteGitDir} cat-file -p ${newCommit}".execute() + def latestCommit = proc.in.text + // either it will work and sign or the key will be missing and it won't be able to + latestCommit.contains("gpgsig") || result.output.contains("gpg: signing failed: No secret key") } def 'can deactivate signing'() { @@ -451,6 +458,12 @@ gitPublish { then: result.task(':gitPublishPush').outcome == TaskOutcome.SUCCESS + + def newCommit = remote.resolve.toCommit("gh-pages").id + def remoteGitDir = "${remote.repository.rootDir}/.git" + def proc = "git --git-dir ${remoteGitDir} cat-file -p ${newCommit}".execute() + def latestCommit = proc.in.text + !latestCommit.contains('gpgsign') } private BuildResult build(String... args = ['gitPublishPush', '--stacktrace', '--configuration-cache']) { @@ -461,6 +474,14 @@ gitPublish { return runner(args).buildAndFail() } + private BuildResult buildOrFail(String... args = ['gitPublishPush', '--stacktrace', '--configuration-cache']) { + try { + return runner(args).build() + } catch (UnexpectedBuildFailure e) { + return e.buildResult + } + } + private GradleRunner runner(String... args) { return GradleRunner.create() .withGradleVersion(System.properties['compat.gradle.version']) From a8c92ad4c92cb4e92dbce59e77efac97919113dc Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 13:24:12 -0600 Subject: [PATCH 2/8] patch: Explicitly set branch on init'd repo When using git CLI, if you don't specify the initial branch for git init, it gives a warning about you not having specified a preference for what your initial branch should be. --- .../ajoberstar/gradle/git/publish/tasks/GitPublishReset.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java index 691f5e1..4e3ca7b 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java @@ -69,7 +69,7 @@ public void reset() throws IOException { // initialize git repo if (!new File(repoDir, ".git").exists()) { getExecOperations().exec(spec -> { - spec.commandLine("git", "init"); + spec.commandLine("git", "init", "--initial-branch=" + pubBranch); spec.workingDir(repoDir); spec.setStandardOutput(OutputStream.nullOutputStream()); }); From 86c93573c3a627278d8bfcdeb60100aff1e6641f Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 14:40:50 -0600 Subject: [PATCH 3/8] patch: Suppress error output in value source Might regret this, but it's confusing to print out fatal errors here when we handle the result either way. It's normal that some of these value source's might fail, e.g. if your project isn't running from a Git repo. --- .../org/ajoberstar/gradle/git/publish/GitCliValueSource.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/GitCliValueSource.java b/src/main/java/org/ajoberstar/gradle/git/publish/GitCliValueSource.java index 664c4ae..3f55c12 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/GitCliValueSource.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/GitCliValueSource.java @@ -1,6 +1,7 @@ package org.ajoberstar.gradle.git.publish; import java.io.ByteArrayOutputStream; +import java.io.OutputStream; import java.nio.charset.StandardCharsets; import javax.inject.Inject; @@ -27,6 +28,7 @@ public interface Params extends ValueSourceParameters { spec.executable("git"); spec.setArgs(getParameters().getGitArguments().get()); spec.setStandardOutput(output); + spec.setErrorOutput(OutputStream.nullOutputStream()); }); return output.toString(StandardCharsets.UTF_8).trim(); } catch (Exception e) { From c7abc5845c0743940ce3f31434f99b5c5e3cd4af Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 14:42:22 -0600 Subject: [PATCH 4/8] chore: Remove unused import --- .../org/ajoberstar/gradle/git/publish/GitPublishPlugin.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java index eb4023c..46acb3c 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/GitPublishPlugin.java @@ -1,7 +1,5 @@ package org.ajoberstar.gradle.git.publish; -import java.nio.file.Path; - import org.ajoberstar.gradle.git.publish.tasks.GitPublishCommit; import org.ajoberstar.gradle.git.publish.tasks.GitPublishPush; import org.ajoberstar.gradle.git.publish.tasks.GitPublishReset; From 2875bb555d6c852cfdb8b7185ddc5f1930e1ceb7 Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 14:42:50 -0600 Subject: [PATCH 5/8] patch: Use reference only as an alternate obj store Old behavior was to use the reference repo (usually the project's checkout repo) as a full remote that we would fetch from. However, Git has a more direct way to reference an existing repo, using `objects/info/alternates`. This mechanism will just let you reuse objects that already exist in the reference repo rather than fetching from the real remotes. So now only origin is a remote and we just try to reuse objects from the remote. This also simplifies things where we had to check if the branch we cared about existed. Now, we don't care and if the objects are relevant they get used and if not, it should be no harm, no foul. This will hopefully address the issue that reported in #112. --- .../gradle/git/publish/BaseCompatTest.groovy | 6 +- .../git/publish/tasks/GitPublishReset.java | 62 ++++++------------- 2 files changed, 21 insertions(+), 47 deletions(-) diff --git a/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy b/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy index 5f93462..7b54c5e 100644 --- a/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy +++ b/src/compatTest/groovy/org/ajoberstar/gradle/git/publish/BaseCompatTest.groovy @@ -127,7 +127,7 @@ gitPublish { working.close() } - def 'reset pulls from reference repo if available before pulling from remote'() { + def 'reset uses reference repo objects if available before pulling from remote'() { given: def referenceDir = new File(tempDir, 'reference') def reference = Grgit.clone(dir: referenceDir, uri: repoPath(remote)) @@ -159,7 +159,6 @@ gitPublish { remote.checkout(branch: 'gh-pages') then: result.task(':gitPublishPush').outcome == TaskOutcome.SUCCESS - result.output.contains('gh-pages -> reference/gh-pages') remote.log().size() == 2 remoteFile('content.txt').text == 'published content here' !remoteFile('newFile.txt').exists() @@ -328,7 +327,6 @@ gitPublish { } def working = Grgit.clone(dir: "${projectDir}/build/gitPublish", uri: badRemote.repository.rootDir.toURI()) - working.checkout(branch: 'gh-pages', startPoint: 'origin/master', createBranch: true) working.close() new File(projectDir, 'content.txt') << 'published content here' @@ -350,9 +348,11 @@ gitPublish { and: remote.checkout(branch: 'gh-pages') working = Grgit.open(dir: "${projectDir}/build/gitPublish") + working.checkout(branch: 'master') then: result.task(':gitPublishPush').outcome == TaskOutcome.SUCCESS remote.log().size() == 2 + working.head().fullMessage == 'bad first commit' } def 'when no git publish tasks are run, build completes successfully'() { diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java index 4e3ca7b..c3eea93 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java @@ -4,7 +4,10 @@ import java.io.IOException; import java.io.OutputStream; import java.io.UncheckedIOException; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import javax.inject.Inject; @@ -91,51 +94,21 @@ public void reset() throws IOException { }); } - // set reference + // set alternate object store if reference used if (getReferenceRepoUri().isPresent()) { - try { - getExecOperations().exec(spec -> { - spec.commandLine("git", "remote", "add", "reference", getReferenceRepoUri().get()); - spec.workingDir(repoDir); - spec.setStandardOutput(OutputStream.nullOutputStream()); - spec.setErrorOutput(OutputStream.nullOutputStream()); - }); - } catch (Exception e) { - getExecOperations().exec(spec -> { - spec.commandLine("git", "remote", "set-url", "reference", getReferenceRepoUri().get()); - spec.workingDir(repoDir); - spec.setStandardOutput(OutputStream.nullOutputStream()); - }); - } - - // check reference for branch - boolean referenceHasBranch; - try { - getExecOperations().exec(spec -> { - spec.commandLine("git", "ls-remote", "--exit-code", "reference", pubBranch); - spec.workingDir(repoDir); - spec.setStandardOutput(OutputStream.nullOutputStream()); - }); - referenceHasBranch = true; - } catch (Exception e) { - referenceHasBranch = false; - } - - if (referenceHasBranch) { - // get local branch reset to remote state - getExecOperations().exec(spec -> { - var refSpec = String.format("+refs/heads/%s:refs/remotes/reference/%s", pubBranch, pubBranch); - - spec.executable("git"); - spec.args("fetch"); - if (getFetchDepth().isPresent()) { - spec.args("--depth", getFetchDepth().get()); - } - spec.args("reference", refSpec); - - spec.workingDir(repoDir); - spec.setStandardOutput(OutputStream.nullOutputStream()); - }); + Path repoObjectsPath = repoDir.toPath().resolve(".git").resolve("objects"); + Path alternatesPath = repoObjectsPath.resolve("info").resolve("alternates"); + + Path referenceRepoPath = Path.of(getReferenceRepoUri().get()); + + Path referenceRepoObjectsPath = referenceRepoPath.resolve(".git").resolve("objects"); + Path referenceBareRepoObjectsPath = referenceRepoPath.resolve("objects"); + if (Files.exists(referenceRepoObjectsPath)) { + Files.writeString(alternatesPath, referenceRepoObjectsPath + "\n", StandardCharsets.UTF_8); + } else if (Files.exists(referenceBareRepoObjectsPath)) { + Files.writeString(alternatesPath, referenceBareRepoObjectsPath + "\n", StandardCharsets.UTF_8); + } else { + getLogger().warn("Reference repo doesn't seem to have an objects database: {}", referenceRepoPath); } } @@ -146,6 +119,7 @@ public void reset() throws IOException { spec.commandLine("git", "ls-remote", "--exit-code", "origin", pubBranch); spec.workingDir(repoDir); spec.setStandardOutput(OutputStream.nullOutputStream()); + spec.setErrorOutput(OutputStream.nullOutputStream()); }); hasBranch = true; } catch (Exception e) { From 0db4f9df5aad519fa045774432fb7df14ee13cf0 Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 14:48:10 -0600 Subject: [PATCH 6/8] chore: Test against Gradle 8.11 --- stutter.lockfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stutter.lockfile b/stutter.lockfile index e55c85c..74b9d1b 100644 --- a/stutter.lockfile +++ b/stutter.lockfile @@ -1,4 +1,4 @@ # DO NOT MODIFY: Generated by Stutter plugin. -java11=7.0.2,7.6.4,8.0.2,8.10.2 -java17=7.3.3,7.6.4,8.0.2,8.10.2 -java21=8.4,8.10.2 +java11=7.0.2,7.6.4,8.0.2,8.11.1 +java17=7.3.3,7.6.4,8.0.2,8.11.1 +java21=8.4,8.11.1 From f6c6235e7a0ba387f144dd03fa7b75e3999c312f Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 14:49:28 -0600 Subject: [PATCH 7/8] chore: Build against Gradle 8.11 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index df97d72..e2847c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From af99ce39537e08bf5beecf6b6dc65fe898178985 Mon Sep 17 00:00:00 2001 From: Andrew Oberstar Date: Sat, 23 Nov 2024 15:06:47 -0600 Subject: [PATCH 8/8] patch: Disable fetching tags This is unnecessary for this plugin behavior. --- .../org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java index c3eea93..73aaf9a 100644 --- a/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java +++ b/src/main/java/org/ajoberstar/gradle/git/publish/tasks/GitPublishReset.java @@ -136,6 +136,7 @@ public void reset() throws IOException { if (getFetchDepth().isPresent()) { spec.args("--depth", getFetchDepth().get()); } + spec.args("--no-tags"); spec.args("origin", refSpec); spec.workingDir(repoDir);