You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/02/01 18:35:21 UTC

[41/51] [abbrv] brooklyn-dist git commit: move subdir from incubator up a level as it is promoted to its own repo (first non-incubator commit!)

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/dist/src/main/license/files/NOTICE
----------------------------------------------------------------------
diff --git a/dist/src/main/license/files/NOTICE b/dist/src/main/license/files/NOTICE
new file mode 100644
index 0000000..f790f13
--- /dev/null
+++ b/dist/src/main/license/files/NOTICE
@@ -0,0 +1,5 @@
+Apache Brooklyn
+Copyright 2014-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/dist/src/test/java/org/apache/brooklyn/cli/BaseCliIntegrationTest.java
----------------------------------------------------------------------
diff --git a/dist/src/test/java/org/apache/brooklyn/cli/BaseCliIntegrationTest.java b/dist/src/test/java/org/apache/brooklyn/cli/BaseCliIntegrationTest.java
new file mode 100644
index 0000000..4cb2d2b
--- /dev/null
+++ b/dist/src/test/java/org/apache/brooklyn/cli/BaseCliIntegrationTest.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.brooklyn.cli;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.NoSuchElementException;
+import java.util.Scanner;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.apache.brooklyn.core.entity.factory.ApplicationBuilder;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Command line interface test support.
+ */
+public class BaseCliIntegrationTest {
+
+    // TODO does this need to be hard-coded?
+    private static final String BROOKLYN_BIN_PATH = "./target/brooklyn-dist/bin/brooklyn";
+    private static final String BROOKLYN_CLASSPATH = "./target/test-classes/:./target/classes/";
+
+    // Times in seconds to allow Brooklyn to run and produce output
+    private static final long DELAY = 10l;
+    private static final long TIMEOUT = DELAY + 30l;
+
+    private ExecutorService executor;
+
+    @BeforeMethod(alwaysRun = true)
+    public void setup() {
+        executor = Executors.newCachedThreadPool();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void teardown() {
+        executor.shutdownNow();
+    }
+
+    /** Invoke the brooklyn script with arguments. */
+    public Process startBrooklyn(String...argv) throws Throwable {
+        ProcessBuilder pb = new ProcessBuilder();
+        pb.environment().remove("BROOKLYN_HOME");
+        pb.environment().put("BROOKLYN_CLASSPATH", BROOKLYN_CLASSPATH);
+        pb.command(Lists.asList(BROOKLYN_BIN_PATH, argv));
+        return pb.start();
+    }
+
+    public void testBrooklyn(Process brooklyn, BrooklynCliTest test, int expectedExit) throws Throwable {
+        testBrooklyn(brooklyn, test, expectedExit, false);
+    }
+
+    /** Tests the operation of the Brooklyn CLI. */
+    public void testBrooklyn(Process brooklyn, BrooklynCliTest test, int expectedExit, boolean stop) throws Throwable {
+        try {
+            Future<Integer> future = executor.submit(test);
+
+            // Send CR to stop if required
+            if (stop) {
+                OutputStream out = brooklyn.getOutputStream();
+                out.write('\n');
+                out.flush();
+            }
+
+            int exitStatus = future.get(TIMEOUT, TimeUnit.SECONDS);
+
+            // Check error code from process
+            assertEquals(exitStatus, expectedExit, "Command returned wrong status");
+        } catch (TimeoutException te) {
+            fail("Timed out waiting for process to complete", te);
+        } catch (ExecutionException ee) {
+            if (ee.getCause() instanceof AssertionError) {
+                throw ee.getCause();
+            } else throw ee;
+        } finally {
+            brooklyn.destroy();
+        }
+    }
+
+    /** A {@link Callable} that encapsulates Brooklyn CLI test logic. */
+    public static abstract class BrooklynCliTest implements Callable<Integer> {
+
+        private final Process brooklyn;
+
+        private String consoleOutput;
+        private String consoleError;
+
+        public BrooklynCliTest(Process brooklyn) {
+            this.brooklyn = brooklyn;
+        }
+
+        @Override
+        public Integer call() throws Exception {
+            // Wait for initial output
+            Thread.sleep(TimeUnit.SECONDS.toMillis(DELAY));
+
+            // Get the console output of running that command
+            consoleOutput = convertStreamToString(brooklyn.getInputStream());
+            consoleError = convertStreamToString(brooklyn.getErrorStream());
+
+            // Check if the output looks as expected
+            checkConsole();
+
+            // Return exit status on completion
+            return brooklyn.waitFor();
+        }
+
+        /** Perform test assertions on console output and error streams. */
+        public abstract void checkConsole();
+
+        private String convertStreamToString(InputStream is) {
+            try {
+                return new Scanner(is).useDelimiter("\\A").next();
+            } catch (NoSuchElementException e) {
+                return "";
+            }
+        }
+
+        protected void assertConsoleOutput(String...expected) {
+            for (String e : expected) {
+                assertTrue(consoleOutput.contains(e), "Execution output not logged; output=" + consoleOutput);
+            }
+        }
+
+        protected void assertNoConsoleOutput(String...expected) {
+            for (String e : expected) {
+                assertFalse(consoleOutput.contains(e), "Execution output logged; output=" + consoleOutput);
+            }
+        }
+
+        protected void assertConsoleError(String...expected) {
+            for (String e : expected) {
+                assertTrue(consoleError.contains(e), "Execution error not logged; error=" + consoleError);
+            }
+        }
+
+        protected void assertNoConsoleError(String...expected) {
+            for (String e : expected) {
+                assertFalse(consoleError.contains(e), "Execution error logged; error=" + consoleError);
+            }
+        }
+
+        protected void assertConsoleOutputEmpty() {
+            assertTrue(consoleOutput.isEmpty(), "Output present; output=" + consoleOutput);
+        }
+
+        protected void assertConsoleErrorEmpty() {
+            assertTrue(consoleError.isEmpty(), "Error present; error=" + consoleError);
+        }
+    };
+
+    /** An empty application for testing. */
+    public static class TestApplication extends ApplicationBuilder {
+        @Override
+        protected void doBuild() {
+            // Empty, for testing
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/dist/src/test/java/org/apache/brooklyn/cli/CliIntegrationTest.java
----------------------------------------------------------------------
diff --git a/dist/src/test/java/org/apache/brooklyn/cli/CliIntegrationTest.java b/dist/src/test/java/org/apache/brooklyn/cli/CliIntegrationTest.java
new file mode 100644
index 0000000..adf9559
--- /dev/null
+++ b/dist/src/test/java/org/apache/brooklyn/cli/CliIntegrationTest.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.apache.brooklyn.cli;
+
+import org.testng.annotations.Test;
+
+/**
+ * Test the command line interface operation.
+ */
+public class CliIntegrationTest extends BaseCliIntegrationTest {
+
+    /**
+     * Checks if running {@code brooklyn help} produces the expected output.
+     */
+    @Test(groups = {"Integration","Broken"})
+    public void testLaunchCliHelp() throws Throwable {
+        final Process brooklyn = startBrooklyn("help");
+
+        BrooklynCliTest test = new BrooklynCliTest(brooklyn) {
+            @Override
+            public void checkConsole() {
+                assertConsoleOutput("usage: brooklyn"); // Usage info not present
+                assertConsoleOutput("The most commonly used brooklyn commands are:");
+                assertConsoleOutput("help     Display help for available commands",
+                                    "info     Display information about brooklyn",
+                                    "launch   Starts a brooklyn application"); // List of common commands not present
+                assertConsoleOutput("See 'brooklyn help <command>' for more information on a specific command.");
+                assertConsoleErrorEmpty();
+            }
+        };
+
+        testBrooklyn(brooklyn, test, 0);
+    }
+
+    /*
+        Exception java.io.IOException
+        
+        Message: Cannot run program "./target/brooklyn-dist/bin/brooklyn": error=2, No such file or directory
+        Stacktrace:
+        
+        
+        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1047)
+        at org.apache.brooklyn.cli.BaseCliIntegrationTest.startBrooklyn(BaseCliIntegrationTest.java:75)
+        at org.apache.brooklyn.cli.CliIntegrationTest.testLaunchCliApp(CliIntegrationTest.java:56)
+        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+        at java.lang.reflect.Method.invoke(Method.java:606)
+        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
+        at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
+        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
+        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
+        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
+        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
+        at org.testng.TestRunner.privateRun(TestRunner.java:767)
+        at org.testng.TestRunner.run(TestRunner.java:617)
+        at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
+        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
+        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
+        at org.testng.SuiteRunner.run(SuiteRunner.java:254)
+        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
+        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
+        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
+        at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
+        at org.testng.TestNG.run(TestNG.java:1057)
+        at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)
+        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:205)
+        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
+        at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
+        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
+        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
+        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
+        Caused by: java.io.IOException: error=2, No such file or directory
+        at java.lang.UNIXProcess.forkAndExec(Native Method)
+        at java.lang.UNIXProcess.<init>(UNIXProcess.java:186)
+        at java.lang.ProcessImpl.start(ProcessImpl.java:130)
+        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1028)
+        ... 30 more
+     */
+    /**
+     * Checks if launching an application using {@code brooklyn launch} produces the expected output.
+     */
+    @Test(groups = {"Integration","Broken"})
+    public void testLaunchCliApp() throws Throwable {
+        final Process brooklyn = startBrooklyn("--verbose", "launch", "--stopOnKeyPress", "--app", "org.apache.brooklyn.cli.BaseCliIntegrationTest$TestApplication", "--location", "localhost", "--noConsole");
+
+        BrooklynCliTest test = new BrooklynCliTest(brooklyn) {
+            @Override
+            public void checkConsole() {
+                assertConsoleOutput("Launching brooklyn app:"); // Launch message not output
+                assertNoConsoleOutput("Initiating Jersey application"); // Web console started
+                assertConsoleOutput("Started application BasicApplicationImpl"); // Application not started
+                assertConsoleOutput("Server started. Press return to stop."); // Server started message not output
+                assertConsoleErrorEmpty();
+            }
+        };
+
+        testBrooklyn(brooklyn, test, 0, true);
+    }
+
+    /**
+     * Checks if a correct error and help message is given if using incorrect param.
+     */
+    @Test(groups = {"Integration","Broken"})
+    public void testLaunchCliAppParamError() throws Throwable {
+        final Process brooklyn = startBrooklyn("launch", "nothing", "--app");
+
+        BrooklynCliTest test = new BrooklynCliTest(brooklyn) {
+            @Override
+            public void checkConsole() {
+                assertConsoleError("Parse error: Required values for option 'application class or file' not provided");
+                assertConsoleError("NAME", "SYNOPSIS", "OPTIONS", "COMMANDS");
+                assertConsoleOutputEmpty();
+            }
+        };
+
+        testBrooklyn(brooklyn, test, 1);
+    }
+
+    /*
+        Exception java.io.IOException
+        
+        Message: Cannot run program "./target/brooklyn-dist/bin/brooklyn": error=2, No such file or directory
+        Stacktrace:
+        
+        
+        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1047)
+        at org.apache.brooklyn.cli.BaseCliIntegrationTest.startBrooklyn(BaseCliIntegrationTest.java:75)
+        at org.apache.brooklyn.cli.CliIntegrationTest.testLaunchCliAppCommandError(CliIntegrationTest.java:96)
+        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
+        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
+        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
+        at java.lang.reflect.Method.invoke(Method.java:606)
+        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
+        at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
+        at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
+        at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
+        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
+        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
+        at org.testng.TestRunner.privateRun(TestRunner.java:767)
+        at org.testng.TestRunner.run(TestRunner.java:617)
+        at org.testng.SuiteRunner.runTest(SuiteRunner.java:348)
+        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:343)
+        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:305)
+        at org.testng.SuiteRunner.run(SuiteRunner.java:254)
+        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
+        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
+        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
+        at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
+        at org.testng.TestNG.run(TestNG.java:1057)
+        at org.apache.maven.surefire.testng.TestNGExecutor.run(TestNGExecutor.java:115)
+        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.executeMulti(TestNGDirectoryTestSuite.java:205)
+        at org.apache.maven.surefire.testng.TestNGDirectoryTestSuite.execute(TestNGDirectoryTestSuite.java:108)
+        at org.apache.maven.surefire.testng.TestNGProvider.invoke(TestNGProvider.java:111)
+        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:203)
+        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:155)
+        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:103)
+        Caused by: java.io.IOException: error=2, No such file or directory
+        at java.lang.UNIXProcess.forkAndExec(Native Method)
+        at java.lang.UNIXProcess.<init>(UNIXProcess.java:186)
+        at java.lang.ProcessImpl.start(ProcessImpl.java:130)
+        at java.lang.ProcessBuilder.start(ProcessBuilder.java:1028)
+        ... 30 more
+     */
+    /**
+     * Checks if a correct error and help message is given if using incorrect command.
+     */
+    @Test(groups = "Integration")
+    public void testLaunchCliAppCommandError() throws Throwable {
+        final Process brooklyn = startBrooklyn("biscuit");
+
+        BrooklynCliTest test = new BrooklynCliTest(brooklyn) {
+            @Override
+            public void checkConsole() {
+                assertConsoleError("Parse error: No command specified");
+                assertConsoleError("NAME", "SYNOPSIS", "OPTIONS", "COMMANDS");
+                assertConsoleOutputEmpty();
+            }
+        };
+
+        testBrooklyn(brooklyn, test, 1);
+    }
+
+    /**
+     * Checks if a correct error and help message is given if using incorrect application.
+     */
+    @Test(groups = {"Integration","Broken"})
+    public void testLaunchCliAppLaunchError() throws Throwable {
+        final String app = "org.eample.DoesNotExist";
+        final Process brooklyn = startBrooklyn("launch", "--app", app, "--location", "nowhere");
+
+        BrooklynCliTest test = new BrooklynCliTest(brooklyn) {
+            @Override
+            public void checkConsole() {
+                assertConsoleOutput(app, "not found");
+                assertConsoleError("ERROR", "Fatal", "getting resource", app);
+            }
+        };
+
+        testBrooklyn(brooklyn, test, 2);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/downstream-parent/pom.xml
----------------------------------------------------------------------
diff --git a/downstream-parent/pom.xml b/downstream-parent/pom.xml
new file mode 100644
index 0000000..f97dba3
--- /dev/null
+++ b/downstream-parent/pom.xml
@@ -0,0 +1,524 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.brooklyn</groupId>
+    <artifactId>brooklyn-server</artifactId>
+    <version>0.9.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+    <relativePath>../../brooklyn-server/pom.xml</relativePath>
+    <!-- TODO this uses server root pom as a way to get version info without rat check;
+         it means it inherits apache pom, which might not be desired.
+         probably cleaner NOT to have a downstream-parent, instead for project to redeclare their tasks.
+         (yes it violates DRY, but until Maven 4 supporting Mixins that is probably better than
+         hacks in a parent hierarchy to which people won't have visibility. -->
+  </parent>
+
+  <artifactId>brooklyn-downstream-parent</artifactId>
+  <packaging>pom</packaging>
+  <name>Brooklyn Downstream Project Parent</name>
+  <description>
+      Parent pom that can be used by downstream projects that use Brooklyn,
+      or that contribute additional functionality to Brooklyn.
+  </description>
+
+  <properties>
+    <!-- Compilation -->
+    <java.version>1.7</java.version>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+    <!-- Testing -->
+    <testng.version>6.8.8</testng.version>
+    <surefire.version>2.18.1</surefire.version>
+    <includedTestGroups />
+    <excludedTestGroups>Integration,Acceptance,Live,Live-sanity,WIP</excludedTestGroups>
+
+    <!-- Dependencies -->
+    <brooklyn.version>0.9.0-SNAPSHOT</brooklyn.version>  <!-- BROOKLYN_VERSION -->
+    <jclouds.groupId>org.apache.jclouds</jclouds.groupId> <!-- JCLOUDS_GROUPID_VERSION -->
+
+    <!-- versions should match those used by Brooklyn, to avoid conflicts -->
+    <jclouds.version>1.9.2</jclouds.version> <!-- JCLOUDS_VERSION -->
+    <logback.version>1.0.7</logback.version>
+    <slf4j.version>1.6.6</slf4j.version>  <!-- used for java.util.logging jul-to-slf4j interception -->
+    <guava.version>17.0</guava.version>
+    <xstream.version>1.4.7</xstream.version>
+    <jackson.version>1.9.13</jackson.version>  <!-- codehaus jackson, used by brooklyn rest server -->
+    <fasterxml.jackson.version>2.4.5</fasterxml.jackson.version>  <!-- more recent jackson, but not compatible with old annotations! -->
+    <jersey.version>1.19</jersey.version>
+    <httpclient.version>4.4.1</httpclient.version>
+    <commons-lang3.version>3.1</commons-lang3.version>
+    <groovy.version>2.3.7</groovy.version> <!-- Version supported by https://github.com/groovy/groovy-eclipse/wiki/Groovy-Eclipse-2.9.1-Release-Notes -->
+    <jsr305.version>2.0.1</jsr305.version>
+    <snakeyaml.version>1.11</snakeyaml.version>
+  </properties>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <!-- this would pull in all brooklyn entities and clouds;
+             you can cherry pick selected ones instead (for a smaller build) -->
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-all</artifactId>
+        <version>${brooklyn.version}</version>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <!-- this gives us flexible and easy-to-use logging; just edit logback-custom.xml! -->
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-logback-xml</artifactId>
+      <version>${brooklyn.version}</version>
+      <!-- optional so that this project has logging; dependencies may redeclare or supply their own;
+           provided so that it isn't put into the assembly (as it supplies its own explicit logback.xml);
+           see Logging in the Brooklyn website/userguide for more info -->
+      <optional>true</optional>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <!-- includes testng and useful logging for tests -->
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-test-support</artifactId>
+      <version>${brooklyn.version}</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <!-- includes org.apache.brooklyn.test.support.LoggingVerboseReporter -->
+      <groupId>org.apache.brooklyn</groupId>
+      <artifactId>brooklyn-utils-test-support</artifactId>
+      <version>${brooklyn.version}</version>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <testSourceDirectory>src/test/java</testSourceDirectory>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+      </testResource>
+    </testResources>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <artifactId>maven-assembly-plugin</artifactId>
+          <version>2.5.4</version>
+          <configuration>
+            <tarLongFileMode>gnu</tarLongFileMode>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-clean-plugin</artifactId>
+          <version>2.6.1</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.3</version>
+          <configuration>
+            <source>${java.version}</source>
+            <target>${java.version}</target>
+          </configuration>
+        </plugin>
+        <plugin>
+          <artifactId>maven-deploy-plugin</artifactId>
+          <version>2.8.2</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-eclipse-plugin</artifactId>
+          <version>2.10</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-enforcer-plugin</artifactId>
+          <version>1.4</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-failsafe-plugin</artifactId>
+          <version>2.18.1</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-gpg-plugin</artifactId>
+          <version>1.6</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.6</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>2.10.3</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-resources-plugin</artifactId>
+          <version>2.7</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-source-plugin</artifactId>
+          <version>2.4</version>
+        </plugin>
+        <plugin>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.18.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.felix</groupId>
+          <artifactId>maven-bundle-plugin</artifactId>
+          <version>2.3.4</version>
+        </plugin>
+        <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+        <plugin>
+          <groupId>org.eclipse.m2e</groupId>
+          <artifactId>lifecycle-mapping</artifactId>
+          <version>1.0.0</version>
+          <configuration>
+            <lifecycleMappingMetadata>
+              <pluginExecutions>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-assembly-plugin</artifactId>
+                    <versionRange>[2.4.1,)</versionRange>
+                    <goals>
+                      <goal>single</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>build-helper-maven-plugin</artifactId>
+                    <versionRange>[1.7,)</versionRange>
+                    <goals>
+                      <goal>attach-artifact</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-enforcer-plugin</artifactId>
+                    <versionRange>[1.3.1,)</versionRange>
+                    <goals>
+                      <goal>enforce</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-remote-resources-plugin</artifactId>
+                    <versionRange>[1.5,)</versionRange>
+                    <goals>
+                      <goal>process</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <versionRange>[2.8,)</versionRange>
+                    <goals>
+                      <goal>unpack</goal>
+                      <goal>copy</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>com.github.skwakman.nodejs-maven-plugin</groupId>
+                    <artifactId>nodejs-maven-plugin</artifactId>
+                    <versionRange>[1.0.3,)</versionRange>
+                    <goals>
+                      <goal>extract</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-war-plugin</artifactId>
+                    <versionRange>[2.4,)</versionRange>
+                    <goals>
+                      <goal>exploded</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
+              </pluginExecutions>
+             </lifecycleMappingMetadata>
+           </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+
+    <plugins>
+      <plugin>
+        <artifactId>maven-clean-plugin</artifactId>
+        <configuration>
+          <filesets>
+            <fileset>
+              <directory>.</directory>
+              <includes>
+                <include>brooklyn*.log</include>
+                <include>brooklyn*.log.*</include>
+                <include>stacktrace.log</include>
+                <include>test-output</include>
+                <include>prodDb.*</include>
+              </includes>
+            </fileset>
+          </filesets>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-eclipse-plugin</artifactId>
+        <configuration>
+          <additionalProjectnatures>
+            <projectnature>org.maven.ide.eclipse.maven2Nature</projectnature>
+          </additionalProjectnatures>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <argLine>-Xms256m -Xmx512m -XX:MaxPermSize=512m</argLine>
+          <properties>
+            <property>
+              <name>listener</name>
+              <value>org.apache.brooklyn.test.support.LoggingVerboseReporter</value>
+            </property>
+          </properties>
+          <enableAssertions>true</enableAssertions>
+          <groups>${includedTestGroups}</groups>
+          <excludedGroups>${excludedTestGroups}</excludedGroups>
+          <testFailureIgnore>false</testFailureIgnore>
+          <systemPropertyVariables>
+            <verbose>-1</verbose>
+            <net.sourceforge.cobertura.datafile>${project.build.directory}/cobertura/cobertura.ser</net.sourceforge.cobertura.datafile>
+            <cobertura.user.java.nio>false</cobertura.user.java.nio>
+          </systemPropertyVariables>
+          <printSummary>true</printSummary>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <profiles>
+
+    <profile>
+      <id>Tests</id>
+      <activation>
+        <file> <exists>${basedir}/src/test</exists> </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-jar-plugin</artifactId>
+            <inherited>true</inherited>
+            <executions>
+              <execution>
+                <id>test-jar-creation</id>
+                <goals>
+                  <goal>test-jar</goal>
+                </goals>
+                <configuration>
+                  <forceCreation>true</forceCreation>
+                  <archive combine.self="override" />
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <!-- run Integration tests with -PIntegration -->
+    <profile>
+      <id>Integration</id>
+      <properties>
+        <includedTestGroups>Integration</includedTestGroups>
+        <excludedTestGroups>Acceptance,Live,Live-sanity,WIP</excludedTestGroups>
+      </properties>
+    </profile>
+
+    <!-- run Live tests with -PLive -->
+    <profile>
+      <id>Live</id>
+      <properties>
+        <includedTestGroups>Live,Live-sanity</includedTestGroups>
+        <excludedTestGroups>Acceptance,WIP</excludedTestGroups>
+      </properties>
+    </profile>
+
+    <!-- run Live-sanity tests with -PLive-sanity -->
+    <profile>
+      <id>Live-sanity</id>
+      <properties>
+        <includedTestGroups>Live-sanity</includedTestGroups>
+        <excludedTestGroups>Acceptance,WIP</excludedTestGroups>
+      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-jar-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>test-jar-creation</id>
+                <configuration>
+                  <skip>true</skip>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>Bundle</id>
+      <activation>
+        <file>
+          <!-- NB - this is all the leaf projects, including logback-* (with no src);
+               the archetype project neatly ignores this however -->
+          <exists>${basedir}/src</exists>
+        </file>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>maven-bundle-plugin</artifactId>
+            <extensions>true</extensions>
+            <!-- configure plugin to generate MANIFEST.MF
+                 adapted from http://blog.knowhowlab.org/2010/06/osgi-tutorial-from-project-structure-to.html -->
+            <executions>
+              <execution>
+                <id>bundle-manifest</id>
+                <phase>process-classes</phase>
+                <goals>
+                  <goal>manifest</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <supportedProjectTypes>
+                <supportedProjectType>jar</supportedProjectType>
+              </supportedProjectTypes>
+              <instructions>
+                <!--
+                  Exclude packages used by Brooklyn that are not OSGi bundles. Including any
+                  of the below may cause bundles to fail to load into the catalogue with
+                  messages like "Unable to resolve 150.0: missing requirement [150.0]
+                  osgi.wiring.package; (osgi.wiring.package=com.maxmind.geoip2)".
+                -->
+                <Import-Package>
+                  !com.maxmind.geoip2.*,
+                  !io.airlift.command.*,
+                  !io.cloudsoft.winrm4j.*,
+                  !javax.inject.*,
+                  !org.apache.felix.framework.*,
+                  !org.apache.http.*,
+                  !org.jclouds.googlecomputeengine.*,
+                  !org.osgi.jmx,
+                  !org.python.*,
+                  !org.reflections.*,
+                  !org.w3c.tidy.*,
+                  *
+                </Import-Package>
+                <!--
+                  Brooklyn-Feature prefix triggers inclusion of the project's metadata in the
+                  server's features list.
+                -->
+                <Brooklyn-Feature-Name>${project.name}</Brooklyn-Feature-Name>
+              </instructions>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+            <configuration>
+              <archive>
+                <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+              </archive>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <!-- different properties used to deploy to different locations depending on profiles;
+         default is cloudsoft filesystem repo, but some sources still use cloudsoft artifactory as source
+         and soon we will support artifactory. use this profile for the ASF repositories and
+         sonatype-oss-release profile for the Sonatype OSS repositories.
+    -->
+    <!-- profile>
+      <id>apache-release</id>
+      <activation>
+        <property>
+          <name>brooklyn.deployTo</name>
+          <value>apache</value>
+        </property>
+      </activation>
+      <distributionManagement>
+        <repository>
+          <id>apache.releases.https</id>
+          <name>Apache Release Distribution Repository</name>
+          <url>https://repository.apache.org/service/local/staging/deploy/maven2</url>
+        </repository>
+        <snapshotRepository>
+          <id>apache.snapshots.https</id>
+          <name>Apache Development Snapshot Repository</name>
+          <url>https://repository.apache.org/content/repositories/snapshots</url>
+        </snapshotRepository>
+      </distributionManagement>
+    </profile -->
+  </profiles>
+
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..12ebdd9
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.brooklyn</groupId>
+        <artifactId>brooklyn-parent</artifactId>
+        <version>0.9.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+        <relativePath>../brooklyn-server/parent/pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.brooklyn</groupId>
+    <artifactId>brooklyn-dist-root</artifactId>
+    <version>0.9.0-SNAPSHOT</version>  <!-- BROOKLYN_VERSION -->
+    <packaging>pom</packaging>
+
+    <name>Brooklyn Dist Root</name>
+    <description>
+        Brooklyn Dist project root, serving as the ancestor POM for dist projects --
+        declaring modules to build
+    </description>
+    <url>https://brooklyn.apache.org/</url>
+    <inceptionYear>2012</inceptionYear>
+
+    <developers>
+        <!-- TODO update with PMC members and committers -->
+    </developers>
+
+    <scm>
+        <connection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-brooklyn.git</connection>
+        <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/incubator-brooklyn.git</developerConnection>
+        <url>https://git-wip-us.apache.org/repos/asf?p=incubator-brooklyn.git</url>
+        <tag>HEAD</tag>
+    </scm>
+
+    <issueManagement>
+        <system>JIRA</system>
+        <url>https://issues.apache.org/jira/browse/BROOKLYN</url>
+    </issueManagement>
+    <ciManagement>
+        <system>Jenkins</system>
+        <url>https://builds.apache.org/job/incubator-brooklyn-master-build/</url>
+    </ciManagement>
+    <mailingLists>
+        <mailingList>
+            <name>Brooklyn Developer List</name>
+            <subscribe>dev-subscribe@brooklyn.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@brooklyn.apache.org</unsubscribe>
+            <post>dev@brooklyn.apache.org</post>
+            <archive>
+                http://mail-archives.apache.org/mod_mbox/brooklyn-dev/
+            </archive>
+        </mailingList>
+    </mailingLists>
+
+    <modules>
+        <module>downstream-parent</module>
+        <module>all</module>
+        <module>dist</module>
+        <module>vagrant</module>
+        <module>archetypes/quickstart</module>
+    </modules>
+
+</project>

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/.gitignore
----------------------------------------------------------------------
diff --git a/release/.gitignore b/release/.gitignore
new file mode 100644
index 0000000..16d63d3
--- /dev/null
+++ b/release/.gitignore
@@ -0,0 +1,2 @@
+.vagrant
+tmp

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/README.md
----------------------------------------------------------------------
diff --git a/release/README.md b/release/README.md
new file mode 100644
index 0000000..325b165
--- /dev/null
+++ b/release/README.md
@@ -0,0 +1,50 @@
+Release Scripts and Helpers
+===========================
+
+This folder contains a number of items that will assist in the production of Brooklyn releases.
+
+
+Release scripts - change-version.sh and make-release-artifacts.sh
+-----------------------------------------------------------------
+
+`change-version.sh` will update version numbers across the whole distribution.  It is recommended to use this script
+rather than "rolling your own" or using a manual process, as you risk missing out some version numbers (and
+accidentally changing some that should not be changed).
+
+`make-release-artifacts.sh` will produce the release artifacts with appropriate signatures. It is recommended to use
+this script rather than "rolling your own" or using a manual process, as this script codifies several Apache
+requirements about the release artifacts.
+
+These scripts are fully documented in **Release Process** pages on the website.
+
+
+Vagrant configuration
+---------------------
+
+The `Vagrantfile` and associated files `settings.xml` and `gpg-agent.conf` are for setting up a virtual machine hosting
+a complete and clean development environment. You may benefit from using this environment when making the release, but
+it is not required that you do so.
+
+The environment is a single VM that configured with all the tools needed to make the release. It also configures GnuPG
+by copying your `gpg.conf`, `secring.gpg` and `pubring.gpg` into the VM; also copied is your `.gitconfig`. The
+GnuPG agent is configured to assist with the release signing by caching your passphrase, so you will only need to enter
+it once during the build process. A Maven `settings.xml` is provided to assist with the upload to Apache's Nexus server.
+Finally the canonical Git repository for Apache Brooklyn is cloned into the home directory.
+
+You should edit `settings.xml` before deployment, or `~/.m2/settings.xml` inside the VM after deployment, to include
+your Apache credentials.
+
+Assuming you have VirtualBox and Vagrant already installed, you should simply be able to run `vagrant up` to create the
+VM, and then `vagrant ssh` to get a shell prompt inside the VM. Finally run `vagrant destroy` to clean up afterwards.
+
+This folder is mounted at `/vagrant` inside the VM - this means the release helpers are close to hand, so you can
+run for example `/vagrant/make-release/artifacts.sh`.
+
+
+Pull request reporting
+----------------------
+
+The files in `pull-request-reports`, mainly `pr_report.rb` 
+(and associated files `Gemfile` and `Gemfile.lock`) uses the GitHub API to extract a list of open pull
+requests, and writes a summary into `pr_report.tsv`. This could then be imported into Google Sheets to provide a handy
+way of classifying and managing outstanding PRs ahead of making a release.

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/Vagrantfile
----------------------------------------------------------------------
diff --git a/release/Vagrantfile b/release/Vagrantfile
new file mode 100644
index 0000000..016c48f
--- /dev/null
+++ b/release/Vagrantfile
@@ -0,0 +1,66 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+# Vagrantfile that creates a basic workstation for compiling Brooklyn and
+# running tests. Particularly useful for running integration tests, as you
+# can clean up any failed tests simply by destroying and rebuilding the
+# Vagrant instance.
+
+# All Vagrant configuration is done below. The "2" in Vagrant.configure
+# configures the configuration version (we support older styles for
+# backwards compatibility). Please don't change it unless you know what
+# you're doing.
+Vagrant.configure(2) do |config|
+
+  # Base on Ubuntu 14.04 LTS
+  config.vm.box = "ubuntu/trusty64"
+
+  # Provider-specific configuration so you can fine-tune various
+  # backing providers for Vagrant. These expose provider-specific options.
+  config.vm.provider "virtualbox" do |vb|
+    vb.memory = "2048"
+  end
+
+  config.vm.network "forwarded_port", guest: 8008, host: 8008
+
+  config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig"
+  config.vm.provision "file", source: "~/.gnupg/gpg.conf", destination: ".gnupg/gpg.conf"
+  config.vm.provision "file", source: "~/.gnupg/pubring.gpg", destination: ".gnupg/pubring.gpg"
+  config.vm.provision "file", source: "~/.gnupg/secring.gpg", destination: ".gnupg/secring.gpg"
+  config.vm.provision "file", source: "gpg-agent.conf", destination: ".gnupg/gpg-agent.conf"
+  config.vm.provision "file", source: "settings.xml", destination: ".m2/settings.xml"
+
+  # Update the VM, install Java and Maven, enable passwordless-ssh-to-localhost,
+  # clone the canonical repository
+  config.vm.provision "shell", inline: <<-SHELL
+    apt-get update
+    apt-get upgrade -y
+    apt-get install -y default-jdk maven git xmlstarlet zip unzip language-pack-en vim-nox gnupg2 gnupg-agent pinentry-curses
+    wget -q -O /tmp/artifactory.zip http://bit.ly/Hqv9aj
+    mkdir -p /opt
+    unzip /tmp/artifactory.zip -d /opt
+    sudo sed -i -e '/Connector port=/ s/=\".*\"/=\"'"8008"'\"/' /opt/artifactory*/tomcat/conf/server.xml
+    /opt/artifactory*/bin/installService.sh
+    service artifactory start
+    chmod -R go= ~vagrant/.gnupg
+    cat /etc/ssh/ssh_host_*_key.pub | awk '{print "localhost,127.0.0.1 "$0}' >> /etc/ssh/ssh_known_hosts
+    su -c 'ssh-keygen -t rsa -b 2048 -N "" -f ~/.ssh/id_rsa; cat ~/.ssh/*.pub >> ~/.ssh/authorized_keys' vagrant
+    su -c 'git clone https://git-wip-us.apache.org/repos/asf/incubator-brooklyn.git apache-brooklyn-git' vagrant
+  SHELL
+end

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/change-version.sh
----------------------------------------------------------------------
diff --git a/release/change-version.sh b/release/change-version.sh
new file mode 100755
index 0000000..4b77749
--- /dev/null
+++ b/release/change-version.sh
@@ -0,0 +1,70 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+set -e
+
+# changes the version everywhere
+# usage, e.g.:  change-version.sh 0.3.0-SNAPSHOT 0.3.0-RC1
+#          or:  change-version.sh MARKER 0.3.0-SNAPSHOT 0.3.0-RC1
+
+[ -d .git ] || {
+  echo "Must run in brooklyn project root directory"
+  exit 1
+}
+
+if [ "$#" -eq 2 ]; then
+  VERSION_MARKER=BROOKLYN_VERSION
+elif [ "$#" -eq 3 ]; then
+  VERSION_MARKER=$1_VERSION
+  shift;
+else
+  echo "Usage:  "$0" [VERSION_MARKER] CURRENT_VERSION NEW_VERSION"
+  echo " e.g.:  "$0" BROOKLYN 0.3.0-SNAPSHOT 0.3.0-RC1"
+  exit 1
+fi
+
+# remove binaries and stuff
+if [ -f pom.xml ] && [ -d target ] ; then mvn clean ; fi
+
+VERSION_MARKER_NL=${VERSION_MARKER}_BELOW
+CURRENT_VERSION=$1
+NEW_VERSION=$2
+
+# grep --exclude-dir working only in recent versions, not on all platforms, replace with find;
+# skip folders named "ignored" or .xxx (but not the current folder ".");
+# exclude log, war, etc. files;
+# use null delimiters so files containing spaces are supported;
+# pass /dev/null as the first file to search in, so the command doesn't fail if find doesn't match any files;
+# add || true for the case where grep doesn't have matches, so the script doesn't halt
+# If there's an error "Argument list too long" add -n20 to xargs arguments and loop over $FILE around sed
+FILES=`find . -type d \( -name ignored -or -name .?\* \) -prune \
+       -o -type f -not \( -name \*.log -or -name '*.war' -or -name '*.min.js' -or -name '*.min.css' \) -print0 | \
+       xargs -0 grep -l "${VERSION_MARKER}\|${VERSION_MARKER_NL}" /dev/null || true`
+
+FILES_COUNT=`echo $FILES | wc | awk '{print $2}'`
+
+if [ ${FILES_COUNT} -ne 0 ]; then
+    # search for files containing version markers
+    sed -i.bak -e "/${VERSION_MARKER}/s/${CURRENT_VERSION}/${NEW_VERSION}/g" $FILES
+    sed -i.bak -e "/${VERSION_MARKER_NL}/{n;s/${CURRENT_VERSION}/${NEW_VERSION}/g;}" $FILES
+fi
+
+echo "Changed ${VERSION_MARKER} from ${CURRENT_VERSION} to ${NEW_VERSION} for "${FILES_COUNT}" files"
+echo "(Do a \`find . -name \"*.bak\" -delete\`  to delete the backup files.)"

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/gpg-agent.conf
----------------------------------------------------------------------
diff --git a/release/gpg-agent.conf b/release/gpg-agent.conf
new file mode 100644
index 0000000..3cd0291
--- /dev/null
+++ b/release/gpg-agent.conf
@@ -0,0 +1,2 @@
+default-cache-ttl 7200
+max-cache-ttl 86400

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/make-release-artifacts.sh
----------------------------------------------------------------------
diff --git a/release/make-release-artifacts.sh b/release/make-release-artifacts.sh
new file mode 100755
index 0000000..90f138e
--- /dev/null
+++ b/release/make-release-artifacts.sh
@@ -0,0 +1,273 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+# Creates the following releases with archives (.tar.gz/.zip), signatures and checksums:
+#   binary  (-bin)     - contains the brooklyn dist binary release
+#   source  (-src)     - contains all the source code files that are permitted to be released
+#   vagrant (-vagrant) - contains a Vagrantfile/scripts to start a Brooklyn getting started environment
+
+set -e
+
+###############################################################################
+fail() {
+    echo >&2 "$@"
+    exit 1
+}
+
+###############################################################################
+show_help() {
+    cat >&2 <<END
+Usage: make-release-artifacts.sh [-v version] [-r rc_number]
+Prepares and builds the source and binary distribution artifacts of a Brooklyn
+release.
+
+  -vVERSION                  overrides the name of this version, if detection
+                             from pom.xml is not accurate for any reason.
+  -rRC_NUMBER                specifies the release candidate number. The
+                             produced artifact names include the 'rc' suffix,
+                             but the contents of the archive artifact do *not*
+                             include the suffix. Therefore, turning a release
+                             candidate into a release requires only renaming
+                             the artifacts.
+  -y                         answers "y" to all questions automatically, to
+                             use defaults and make this suitable for batch mode
+
+Specifying the RC number is required. Specifying the version number is
+discouraged; if auto detection is not working, then this script is buggy.
+
+Additionally if APACHE_DIST_SVN_DIR is set, this will transfer artifacts to
+that directory and svn commit them.
+END
+# ruler                      --------------------------------------------------
+}
+
+###############################################################################
+confirm() {
+    # call with a prompt string or use a default
+    if [ "${batch_confirm_y}" == "true" ] ; then
+        true
+    else
+      read -r -p "${1:-Are you sure? [y/N]} " response
+      case $response in
+        [yY][eE][sS]|[yY]) 
+            true
+            ;;
+        *)
+            false
+            ;;
+      esac
+    fi
+}
+
+###############################################################################
+detect_version() {
+    if [ \! -z "${current_version}" ]; then
+        return
+    fi
+
+    set +e
+    current_version=$( xmlstarlet select -t -v '/_:project/_:version/text()' pom.xml 2>/dev/null )
+    success=$?
+    set -e
+    if [ "${success}" -ne 0 -o -z "${current_version}" ]; then
+        fail Could not detect version number
+    fi
+}
+
+###############################################################################
+# Argument parsing
+rc_suffix=
+OPTIND=1
+while getopts "h?v:r:y?" opt; do
+    case "$opt" in
+        h|\?)
+            show_help
+            exit 0
+            ;;
+        v)
+            current_version=$OPTARG
+            ;;
+        r)
+            rc_suffix=$OPTARG
+            ;;
+        y)
+            batch_confirm_y=true
+            ;;
+        *)
+            show_help
+            exit 1
+    esac
+done
+
+shift $((OPTIND-1))
+[ "$1" = "--" ] && shift
+
+###############################################################################
+# Prerequisite checks
+[ -d .git ] || fail Must run in brooklyn project root directory
+
+detect_version
+
+###############################################################################
+# Determine all filenames and paths, and confirm
+
+release_name=apache-brooklyn-${current_version}
+if [ -z "$rc_suffix" ]; then
+    fail Specifying the RC number is required
+else
+    artifact_name=${release_name}-rc${rc_suffix}
+fi
+
+release_script_dir=$( cd $( dirname $0 ) && pwd )
+brooklyn_dir=$( pwd )
+rm -rf ${release_script_dir}/tmp
+staging_dir="${release_script_dir}/tmp/source/"
+src_staging_dir="${release_script_dir}/tmp/source/${release_name}-src"
+bin_staging_dir="${release_script_dir}/tmp/bin/"
+artifact_dir="${release_script_dir}/tmp/${artifact_name}"
+
+echo "The version is ${current_version}"
+echo "The rc suffix is rc${rc_suffix}"
+echo "The release name is ${release_name}"
+echo "The artifact name is ${artifact_name}"
+echo "The artifact directory is ${artifact_dir}"
+if [ ! -z "${APACHE_DIST_SVN_DIR}" ] ; then
+  echo "The artifacts will be copied and uploaded via ${APACHE_DIST_SVN_DIR}"
+else
+  echo "The artifacts will not be copied and uploaded to the svn repo"
+fi
+echo ""
+confirm "Is this information correct? [y/N]" || exit
+echo ""
+echo "WARNING! This script will run 'git clean -dxf' to remove ALL files that are not under Git source control."
+echo "This includes build artifacts and all uncommitted local files and directories."
+echo "If you want to check what will happen, answer no and run 'git clean -dxn' to dry run."
+echo ""
+confirm || exit
+echo ""
+echo "This script will cause uploads to be made to a staging repository on the Apache Nexus server."
+echo ""
+confirm "Shall I continue?  [y/N]" || exit
+
+###############################################################################
+# Clean the workspace
+git clean -dxf
+
+###############################################################################
+# Source release
+echo "Creating source release folder ${release_name}"
+set -x
+mkdir -p ${src_staging_dir}
+mkdir -p ${bin_staging_dir}
+# exclude: 
+# * docs (which isn't part of the release, and adding license headers to js files is cumbersome)
+# * sandbox (which hasn't been vetted so thoroughly)
+# * release (where this is running, and people who *have* the release don't need to make it)
+# * jars and friends (these are sometimes included for tests, but those are marked as skippable,
+#     and apache convention does not allow them in source builds; see PR #365
+rsync -rtp --exclude .git\* --exclude brooklyn-docs/ --exclude brooklyn-library/sandbox/ --exclude brooklyn-dist/release/ --exclude '**/*.[ejw]ar' . ${staging_dir}/${release_name}-src
+
+rm -rf ${artifact_dir}
+mkdir -p ${artifact_dir}
+set +x
+echo "Creating artifact ${artifact_dir}/${artifact_name}-src.tar.gz and .zip"
+set -x
+( cd ${staging_dir} && tar czf ${artifact_dir}/${artifact_name}-src.tar.gz ${release_name}-src )
+( cd ${staging_dir} && zip -qr ${artifact_dir}/${artifact_name}-src.zip ${release_name}-src )
+
+###############################################################################
+# Binary release
+set +x
+echo "Proceeding to build binary release"
+set -x
+
+# Set up GPG agent
+if ps x | grep [g]pg-agent ; then
+  echo "gpg-agent already running; assuming it is set up and exported correctly."
+else
+  eval $(gpg-agent --daemon --no-grab --write-env-file $HOME/.gpg-agent-info)
+  GPG_TTY=$(tty)
+  export GPG_TTY GPG_AGENT_INFO
+fi
+
+# Workaround for bug BROOKLYN-1
+( cd ${src_staging_dir} && mvn clean --projects :brooklyn-archetype-quickstart )
+
+# Perform the build and deploy to Nexus staging repository
+( cd ${src_staging_dir} && mvn deploy -Papache-release )
+## To test the script without a big deploy, use the line below instead of above
+#( cd ${src_staging_dir} && mvn clean install )
+
+# Re-pack the archive with the correct names
+tar xzf ${src_staging_dir}/brooklyn-dist/dist/target/brooklyn-dist-${current_version}-dist.tar.gz -C ${bin_staging_dir}
+mv ${bin_staging_dir}/brooklyn-dist-${current_version} ${bin_staging_dir}/${release_name}-bin
+
+( cd ${bin_staging_dir} && tar czf ${artifact_dir}/${artifact_name}-bin.tar.gz ${release_name}-bin )
+( cd ${bin_staging_dir} && zip -qr ${artifact_dir}/${artifact_name}-bin.zip ${release_name}-bin )
+
+###############################################################################
+# Vagrant release
+set +x
+echo "Proceeding to rename and repackage vagrant environment release"
+set -x
+
+# Re-pack the archive with the correct names
+tar xzf ${src_staging_dir}/brooklyn-dist/vagrant/target/brooklyn-vagrant-${current_version}-dist.tar.gz -C ${bin_staging_dir}
+mv ${bin_staging_dir}/brooklyn-vagrant-${current_version} ${bin_staging_dir}/${release_name}-vagrant
+
+( cd ${bin_staging_dir} && tar czf ${artifact_dir}/${artifact_name}-vagrant.tar.gz ${release_name}-vagrant )
+( cd ${bin_staging_dir} && zip -qr ${artifact_dir}/${artifact_name}-vagrant.zip ${release_name}-vagrant )
+
+###############################################################################
+# Signatures and checksums
+
+# OSX doesn't have sha256sum, even if MacPorts md5sha1sum package is installed.
+# Easy to fake it though.
+which sha256sum >/dev/null || alias sha256sum='shasum -a 256' && shopt -s expand_aliases
+
+( cd ${artifact_dir} &&
+    for a in *.tar.gz *.zip; do
+        md5sum -b ${a} > ${a}.md5
+        sha1sum -b ${a} > ${a}.sha1
+        sha256sum -b ${a} > ${a}.sha256
+        gpg2 --armor --output ${a}.asc --detach-sig ${a}
+    done
+)
+
+###############################################################################
+
+if [ ! -z "${APACHE_DIST_SVN_DIR}" ] ; then
+  pushd ${APACHE_DIST_SVN_DIR}
+  rm -rf ${artifact_name}
+  cp -r ${artifact_dir} ${artifact_name}
+  svn add ${artifact_name}
+  svn commit --message "Add ${artifact_name} artifacts for incubator/brooklyn"
+  artifact_dir=${APACHE_DIST_SVN_DIR}/${artifact_name}
+  popd
+fi
+
+###############################################################################
+# Conclusion
+
+set +x
+echo "The release is done - here is what has been created:"
+ls ${artifact_dir}
+echo "You can find these files in: ${artifact_dir}"
+echo "The git commit ID for the voting emails is: $( git rev-parse HEAD )"

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/print-vote-email.sh
----------------------------------------------------------------------
diff --git a/release/print-vote-email.sh b/release/print-vote-email.sh
new file mode 100755
index 0000000..5fd2256
--- /dev/null
+++ b/release/print-vote-email.sh
@@ -0,0 +1,130 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+# prints a sample email with all the correct information
+
+set +x
+
+fail() {
+    echo >&2 "$@"
+    exit 1
+}
+
+if [ -z "${VERSION_NAME}" ] ; then fail VERSION_NAME must be set ; fi
+if [ -z "${RC_NUMBER}" ] ; then fail RC_NUMBER must be set ; fi
+
+base=apache-brooklyn-${VERSION_NAME}-rc${RC_NUMBER}
+
+if [ -z "$1" ] ; then fail "A single argument being the staging repo ID must be supplied, e.g. orgapachebrooklyn-1234" ; fi
+
+staging_repo_id=$1
+archetype_check=`curl https://repository.apache.org/content/repositories/${staging_repo_id}/archetype-catalog.xml 2> /dev/null`
+if ! echo $archetype_check | grep brooklyn-archetype-quickstart > /dev/null ; then
+  fail staging repo looks wrong at https://repository.apache.org/content/repositories/${staging_repo_id}
+fi
+if ! echo $archetype_check | grep ${VERSION_NAME} > /dev/null ; then
+  fail wrong version at https://repository.apache.org/content/repositories/${staging_repo_id}
+fi
+
+artifact=release/tmp/${base}/${base}-bin.tar.gz
+if [ ! -f $artifact ] ; then
+  fail could not find artifact $artifact
+fi
+if [ -z "$APACHE_ID" ] ; then
+  APACHE_ID=`gpg2 --verify ${artifact}.asc ${artifact} 2>&1 | egrep -o '[^<]*...@apache.org>' | cut -d @ -f 1`
+fi
+if [ -z "$APACHE_ID" ] ; then
+  fail "could not deduce APACHE_ID (your apache username); are files signed correctly?"
+fi
+if ! ( gpg2 --verify ${artifact}.asc ${artifact} 2>&1 | grep ${APACHE_ID}@apache.org > /dev/null ) ; then
+  fail "could not verify signature; are files signed correctly and ID ${APACHE_ID} correct?"
+fi
+
+cat <<EOF
+
+Subject: [VOTE] Release Apache Brooklyn ${VERSION_NAME} [rc${RC_NUMBER}]
+
+
+This is to call for a vote for the release of Apache Brooklyn ${VERSION_NAME}.
+
+This release comprises of a source code distribution, and a corresponding
+binary distribution, and Maven artifacts.
+
+The source and binary distributions, including signatures, digests, etc. can
+be found at:
+
+  https://dist.apache.org/repos/dist/dev/incubator/brooklyn/${base}
+
+The artifact SHA-256 checksums are as follows:
+
+EOF
+
+cat release/tmp/${base}/*.sha256 | awk '{print "  "$0}'
+
+cat <<EOF
+
+The Nexus staging repository for the Maven artifacts is located at:
+
+    https://repository.apache.org/content/repositories/${staging_repo_id}
+
+All release artifacts are signed with the following key:
+
+    https://people.apache.org/keys/committer/${APACHE_ID}.asc
+
+KEYS file available here:
+
+    https://dist.apache.org/repos/dist/release/incubator/brooklyn/KEYS
+
+
+The artifacts were built from git commit ID $( git rev-parse HEAD ):
+
+    https://git-wip-us.apache.org/repos/asf?p=incubator-brooklyn.git;a=commit;h=$( git rev-parse HEAD )
+
+
+Please vote on releasing this package as Apache Brooklyn ${VERSION_NAME}.
+
+The vote will be open for at least 72 hours.
+[ ] +1 Release this package as Apache Brooklyn ${VERSION_NAME}
+[ ] +0 no opinion
+[ ] -1 Do not release this package because ...
+
+
+Thanks!
+EOF
+
+cat <<EOF
+
+
+
+CHECKLIST for reference
+
+[ ] Download links work.
+[ ] Binaries work.
+[ ] Checksums and PGP signatures are valid.
+[ ] Expanded source archive matches contents of RC tag.
+[ ] Expanded source archive builds and passes tests.
+[ ] LICENSE is present and correct.
+[ ] NOTICE is present and correct, including copyright date.
+[ ] All files have license headers where appropriate.
+[ ] All dependencies have compatible licenses.
+[ ] No compiled archives bundled in source archive.
+[ ] I follow this project’s commits list.
+
+EOF

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/pull-request-reports/Gemfile
----------------------------------------------------------------------
diff --git a/release/pull-request-reports/Gemfile b/release/pull-request-reports/Gemfile
new file mode 100644
index 0000000..8ab84b5
--- /dev/null
+++ b/release/pull-request-reports/Gemfile
@@ -0,0 +1,5 @@
+#ruby=ruby-2.1.2
+#ruby-gemset=brooklyn-release-helpers
+
+source 'https://rubygems.org'
+gem 'github_api'

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/pull-request-reports/Gemfile.lock
----------------------------------------------------------------------
diff --git a/release/pull-request-reports/Gemfile.lock b/release/pull-request-reports/Gemfile.lock
new file mode 100644
index 0000000..859202a
--- /dev/null
+++ b/release/pull-request-reports/Gemfile.lock
@@ -0,0 +1,38 @@
+GEM
+  remote: https://rubygems.org/
+  specs:
+    addressable (2.3.8)
+    descendants_tracker (0.0.4)
+      thread_safe (~> 0.3, >= 0.3.1)
+    faraday (0.9.1)
+      multipart-post (>= 1.2, < 3)
+    github_api (0.12.3)
+      addressable (~> 2.3)
+      descendants_tracker (~> 0.0.4)
+      faraday (~> 0.8, < 0.10)
+      hashie (>= 3.3)
+      multi_json (>= 1.7.5, < 2.0)
+      nokogiri (~> 1.6.3)
+      oauth2
+    hashie (3.4.2)
+    jwt (1.5.1)
+    mini_portile (0.6.2)
+    multi_json (1.11.1)
+    multi_xml (0.5.5)
+    multipart-post (2.0.0)
+    nokogiri (1.6.6.2)
+      mini_portile (~> 0.6.0)
+    oauth2 (1.0.0)
+      faraday (>= 0.8, < 0.10)
+      jwt (~> 1.0)
+      multi_json (~> 1.3)
+      multi_xml (~> 0.5)
+      rack (~> 1.2)
+    rack (1.6.4)
+    thread_safe (0.3.5)
+
+PLATFORMS
+  ruby
+
+DEPENDENCIES
+  github_api

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/pull-request-reports/pr_report.rb
----------------------------------------------------------------------
diff --git a/release/pull-request-reports/pr_report.rb b/release/pull-request-reports/pr_report.rb
new file mode 100644
index 0000000..95b6317
--- /dev/null
+++ b/release/pull-request-reports/pr_report.rb
@@ -0,0 +1,12 @@
+#ruby
+
+require 'CSV'
+require 'github_api'
+
+gh = Github.new
+
+CSV.open("pr_report.tsv", "wb", { :col_sep => "\t" }) do |csv|
+  gh.pull_requests.list('apache', 'incubator-brooklyn').
+      select { |pr| pr.state == "open" }.
+      each { |pr| csv << [ pr.number, pr.title, pr.created_at, pr.user.login ] }
+end

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/release/settings.xml
----------------------------------------------------------------------
diff --git a/release/settings.xml b/release/settings.xml
new file mode 100644
index 0000000..2b03994
--- /dev/null
+++ b/release/settings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd"
+          xmlns="http://maven.apache.org/SETTINGS/1.1.0"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+    <servers>
+        <!-- Required for uploads to Apache's Nexus instance. These are LDAP credentials - the same credentials you
+           - would use to log in to Git and Jenkins (but not JIRA) -->
+        <server>
+            <id>apache.snapshots.https</id>
+            <username>xxx</username>
+            <password>xxx</password>
+        </server>
+        <server>
+            <id>apache.releases.https</id>
+            <username>xxx</username>
+            <password>xxx</password>
+        </server>
+
+        <!-- This is used for deployments to the play Artifactory instance that is provisioned by the Vagrant scripts.
+           - It may be safely ignored. -->
+        <server>
+            <id>vagrant-ubuntu-trusty-64</id>
+            <username>admin</username>
+            <password>password</password>
+        </server>
+    </servers>
+
+</settings>

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/scripts/buildAndTest
----------------------------------------------------------------------
diff --git a/scripts/buildAndTest b/scripts/buildAndTest
new file mode 100755
index 0000000..45c1a26
--- /dev/null
+++ b/scripts/buildAndTest
@@ -0,0 +1,102 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+# Convenience script to clean, build, install and run unit and/or integration tests.
+# Recommend you run this prior to pushing to Github to reduce the chances of breaking
+# the continuous integration (unit tests) or overnight builds (integration tests.)
+#
+# Also very useful when using "git bisect" to find out which commit was responsible
+# for breaking the overnight build - invoke as "git bisect run ./buildAndRun"
+#
+# Run "./buildAndRun --help" to see the usage.
+#
+
+# Has an integration test left a Java process running? See if there is any running
+# Java processes and offer to kill them/
+cleanup(){
+    PROCS=$(ps ax | grep '[j]ava' | grep -v set_tab_title)
+    if [ ! -z "${PROCS}" ]; then
+	echo "These Java processes are running:"
+	echo ${PROCS}
+	echo -n "Kill them? y=yes, n=no, x=abort: "
+	read $RESPONSE
+	[ "${RESPONSE}" = "y" ] && killall java && sleep 1s
+	[ "${RESPONSE}" = "x" ] && exit 50
+    fi
+}
+
+# Check a return value, and bail if its non-zero - invoke as "assert $? 'Unit tests'"
+assert(){
+    [ $1 -eq 0 ] && return
+    echo '*** Command returned '$1' on '$2
+    exit $1
+}
+
+# The defaults
+unit=1
+integration=1
+
+if [ ! -z "$1" ]; then
+    case "$1" in
+	u)
+	    unit=1
+	    integration=0
+	    ;;
+	i)
+	    unit=0
+	    integration=1
+	    ;;
+	ui)
+	    unit=1
+	    integration=1
+	    ;;
+	b)
+	    unit=0
+	    integration=0
+	    ;;
+	*)
+	    echo >&2 Usage: buildAndTest [action]
+	    echo >&2 where action is:
+	    echo >&2 u - build from clean and run unit tests
+	    echo >&2 i - build from clean and run integration tests
+	    echo >&2 ui - build from clean and run unit and integration tests \(default\)
+	    echo >&2 b - build from clean and do not run any tests
+	    exit 1
+	    ;;
+    esac
+fi
+
+echo '*** BUILD'
+mvn clean install -DskipTests -PConsole
+assert $? 'BUILD'
+cleanup
+if [ $unit -eq 1 ]; then
+    echo '*** UNIT TEST'
+    mvn integration-test -PConsole
+    assert $? 'UNIT TEST'
+    cleanup
+fi
+if [ $integration -eq 1 ]; then
+    echo '*** INTEGRATION TEST'
+    mvn integration-test -PConsole,Integration
+    assert $? 'INTEGRATION TEST'
+    cleanup
+fi
+
+exit 0

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/scripts/grep-in-poms.sh
----------------------------------------------------------------------
diff --git a/scripts/grep-in-poms.sh b/scripts/grep-in-poms.sh
new file mode 100755
index 0000000..aca9258
--- /dev/null
+++ b/scripts/grep-in-poms.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+# usage: run in the root dir of a project, it will grep in poms up to 3 levels deep
+# e.g. where are shaded jars defined?
+# brooklyn% grep-in-poms -i slf4j
+
+grep $* {.,*,*/*,*/*/*}/pom.xml

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/scripts/release-branch-from-master
----------------------------------------------------------------------
diff --git a/scripts/release-branch-from-master b/scripts/release-branch-from-master
new file mode 100755
index 0000000..8d7befa
--- /dev/null
+++ b/scripts/release-branch-from-master
@@ -0,0 +1,114 @@
+#!/bin/bash -e
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+usage(){
+	echo >&2 'Usage: release-branch-from-master --release <version> [ --release-suffix <suffix> ]'
+	echo >&2 '                                  --master <version>  [ --master-suffix <suffix> ]'
+	echo >&2 'Creates a release branch, and updates the version number in both the branch and master.'
+	echo >&2 '<version> should be a two-part version number, such as 3.6 or 4.0.'
+	echo >&2 '<suffix> will normally be of the form ".patchlevel", plus "-RC1" or similar if required,'
+	echo >&2 'plus "-SNAPSHOT". Example: ".0.RC1-SNAPSHOT". The defaults for the suffix are normally sensible.'
+	echo >&2 'This command will preview what it is going to do and require confirmation before it makes changes.'
+}
+
+release_ver=
+release_ver_suffix=.0-RC1-SNAPSHOT
+master_ver=
+master_ver_suffix=.0-SNAPSHOT
+
+[ $# -eq 0 ] && echo >&2 "No arguments given, so I'm going to try and figure it out myself. Invoke with the --help option if you want to find how to invoke this script."
+
+while [ $# -gt 0 ]; do
+	case $1 in
+		--release)			shift; release_ver=$1;;
+		--release-suffix)	shift; release_ver_suffix=$1;;
+		--master)			shift; master_ver=$1;;
+		--master-suffix)	shift; master_ver_suffix=$1;;
+		*)					usage; exit 1;;
+	esac
+	shift
+done
+
+# Use xpath to query the current version number in the pom
+xpath='xpath'
+type -P $xpath &>/dev/null && {
+	set +e
+	current_version=$( xpath pom.xml '/project/version/text()' 2>/dev/null )
+	( echo ${current_version} | grep -qE '^([0-9]+).([0-9]+).0-SNAPSHOT$' )
+	current_version_valid=$?
+	set -e 
+} || { 
+	echo "Cannot guess version number as $xpath command not found."
+	current_version_valid=1
+}
+
+if [ "${current_version_valid}" -ne 0 -a -z "${release_ver}" -a -z "${master_ver}" ]; then
+	echo >&2 "Detected current version as '${current_version}', but I can't parse this. Please supply --release and --master parameters."
+	exit 1
+fi
+
+[ -z "${release_ver}" ] && {
+	release_ver=${current_version%-SNAPSHOT}
+	release_ver=${release_ver%.0}
+	[ -z "${release_ver}" ] && { echo >&2 Could not determine the version of the release branch. Please use the --release parameter. ; exit 1 ; }
+}
+
+[ -z "${master_ver}" ] && {
+	master_ver=$( echo ${current_version} | perl -n -e 'if (/^(\d+).(\d+)(.*)$/) { printf "%s.%s\n", $1, $2+1 }' )
+	[ -z "${master_ver}" ] && { echo >&2 Could not determine the version of the master branch. Please use the --master parameter. ; exit 1 ; }
+}
+
+version_on_branch=${release_ver}${release_ver_suffix}
+version_on_master=${master_ver}${master_ver_suffix}
+branch_name=${version_on_branch}
+
+# Show the details and get confirmation
+echo "The current version is:                                  ${current_version}"
+echo "The release branch will be named:                        ${branch_name}"
+echo "The version number on the release branch will be set to: ${version_on_branch}"
+echo "The version number on 'master' will be set to:           ${version_on_master}"
+echo "If you proceed, the new branch and version number changes will be pushed to GitHub."
+echo -n 'Enter "y" if this is correct, anything else to abort: '
+read input
+[ "$input" == "y" ] || { echo >&2 Aborted. ; exit 1 ; }
+
+# Fail if not in a Git repository
+[ -d .git ] || {
+	echo >&2 Error: this directory is not a git repository root. Nothing happened.
+	exit 1
+}
+
+# Warn if the current branch isn't master
+current_branch=$( git name-rev --name-only HEAD )
+[ ${current_branch} == "master" ] || {
+	echo Current branch is ${current_branch}. Usually, release branches are made from master.
+	echo -n 'Enter "y" if this is correct, anything else to abort: '
+	read input
+	[ "$input" == "y" ] || { echo >&2 Aborted. ; exit 1 ; }
+}
+
+# Get Maven to make the branch
+set -x
+mvn release:clean release:branch -P Brooklyn,Console,Example,Launcher,Acceptance,Documentation --batch-mode -DautoVersionSubmodules=true -DbranchName=${branch_name} -DupdateBranchVersions=true -DreleaseVersion=${version_on_branch} -DdevelopmentVersion=${version_on_master}
+set +x
+
+# Done!
+echo Completed. Your repository is still looking at ${current_branch}. To switch to the release branch, enter:
+echo git checkout ${branch_name}

http://git-wip-us.apache.org/repos/asf/brooklyn-dist/blob/26c4604c/scripts/release-make
----------------------------------------------------------------------
diff --git a/scripts/release-make b/scripts/release-make
new file mode 100755
index 0000000..df46ea1
--- /dev/null
+++ b/scripts/release-make
@@ -0,0 +1,83 @@
+#!/bin/bash -e -u
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you 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.
+#
+
+usage(){
+	echo >&2 'Usage: release-make [ --release <version> ] [ --next <version> ]'
+	echo >&2 'Creates and tags a release based on the current branch.'
+	echo >&2 'Arguments are optional - if omitted, the script tries to work out the correct versions.'
+	echo >&2 'release <version> should be a full version number, such as 3.6.0-RC1'
+	echo >&2 'next <version> should be a snapshot version number, such as 3.6.0-RC2-SNAPSHOT'
+	echo >&2 'This command will preview what it is going to do and require confirmation before it makes changes.'
+}
+
+[ $# -eq 0 ] && echo >&2 "No arguments given, so I'm going to try and figure it out myself. Invoke with the --help option if you want to find how to invoke this script."
+
+release_tag_ver=
+release_branch_ver=
+
+while [ $# -gt 0 ]; do
+	case $1 in
+		--release)	shift; release_tag_ver=$1;;
+		--next)		shift; release_branch_ver=$1;;
+		*)					usage; exit 1;;
+	esac
+	shift
+done
+
+# Some magic to derive the anticipated version of the release.
+# Use xpath to query the version number in the pom
+xpath='xpath'
+type -P $xpath &>/dev/null && {
+	set +e
+	current_version=$( xpath pom.xml '/project/version/text()' 2>/dev/null )
+	set -e
+} || {
+        echo "Cannot guess version number as $xpath command not found."
+}
+# If the user didn't supply the release version, strip -SNAPSHOT off the current version and use that
+[ -z "$release_tag_ver" ] && release_tag_ver=${current_version%-SNAPSHOT}
+
+# More magic, this time to guess the next version.
+# If the user didn't supply the next version, modify the digits off the end of the release to increment by one and append -SNAPSHOT
+[ -z "$release_branch_ver" ] && release_branch_ver=$( echo ${release_tag_ver} | perl -n -e 'if (/^(.*)(\d+)$/) { print $1.($2+1)."-SNAPSHOT\n" }' )
+
+current_branch=$( git name-rev --name-only HEAD )
+
+echo "The release is on the branch:                             ${current_branch}"
+echo "The current version (detected) is:                        ${current_version}"
+echo "The release version is:                                   ${release_tag_ver}"
+echo "Development on the release branch continues with version: ${release_branch_ver}"
+echo -n 'Enter "y" if this is correct, anything else to abort: '
+read input
+[ "$input" == "y" ] || { echo >&2 Aborted. ; exit 1 ; }
+
+# Warn if the current branch is master
+[ ${current_branch} == "master" ] && {
+	echo Current branch is ${current_branch}. Usually, releases are made from a release branch.
+	echo -n 'Enter "y" if this is correct, anything else to abort: '
+	read input
+	[ "$input" == "y" ] || { echo >&2 Aborted. ; exit 1 ; }
+}
+
+# Release prepare
+mvn release:clean release:prepare -PExample,Launcher,Four,Three --batch-mode -DautoVersionSubmodules=true -DreleaseVersion=${release_tag_ver} -DdevelopmentVersion=${release_branch_ver}
+
+# Release perform
+mvn release:perform -PExample,Launcher,Four,Three --batch-mode