mirror of
https://github.com/spring-projects/spring-security.git
synced 2026-03-25 03:21:18 +00:00
Gracefully handle detached HEAD in branch version check
Previously, the `CheckExpectedBranchVersionPlugin` would crash the Gradle configuration phase if the project was in a detached HEAD state or not in a Git repository, e.g., downloaded as a ZIP. This commit refactors the plugin to be lazy and adopts several Gradle best practices: - Prevents build crashes on Git failures by gracefully catching non-zero exit codes, e.g., when checked out in a detached HEAD state. - Moves the branch validation out of the task's main execution action and into an `onlyIf` predicate, allowing Gradle to skip the task entirely instead of executing an early return. This makes the skip outcome and reason visible in a Build Scan, rather than making it appear as if it executed. - Defers the Git `exec` call to the execution phase using a lazy provider. - Makes the task configuration cache compatible by avoiding illegal `Project` access inside the execution-time `onlyIf` closure. - Improves user-facing logs and adds actionable bypass instructions when the project version doesn't match the branch version. Signed-off-by: Eric Haag <ehaag@gradle.com>
This commit is contained in:
parent
2fda37de53
commit
91199e7202
@ -21,8 +21,12 @@ import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.Task;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.provider.ProviderFactory;
|
||||
import org.gradle.api.specs.Spec;
|
||||
import org.gradle.api.tasks.CacheableTask;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
@ -30,6 +34,7 @@ import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.api.tasks.TaskExecutionException;
|
||||
import org.gradle.api.tasks.TaskProvider;
|
||||
import org.gradle.api.tasks.VerificationException;
|
||||
import org.gradle.process.ExecOutput;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@ -44,21 +49,53 @@ public class CheckExpectedBranchVersionPlugin implements Plugin<Project> {
|
||||
TaskProvider<CheckExpectedBranchVersionTask> checkExpectedBranchVersionTask = project.getTasks().register("checkExpectedBranchVersion", CheckExpectedBranchVersionTask.class, (task) -> {
|
||||
task.setGroup("Build");
|
||||
task.setDescription("Check if the project version matches the branch version");
|
||||
task.onlyIf("skipCheckExpectedBranchVersion property is false or not present", CheckExpectedBranchVersionPlugin::skipPropertyFalseOrNotPresent);
|
||||
task.onlyIf("Property 'skipCheckExpectedBranchVersion' is false or not present", skipPropertyFalseOrNotPresent(project.getProviders()));
|
||||
task.onlyIf("Branch name matches expected version pattern *.x", CheckExpectedBranchVersionPlugin::isVersionBranch);
|
||||
task.getVersion().convention(project.provider(() -> project.getVersion().toString()));
|
||||
task.getBranchName().convention(project.getProviders().exec((execSpec) -> execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD")).getStandardOutput().getAsText());
|
||||
task.getBranchName().convention(getBranchName(project.getProviders(), project.getLogger()));
|
||||
task.getOutputFile().convention(project.getLayout().getBuildDirectory().file("check-expected-branch-version"));
|
||||
});
|
||||
project.getTasks().named(JavaBasePlugin.CHECK_TASK_NAME, checkTask -> checkTask.dependsOn(checkExpectedBranchVersionTask));
|
||||
}
|
||||
|
||||
private static boolean skipPropertyFalseOrNotPresent(Task task) {
|
||||
return task.getProject()
|
||||
.getProviders()
|
||||
private static Spec<Task> skipPropertyFalseOrNotPresent(ProviderFactory providers) {
|
||||
Provider<Boolean> skipPropertyFalseOrNotPresent = providers
|
||||
.gradleProperty("skipCheckExpectedBranchVersion")
|
||||
.orElse("false")
|
||||
.map("false"::equalsIgnoreCase)
|
||||
.get();
|
||||
.map("false"::equalsIgnoreCase);
|
||||
return (task) -> skipPropertyFalseOrNotPresent.get();
|
||||
}
|
||||
|
||||
private static boolean isVersionBranch(Task task) {
|
||||
return isVersionBranch((CheckExpectedBranchVersionTask) task);
|
||||
}
|
||||
|
||||
private static boolean isVersionBranch(CheckExpectedBranchVersionTask task) {
|
||||
String branchName = task.getBranchName().getOrNull();
|
||||
if (branchName == null) {
|
||||
return false;
|
||||
}
|
||||
return branchName.matches("^[0-9]+\\.[0-9]+\\.x$");
|
||||
}
|
||||
|
||||
private static Provider<String> getBranchName(ProviderFactory providers, Logger logger) {
|
||||
ExecOutput execOutput = providers.exec((execSpec) -> {
|
||||
execSpec.setCommandLine("git", "symbolic-ref", "--short", "HEAD");
|
||||
execSpec.setIgnoreExitValue(true);
|
||||
});
|
||||
|
||||
return providers.provider(() -> {
|
||||
int exitValue = execOutput.getResult().get().getExitValue();
|
||||
if (exitValue != 0) {
|
||||
logger.warn("Unable to determine branch name. Received exit code '{}' from `git`.", exitValue);
|
||||
logger.warn(execOutput.getStandardError().getAsText().getOrNull());
|
||||
return null;
|
||||
}
|
||||
|
||||
String branchName = execOutput.getStandardOutput().getAsText().get().trim();
|
||||
logger.info("Git branch name is '{}'.", branchName);
|
||||
return branchName;
|
||||
});
|
||||
}
|
||||
|
||||
@CacheableTask
|
||||
@ -77,15 +114,10 @@ public class CheckExpectedBranchVersionPlugin implements Plugin<Project> {
|
||||
public void run() {
|
||||
String version = getVersion().get();
|
||||
String branchVersion = getBranchName().map(String::trim).get();
|
||||
if (!branchVersion.matches("^[0-9]+\\.[0-9]+\\.x$")) {
|
||||
String msg = String.format("Branch version [%s] does not match *.x, ignoring", branchVersion);
|
||||
getLogger().warn(msg);
|
||||
writeExpectedVersionOutput(msg);
|
||||
return;
|
||||
}
|
||||
if (!versionsMatch(version, branchVersion)) {
|
||||
String msg = String.format("Project version [%s] does not match branch version [%s]. " +
|
||||
"Please verify that the branch contains the right version.", version, branchVersion);
|
||||
"Please verify that the branch contains the right version. " +
|
||||
"To bypass this check, run the build with -PskipCheckExpectedBranchVersion.", version, branchVersion);
|
||||
writeExpectedVersionOutput(msg);
|
||||
throw new VerificationException(msg);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user