This is an automated email from the ASF dual-hosted git repository.
rabbah pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk.git
The following commit(s) were added to refs/heads/master by this push:
new c6864b8 Add module listing page with required tooling (#3825)
c6864b8 is described below
commit c6864b804748bb15f4c1976ae52873d2a79a5b7c
Author: Chetan Mehrotra <[email protected]>
AuthorDate: Thu Jul 12 17:26:05 2018 +0530
Add module listing page with required tooling (#3825)
---
README.md | 2 +-
docs/dev/modules.md | 125 +++++++++++++++++++++
settings.gradle | 1 +
tools/dev/README.md | 45 +++++++-
tools/dev/build.gradle | 15 +++
tools/dev/src/main/groovy/CategoryManager.groovy | 83 ++++++++++++++
tools/dev/src/main/groovy/listRepos.groovy | 99 ++++++++++++++++
.../dev/src/main/groovy/renderModuleDetails.groovy | 51 +++++++++
tools/dev/src/main/resources/modules.md | 37 ++++++
9 files changed, 454 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index cb047b1..35e99f1 100644
--- a/README.md
+++ b/README.md
@@ -112,7 +112,7 @@ interested in:
### Repository Structure
-The OpenWhisk system is built from a number of components. The picture below
groups the components by their GitHub repos. Please open issues for a component
against the appropriate repo (if in doubt just open against the main openwhisk
repo).
+The OpenWhisk system is built from a [number of
components](docs/dev/modules.md). The picture below groups the components by
their GitHub repos. Please open issues for a component against the appropriate
repo (if in doubt just open against the main openwhisk repo).

diff --git a/docs/dev/modules.md b/docs/dev/modules.md
new file mode 100644
index 0000000..a6bdf00
--- /dev/null
+++ b/docs/dev/modules.md
@@ -0,0 +1,125 @@
+<!--
+#
+# 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.
+#
+-->
+<!--
+DO NOT EDIT.
+This page is generated via script `./gradlew :tools:dev:renderModuleDetails`.
See tools/dev/README.md for details.
+-->
+
+# Modules
+
+
+## Main
+
+| Module | Description | Module Status |
+|--- |--- |--- |
+| [incubator-openwhisk](https://github.com/apache/incubator-openwhisk) |
Apache OpenWhisk is a serverless event-based programming service and an Apache
Incubator project. | [](https://travis-ci.org/apache/incubator-openwhisk)
|
+|
[incubator-openwhisk-apigateway](https://github.com/apache/incubator-openwhisk-apigateway)
| A performant API Gateway based on Openresty and NGINX | [](https://travis-ci.org/apache/incubator-openwhisk-apigateway)
|
+|
[incubator-openwhisk-catalog](https://github.com/apache/incubator-openwhisk-catalog)
| Curated catalog of Apache OpenWhisk packages to interface with event
producers and consumers | [](https://travis-ci.org/apache/incubator-openwhisk-catalog)
|
+| [incubator-openwhisk-cli](https://github.com/apache/incubator-openwhisk-cli)
| OpenWhisk Command Line Interface (CLI) | [](https://travis-ci.org/apache/incubator-openwhisk-cli)
|
+|
[incubator-openwhisk-wskdeploy](https://github.com/apache/incubator-openwhisk-wskdeploy)
| Utility for deploying and managing Apache OpenWhisk packages and projects |
[](https://travis-ci.org/apache/incubator-openwhisk-wskdeploy)
|
+
+
+## Clients
+
+| Module | Description | Module Status |
+|--- |--- |--- |
+|
[incubator-openwhisk-client-go](https://github.com/apache/incubator-openwhisk-client-go)
| This project openwhisk-client-go is a Go client library to access Openwhisk
API | [](https://travis-ci.org/apache/incubator-openwhisk-client-go)
|
+|
[incubator-openwhisk-client-js](https://github.com/apache/incubator-openwhisk-client-js)
| JavaScript client library for the OpenWhisk platform | [](https://travis-ci.org/apache/incubator-openwhisk-client-js)
|
+|
[incubator-openwhisk-client-python](https://github.com/apache/incubator-openwhisk-client-python)
| REST API of OpenWhisk can be used directly from Python | [](https://travis-ci.org/apache/incubator-openwhisk-client-python)
|
+|
[incubator-openwhisk-client-swift](https://github.com/apache/incubator-openwhisk-client-swift)
| openwhisk-client-swift is a Swift client SDK for OpenWhisk with support for
iOS, WatchOS2, and Darwin CLI apps | [](https://travis-ci.org/apache/incubator-openwhisk-client-swift)
|
+
+
+## Runtimes
+
+| Module | Description | Module Status |
+|--- |--- |--- |
+|
[incubator-openwhisk-runtime-docker](https://github.com/apache/incubator-openwhisk-runtime-docker)
| Apache openwhisk | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-docker)
|
+|
[incubator-openwhisk-runtime-go](https://github.com/apache/incubator-openwhisk-runtime-go)
| Apache openwhisk runtime for go actions | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-go)
|
+|
[incubator-openwhisk-runtime-java](https://github.com/apache/incubator-openwhisk-runtime-java)
| Apache Openwhisk java runtimes | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-java)
|
+|
[incubator-openwhisk-runtime-nodejs](https://github.com/apache/incubator-openwhisk-runtime-nodejs)
| Apache openwhisk nodejs runtime | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-nodejs)
|
+|
[incubator-openwhisk-runtime-php](https://github.com/apache/incubator-openwhisk-runtime-php)
| Apache openwhisk php runtime | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-php)
|
+|
[incubator-openwhisk-runtime-python](https://github.com/apache/incubator-openwhisk-runtime-python)
| Apache openwhisk python runtime | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-python)
|
+|
[incubator-openwhisk-runtime-swift](https://github.com/apache/incubator-openwhisk-runtime-swift)
| Apache openwhisk swift runtime | [](https://travis-ci.org/apache/incubator-openwhisk-runtime-swift)
|
+
+
+## Deployments
+
+| Module | Description | Module Status |
+|--- |--- |--- |
+|
[incubator-openwhisk-deploy-kube](https://github.com/apache/incubator-openwhisk-deploy-kube)
| This project can be used to deploy Apache OpenWhisk to a Kubernetes cluster
| [](https://travis-ci.org/apache/incubator-openwhisk-deploy-kube)
|
+|
[incubator-openwhisk-deploy-mesos](https://github.com/apache/incubator-openwhisk-deploy-mesos)
| Apache OpenWhisk deployment scripts and configuration files for running
under Apache Mesos. | [](https://travis-ci.org/apache/incubator-openwhisk-deploy-mesos)
|
+|
[incubator-openwhisk-deploy-openshift](https://github.com/apache/incubator-openwhisk-deploy-openshift)
| This project can be used to deploy Apache OpenWhisk to the OpenShift
platform | [](https://travis-ci.org/apache/incubator-openwhisk-deploy-openshift)
|
+
+
+## Packages
+
+| Module | Description | Module Status |
+|--- |--- |--- |
+|
[incubator-openwhisk-package-alarms](https://github.com/apache/incubator-openwhisk-package-alarms)
| Apache OpenWhisk package that can be used to create periodic, time-based
alarms | [](https://travis-ci.org/apache/incubator-openwhisk-package-alarms)
|
+|
[incubator-openwhisk-package-cloudant](https://github.com/apache/incubator-openwhisk-package-cloudant)
| The /whisk.system/cloudant package enables you to work with a Cloudant
database | [](https://travis-ci.org/apache/incubator-openwhisk-package-cloudant)
|
+|
[incubator-openwhisk-package-deploy](https://github.com/apache/incubator-openwhisk-package-deploy)
| Apache openwhisk | [](https://travis-ci.org/apache/incubator-openwhisk-package-deploy)
|
+|
[incubator-openwhisk-package-jira](https://github.com/apache/incubator-openwhisk-package-jira)
| Interact with JIRA software software development tool used for issue
tracking, and project management functions | [](https://travis-ci.org/apache/incubator-openwhisk-package-jira)
|
+|
[incubator-openwhisk-package-kafka](https://github.com/apache/incubator-openwhisk-package-kafka)
| Apache OpenWhisk package for communicating with Kafka or Message Hub |
[](https://travis-ci.org/apache/incubator-openwhisk-package-kafka)
|
+|
[incubator-openwhisk-package-pushnotifications](https://github.com/apache/incubator-openwhisk-package-pushnotifications)
| OpenWhisk Package for Bluemix Push Notifications Service | [](https://travis-ci.org/apache/incubator-openwhisk-package-pushnotifications)
|
+|
[incubator-openwhisk-package-rss](https://github.com/apache/incubator-openwhisk-package-rss)
| RSS feed package | [](https://travis-ci.org/apache/incubator-openwhisk-package-rss)
|
+|
[incubator-openwhisk-package-template](https://github.com/apache/incubator-openwhisk-package-template)
| This is a template to be use when creating new packages for OpenWhisk |
[](https://travis-ci.org/apache/incubator-openwhisk-package-template)
|
+
+
+## Samples and Examples
+
+| Module | Description |
+|--- |--- |
+|
[incubator-openwhisk-GitHubSlackBot](https://github.com/apache/incubator-openwhisk-GitHubSlackBot)
| Demonstration of integration of GitHub Pull Request management with Slack
and using Alarms |
+|
[incubator-openwhisk-sample-matos](https://github.com/apache/incubator-openwhisk-sample-matos)
| sample application with Message Hub and Object Store |
+|
[incubator-openwhisk-sample-slackbot](https://github.com/apache/incubator-openwhisk-sample-slackbot)
| A proof-of-concept Slackbot to invoke OpenWhisk actions. |
+|
[incubator-openwhisk-slackinvite](https://github.com/apache/incubator-openwhisk-slackinvite)
| Invite for Apache OpenWhisk Team on Slack |
+|
[incubator-openwhisk-tutorial](https://github.com/apache/incubator-openwhisk-tutorial)
| An interactive learning environment for the Apache OpenWhisk command line |
+|
[incubator-openwhisk-workshop](https://github.com/apache/incubator-openwhisk-workshop)
| OpenWhisk workshop to help developers learn how to build serverless
applications using the platform. |
+
+
+## Development Tools
+
+| Module | Description |
+|--- |--- |
+|
[incubator-openwhisk-debugger](https://github.com/apache/incubator-openwhisk-debugger)
| The OpenWhisk debugger project |
+|
[incubator-openwhisk-devtools](https://github.com/apache/incubator-openwhisk-devtools)
| Development tools for building and deploying Apache OpenWhisk |
+|
[incubator-openwhisk-playground](https://github.com/apache/incubator-openwhisk-playground)
| This library provides functionality of executing a snippet of source code as
OpenWhisk action for OpenWhisk Xcode Source Editor Extension |
+|
[incubator-openwhisk-vscode](https://github.com/apache/incubator-openwhisk-vscode)
| Visual Studio Code extension (prototype) for authoring OpenWhisk actions
inside the editor. |
+|
[incubator-openwhisk-xcode](https://github.com/apache/incubator-openwhisk-xcode)
| Collection of OpenWhisk tools for OS X implemented in Swift 3. |
+
+
+## Utilities
+
+| Module | Description |
+|--- |--- |
+|
[incubator-openwhisk-release](https://github.com/apache/incubator-openwhisk-release)
| Apache openwhisk release |
+|
[incubator-openwhisk-utilities](https://github.com/apache/incubator-openwhisk-utilities)
| Shared utilities used across Apache OpenWhisk project repositories. |
+
+
+## Others
+
+| Module | Description |
+|--- |--- |
+|
[incubator-openwhisk-external-resources](https://github.com/apache/incubator-openwhisk-external-resources)
| ✨ Curated list of awesome OpenWhisk things ✨ |
+|
[incubator-openwhisk-podspecs](https://github.com/apache/incubator-openwhisk-podspecs)
| CocoaPods Podspecs repo for openwhisk-client-swift |
+|
[incubator-openwhisk-selfserve-test](https://github.com/apache/incubator-openwhisk-selfserve-test)
| Apache openwhisk |
+|
[incubator-openwhisk-test](https://github.com/apache/incubator-openwhisk-test)
| Test repo. for Apache OpenWhisk client-side tooling. |
+|
[incubator-openwhisk-website](https://github.com/apache/incubator-openwhisk-website)
| Apache OpenWhisk website (openwhisk.incubator.apache.org) code built using
Jekyll |
+
+
diff --git a/settings.gradle b/settings.gradle
index 9e37f87..d0f0d09 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -24,6 +24,7 @@ include 'tests'
include 'tests:performance:gatling_tests'
include 'tools:actionProxy'
+include 'tools:dev'
include 'tools:admin'
diff --git a/tools/dev/README.md b/tools/dev/README.md
index 119493f..ed3aa67 100644
--- a/tools/dev/README.md
+++ b/tools/dev/README.md
@@ -25,7 +25,7 @@ change
With current directory set to OpenWhisk home
- ./gradlew -p tools/dev <taskName>
+ ./gradlew :tools:dev:<taskName>
With this module being base directory
@@ -38,7 +38,7 @@ _<OPENWHISH_HOME>/ansibles/files_ and dumps them in
_build/views_ directory
Sample output
- $./gradlew -p tools/dev couchdbViews
+ $./gradlew :tools:dev:couchdbViews
Processing whisks_design_document_for_entities_db_v2.1.0.json
- whisks.v2.1.0-rules.js
- whisks.v2.1.0-packages-public.js
@@ -71,7 +71,7 @@ project is file based (uses ipr files) then you can convert
it to directory base
First setup OpenWhisk so that Controller and Invoker containers are up and
running. Then run the script:
- ./gradlew -p tools/dev intellij
+ ./gradlew :tools:dev:intellij
It would inspect the running docker containers and then generate the launch
configs with name 'controller0'
and 'invoker0'.
@@ -125,7 +125,46 @@ The config allows following properties:
* `props` - Map of system properties which should be passed to the application.
* `env` - Map of environment variables which should be set for application
process.
+## Github Repository Lister
+
+Lists all Apache OpenWhisk related repositories by using [Github Search
API][5] with pagination. Its preferable that prior
+to using this you specify a [Github Access Token][6] as otherwise requests
will quickly become rate limited. The token
+can be specified by setting environment variable `GITHUB_ACCESS_TOKEN`
+
+```bash
+$ ./gradlew :tools:dev:listRepos
+Found 44 repositories
+incubator-openwhisk
+incubator-openwhisk-GitHubSlackBot
+incubator-openwhisk-apigateway
+incubator-openwhisk-catalog
+...
+Stored the list in /openwhisk_home/build/repos/repos.txt
+Stored the json details in /openwhisk_home/build/repos/repos.json
+
+```
+
+It generates 2 files
+
+* `repos.txt` - List repository names one per line.
+* `repos.json` - Stores an array of repository details json containing various
repository related details.
+
+## OpenWhisk Module Status Generator
+
+It renders a markdown file which lists the status of various OpenWhisk modules
by using the output generated by `listRepos`
+task. The rendered markdown file is stored in `docs/dev/modules.md`. This
rendered file should be later checked in.
+
+```bash
+$ ./gradlew :tools:dev:renderModuleDetails
+
+ > Task :tools:dev:renderModuleDetails
+ Generated modules details at /openwhisk_home/docs/dev/modules.md
+
+```
+
[1]:
https://www.jetbrains.com/help/idea/run-debug-configurations-dialog.html#run_config_common_options
[2]: https://github.com/apache/incubator-openwhisk/issues/3195
[3]:
https://www.jetbrains.com/help/idea/configuring-projects.html#project-formats
[4]: http://docs.groovy-lang.org/2.4.2/html/gapi/groovy/util/ConfigSlurper.html
+[5]: https://developer.github.com/v3/search/
+[6]:
https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
diff --git a/tools/dev/build.gradle b/tools/dev/build.gradle
index a721e9d..0ce1183 100644
--- a/tools/dev/build.gradle
+++ b/tools/dev/build.gradle
@@ -25,6 +25,7 @@ def owHome = project.projectDir.parentFile.parentFile
dependencies {
compile "org.codehaus.groovy:groovy-all:2.4.14"
+ compile 'org.apache.commons:commons-io:1.3.2'
}
task couchdbViews(type: JavaExec) {
@@ -40,3 +41,17 @@ task intellij(type: JavaExec) {
args owHome.absolutePath
classpath = sourceSets.main.runtimeClasspath
}
+
+task listRepos(type: JavaExec) {
+ description 'Generates a list of all OpenWhisk related Git repos'
+ main = 'listRepos'
+ args owHome.absolutePath
+ classpath = sourceSets.main.runtimeClasspath
+}
+
+task renderModuleDetails(type: JavaExec) {
+ description 'Renders modules details'
+ main = 'renderModuleDetails'
+ args owHome.absolutePath
+ classpath = sourceSets.main.runtimeClasspath
+}
diff --git a/tools/dev/src/main/groovy/CategoryManager.groovy
b/tools/dev/src/main/groovy/CategoryManager.groovy
new file mode 100644
index 0000000..a542139
--- /dev/null
+++ b/tools/dev/src/main/groovy/CategoryManager.groovy
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+import java.util.function.Predicate
+
+class CategoryManager {
+ def categories = process([
+ [name: "Main", travis: true, suffixes: ['openwhisk', 'apigateway',
'catalog', 'cli', 'wskdeploy']],
+ [name: "Clients", travis: true, contains: ['-client-']],
+ [name: "Runtimes", travis: true, contains: ['-runtime-']],
+ [name: "Deployments", travis: true, contains: ['-deploy-']],
+ [name: "Packages", travis: true, contains: ['-package-']],
+ [name: "Samples and Examples", travis: false, suffixes: ['workshop',
'slackinvite', 'sample-slackbot', 'sample-matos', 'tutorial',
'GitHubSlackBot']],
+ [name: "Development Tools", travis: false, suffixes: ['devtools',
'xcode', 'vscode', 'playground', 'debugger']],
+ [name: "Utilities", travis: false, suffixes: ['utilities', 'release']],
+ [name: "Others", travis: false]
+ ])
+
+ private def suffixMatcher(List<String> suffixes) {
+ return {name -> suffixes.any {name.endsWith("-"+it)}} as
Predicate<String>
+ }
+
+ private def containsMatcher(String marker) {
+ return {name -> name.contains(marker)} as Predicate<String>
+ }
+
+ private def createMatcher(Map m){
+ if (m.containsKey('suffixes')) return suffixMatcher(m.suffixes)
+ else if (m.containsKey('contains')) return
containsMatcher(m['contains'])
+ else return {true} as Predicate
+ }
+
+ private def process(List<Map> repos) {
+ repos.collect {m -> new Category(m.name, m.travis, createMatcher(m))}
+ }
+
+ def addToCategory(repo) {
+ categories.find {c -> c.matches(repo.name)}.addRepo(repo)
+ }
+
+ def sort(){
+ categories.each {it.sort()}
+ }
+}
+
+class Category {
+ String name
+ boolean travisEnabled
+ List repos = []
+ Predicate<String> matcher
+
+ Category(name, travisEnabled, matcher) {
+ this.name = name
+ this.travisEnabled = travisEnabled
+ this.matcher = matcher
+ }
+
+ def matches(String repoName) {
+ matcher.test(repoName)
+ }
+
+ def addRepo(repo){
+ repos << repo
+ }
+
+ def sort() {
+ repos.sort {a, b -> a.name <=> b.name}
+ }
+}
diff --git a/tools/dev/src/main/groovy/listRepos.groovy
b/tools/dev/src/main/groovy/listRepos.groovy
new file mode 100644
index 0000000..afadedc
--- /dev/null
+++ b/tools/dev/src/main/groovy/listRepos.groovy
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+import groovy.json.JsonOutput
+import groovy.json.JsonSlurper
+import org.apache.commons.io.FilenameUtils
+
+// script to read the Apache OpenWhisk repositories using the Github API
+// it is recommended to use authentication by setting the
'GITHUB_ACCESS_TOKEN' env
+// as otherwise requests will quickly become rate limited
+
+assert args : "Expecting the OpenWhisk home directory to passed"
+owHomePath = args[0]
+
+def parser = new JsonSlurper()
+
+// get as many repos per page as possible to cut down on the number of calls
+def link = "https://api.github.com/orgs/apache/repos?per_page=100"
+def creds = getCredentials()
+def owRepos = []
+
+if (!creds) {
+ println "It is recommended to pass access token via env variable
'GITHUB_ACCESS_TOKEN' as otherwise requests will quickly become rate limited"
+}
+
+while ( link ) {
+ def url = new URL(link)
+ def conn = url.openConnection()
+ if ( creds ) {
+ conn.setRequestProperty("Authorization", "Basic " +
creds.bytes.encodeBase64())
+ }
+
+ // add all projects matching naming conventions
+ def result = parser.parse(conn.inputStream)
+ owRepos += result
+ .findAll { it.name.startsWith('incubator-openwhisk') }
+
+ // find link to next page, if applicable
+ link = null
+
+ def links = conn.headerFields['Link']
+ if ( links ) {
+ def next = links[0].split(',').find{ it.contains('rel="next"') }
+ link = next != null ? next.find('<(.*)>').replaceAll('<|>',''): null
+ }
+}
+
+
+// ensure a consistent order
+owRepos.sort {
+ a,b -> a.name <=> b.name
+}
+
+def owReoNames = owRepos.collect {it.name}
+
+def nameListFile = createNameListFile()
+def jsonFile = createRepoJsonFile()
+def list = owReoNames.join("\n")
+
+nameListFile.text = list
+jsonFile.text = JsonOutput.prettyPrint(JsonOutput.toJson(owRepos))
+
+println("Found ${owRepos.size()} repositories")
+println(list)
+println("Stored the list in ${nameListFile.getAbsolutePath()}")
+println("Stored the json details in ${jsonFile.getAbsolutePath()}")
+
+def getCredentials(){
+ String creds = System.getenv("GITHUB_ACCESS_TOKEN")
+ creds
+}
+
+def createNameListFile(){
+ new File(getOutDir(), "repos.txt")
+}
+
+def createRepoJsonFile(){
+ new File(getOutDir(), "repos.json")
+}
+
+def getOutDir(){
+ def dir = new File(FilenameUtils.concat(owHomePath, "build/repos"))
+ dir.mkdirs()
+ dir
+}
diff --git a/tools/dev/src/main/groovy/renderModuleDetails.groovy
b/tools/dev/src/main/groovy/renderModuleDetails.groovy
new file mode 100644
index 0000000..9f6da34
--- /dev/null
+++ b/tools/dev/src/main/groovy/renderModuleDetails.groovy
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+import groovy.json.JsonSlurper
+import groovy.text.SimpleTemplateEngine
+import org.apache.commons.io.FilenameUtils
+
+assert args : "Expecting the OpenWhisk home directory to passed"
+owHomePath = args[0]
+
+def repos = loadRepoJson()
+
+def template = getClass().getResource("./modules.md").text
+def engine = new SimpleTemplateEngine()
+
+def categoryManager = new CategoryManager()
+
+repos.each{ repo ->categoryManager.addToCategory(repo)}
+categoryManager.sort()
+
+def binding = ["categories":categoryManager.categories]
+def result = engine.createTemplate(template).make(binding)
+
+def file = getModuleOutputFile()
+file.setText(result.toString(), 'UTF-8')
+println "Generated modules details at ${file.getAbsolutePath()}"
+
+def loadRepoJson(){
+ File file = new File(FilenameUtils.concat(owHomePath,
"build/repos/repos.json"))
+ assert file.exists() : "Did not found ${file.absolutePath}. Run './gradlew
:tools:dev:listRepos' prior to this script"
+ def parser = new JsonSlurper()
+ parser.parseText(file.text)
+}
+
+def getModuleOutputFile(){
+ new File(FilenameUtils.concat(owHomePath, "docs/dev/modules.md"))
+}
diff --git a/tools/dev/src/main/resources/modules.md
b/tools/dev/src/main/resources/modules.md
new file mode 100644
index 0000000..86c5a01
--- /dev/null
+++ b/tools/dev/src/main/resources/modules.md
@@ -0,0 +1,37 @@
+<!--
+#
+# 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.
+#
+-->
+<!--
+DO NOT EDIT.
+This page is generated via script `./gradlew :tools:dev:renderModuleDetails`.
See tools/dev/README.md for details.
+-->
+
+# Modules
+
+<% categories.each { c -> %>
+## ${c.name}
+<% if (c.travisEnabled) {%>
+| Module | Description | Module Status |
+|--- |--- |--- |
+<% c.repos.each { repo -> %>|
[${repo.name}](https://github.com/apache/${repo.name}) | ${repo.description} |
[](https://travis-ci.org/apache/${repo.name})
|
+<% } %><% } else { %>
+| Module | Description |
+|--- |--- |
+<% c.repos.each { repo -> %>|
[${repo.name}](https://github.com/apache/${repo.name}) | ${repo.description} |
+<% } %><% } %>
+<% } %>