Skip to content

Commit

Permalink
Merge pull request #59 from BarDweller/platform-12
Browse files Browse the repository at this point in the history
Updates to support Platform Spec 0.4-0.12
  • Loading branch information
BarDweller authored Jun 5, 2024
2 parents f1e643f + 4b218a3 commit e109913
Show file tree
Hide file tree
Showing 85 changed files with 7,657 additions and 735 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11]
java: [8, 11, 17]
steps:
- name: Checkout
uses: actions/checkout@v2.3.4
Expand Down
17 changes: 16 additions & 1 deletion .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
java: [8, 11]
java: [8, 11, 17]
jbang: [0.84.2]
steps:
- name: Checkout
Expand Down Expand Up @@ -68,6 +68,21 @@ jobs:
- name: Integration Tests
run: |
if [ ${{ github.event_name }} = 'pull_request' ]; then
REPO="${{ github.event.pull_request.head.repo.full_name }}"
REPO_NAME=`echo $REPO | cut -d'/' -f2`
REPO_OWNER=`echo $REPO | cut -d'/' -f1`
SHA="${{ github.event.pull_request.head.sha }}"
else
REPO="$GITHUB_REPOSITORY"
REPO_NAME=`echo $REPO | cut -d'/' -f2`
REPO_OWNER=`echo $REPO | cut -d'/' -f1`
SHA=$GITHUB_SHA
fi
export CURRENT_WORKFLOW_DEP=com.github.$REPO_OWNER.$REPO_NAME:buildpack-client:$SHA
echo Tests using dependency $CURRENT_WORKFLOW_DEP
cd samples/hello-spring
./pack.java
cd ../../samples/hello-quarkus
./pack.java
198 changes: 128 additions & 70 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@ Prototype of a simple buildpack (https://buildpacks.io/) client for java.
This project represents a simple implementation of the buildpack platform spec,
and can be used to build projects using specified buildpacks.

The client uses the combined `creator` lifecycle phase from the buildpack to
drive the entire build. A fluent interface is provided to allow creation & configuration
This project implements up to version 0.10 of the buildpack platform spec, and should
work with builders requesting from 0.4 through to 0.10. 0.12 is available but experimental.

A fluent interface is provided to allow creation & configuration
of the build to be performed.

A very simple build can be performed with as little as.
```
Buildpack.builder()
.withContent(new File("/home/user/java-project"))
.withFinalImage("test/testimage:latest")
.build();
```java
int exitCode = BuildConfig.builder()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```

This will use the default builder image from (https://paketo.io) to handle the build
Expand All @@ -26,27 +29,36 @@ be stored in the local docker daemon as `test/testimage:latest`.

## Overview

The [`BuildpackBuilder`](src/main/java/dev/snowdrop/buildpack/BuildpackBuilder.java) offers other configuration methods to customise behavior.

- run/build Image can be specified
- docker socket location can be configured
- cache volume names for build/launch can be specified, and optionally auto deleted after the build
- `creator` debug level can be set
- pull timeout can be configured in seconds

Options exist, but are not (yet) active, for.

- use docker registry instead of daemon (requires additional auth config, not implemented yet)
- passing Env content to the build stage (not implemented yet)
The [`BuildpackConfig`](client/src/main/java/dev/snowdrop/buildpack/BuildConfig.java) offers other configuration methods to customise behavior.

- run/build/output Image can be specified
- docker can be configured with..
- pull timeout
- host
- network
- docker socket path
- if Daemon should be used or not. (If yes, docker socket is mounted into build container so buildpack can make use of daemon directly,
if no, then docker will read/create output images with remote registry directly. Note that daemon is
still used to run the various build containers, just that the containers do not themselves have access to the daemon.)
- caches (launch/build/kaniko) can be configured with..
- cache volume name. (if omitted, a randomly generated name is used)
- cache delete after build. (if yes, cache volume will be removed after build exits, defaults to TRUE)
- logging from the build containers can be customized..
- log level, can be info, warn, debug. Affects the amount of verbosity from the lifecycle during build.
- logger instance, system logger (to sysout/syserr) and slf4j loggers are supplied.
- platform aspects can be customized..
- platform level can be forced to a version, by default platform level is derived from the intersection of builder/lifecycle and platform supported versions.
- environment vars can be set that will be accessible during the build as platform env vars.
- the builder can be 'trusted'. This means the creator lifecycle is used, where all phases happen within a single container, faster, but does not support extensions, and can expose some lifecycle phases to credentials that may be otherwise protected.
- lifecycle image can be specified. If set, the lifecycle from the specified image will be used instead of the one within the builder image. Allows for easy testing with newer lifecycles.

A variety of methods are supported for adding content to be build, content is combined in the order
passed, allowing for sparse source directories, or multiple project dirs to be combined.

- File/Directory, with prefix. Eg, take this directory /home/fish/wibble, and make it appear in the application content as /prodcode
- String Content, with path. Eg, take this String content "FISH" and make it appear in the application content as /prodcode/fish.txt
- InputStream Content, with path. Similar to String, except with data pulled from an InputStream.
- [`ContainerEntry`](src/main/java/dev/snowdrop/buildpack/docker/ContainerEntry.java) interface, for custom integration.

- [`ContainerEntry`](client/src/main/java/dev/snowdrop/buildpack/docker/ContainerEntry.java) interface, for custom integration.

Build/RunImages will be pulled as required.

Expand All @@ -59,48 +71,66 @@ docker socket is extracted and used during the build phase. If unset, this defau
Want to try out this project? The packages/api are not fixed in stone yet, so be aware! But here are the basic steps to get you up and running.


1. Add this project as a dependency via jitpack.
```
1. Add this project as a dependency.. (use the latest version instead of XXX)
```xml
<dependency>
<groupId>dev.snowdrop</groupId>
<artifactId>buildpack-client</artifactId>
<version>0.0.6</version>
<version>0.0.XXX</version>
</dependency>
```

2. Instantiate a BuildpackBuilder
```
BuildpackBuilder bpb = Buildpack.builder();
2. Instantiate a BuildConfig
```java
BuildConfig bc = BuildConfig.builder();
```

3. Define the content to be built..
```
bpb = bpb.addNewFileContent(new File("/path/to/the/project/to/build));
```java
bc = bc.addNewFileContentApplication(new File("/path/to/the/project/to/build));
```
4. Configure the name/tags for the image to create
```
bpb = bpb.withFinalImage("myorg/myimage:mytag");
```java
bc = bc.withOutputImage(new ImageReference("myorg/myimage:mytag"));
```
5. Invoke the build
```java
bc.build();
```
bpb.build();
6. Retrieve the build exit code
```java
bc.getExitCode();
```
Or combine all the above steps into a single callchain.
```java
int exitCode = BuildConfig.builder()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
Buildpack.builder()
.withFileContent(new File("/path/to/the/project/to/build))
.withFinalImage("myorg/myimage:mytag")
.build();
```
There are many more ways to customize & configure the BuildpackBuilder, take a look at the [interface](src/main/java/dev/snowdrop/buildpack/BuildpackBuilder.java) to see everything thats currently possible.
There are many more ways to customize & configure the BuildConfig, take a look at the [interface](client/src/main/java/dev/snowdrop/buildpack/BuildConfig.java) to see everything thats currently possible.
A demo project has been created to allow easy exploration of uses of `BuildConfig` [here](https://github.com/snowdrop/java-buildpack-demo) :-)
A demo project has been created to play with the Java `BuildpackBuilder` [here](https://github.com/snowdrop/java-buildpack-demo) :-)
Most likely if you are using this to integrate to existing tooling, you will want to supply a custom LogReader to receive the messages output by the Build Containers during the build. You may also want to associate cache names to a project, to enable faster rebuilds for a given project. Note that if you wish caches to survive beyond a build, you should set `deleteCacheAfterBuild` to `false` for each cache. Eg.
Most likely if you are using this to integrate to existing tooling, you will want to supply a custom LogReader to receive the messages output by BuildPacks during the build. You may also want to associate cache names to a project, to enable faster rebuilds for a given project.
```java
int exitCode = BuildConfig.builder()
.withNewBuildCacheConfig()
.withCacheVolumeName("my-project-specific-cache-name")
.withDeleteCacheAfterBuild(true)
.and()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
## Logging
Expand All @@ -113,22 +143,30 @@ At the moment two kinds of logger are supported:
Both can be configured using the builder:
```java
Buildpack.builder()
.withContent(new File("."))
.withFinalImage("test/my-image:latest")
.withLogger(new SystemLogger())
.build();
int exitCode = BuildConfig.builder()
.withNewLogConfig()
.withLogger(new SystemLogger())
.withLogLevel("debug")
.and()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
or
```java
Buildpack.builder()
.withContent(new File("."))
.withFinalImage("test/my-image:latest")
.withLogger(new Slf4jLogger())
.build();
int exitCode = BuildConfig.builder()
.withNewLogConfig()
.withLogger(new Slf4jLogger())
.withLogLevel("debug")
.and()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
Expand All @@ -138,11 +176,15 @@ The builder DSL supports inlining `Logger` configuration:
```java
Buildpack.builder()
.withContent(new File("."))
.withFinalImage("test/my-image:latest")
.withNewSystemLogger(false) //Explicitly disables ansi colors
.build();
int exitCode = BuildConfig.builder()
.withNewLogConfig()
.withNewSystemLogger(false)
.withLogLevel("debug")
.and()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
Expand All @@ -152,26 +194,32 @@ Similarly, with `Slf4jLogger` one can inline the name of the logger:
```java
Buildpack.builder()
.withContent(new File("."))
.withFinalImage("test/my-image:latest")
.withNewSlf4jLogger(MyApp.class.getCanonicalName()) //Explicitly specify the Logger
.build();
int exitCode = BuildConfig.builder()
.withNewLogConfig()
.withNewSlf4jLogger(MyApp.class.getCanonicalName())
.withLogLevel("debug")
.and()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
```
## Error Handling
If the build fails for any reason, a `BuildpackException` will be thrown, this is a RuntimeException, so does not need an explicit catch block. There are many many ways in which a build can fail, from something environmental, like docker being unavailable, to build related issues, like the chosen builder image requiring a platformlevel not implemented by this library.
## Using the buildpack client with jbang
The easiest way to invoke arbitrary java code, without much hassle is by using [jbang](https://www.jbang.dev/).
So, you can drop the following file in your project:
So, you can drop the following file in your project: (swap XXX for latest release of buildpack-client)
```java
///usr/bin/env jbang "$0" "$@" ; exit $?
//DEPS dev.snowdrop:buildpack-client:0.0.6
//DEPS dev.snowdrop:buildpack-client:0.0.XXX
import static java.lang.System.*;
import java.io.File;
Expand All @@ -180,10 +228,12 @@ import dev.snowdrop.buildpack.*;
public class pack {
public static void main(String... args) {
Buildpack.builder()
.withContent(new File("."))
.withFinalImage("test/my-image:latest")
.build();
int exitCode = BuildConfig.builder()
.withOutputImage(new ImageReference("test/testimage:latest"))
.addNewFileContentApplication(new File("/home/user/java-project"))
.build()
.getExitCode();
System.exit(exitCode);
}
}
Expand All @@ -195,13 +245,13 @@ public class pack {
./pack.java
```
See how it's used in the included [samples](./samples).
The samples use jbang too, but allow the version of the library to be set via an env var for use in our tests! [samples](./samples).
## FAQ:
**Will this work with Podman?:**
Not yet. Once the regular `pack` cli works with Podman, I'll revisit this and ensure it works too.
Yes, tested with Podman 4.7.0 on Fedora, rootless and rootful.
**Does this work on Windows?:**
Expand All @@ -210,8 +260,16 @@ Tested with Win10 + Docker on WSL2
**Does this work on Linux?:**
Yes.. with Docker (real docker, not podman pretending to be docker).
Tested with Ubuntu + Docker
Yes..
Tested with Ubuntu & Fedora with Docker
**Can I supply buildpacks/extensions to add to a builder like pack?:**
The code is structured to allow for this, but the feature is not exposed via the builder api,
as using additional buildpacks/extensions requires updating order.toml in the base builder,
and that would require additional config to either override, or specify the behavior for manipulating
the toml. If you are interested in this kind of functionality, raise an Issue so I can better understand
the use case, or send a PR!
4 changes: 4 additions & 0 deletions client/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
<groupId>com.github.docker-java</groupId>
<artifactId>docker-java-transport-httpclient5</artifactId>
</dependency>
<dependency>
<groupId>org.tomlj</groupId>
<artifactId>tomlj</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
Expand Down
Loading

0 comments on commit e109913

Please sign in to comment.