org.jenkinsci.plugins.django.PythonVirtualenv.java Source code

Java tutorial

Introduction

Here is the source code for org.jenkinsci.plugins.django.PythonVirtualenv.java

Source

/*
 * The MIT License Copyright (c) 2015, Evili del Rio i Silvan. Permission is
 * hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the
 * Software without restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions: The above copyright notice and this
 * permission notice shall be included in all copies or substantial portions of
 * the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
 * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
 * OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */
package org.jenkinsci.plugins.django;

import hudson.FilePath;
import hudson.Launcher;
import hudson.model.BuildListener;
import hudson.model.AbstractBuild;

import java.io.IOException;
import java.io.PrintStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;

import jenkins.plugins.shiningpanda.builders.VirtualenvBuilder;
import jenkins.plugins.shiningpanda.tools.PythonInstallationFinder;
import jenkins.plugins.shiningpanda.tools.PythonInstallation;

import org.apache.commons.lang.StringUtils;

/**
 * The Class PythonVirtualenv.
 */
public class PythonVirtualenv implements Serializable {
    /** (non-Javadoc) @see java.io.Serializable#serialVersionUID. */
    private static final long serialVersionUID = 2L;
    /** PIP Install command */
    static final String PIP_INSTALL = "pip install";
    static final String PIP_UPGRADE = " --upgrade ";
    /** Python requirements needed for the django-jenkins module. */
    static final String DJANGO_JENKINS_REQUIREMENTS = "nosexcover django-extensions django-jenkins selenium";
    /** Name of the python package created to run django-jenkins tasks. */
    static final String DJANGO_JENKINS_MODULE = "jenkins_build";
    /**
     * Name of the django settings module loaded to run django-jenkins tasks.
     */
    static final String DJANGO_JENKINS_SETTINGS = "jenkins_settings";
    /** CLI flag to run coverage tool. */
    private static final String ENABLE_COVERAGE = "--enable-coverage";
    /** Python requirement for coverage tool. */
    // django_jenkins<=0.17.0 needs coverage<4.0
    private static final String COVERAGE_REQUIREMENT = "coverage";

    /**
     * AbstractBuild. (non-Javadoc)
     *
     * @see DjangoJenkinsBuilder#perform(AbstractBuild, Launcher, BuildListener)
     */
    private final AbstractBuild<?, ?> build;
    /**
     * Launcher. (non-Javadoc)
     *
     * @see DjangoJenkinsBuilder#perform(AbstractBuild, Launcher, BuildListener)
     */
    private final Launcher launcher;
    /**
     * BuildListener. (non-Javadoc)
     *
     * @see DjangoJenkinsBuilder#perform(AbstractBuild, Launcher, BuildListener)
     */
    private final BuildListener listener;

    /** Workspace FilePah directory for the current build */
    private FilePath workspace = null;

    /**
     * Instantiates a new python virtualenv.
     *
     * @param build
     *            the build
     * @param launcher
     *            the launcher
     * @param listener
     *            the listener
     */
    public PythonVirtualenv(final AbstractBuild<?, ?> build, final Launcher launcher,
            final BuildListener listener) {
        this.build = build;
        this.launcher = launcher;
        this.listener = listener;
    }

    /**
     * Perform.
     *
     * @param actualTasks
     *            the actual tasks
     * @param projectApps
     *            the project apps
     * @param settingsModule 
     * @param requirementsFile 
     * @param enableCoverage
     *            the enable coverage
     * @return true, if successful
     * @throws InterruptedException
     *             the interrupted exception
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     */
    public final boolean perform(final EnumSet<Task> actualTasks, final String projectApps, String settingsModule,
            String requirementsFile, final boolean enableCoverage) throws InterruptedException, IOException {
        PrintStream logger = listener.getLogger();

        logger.println("Perfroming " + actualTasks);
        List<PythonInstallation> pInstalls;

        try {
            pInstalls = PythonInstallationFinder.configure();
        } catch (final NullPointerException e) {
            logger.println("No Python Installations found: " + e.getMessage());
            return false;
        }

        workspace = build.getWorkspace();
        if (workspace == null) {
            throw new IOException("No workspace found");
        }

        final String pythonName = pInstalls.get(0).getName();

        final ArrayList<String> commandList = new ArrayList<String>();
        /* First upgrade pip and friends */
        logger.println("Upgrade pip first.");
        commandList.add(PIP_INSTALL + PIP_UPGRADE + "pip");

        /* DjangoJenkins Requirements (can be overridden by project ones) */
        logger.println("Installing Django Requirements");
        commandList.add(installDjangoJenkinsRequirements(actualTasks, enableCoverage));

        /* Project Requirements */
        logger.println("Installing Project Requirements");
        commandList.add(installProjectRequirements(requirementsFile));

        logger.println("Building jenkins package/module");
        commandList.add(createBuildPackage(actualTasks, projectApps, settingsModule));

        logger.println("Adding jenkins tasks");
        String jenkinsCli = "$PYTHON_EXE manage.py jenkins";
        if (enableCoverage) {
            jenkinsCli += " " + ENABLE_COVERAGE;
        }
        commandList.add(jenkinsCli + "\n");

        final String command = StringUtils.join(commandList, "\n");
        logger.println("Command:\n" + command);

        logger.println("Final Command: ");
        logger.println(command);

        logger.println("Creating VirtualnevBuilder");
        final VirtualenvBuilder venv = new VirtualenvBuilder(pythonName, "django-jenkins", false, false, "Shell",
                command.toString(), false);
        logger.println("Performing in VirtualenvBuilder");
        return venv.perform(build, launcher, listener);
    }

    /**
     * Install django jenkins requirements.
     *
     * @param actualTasks
     *            the actual tasks
     * @param enableCoverage
     *            the enable coverage
     * @return the string
     */
    private String installDjangoJenkinsRequirements(final EnumSet<Task> actualTasks, final boolean enableCoverage) {
        PrintStream logger = listener.getLogger();
        String pip = PIP_INSTALL + PIP_UPGRADE + DJANGO_JENKINS_REQUIREMENTS;
        if (enableCoverage) {
            pip += " " + COVERAGE_REQUIREMENT;
        }

        for (final Task t : actualTasks) {
            if (t.getRequirements() != null) {
                pip += " " + t.getRequirements();
            } else {
                logger.println("WARINING: Task " + t.getName() + " has non-python requirements.");
            }
        }
        return pip;
    }

    /**
     * Install project requirements.
     * @param requirementsFile 
     *
     * @return the requirements file found
     * @throws InterruptedException, IOException
     */
    private String installProjectRequirements(String requirementsFile) throws InterruptedException, IOException {
        PrintStream logger = listener.getLogger();
        if (requirementsFile == null || (requirementsFile.trim().length() == 0)) {
            requirementsFile = "# No project requirements found";
            try {
                requirementsFile = workspace.act(new ProjectRequirementsFinder());
            } catch (final IOException e) {
                logger.println("No requirements file found:");
                logger.println(e.getMessage());
            }
        }
        return PIP_INSTALL + PIP_UPGRADE + " -r " + requirementsFile;
    }

    /**
     * Creates the build package.
     *
     * @param actualTasks
     *            the actual tasks
     * @param projectApps
     *            the project apps
     * @param settingsModule 
     * @return the string
     * @throws IOException
     *             Signals that an I/O exception has occurred.
     * @throws InterruptedException
     *             the interrupted exception
     */
    private String createBuildPackage(final EnumSet<Task> actualTasks, final String projectApps,
            final String settingsModule) throws IOException, InterruptedException {

        PrintStream logger = listener.getLogger();

        String actualProjectApps = projectApps;
        String actualSettings = settingsModule;
        final FilePath djModule = new FilePath(workspace, DJANGO_JENKINS_MODULE);
        logger.println("Finding Django project settings");
        if (actualSettings == null || (actualSettings.trim().length() == 0)) {
            logger.println("No settings provided. Trying to find one.");
            actualSettings = workspace.act(new DjangoProjectSettingsFinder());
        }

        logger.println("Creating Build Package");
        if (!djModule.act(new CreateBuildPackage())) {
            throw new IOException("Could not create Build Package.");
        }

        if ((actualProjectApps == null) || (actualProjectApps.trim().length() == 0)) {
            logger.println("No project apps provided. Trying to find some");
            actualProjectApps = workspace.act(new ProjectApplicationsFinder());
        }

        logger.println("Creating jenkins settings module");
        if (!djModule.act(new CreateDjangoModuleSettings(actualSettings, actualTasks, actualProjectApps))) {
            throw new IOException("Could not create jenkins setting module.");
        }

        logger.println("Returning settings: " + settingsModule);
        return "export DJANGO_SETTINGS_MODULE=" + DJANGO_JENKINS_MODULE + "." + DJANGO_JENKINS_SETTINGS;
    }
}