Skip to content
This repository has been archived by the owner on Oct 7, 2024. It is now read-only.

Commit

Permalink
Add condaBuild task to trigger conda build (#35)
Browse files Browse the repository at this point in the history
* Add condaBuild task to trigger conda build

* React to CR

* Add install task for conda build

* React to Justin's comments

* Satisfy Checkstyle

* Fix circle jvm brokenness by upgrading

* Make conda build --output-folder configurable

* Build with no upload, fail if meta.yaml broken, up to date setupCondaBuild

* Add condaBuildCheck to verify meta.yaml

* Use conda in bootstrap dir for setupCondaBuild

* Show more output in circle

* ignore exit value of check for conda build
  • Loading branch information
jakobjuelich authored and justinuang committed Mar 16, 2017
1 parent c5ed1d9 commit 3a1ebd5
Show file tree
Hide file tree
Showing 20 changed files with 498 additions and 23 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/build/
*.ipr
*.iws
out
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,24 @@ miniconda {
If you need to customize where the Miniconda installer script is downloaded from, you can add your artifact to the `minicondaInstaller`
configuration. The default location where it is downloaded from is: [`https://repo.continuum.io`](https://repo.continuum.io).

Tasks
-----

### bootstrapPython
Installs Miniconda.

### setupPython
Sets up conda environment in the project running `conda create`.

### condaBuildSetup
Installs conda-build using `conda install conda-build`.

### condaBuildCheck
Only checks (validates) the recipe.

### condaBuild
Builds and packages the project using `conda build`.

License
-------

Expand Down
7 changes: 2 additions & 5 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ dependencies {
testCompile('com.netflix.nebula:nebula-test:4.2.2') {
exclude group: 'org.codehaus.groovy'
}

testCompile 'com.google.code.findbugs:annotations:3.0.1'
}

pluginBundle {
Expand All @@ -68,8 +70,3 @@ pluginBundle {
}
}
}

test {
maxParallelForks = 10
forkEvery = 1
}
4 changes: 2 additions & 2 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
machine:
java:
version: oraclejdk7
version: oraclejdk8
environment:
TERM: dumb

Expand All @@ -14,7 +14,7 @@ dependencies:

test:
override:
- ./gradlew build
- ./gradlew build --info
post:
- mkdir -p "$CIRCLE_TEST_REPORTS/junit/"
- cp build/test-results/test/*.xml "$CIRCLE_TEST_REPORTS/junit/"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package com.palantir.python.miniconda;

import com.palantir.python.miniconda.tasks.BootstrapPython;
import com.palantir.python.miniconda.tasks.CondaBuild;
import com.palantir.python.miniconda.tasks.CondaBuildCheck;
import com.palantir.python.miniconda.tasks.SetupCondaBuild;
import com.palantir.python.miniconda.tasks.SetupPython;
import org.gradle.api.Action;
import org.gradle.api.Project;
Expand All @@ -35,16 +38,25 @@ public class AfterEvaluateAction implements Action<Project> {
private final Configuration configuration;
private final BootstrapPython bootstrapPython;
private final SetupPython setupPython;
private final SetupCondaBuild setupCondaBuild;
private final CondaBuildCheck condaBuildCheck;
private final CondaBuild condaBuild;

public AfterEvaluateAction(
OperatingSystem os,
Configuration configuration,
BootstrapPython bootstrapPython,
SetupPython setupPython) {
SetupPython setupPython,
SetupCondaBuild setupCondaBuild,
CondaBuildCheck condaBuildCheck,
CondaBuild condaBuild) {
this.os = os;
this.configuration = configuration;
this.bootstrapPython = bootstrapPython;
this.setupPython = setupPython;
this.setupCondaBuild = setupCondaBuild;
this.condaBuildCheck = condaBuildCheck;
this.condaBuild = condaBuild;
}

@Override
Expand All @@ -55,6 +67,9 @@ public void execute(Project project) {
addMinicondaInstallerDependency(project, miniconda);
bootstrapPython.configureAfterEvaluate(miniconda, configuration.getSingleFile(), os);
setupPython.configureAfterEvaluate(miniconda);
setupCondaBuild.configureAfterEvaluate(miniconda);
condaBuildCheck.configureAfterEvaluate(miniconda);
condaBuild.configureAfterEvaluate(miniconda);
}

private void addMinicondaInstallerDependency(final Project project, final MinicondaExtension miniconda) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand All @@ -38,6 +39,7 @@ public class MinicondaExtension {
private static final File DEFAULT_BOOTSTRAP_DIRECTORY_PREFIX =
new File(System.getProperty("user.home"), ".miniconda-bootstrap");
private static final String DEFAULT_BUILD_ENVIRONMENT_DIRECTORY = "build/miniconda";
private static final String DEFAULT_META_YAML_DIR = "conda_recipe/";
private static final int DEFAULT_PYTHON_VERSION = 2;

private final Project project;
Expand All @@ -46,6 +48,8 @@ public class MinicondaExtension {
private int pythonVersion = DEFAULT_PYTHON_VERSION;
private File bootstrapDirectoryPrefix = DEFAULT_BOOTSTRAP_DIRECTORY_PREFIX;
private File buildEnvironmentDirectory = null;
private File buildOutputDirectory = null;
private Path metaYaml = null;
private List<String> packages = new ArrayList<>();
private List<String> channels = new ArrayList<>(Collections.singletonList(DEFAULT_CHANNEL));

Expand Down Expand Up @@ -102,6 +106,29 @@ public File getBuildEnvironmentDirectory() {
return buildEnvironmentDirectory;
}

public File getBuildOutputDirectory() {
return buildOutputDirectory;
}

public void setMetaYaml(Path metaYaml) {
this.metaYaml = metaYaml;
}

public void setMetaYaml(File metaYaml) {
setMetaYaml(metaYaml.toPath());
}

public void setMetaYaml(String metaYaml) {
setMetaYaml(Paths.get(metaYaml));
}

public Path getMetaYaml() {
if (metaYaml == null) {
return project.file(DEFAULT_META_YAML_DIR).toPath();
}
return metaYaml;
}

public void setBuildEnvironmentDirectory(String buildEnvironmentDirectory) {
setBuildEnvironmentDirectory(new File(buildEnvironmentDirectory));
}
Expand All @@ -114,6 +141,18 @@ public void setBuildEnvironmentDirectory(File buildEnvironmentDirectory) {
this.buildEnvironmentDirectory = buildEnvironmentDirectory;
}

public void setBuildOutputDirectory(String buildOutputDirectory) {
setBuildOutputDirectory(new File(buildOutputDirectory));
}

public void setBuildOutputDirectory(Path buildOutputDirectory) {
setBuildOutputDirectory(buildOutputDirectory.toFile());
}

public void setBuildOutputDirectory(File buildOutputDirectory) {
this.buildOutputDirectory = buildOutputDirectory;
}

public String getMinicondaVersion() {
return minicondaVersion;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

import com.palantir.python.miniconda.tasks.BootstrapPython;
import com.palantir.python.miniconda.tasks.CleanTaskUtils;
import com.palantir.python.miniconda.tasks.CondaBuild;
import com.palantir.python.miniconda.tasks.CondaBuildCheck;
import com.palantir.python.miniconda.tasks.SetupCondaBuild;
import com.palantir.python.miniconda.tasks.SetupPython;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
Expand Down Expand Up @@ -51,6 +54,9 @@ public void apply(Project project) {
TaskContainer tasks = project.getTasks();
BootstrapPython bootstrapPython = BootstrapPython.createTask(tasks);
SetupPython setupPython = SetupPython.createTask(tasks, bootstrapPython);
SetupCondaBuild setupCondaBuild = SetupCondaBuild.createTask(tasks, setupPython);
CondaBuildCheck condaBuildCheck = CondaBuildCheck.createTask(tasks, setupCondaBuild);
CondaBuild condaBuild = CondaBuild.createTask(tasks, condaBuildCheck);

Task cleanBootstrapPython = project.getTasks().getByName(CleanTaskUtils.getCleanTaskName(bootstrapPython));
Task cleanSetupPython = project.getTasks().getByName(CleanTaskUtils.getCleanTaskName(setupPython));
Expand All @@ -60,7 +66,9 @@ public void apply(Project project) {

LOG.debug("MinicondaPlugin tasks created.");
Configuration configuration = project.getConfigurations().create(CONFIGURATION_NAME);
project.afterEvaluate(new AfterEvaluateAction(OS, configuration, bootstrapPython, setupPython));
project.afterEvaluate(
new AfterEvaluateAction(
OS, configuration, bootstrapPython, setupPython, setupCondaBuild, condaBuildCheck, condaBuild));
}

private static void createIvyRepository(Project project) {
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/com/palantir/python/miniconda/MinicondaUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* 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 com.palantir.python.miniconda;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public final class MinicondaUtils {

public static List<String> convertChannelsToArgs(List<String> channels) {
List<String> args = new ArrayList<>();
for (String channel : channels) {
args.add("--channel");
args.add(channel);
}
return Collections.unmodifiableList(args);
}

private MinicondaUtils() {}
}
70 changes: 70 additions & 0 deletions src/main/java/com/palantir/python/miniconda/tasks/CondaBuild.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* 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 com.palantir.python.miniconda.tasks;

import com.palantir.python.miniconda.MinicondaExtension;
import com.palantir.python.miniconda.MinicondaUtils;
import java.util.Objects;
import org.gradle.api.tasks.AbstractExecTask;
import org.gradle.api.tasks.TaskContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Task which builds and packages a Conda package.
*
* @author jakobjuelich
*/
public class CondaBuild extends AbstractExecTask<CondaBuild> {
private static final Logger LOG = LoggerFactory.getLogger(CondaBuild.class);

private static final String DEFAULT_GROUP = "build";
private static final String DEFAULT_DESCRIPTION = "Builds conda package using conda-build.";

public static CondaBuild createTask(TaskContainer tasks, CondaBuildCheck condaBuildCheck) {
Objects.requireNonNull(tasks, "tasks must not be null");
Objects.requireNonNull(condaBuildCheck, "condaBuildCheck must not be null");

CondaBuild task = tasks.create("condaBuild", CondaBuild.class);
task.setGroup(DEFAULT_GROUP);
task.setDescription(DEFAULT_DESCRIPTION);
task.dependsOn(condaBuildCheck);

CleanTaskUtils.createCleanupTask(tasks, task);
return task;
}

public CondaBuild() {
super(CondaBuild.class);
}

public void configureAfterEvaluate(final MinicondaExtension miniconda) {
Objects.requireNonNull(miniconda, "miniconda must not be null");

executable(miniconda.getBuildEnvironmentDirectory().toPath().resolve("bin/conda"));
args("build", miniconda.getMetaYaml());
args("--override-channels");
args("--no-anaconda-upload");
args(MinicondaUtils.convertChannelsToArgs(miniconda.getChannels()));
if (miniconda.getBuildOutputDirectory() != null) {
args("--output-folder", miniconda.getBuildOutputDirectory().getAbsolutePath());
}

LOG.info("{} configured to execute {}", getName(), getCommandLine());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Copyright 2017 Palantir Technologies, Inc. All rights reserved.
*
* 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 com.palantir.python.miniconda.tasks;

import com.palantir.python.miniconda.MinicondaExtension;
import java.util.Objects;
import org.gradle.api.tasks.AbstractExecTask;
import org.gradle.api.tasks.TaskContainer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Task to run conda build --check to only check (validate) the recipe.
*
* @author jakobjuelich
*/
public class CondaBuildCheck extends AbstractExecTask<CondaBuildCheck> {
private static final Logger LOG = LoggerFactory.getLogger(CondaBuildCheck.class);

private static final String DEFAULT_GROUP = "build";
private static final String DEFAULT_DESCRIPTION = "Runs `conda build --check` to only check (validate) the recipe.";

public static CondaBuildCheck createTask(TaskContainer tasks, SetupCondaBuild setupCondaBuild) {
Objects.requireNonNull(tasks, "tasks must not be null");
Objects.requireNonNull(setupCondaBuild, "setupCondaBuild must not be null");

CondaBuildCheck task = tasks.create("condaBuildCheck", CondaBuildCheck.class);
task.setGroup(DEFAULT_GROUP);
task.setDescription(DEFAULT_DESCRIPTION);
task.dependsOn(setupCondaBuild);

CleanTaskUtils.createCleanupTask(tasks, task);
return task;
}

public CondaBuildCheck() {
super(CondaBuildCheck.class);
}

public void configureAfterEvaluate(final MinicondaExtension miniconda) {
Objects.requireNonNull(miniconda, "miniconda must not be null");

executable(miniconda.getBuildEnvironmentDirectory().toPath().resolve("bin/conda"));
args("build", miniconda.getMetaYaml());
args("--check");

LOG.info("{} configured to execute {}", getName(), getCommandLine());
}

}
Loading

0 comments on commit 3a1ebd5

Please sign in to comment.