|
| 1 | +# Using GraalVM Enterprise in OCI DevOps Build Pipelines |
| 2 | + |
| 3 | +This sample shows how to use `Oracle GraalVM Enterprise Edition` in `OCI DevOps build pipelines` to build a Java hello world application. You can use this approach to build any high-performance Java application with GraalVM Enterprise and OCI DevOps. |
| 4 | + |
| 5 | +## What is GraalVM? |
| 6 | + |
| 7 | +- Oracle GraalVM Enterprise is a high-performance JDK distribution that can accelerate any Java workload running on the HotSpot JVM. |
| 8 | + |
| 9 | +- Oracle GraalVM Enterprise Native Image ahead-of-time compilation enables you to build lightweight Java applications that are smaller, faster, and use less memory and CPU. At build time, GraalVM Native Image analyzes a Java application and its dependencies to identify just what classes, methods, and fields are necessary and generates optimized machine code for just those elements. |
| 10 | + |
| 11 | +- Oracle GraalVM Enterprise Edition is available for use on Oracle Cloud Infrastructure (OCI) at no additional cost. |
| 12 | + |
| 13 | + |
| 14 | + |
| 15 | +## Specific instruction to clone only this example. |
| 16 | + |
| 17 | + ``` |
| 18 | + $ git init oci_devops_build_with_graalenterprise |
| 19 | + $ cd oci_devops_build_with_graalenterprise |
| 20 | + $ git remote add origin <url to this git repo> |
| 21 | + $ git config core. sparsecheckout true |
| 22 | + $ echo "oci-build-examples/oci_devops_build_with_graalenterprise/*">>.git/info/sparse-checkout |
| 23 | + $ git pull --depth=1 origin main |
| 24 | +
|
| 25 | + ``` |
| 26 | + |
| 27 | +## Objectives |
| 28 | + |
| 29 | +- Create an OCI build pipeline. |
| 30 | +- Make a build using Oracle GraalVM Enterprise edition. |
| 31 | +- Here the focus will be on Build instructions and OCI build pipeline |
| 32 | + |
| 33 | + |
| 34 | +## Procedure to use this illustration. |
| 35 | + |
| 36 | +- Create an OCI notification topic - https://docs.oracle.com/en-us/iaas/Content/Notification/Tasks/managingtopicsandsubscriptions.htm#createTopic |
| 37 | +- Create a DevOps project - https://docs.oracle.com/en-us/iaas/Content/devops/using/create_project.htm#create_a_project. |
| 38 | + Associate with the notification topic. |
| 39 | + |
| 40 | + |
| 41 | + |
| 42 | +- Enable logging for the DevOps project. |
| 43 | + |
| 44 | + |
| 45 | + |
| 46 | +Create an OCI Dynamic group and add the below rules. - https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingdynamicgroups.htm |
| 47 | + |
| 48 | +```markdown |
| 49 | +ALL {resource.type = 'devopsbuildpipeline', resource.compartment.id = 'COMPARMENT OCID'} |
| 50 | + |
| 51 | +ALL {resource.type = 'devopsrepository', resource.compartment.id = 'COMPARMENT OCID'} |
| 52 | +``` |
| 53 | + |
| 54 | +- Create an OCI policy and add the below policies - https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policies.htm |
| 55 | + |
| 56 | +```markdown |
| 57 | +Allow dynamic-group "NAME OF THE DynamicGroup" to manage repos in compartment "COMPARTMENT NAME" |
| 58 | +Allow dynamic-group "NAME OF THE DynamicGroup" to use ons-topics in compartment "COMPARTMENT NAME" |
| 59 | +``` |
| 60 | + |
| 61 | +- Switch back to OCI DevOps Project and create an OCI Code repo - https://docs.oracle.com/en-us/iaas/Content/devops/using/create_repo.htm#create_repo |
| 62 | + |
| 63 | + |
| 64 | + |
| 65 | +- Push the content to OCI Code repo - https://docs.oracle.com/en-us/iaas/Content/devops/using/clone_repo.htm |
| 66 | + |
| 67 | + |
| 68 | + |
| 69 | +- You may use other support version control repos as well (like Github.com,Bitbucket.com, Bitbucket Cloud etc). You may also need to adjust the policies according to connection and setup external connections accordingly - https://docs.oracle.com/en-us/iaas/Content/devops/using/create_connection.htm |
| 70 | + |
| 71 | +- Create a new build pipeline. - https://docs.oracle.com/en-us/iaas/Content/devops/using/create_buildpipeline.htm |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +- Use the `Add Stage` option and add a `Managed Build` stage to the build pipeline - https://docs.oracle.com/en-us/iaas/Content/devops/using/add_buildstage.htm |
| 76 | + |
| 77 | + |
| 78 | + |
| 79 | +- Click `Next` and provide the details. |
| 80 | + |
| 81 | + |
| 82 | + |
| 83 | +- Associate the Primary code repository with the code repo containing the actual code. |
| 84 | + |
| 85 | + |
| 86 | + |
| 87 | +- Click `Add` and add the stage. |
| 88 | + |
| 89 | + |
| 90 | + |
| 91 | + |
| 92 | +## Take a closer look at the build instructions below |
| 93 | + |
| 94 | +To install and use GraalVM Enterprise in the DevOps build pipeline, the build specification file is as follows: |
| 95 | + |
| 96 | +1. Add the following command to install one or more required GraalVM Enterprise components. For example, this command installs Native Image along with the Java Development Kit (JDK) and other necessary dependencies. |
| 97 | + |
| 98 | + ```shell |
| 99 | + steps: |
| 100 | + - type: Command |
| 101 | + name: "Install GraalVM 22.x Native Image for Java17" |
| 102 | + command: | |
| 103 | + yum -y install graalvm22-ee-17-native-image |
| 104 | + ``` |
| 105 | + |
| 106 | +2. Set the JAVA_HOME environment variable. |
| 107 | + |
| 108 | + ```shell |
| 109 | + env: |
| 110 | + variables: |
| 111 | + "JAVA_HOME" : "/usr/lib64/graalvm/graalvm22-ee-java17" |
| 112 | + ``` |
| 113 | + |
| 114 | +3. Set the PATH environment variable. |
| 115 | + |
| 116 | + ```shell |
| 117 | + env: |
| 118 | + variables: |
| 119 | + # PATH is a reserved variable and cannot be defined as a variable. |
| 120 | + # PATH can be changed in a build step and the change is visible in subsequent steps. |
| 121 | + |
| 122 | + steps: |
| 123 | + - type: Command |
| 124 | + name: "Set PATH Variable" |
| 125 | + command: | |
| 126 | + export PATH=$JAVA_HOME/bin:$PATH |
| 127 | + ``` |
| 128 | + |
| 129 | +4. Build a native executable for your Java application. |
| 130 | + |
| 131 | + ```shell |
| 132 | + steps: |
| 133 | + - type: Command |
| 134 | + name: "Build a native executable" |
| 135 | + command: | |
| 136 | + mvn --no-transfer-progress -Pnative -DskipTests package |
| 137 | + ``` |
| 138 | + |
| 139 | +Here's the complete [build specification](build_spec.yaml) file. |
| 140 | +
|
| 141 | +5. The executable file can be found under path target/my-app. |
| 142 | +
|
| 143 | +```markdown |
| 144 | + - name: app_native_executable |
| 145 | + type: BINARY |
| 146 | + location: target/my-app |
| 147 | +``` |
| 148 | +
|
| 149 | +## How to export the executable file outside of the build pipeline stage. |
| 150 | +
|
| 151 | +The following instructions will help you to export the `executable app file` to OCI Artifactory and which can then be used in the further stage including deployment pipelines. |
| 152 | +
|
| 153 | +- Create an OCI artifact registry. https://docs.oracle.com/en-us/iaas/Content/artifacts/home.htm |
| 154 | +
|
| 155 | + |
| 156 | +
|
| 157 | +- Switch back to `DevOps Project` and create an `Artifact`- https://docs.oracle.com/en-us/iaas/Content/devops/using/artifacts.htm |
| 158 | +
|
| 159 | +- Select the type as `General artifact` |
| 160 | +
|
| 161 | + |
| 162 | +
|
| 163 | +- Select the `Artifact source` as the Artifact Registry repository. Use `Select` and associate with the artifact registry created. |
| 164 | +
|
| 165 | + |
| 166 | +
|
| 167 | +
|
| 168 | +- Use option `Set Custom Location` as Artifact location. |
| 169 | +- Provide a path and version as `${BUILDRUN_HASH}`, this is to maintain immutable artifacts. |
| 170 | +- The variable `BUILDRUN_HASH` is derived during managed build stage and exported as an exportedVariables.You may use any other name ,but ensure to update the file [build_spec.yaml](build_spec.yaml). |
| 171 | +- Select `Yes, substitute placeholders` as an option and click `Add`. |
| 172 | +
|
| 173 | + |
| 174 | +
|
| 175 | +- Under `Build pipeline ` use the `+` icon after the current stage and add a new stage named `Deliver artifacts` |
| 176 | +
|
| 177 | + |
| 178 | +
|
| 179 | +- Associate it with the `DevOps Artifact` created. |
| 180 | +
|
| 181 | + |
| 182 | +
|
| 183 | +
|
| 184 | +- Use `app_native_executable` result artifact name. |
| 185 | +- The name `app_native_executable` is a reference to the outputArtifact defined under the the file [build_spec.yaml](build_spec.yaml). |
| 186 | +- Click `Add` and add the stage. |
| 187 | +
|
| 188 | + |
| 189 | +
|
| 190 | +
|
| 191 | +- The build pipeline with two stages would look like the one below. |
| 192 | +
|
| 193 | + |
| 194 | +
|
| 195 | +
|
| 196 | +## Let's test. |
| 197 | + |
| 198 | +- Use `Start manual run` under OCI Buildpipeline and run the pipeline stages. |
| 199 | + |
| 200 | + |
| 201 | + |
| 202 | +- Wait for all the stages to complete |
| 203 | +  |
| 204 | + |
| 205 | + |
| 206 | + |
| 207 | +- You should see a new artfact under the `Artifact registry repo` created earlier. |
| 208 | + |
| 209 | + |
| 210 | + |
| 211 | +- The exported executable can be used on any of the supporting infrastructures to execute or can use to deploy via `OCI deployment pipeline ` to compute, container or function resources. |
| 212 | + |
| 213 | +## Optional - Run build with more verbose output. |
| 214 | + |
| 215 | +- An additional build instruction file as [build_spec_verbose.yaml](build_spec_verbose.yaml) |
| 216 | + can be used for more verbose output with the managed build. |
| 217 | +- To do so, switch to `OCI DevOps project` > `OCI Build pipeline ` > Click `3 dots` on the `Managed Build` stage and click on `View details` and then `Edit Stage`. |
| 218 | + |
| 219 | + |
| 220 | + |
| 221 | +- Change `Build spec file path ` as `build_spec_verbose.yaml` and `Save changes` |
| 222 | + |
| 223 | + |
| 224 | + |
| 225 | +- Do another manal run for the build pipeline and you will see more verbose build logs. |
| 226 | + |
| 227 | +## Sample Build Logs (Non-verbose mode) |
| 228 | + |
| 229 | +1. The `yum install` build log statements should be similar to: |
| 230 | + |
| 231 | + ```shell |
| 232 | + ... |
| 233 | + EXEC: Installed: |
| 234 | + EXEC: graalvm22-ee-17-native-image.x86_64 0:22.1.0.1-1.el7 |
| 235 | + EXEC: |
| 236 | + EXEC: Dependency Installed: |
| 237 | + EXEC: glibc-static.x86_64 0:2.17-326.0.1.el7_9 |
| 238 | + EXEC: graalvm22-ee-17-jdk.x86_64 0:22.1.0.1-1.el7 |
| 239 | + EXEC: libstdc++-static.x86_64 0:4.8.5-44.0.3.el7 |
| 240 | + EXEC: zlib-static.x86_64 0:1.2.7-20.el7_9 |
| 241 | + EXEC: |
| 242 | + EXEC: Complete! |
| 243 | + ... |
| 244 | + ``` |
| 245 | + |
| 246 | +2. The native executable build log statements should be similar to: |
| 247 | + |
| 248 | + ```shell |
| 249 | + ... |
| 250 | + EXEC: ================================================================== |
| 251 | + EXEC: GraalVM Native Image: Generating 'my-app' (executable)... |
| 252 | + EXEC: ================================================================== |
| 253 | + EXEC: [1/7] Initializing... (5.6s @ 0.11GB) |
| 254 | + EXEC: Version info: 'GraalVM 22.1.0.1 Java 17 EE' |
| 255 | + EXEC: C compiler: gcc (redhat, x86_64, 4.8.5) |
| 256 | + EXEC: Garbage collector: Serial GC |
| 257 | + EXEC: [2/7] Performing analysis... [******] (9.5s @ 0.32GB) |
| 258 | + EXEC: 1,880 (62.46%) of 3,010 classes reachable |
| 259 | + EXEC: 1,684 (46.71%) of 3,605 fields reachable |
| 260 | + EXEC: 7,784 (36.98%) of 21,049 methods reachable |
| 261 | + EXEC: 21 classes, 0 fields, and 285 methods registered for reflection |
| 262 | + EXEC: 48 classes, 32 fields, and 47 methods registered for JNI access |
| 263 | + EXEC: [3/7] Building universe... (1.1s @ 0.45GB) |
| 264 | + EXEC: [4/7] Parsing methods... [*] (0.8s @ 0.58GB) |
| 265 | + EXEC: [5/7] Inlining methods... [****] (1.2s @ 0.97GB) |
| 266 | + EXEC: [6/7] Compiling methods... [*****] (21.2s @ 0.75GB) |
| 267 | + EXEC: [7/7] Creating image... (0.9s @ 0.92GB) |
| 268 | + EXEC: 2.62MB (46.31%) for code area: 3,708 compilation units |
| 269 | + EXEC: 2.45MB (43.34%) for image heap: 945 classes and 38,518 objects |
| 270 | + EXEC: 600.06KB (10.35%) for other data |
| 271 | + EXEC: 5.66MB in total |
| 272 | + EXEC: ------------------------------------------------------------------ |
| 273 | + ... |
| 274 | + EXEC: ------------------------------------------------------------------ |
| 275 | + EXEC: 0.9s (2.1% of total time) in 18 GCs | Peak RSS: 2.44GB | CPU load: 3.41 |
| 276 | + EXEC: ------------------------------------------------------------------ |
| 277 | + EXEC: Produced artifacts: |
| 278 | + EXEC: /workspace/gvmee-yum/target/my-app (executable) |
| 279 | + EXEC: /workspace/gvmee-yum/target/my-app.build_artifacts.txt |
| 280 | + EXEC: ================================================================== |
| 281 | + EXEC: Finished generating 'my-app' in 41.7s. |
| 282 | + ... |
| 283 | + ``` |
| 284 | + |
| 285 | +References |
| 286 | +========== |
| 287 | + |
| 288 | +- Oracle Cloud Infrastructure DevOps - https://docs.oracle.com/en-us/iaas/Content/devops/using/home.htm |
| 289 | +- Oracle Graal VM Enterprise - https://www.oracle.com/java/graalvm/ |
| 290 | + |
| 291 | +Contributors |
| 292 | +=========== |
| 293 | + |
| 294 | +- Author: [Rahul M R](https://github.com/RahulMR42). |
| 295 | +- Collaborators: [Sachin Pikle](https://github.com/sachin-pikle) |
| 296 | +- Last release: July 2022 |
| 297 | + |
| 298 | +### Back to examples. |
| 299 | +---- |
| 300 | + |
| 301 | +- 🍿 [Back to OCI DevOps Build sample](./../README.md) |
| 302 | +- 🏝️ [Back to OCI Devops sample](./../../README.md) |
| 303 | + |
| 304 | + |
| 305 | +Regards, |
| 306 | +M R |
| 307 | + |
| 308 | + |
0 commit comments