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

Guides publication/upgrade/testing automation #7

Open
sdelamo opened this issue Aug 3, 2020 · 4 comments
Open

Guides publication/upgrade/testing automation #7

sdelamo opened this issue Aug 3, 2020 · 4 comments
Labels
relates-to: build label for issues related to the build file or CI

Comments

@sdelamo
Copy link

sdelamo commented Aug 3, 2020

This is my vision for this.

Instead of being a guide per language, lets have a single guide. Each guide will contain build samples (Maven and Gradle), code samples in three languages (Java, Groovy, Kotlin) and test samples (Java Junit, Spock Groovy, Junit Kotlin).

My idea is to use the Launch infrastructure to create guides which upgrade automatically with new version and whose test are execute it each time the Micronaut Launch test suite is run.

For example, the Create your first Micronaut app would be a set of rocker templates:

@import io.micronaut.starter.application.Project

@args (
Project project
)

@if (project.getPackageName() != null) {
package @project.getPackageName()
}

package example.micronaut;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;

import io.micronaut.http.HttpRequest;
import io.micronaut.http.client.RxHttpClient;
import io.micronaut.http.client.annotation.Client;
import io.micronaut.test.annotation.MicronautTest;
import org.junit.jupiter.api.Test;

import javax.inject.Inject;

@@MicronautTest 
public class HelloControllerTest {

    @@Inject
    @@Client("/")
    RxHttpClient client; 

    @Test
    public void testHello() {
        HttpRequest<String> request = HttpRequest.GET("/hello"); 
        String body = client.toBlocking().retrieve(request);

        assertNotNull(body);
        assertEquals("Hello World", body);
    }
} 

and a Feature per guide:

@Singleton
public class CreatingYourFirstMicronautApp implements Feature, Guide {

    @Override
    public String getName() {
        return "creating-your-first-micronaut-app";
    }

    @Override
    public String getTitle() {
        return "Creating your first Micronaut App";
    }

    @Override
    public String getDescription() {
        return "Learn how to create a Hello World Micronaut app with Java with a controller and a functional test.";
    }

    @Override
    public void apply(GeneratorContext generatorContext) {
        Project project = generatorContext.getProject();
        generateCode(generatorContext, project)

Per guide, before rendering the HTML we will do some curl request to generate the sample projects:

Some projects, those with multiple apps (e.g. distributed tracing) may need to generate six projects or more.

curl micronaut.io/launch 
--features=guide-creating-your-first-micronaut-app 
    --lang=kotlin

curl micronaut.io/launch --features=guide-creating-your-first-micronaut-app 
--lang=groovy

curl micronaut.io/launch 
--features=guide-creating-your-first-micronaut-app 
--lang=java

We can make the Guide features hidden at the CLI and UI.

  • We will need to create an asciidoctor macro for the test samples (Java Junit, Spock Groovy, Junit Kotlin).
  • Ability to wrap some asciidoc comments around configurtation and dependencies since we often embeeded configuration and dependnecies in the guides.
  • Github actions to republish

I think automating guides it is key to be able to write documentation and will provide a safety net of functional tests.

In fact, my recommendation is that we don't write new guides until we have automate it.

Before going rouge for every guide, I would recommend lets try to create a prototype with one guide.

@sdelamo sdelamo changed the title Guides publication automation Guides publication/upgrade/testing automation Aug 3, 2020
@sdelamo sdelamo added the relates-to: build label for issues related to the build file or CI label Aug 3, 2020
@ilopmar
Copy link

ilopmar commented Aug 10, 2020

I like this idea of generating the guides automatically. As someone that has updated the guides manually many times this would be great 😃

Some random thoughts in no particular order:

Instead of coupling the guides with Starter I think it would be better to fork the project and keep the guides code only in the fork.
The main two benefits I see for this are to reduce the Starter build time (which already takes too much time) and do not mix the guides code with the features code.
Keeping the fork up to date should be easy because we're not doing big changes in Starter anymore and we won't modify anything related to Starter in the Guides. Probably it would be a matter of merging the changes done upstream once a week and it won't be any merge conflicts.

I agree we should migrate 2-3 guides following this approach to really see how big the effort is and find any problems.

I'm afraid that migrating some of the "complex" guides (the ones with 3-4 microservices), with a lot of steps can be tricky and complicated. A few guides have "intermediate" directory (beside "complete" and "initial") and we fetch files from there as an intermediate solution. Then we explain a better solution and fetch the files from "complete" directory. Maybe we should re-think this and simplify those guides a little bit.

On the user side, I think with this approach it will be more complicated to users to send PRs because the code "is not there" but it's generated from rocker templates.

So, as a summary, 👍. I think we should prioritize it and if we all agree start working on it. We have ideas for new guides on the pipeline and if the plan is not create more until this is done (or at least, only create new guides with this new approach during the migration), it's better to start soon.

@alvarosanchez
Copy link
Member

I used a similar approach in Spring Security REST, by having a profile with the tests, and different features with their own dependencies and configurations to test different scenarios. Then I would generate all possible combinations with this custom profile, and add the generated projects to settings.gradle, so at that point it was a matter of ./gradlew test to test everything.

I really miss the possibility to package profiles as JAR files. If micronaut-starter supported that, you wouldn't need to mess with forks.

A poor-man's alternative would be to create blank applications:

curl micronaut.io/launch --lang=kotlin
curl micronaut.io/launch --lang=groovy
curl micronaut.io/launch --lang=java

Then copy the artifacts (controller, test, configuration, etc).

And a third alternative coming to my mind is, instead of forking micronaut-starter, you have a Gradle project with your features that has starter-core and starter-cli as dependencies.

In general, micronaut-starter extensibility is something that should be revisited, and based on that, your strategy to implement this task might vary.

@jameskleeh
Copy link

I think the idea of using starter is good. You don't have to fork it though as Alvaro said. You can simply add a dependency on it and your features will be picked up as they are just beans. Looking forward to the POC

@jeffscottbrown
Copy link

In fact, my recommendation is that we don't write new guides until we have automate it.

With your recommendation, is there an ETA on when guide publishing would resume?

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
relates-to: build label for issues related to the build file or CI
Projects
None yet
Development

No branches or pull requests

5 participants