All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gradle.api.plugins.buildcomparison.gradle.CompareGradleBuilds Maven / Gradle / Ivy

/*
 * Copyright 2012 the original author or authors.
 *
 * 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 org.gradle.api.plugins.buildcomparison.gradle;

import org.gradle.api.*;
import org.gradle.api.logging.Logger;
import org.gradle.api.plugins.buildcomparison.compare.internal.BuildComparisonResult;
import org.gradle.api.plugins.buildcomparison.gradle.internal.ComparableGradleBuildExecuter;
import org.gradle.api.plugins.buildcomparison.gradle.internal.DefaultGradleBuildInvocationSpec;
import org.gradle.api.plugins.buildcomparison.gradle.internal.GradleBuildComparison;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcomeComparator;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcomeComparisonResultHtmlRenderer;
import org.gradle.api.plugins.buildcomparison.outcome.internal.archive.GeneratedArchiveBuildOutcomeHtmlRenderer;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcome;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcomeComparator;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcomeComparisonResultHtmlRenderer;
import org.gradle.api.plugins.buildcomparison.outcome.internal.unknown.UnknownBuildOutcomeHtmlRenderer;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.VerificationTask;
import org.gradle.internal.file.PathToFileResolver;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.resource.local.FileStore;
import org.gradle.internal.resource.local.PathNormalisingKeyFileStore;
import org.gradle.internal.logging.ConsoleRenderer;
import org.gradle.internal.logging.progress.ProgressLogger;
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.util.GradleVersion;

import javax.inject.Inject;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Executes two Gradle builds (that can be the same build) with specified versions and compares the outcomes.
 *
 * Please see the “Comparing Builds” chapter of the Gradle User Guide for more information.
 */
@Incubating
public class CompareGradleBuilds extends DefaultTask implements VerificationTask {

    public static final List DEFAULT_TASKS = Arrays.asList("clean", "assemble");

    private static final String TMP_FILESTORAGE_PREFIX = "tmp-filestorage";

    private final GradleBuildInvocationSpec sourceBuild;
    private final GradleBuildInvocationSpec targetBuild;
    private boolean ignoreFailures;
    private Object reportDir;

    public CompareGradleBuilds() {
        PathToFileResolver fileResolver = getFileResolver();
        Instantiator instantiator = getInstantiator();
        sourceBuild = instantiator.newInstance(DefaultGradleBuildInvocationSpec.class, fileResolver, getProject().getRootDir());
        sourceBuild.setTasks(DEFAULT_TASKS);
        targetBuild = instantiator.newInstance(DefaultGradleBuildInvocationSpec.class, fileResolver, getProject().getRootDir());
        targetBuild.setTasks(DEFAULT_TASKS);

        // Never up to date
        getOutputs().upToDateWhen(new Spec() {
            public boolean isSatisfiedBy(Task element) {
                return false;
            }
        });
    }

    @Inject
    protected PathToFileResolver getFileResolver() {
        throw new UnsupportedOperationException();
    }

    @Inject
    protected ProgressLoggerFactory getProgressLoggerFactory() {
        throw new UnsupportedOperationException();
    }

    @Inject
    protected Instantiator getInstantiator() {
        throw new UnsupportedOperationException();
    }

    /**
     * The specification of how to invoke the source build.
     *
     * Defaults to {@link org.gradle.api.Project#getRootDir() project.rootDir} with the current Gradle version
     * and the tasks “clean assemble”.
     *
     * The {@code projectDir} must be the project directory of the root project if this is a multi project build.
     *
     * @return The specification of how to invoke the source build.
     */
    public GradleBuildInvocationSpec getSourceBuild() {
        return sourceBuild;
    }

    /**
     * Configures the source build.
     *
     * A Groovy closure can be used as the action.
     * 
     * sourceBuild {
     *   gradleVersion = "1.1"
     * }
     * 
* * @param config The configuration action. */ @SuppressWarnings("UnusedDeclaration") public void sourceBuild(Action config) { config.execute(getSourceBuild()); } /** * The specification of how to invoke the target build. * * Defaults to {@link org.gradle.api.Project#getRootDir() project.rootDir} with the current Gradle version * and the tasks “clean assemble”. * * The {@code projectDir} must be the project directory of the root project if this is a multi project build. * * @return The specification of how to invoke the target build. */ public GradleBuildInvocationSpec getTargetBuild() { return targetBuild; } /** * Configures the target build. * * A Groovy closure can be used as the action. *
     * targetBuild {
     *   gradleVersion = "1.1"
     * }
     * 
* * @param config The configuration action. */ @SuppressWarnings("UnusedDeclaration") public void targetBuild(Action config) { config.execute(getTargetBuild()); } /** * Whether a comparison between non identical builds will fail the task execution. * * @return True if a comparison between non identical builds will fail the task execution, otherwise false. */ public boolean getIgnoreFailures() { return ignoreFailures; } /** * Sets whether a comparison between non identical builds will fail the task execution. * * @param ignoreFailures false to fail the task on non identical builds, true to not fail the task. The default is false. */ public void setIgnoreFailures(boolean ignoreFailures) { this.ignoreFailures = ignoreFailures; } /** * The directory that will contain the HTML comparison report and any other report files. * * @return The directory that will contain the HTML comparison report and any other report files. */ @OutputDirectory public File getReportDir() { return reportDir == null ? null : getFileResolver().resolve(reportDir); } /** * Sets the directory that will contain the HTML comparison report and any other report files. * * The value will be evaluated by {@link Project#file(Object) project.file()}. * * @param reportDir The directory that will contain the HTML comparison report and any other report files. */ @SuppressWarnings("UnusedDeclaration") public void setReportDir(Object reportDir) { if (reportDir == null) { throw new IllegalArgumentException("reportDir cannot be null"); } this.reportDir = reportDir; } private File getReportFile() { return new File(getReportDir(), GradleBuildComparison.HTML_REPORT_FILE_NAME); } @SuppressWarnings("UnusedDeclaration") @TaskAction void compare() { GradleBuildInvocationSpec sourceBuild = getSourceBuild(); GradleBuildInvocationSpec targetBuild = getTargetBuild(); if (sourceBuild.equals(targetBuild)) { getLogger().warn("The source build and target build are identical. Set '{}.targetBuild.gradleVersion' if you want to compare with a different Gradle version.", getName()); } ComparableGradleBuildExecuter sourceBuildExecuter = new ComparableGradleBuildExecuter(sourceBuild); ComparableGradleBuildExecuter targetBuildExecuter = new ComparableGradleBuildExecuter(targetBuild); Logger logger = getLogger(); ProgressLogger progressLogger = getProgressLoggerFactory().newOperation(getClass()); progressLogger.setDescription("Gradle Build Comparison"); progressLogger.setShortDescription(getName()); GradleBuildComparison comparison = new GradleBuildComparison( sourceBuildExecuter, targetBuildExecuter, logger, progressLogger, getProject().getGradle() ); comparison.registerType( GeneratedArchiveBuildOutcome.class, new GeneratedArchiveBuildOutcomeComparator(), new GeneratedArchiveBuildOutcomeComparisonResultHtmlRenderer(), new GeneratedArchiveBuildOutcomeHtmlRenderer() ); comparison.registerType( UnknownBuildOutcome.class, new UnknownBuildOutcomeComparator(), new UnknownBuildOutcomeComparisonResultHtmlRenderer(), new UnknownBuildOutcomeHtmlRenderer() ); File fileStoreTmpBase = getFileResolver().resolve(String.format(TMP_FILESTORAGE_PREFIX + "-%s-%s", getName(), System.currentTimeMillis())); FileStore fileStore = new PathNormalisingKeyFileStore(fileStoreTmpBase); Map hostAttributes = new LinkedHashMap(4); hostAttributes.put("Project", getProject().getRootDir().getAbsolutePath()); hostAttributes.put("Task", getPath()); hostAttributes.put("Gradle version", GradleVersion.current().getVersion()); hostAttributes.put("Executed at", new SimpleDateFormat().format(new Date())); BuildComparisonResult result = comparison.compare(fileStore, getReportDir(), hostAttributes); communicateResult(result); } private void communicateResult(BuildComparisonResult result) { String reportUrl = new ConsoleRenderer().asClickableFileUrl(getReportFile()); if (result.isBuildsAreIdentical()) { getLogger().info("The build outcomes were found to be identical. See the report at: {}", reportUrl); } else { String message = String.format("The build outcomes were not found to be identical. See the report at: %s", reportUrl); if (getIgnoreFailures()) { getLogger().warn(message); } else { throw new GradleException(message); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy