Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Behind the scenes of the new Groovy website and documentation

Behind the scenes of the new Groovy website and documentation

The new Groovy website is the perfect example of the ""eating your own dogfood"" mantra. In this talk, we will explain the technologies used to build the new Groovy website, including Gradle, the Groovy MarkupTemplateEngine, Asciidoctor and automation of publication through TeamCity. You will learn how we put all those pieces together to create a toolchain that allows us to release new versions of Groovy will a fully tested documentation, as well as the generation of a static website only using Groovy technologies!

Guillaume Laforge

December 11, 2014

More Decks by Guillaume Laforge

Other Decks in Programming


  1. @glaforge New documentation goals • One documentation version per release

    • Integrated in the build process • Should be easy to write • Should be tested 10
  2. @glaforge How? Asciidoctor to the rescue! • Markup based documentation

    engine • Derived from Asciidoc • Lightweight syntax • Feature rich • Highly customizable 12
  3. @glaforge How? Asciidoctor to the rescue! 13 = Syntax

    This chapter covers the syntax of the Groovy programming language.
 The grammar of the language derives from the Java grammar,
 but enhances it with specific constructs for Groovy, and allows certain simplifications.
 == Comments
 === Single line comment
 Single line comments start with `//` and can be found at any position in the line.
 The characters following `//`, till the end of the line, are considered part of the comment.
  4. @glaforge Directory structure 14 src/spec/ assets doc test test-resources images,

    css, javascript… asciidoctor source files documentation specific tests
  5. @glaforge Directory structure 14 src/spec/ assets doc test test-resources images,

    css, javascript… asciidoctor source files documentation specific tests test sources
  6. @glaforge Including external snippets of code 17 [source,groovy]

    ---- Groovy syntax highlighting for the block of code include directive source file to include just include a portion
  7. @glaforge Snippet demarcation 18 void testSingleLineComment() {
 // tag::single_line_comment[]

    a standalone single line comment
 println "hello" // a comment till the end of the line
 // end::single_line_comment[]
  8. @glaforge Snippet demarcation 18 void testSingleLineComment() {
 // tag::single_line_comment[]

    a standalone single line comment
 println "hello" // a comment till the end of the line
 // end::single_line_comment[]
 } tag::tag_name[] end::tag_name[]
  9. @glaforge Narrative 19 They can be seen as *interfaces* carrying

    both *default implementations* and *state*. A trait is defined using the `trait` keyword:
 <1> declaration of a trait
 <2> declaration of a method inside a trait
  10. @glaforge Callouts 20 class TraitsSpecTest extends GroovyTestCase {
 void testTraitDeclaration()

 assertScript ''' // tag::flying_simple[]
 trait FlyingAbility { // <1>
 String fly() { "I'm flying!" } // <2>
 // end::flying_simple[]
 // tag::bird[]
 class Bird implements FlyingAbility {} // <1>
 def b = new Bird() // <2>
 assert b.fly() == "I'm flying!" // <3>
 // end::bird[]
  11. @glaforge Gradle 22 apply plugin: 'org.asciidoctor.gradle.asciidoctor'
 asciidoctor {

    (full, major, minor, patch, flavor) = (groovyVersion =~ /(\d+)\.(\d++)\.(\d+)(?:-(.+))?/)[0]
 logDocuments = true
 sourceDir = project.file('src/spec/doc')
 options = [
 attributes: [
 'rootProjectDir': rootProject.projectDir,
 'source-highlighter': 'prettify',
 groovyversion: groovyVersion,
 'groovy-major-version': major,
 'groovy-minor-version': minor,
 'groovy-patch-version': patch,
 'groovy-full-version': groovyVersion,
 'groovy-short-version': "${major}.${minor}",
 doctype: 'book',
 revnumber: groovyVersion,
 icons: 'font',
 toc2: '',
 specfolder: 'src/spec/doc',
 linkcss: '',
 stylesheet: "assets/css/style.css",
 encoding: 'utf-8',
 toclevels: 10,
 numbered: ''
  12. @glaforge In summary • Documentation rewritten from scratch – help

    still needed to fill the many gaps though! • Narrative written using Asciidoctor • Code must belong to test cases • Makes guarantees that doc is up-to-date • Integrated through Gradle 23
  13. @glaforge Objectives • Facelifting and responsiveness • Easy maintenance /

    hosting • Well organized • Make contributions easy • Eat your own dog food 26
  14. @glaforge Responsiveness 27 Drop-down menu Lead to Github’s online editor!

    Readable from any modern browsers, both desktop and mobile
  15. @glaforge Technical solution • Bootstrap theme by Damien Vitrac •

    Fully static • Uses a Groovy DSL for contents • Forkable on GitHub • Uses the Markup Template Engine • Baked with Gradle 28
  16. @glaforge Markup template engine • Introduced in Groovy 2.3 •

    Fully fledged template engine • Primarily aimed at generating markup contents • Templates look like Groovy builders • Statically compiled templates • Optional type checking 29
  17. @glaforge Markup template engine • No more closing tag nightmare

    • Can be very fast once templates are compiled • Support for i18n • Used in both Spring Boot and Ratpack 30
  18. @glaforge A basic template 31 downloads.each { dl -> div(class:'download')

 a(href:dl.url, "Groovy $dl.version") }
  19. @glaforge Template rendered 32 <div class="download">
 <a href="groovy238.html">Groovy 2.3.8</a>

    <div class="download">
 <a href="groovy239.html">Groovy 2.3.9</a>
  20. @glaforge Layouts 34 layout 'layouts/main.groovy', true,
 pageTitle: 'The Groovy programming

 mainContent: contents {
 div(id: 'content') {
 include unescaped: 'html/index.html'
 section(class: "row colset-3-article") {
 h1 { strong "Groovy events you shouldn't miss!" }
 allEvents.keySet().take(3).each { String eventName ->
 Event event = allEvents[eventName]
 article {
 div(class: 'content') {
  21. @glaforge Layout 35 layout 'layouts/page.groovy', true,
 mainContent: contents {

 div {
 include template: 'includes/topmenu.groovy'
 // main contents goes here!
 include template: 'includes/bottommenu.groovy'
  22. @glaforge Setting up the engine 37 def tplConf = new

    TemplateConfiguration( autoIndent : true, autoNewLine: true ) 
 def classLoader = … 
 tplEngine = new MarkupTemplateEngine(
 classLoader, tplConf,
 new CachingTemplateResolver())
  23. @glaforge Template resolver • Allows… – custom template resolution/loading –

    overriding i18n behavior – custom caching strategies 38
  24. @glaforge Markup template engine • Even if a template contains

    unresolved variables – Statically compiled – Uses type checking extensions under the hood – Allows optional type checking of model – Even faster if type checked 40
  25. @glaforge Type checked models 41 modelTypes = { List<Page> pages

 pages.each { page -> p("Page title: $page.title") p(page.text)
  26. @glaforge A DSL for the model • Templates generate contents

    • The model describes the website • Our model is described using a Groovy DSL 42
  27. @glaforge Sitemap.groovy 43 menu {
 group('Groovy') {
 item ‘Learn', 'learn.html'

    item 'Documentation', 'documentation.html'
 item 'Download', 'download.html'
 item 'Community', 'community.html'
 item 'Ecosystem', 'ecosystem.html'
 group('About') {
 item 'Contributing', 'contribute.html'
 item 'Source code', 'https://github.com/groovy/groovy-core'
 item 'Build status', 'buildstatus.html'
 item 'Books', 'learn.html#books'
 item 'Sponsors', 'sponsors.html'
 item 'FAQ', 'faq.html'
 item 'Search', 'search.html'
 } …
  28. @glaforge Sitemap.groovy 44 ecosystem {
 project('Grails') {
 description '''Grails is

    an Open Source, full stack, web application framework for the JVM. It takes advantage of the Groovy programming language and convention over configuration to provide a productive and stream-lined development experience.'''
 url 'http://grails.org/'
 logo 'img/ecosystem/grails.png'
 project('Gradle') {
 description '''Gradle is build automation evolved. Gradle can automate the building, testing, publishing, deployment and more of software packages or other types of projects such as generated static websites, generated documentation or indeed anything else.'''
 url 'http://gradle.org'
 logo 'img/ecosystem/gradle.gif'
  29. @glaforge Baking • sitemap.groovy contains the site “data” • MarkupTemplateEngine

    converts it to pages • Gradle – Compiles the generator – Generates the website – Checks for dead links in generated contents 46
  30. @glaforge Deployment • Gradle generates a static website • Can

    be deployed anywhere • For continuous deployment, we use TeamCity 47
  31. @glaforge TeamCity at Groovy • CI Server for Groovy •

    Tests, builds and releases Groovy • Build plans for JDK 5, 6, 7, 8 and even 9 • Tests every pull request before merge • We test early releases of the JDK (EA and sources) • http://ci.groovy-lang.org?guest=1 48
  32. @glaforge TeamCity at Groovy • Server is sponsored by •

    Deployment of Groovy is done through • Releasing Groovy is: – Done through Artifactory plugin – One form + one click 50
  33. @glaforge Website deployment A commit on the master branch of

    website… • Triggers a build • Which generates a static website • Copied to the server if the build is successful 51
  34. @glaforge A word on GVM When a release is done:

    • GVM is notified • Download is made available in GVM • Done through a REST API • API Called directly from TeamCity • Thanks to... a Groovy script! 52
  35. @glaforge Groovy build-step in TeamCity • Groovy Build Step plugin

    – Allows you to write a build step as a Groovy script – Can be used to deploy, copy resources, web hooks ... 53
  36. @glaforge Picture credits London: http://www.100percentoptical.com/images/2014/10/london.jpg Vomit:; http://youoffendmeyouoffendmyfamily.com/wordpress/wp-content/uploads/2011/09/vomit1.jpg Dinos: http://vergapipe.com/wp-content/uploads/2014/11/dinosaurs_wallpapers_free_download.jpg Future:

    http://www.hdwallsource.com/stunning-future-wallpaper-29256.html/stunning-future-wallpaper-29256 Gears: http://gearsoffate.com/wp-content/uploads/2014/09/Gears2.jpg Surprise: http://www.mentalactif.com/wp-content/uploads/2013/03/SURPRISE.jpg Plane: http://i.imgur.com/esCemkx.jpg Baking: http://www.nlinnovators.nl/wp-content/blogs.dir/1/files_mf/1409922073Navy_baking_bread.jpg 60