Skip to content

Commit

Permalink
Refresh codestart guide
Browse files Browse the repository at this point in the history
  • Loading branch information
ia3andy committed Jul 11, 2022
1 parent b57ef54 commit 0de12f1
Showing 1 changed file with 181 additions and 89 deletions.
270 changes: 181 additions & 89 deletions docs/src/main/asciidoc/extension-codestart.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -71,69 +71,189 @@ The https://github.com/quarkusio/quarkus/tree/main/independent-projects/tools/ba

As was mentioned previously, the base project files (pom.xml, dockerfiles, ...) are already generated by base codestarts provided by the Quarkus core. Thanks to this, we can only focus on the important - the starter code for the extension.

The codestart should not include any business logic, instead, it should contain some stub data/hello world to compile. The idea is to bring code that is the starting point to everyone using the extension.
Let's take `io.quarkiverse.aloha:quarkus-aloha` as the example extension gav (don't search, it doesn't exist).

== Writing an Extension Codestart in Quarkus Core
=== The code

- Copy one of the existing https://github.com/quarkusio/quarkus/tree/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts[Quarkus core extension codestarts, window="_blank"]. If the code needs to expose a web resource, `resteasy-qute-codestart` could be a good base Otherwise, `config-yaml-codestart` could be a better starting point. More info on the <<directory-structure>>.
Go to https://code.quarkus.io[code.quarkus.io, window="_blank"], create a new project with the aloha extension and `org.acme` as Group (i.e <<org-acme-package>>). Prepare a nice starter. It should not include any business logic, instead, it should contain some stub data/hello world to compile. The idea is to bring code that is the most common starting point for the extension.

- Edit the <<codestart-yml>>:
Happy with the code? Let's make a Codestart out of it.

- Create the extension binding in the extension metadata (https://github.com/quarkusio/quarkus/blob/main/extensions/config-yaml/runtime/src/main/resources/META-INF/quarkus-extension.yaml#L12-L17[example, window="_blank"]). *Thanks to this, the codestart is added when the user selects the extension*
=== The Codestart (Quarkiverse or Standalone extensions)

- Add the readme <<readme-md>> section template.
* Create `runtime/src/main/codestarts/quarkus/aloha-codestart`

- Add the code in the language folder (it is recommended to at least provide java and kotlin). *You have to use `org.acme` as the package name: <<org-acme-package>>*. It is possible to use <<qute-templates>> if needed.
* Move `src/main/java` to `runtime/src/main/codestarts/quarkus/aloha-codestart/java/src/main/java`

- Optionally, Add the `index.html` section template (<<index-html>>).
* (Optional) Move the config using this convention: <<app-config>>.

- Optionally, add some resources (`./base` directory if they are non language specific)

- Optionally, add the <<app-config>>.
* Create a <<codestart-yml>> file in `runtime/src/main/codestarts/quarkus/aloha-codestart`:
+
[source,yaml]
----
name: aloha-codestart
ref: aloha
type: code
tags: extension-codestart
metadata:
title: Aloha
description: Start to code with the Aloha extension.
related-guide-section: https://quarkiverse.github.io/quarkiverse-docs/quarkus-aloha/dev/
path: /aloha # (optional) for web extensions providing http resources
----

- Create an <<integration-test>>.
* Add the Maven build plugin configuration in `runtime/pom.xml` (to generate the codestart artifact: `/target/quarkus-aloha-VERSION-codestarts.jar`):
+
[source,xml]
----
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>generate-codestart-jar</id>
<phase>generate-resources</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${project.basedir}/src/main</classesDirectory>
<includes>
<include>codestarts/**</include>
</includes>
<classifier>codestarts</classifier>
<skipIfEmpty>true</skipIfEmpty>
</configuration>
</execution>
</executions>
</plugin>
----

- <<generating>>
* Add the codestart binding in the extension metadata `runtime/src/main/resources/META-INF/quarkus-extension.yaml`. *Without this, your codestart won't be added when your extension is picked*:
+
[source,yaml]
----
name: ...
description: ...
metadata:
...
codestart:
name: "aloha"
languages:
- "java"
artifact: "io.quarkiverse.aloha:quarkus-aloha:codestarts:jar:${project.version}"
----

== Writing an Extension Codestart in the Quarkiverse or standalone
* Add the readme <<readme-md>> section template in `base/readme.tpl.qute.md`:
+
[source,html]
----
{#include readme-header /}
----

For extensions hosted outside the Quarkus core[https://github.com/quarkusio/quarkus] repository, codestarts will typically be located in the runtime module (with special instruction in the `pom.xml` to generate a separate codestart artifact). https://github.com/ia3andy/aloha-code/[Here, window="_blank"] is an example extension with a codestart and its tests.
* Run `mvn clean install` in the extension root (or just `runtime`).

* Tell me it works?
+
[source,bash]
----
quarkus create app aloha-app x=io.quarkiverse.aloha:quarkus-aloha:999-SNAPSHOT
...
applying codestarts...
📚 java
🔨 maven
📦 quarkus
📝 config-properties
🔧 dockerfiles
🔧 maven-wrapper
🚀 aloha-codestart <<<<<<<<<<<<<<<<
...
----

[#generating]
== Generating your Extension Codestart
=== Testing

**You need to build your codestart with Maven to make it available in the tooling:**
* Add this dependency to the `integration-tests`:
+
[source,xml]
----
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-devtools-testing</artifactId>
</dependency>
----

- First add the codestart and update the relevant extension's metadata yml file, and build it all (the codestart and the extension if in core).
* Create a `AlohaCodestartTest` in the `integration-tests`:
+
[source,java]
----
- In Quarkus core, you also have to rebuild the `devtools/bom-descriptor-json` module to bind the codestart with the extension in the platform descriptor.
public class AlohaCodestartTest {
=== With the tests
@RegisterExtension
public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder()
.languages(Language.JAVA)
.setupStandaloneExtensionTest("io.quarkiverse.aloha:quarkus-aloha")
.build();
You can use the <<integration-test>> to help develop your codestart with `buildAllProjects` (In Quarkus core we added `@EnabledIfSystemProperty(named = "build-projects", matches = "true")` because codestarts are already built together in another test from `QuarkusCodestartBuildIT`).
@Test
void testContent() throws Throwable {
codestartTest.checkGeneratedSource("org.acme.AlohaResource");
}
Use `-Dbuild-projects=true` when running this test to generate the real project with your codestart. Open it with your IDE, then change the code and copy it back to the codestart (and iterate until you are happy with the result).
@Test
void buildAllProjects() throws Throwable {
codestartTest.buildAllProjects();
}
}
----

=== With the Quarkus tooling
=== Nearly there

NOTE: Using the tooling to generate your local extension codestart during dev is not yet available Quarkiverse/Standalone extension (Until then, you may use the tests and follow https://github.com/quarkusio/quarkus/issues/21165[#21165, window="_blank"] for updates).
* If the extension provide some web resources, add the `base/src/main/resources/META-INF/resources/index.entry.qute.html` template (<<index-html>>).

Using the CLI or Maven plugin to generate a project with your codestart:
* Add another language (it is recommended to provide java and kotlin).

- If using the CLI, you'll probably need to add `-P=io.quarkus:quarkus-bom:999-SNAPSHOT` to the CLI's arguments to use your snapshot of the platform
* You may some other resources (`./base` directory if they are non language specific).

- Example CLI command: `quarkus create app -x smallrye-health --code --java -P=io.quarkus:quarkus-bom:999-SNAPSHOT`
=== Extensions codestarts in Quarkus Core

- Equivalent for the Maven plugin: `mvn io.quarkus:quarkus-maven-plugin:2.3.0.Final:create -Dextensions=smallrye-health -DplatformVersion=999-SNAPSHOT`
* The codestarts are all grouped in a https://github.com/quarkusio/quarkus/tree/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts[specific module, window="_blank"].
* No extra Maven configuration is need needed.
* The https://github.com/quarkusio/quarkus/blob/main/extensions/resteasy-reactive/quarkus-resteasy-reactive-qute/runtime/src/main/resources/META-INF/quarkus-extension.yaml#L18[extension metadata, window="_blank"] reference the artifact containing all the core codestarts.
* The tests are also https://github.com/quarkusio/quarkus/tree/main/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus[grouped, window="_blank"]. You don't need to test the build as there is a specific grouped https://github.com/quarkusio/quarkus/blob/main/integration-tests/devtools/src/test/java/io/quarkus/devtools/codestarts/quarkus/QuarkusCodestartBuildIT.java[test, window="_blank"] for it. e.g.:
+
[source,java]
----
public class ConfigYamlCodestartTest {
@RegisterExtension
public static QuarkusCodestartTest codestartTest = QuarkusCodestartTest.builder()
.codestarts("config-yaml")
.languages(JAVA, KOTLIN)
.build();
@Test
void testContent() throws Throwable {
codestartTest.checkGeneratedSource("org.acme.GreetingConfig");
codestartTest.assertThatGeneratedFileMatchSnapshot(JAVA, "src/main/resources/application.yml");
}
@Test
@EnabledIfSystemProperty(named = "build-projects", matches = "true")
void buildAllProjectsForLocalUse() throws Throwable {
codestartTest.buildAllProjects();
}
}
----


== Specific topics

[#org-acme-package]
=== Dynamic package name generation from org.acme
=== "org.acme" placeholder for package name

You have to use `org.acme` as the package name in your extension codestart sources. In the generated project, the user specified package will be used (and auto-replace `org.acme`).
You have to use `org.acme` as the package name in your extension codestart sources. In the generated project, the user specified package (or Group) will be used (and auto-replace `org.acme`).

It will be auto-replaced in all the source files (.java, .kt, .scala). The package directory will also be automatically adjusted. If for some reason, another type of file needs the user package name then you should use a <<qute-templates>> for it and `{project.package-name}` data placeholder (https://github.com/quarkusio/quarkus/blob/main/devtools/project-core-extension-codestarts/src/main/resources/codestarts/quarkus/extension-codestarts/grpc-codestart/base/src/main/proto/hello.tpl.qute.proto#L4[find an example in the grpc proto file, window="_blank"]).

Expand All @@ -142,27 +262,21 @@ It will be auto-replaced in all the source files (.java, .kt, .scala). The packa

[source,yaml]
----
# the codestart unique name
# codestart unique name
name: resteasy-example
# the codestart reference (the name is used if not set)
# codestart reference, use the extension id
ref: resteasy
# the type of codestart (other types are used for other project files)
# use 'code' (other types are for base codestarts)
type: code
# public metadata for this example (they will also be accessible from this codestart qute templates by using the key: {title})
# use 'extension-codestart'
tags: extension-codestart
# public metadata for this example (accessible as data in the templates e.g. {title})
metadata:
title: RESTEasy JAX-RS example
description: Rest is easy peasy with this Hello World RESTEasy resource.
related-guide-section: https://quarkus.io/guides/getting-started#the-jax-rs-resources
# the path is optional and used by the generated index.html if present
# (optional) use this in web extensions with a specific path (and also add the index page)
path: /some-path
language:
base:
# Specify the extension and possibly other required dependencies
dependencies:
- io.quarkus:quarkus-resteasy
# And maybe test dependencies?
test-dependencies:
- io.rest-assured:rest-assured
----

[#directory-structure]
Expand All @@ -178,57 +292,35 @@ NOTE: `codestart.yml` is the only required file.

[source,bash]
----
gen-info.time: time of generation (in millis)
input.selected-extensions[].name|description|guide: list of selected extensions with info
input.selected-extensions-ga: Set of String with the list of extensions groupId:artifactId, usefull for dynamic codestarts depending on selected extensions
gen-info.time = time of generation (in millis)
input.selected-extensions[].name|description|guide = list of selected extensions with info
input.selected-extensions-ga = Set of String with the list of extensions groupId:artifactId, usefull for dynamic codestarts depending on selected extensions
input.provided-code[].name|tags|title|description|related-guide: list of selected codestarts with info
----

=== Static Config Keys in Codestart

[source,bash]
[source,properties]
----
quarkus.platform.group-id: BOM groupId
quarkus.platform.artifact-id: BOM ArtifactId
quarkus.platform.version: BOM Version
project.group-id: Project groupId
project.artifact-id: project ArtifactId
project.version: Project Version
project.package-name: Project Package name
quarkus.maven-plugin.group-id: Quarkus Maven plugin groupId
quarkus.maven-plugin.artifact-id: Quarkus Maven plugin ArtifactId
quarkus.maven-plugin.version: Quarkus Maven plugin version.
quarkus.gradle-plugin.id: Quarkus gradle pluginId
quarkus.gradle-plugin.version: Quarkus gradle plugin version
quarkus.version: Quarkus version
java.version: Java version
kotlin.version: Kotlin version
scala.version: scala version
scala-maven-plugin.version: scala maven plugin version
maven-compiler-plugin.version: Maven compiler plugin version
maven-surefire-plugin.version: Maven surefire plugin version
quarkus.platform.group-id = BOM groupId
quarkus.platform.artifact-id = BOM ArtifactId
quarkus.platform.version = BOM Version
project.group-id = Project groupId
project.artifact-id = project ArtifactId
project.version = Project Version
project.package-name = Project Package name
quarkus.maven-plugin.group-id = Quarkus Maven plugin groupId
quarkus.maven-plugin.artifact-id = Quarkus Maven plugin ArtifactId
quarkus.maven-plugin.version = Quarkus Maven plugin version.
quarkus.gradle-plugin.id = Quarkus gradle pluginId
quarkus.gradle-plugin.version = Quarkus gradle plugin version
quarkus.version = Quarkus version
java.version = Java version
kotlin.version = Kotlin version
scala.version = scala version
scala-maven-plugin.version = scala maven plugin version
maven-compiler-plugin.version = Maven compiler plugin version
maven-surefire-plugin.version = Maven surefire plugin version
----

=== Naming Convention for files
Expand Down

0 comments on commit 0de12f1

Please sign in to comment.