diff --git a/Justfile b/Justfile index 40d51ec90d..355402b84e 100644 --- a/Justfile +++ b/Justfile @@ -7,7 +7,7 @@ VERSION := `git describe --tags --always | sed -e 's/^v//'` RUNNER_TEMPLATE_ZIP := "backend/controller/scaling/localscaling/template.zip" TIMESTAMP := `date +%s` SCHEMA_OUT := "backend/protos/xyz/block/ftl/v1/schema/schema.proto" -ZIP_DIRS := "go-runtime/compile/build-template go-runtime/compile/external-module-template go-runtime/compile/main-work-template internal/projectinit/scaffolding go-runtime/scaffolding" +ZIP_DIRS := "go-runtime/compile/build-template go-runtime/compile/external-module-template go-runtime/compile/main-work-template internal/projectinit/scaffolding go-runtime/scaffolding jvm-runtime/java/scaffolding jvm-runtime/kotlin/scaffolding" FRONTEND_OUT := "frontend/dist/index.html" EXTENSION_OUT := "extensions/vscode/dist/extension.js" PROTOS_IN := "backend/protos/xyz/block/ftl/v1/schema/schema.proto backend/protos/xyz/block/ftl/v1/console/console.proto backend/protos/xyz/block/ftl/v1/ftl.proto backend/protos/xyz/block/ftl/v1/schema/runtime.proto" diff --git a/cmd/ftl/cmd_new.go b/cmd/ftl/cmd_new.go index 82dde183e4..4b204217fa 100644 --- a/cmd/ftl/cmd_new.go +++ b/cmd/ftl/cmd_new.go @@ -21,10 +21,13 @@ import ( "github.com/TBD54566975/ftl/internal/exec" "github.com/TBD54566975/ftl/internal/log" "github.com/TBD54566975/ftl/internal/projectconfig" + "github.com/TBD54566975/ftl/jvm-runtime/java" + "github.com/TBD54566975/ftl/jvm-runtime/kotlin" ) type newCmd struct { Go newGoCmd `cmd:"" help:"Initialize a new FTL Go module."` + Java newJavaCmd `cmd:"" help:"Initialize a new FTL Java module."` Kotlin newKotlinCmd `cmd:"" help:"Initialize a new FTL Kotlin module."` } @@ -35,12 +38,18 @@ type newGoCmd struct { GoVersion string } +type newJavaCmd struct { + Dir string `arg:"" help:"Directory to initialize the module in."` + Name string `arg:"" help:"Name of the FTL module to create underneath the base directory."` + Group string `help:"The Maven groupId of the project." default:"com.example"` +} type newKotlinCmd struct { - Dir string `arg:"" help:"Directory to initialize the module in."` - Name string `arg:"" help:"Name of the FTL module to create underneath the base directory."` + Dir string `arg:"" help:"Directory to initialize the module in."` + Name string `arg:"" help:"Name of the FTL module to create underneath the base directory."` + Group string `help:"The Maven groupId of the project." default:"com.example"` } -func (i newGoCmd) Run(ctx context.Context) error { +func (i newGoCmd) Run(ctx context.Context, config projectconfig.Config) error { name, path, err := validateModule(i.Dir, i.Name) if err != nil { return err @@ -51,11 +60,6 @@ func (i newGoCmd) Run(ctx context.Context) error { return fmt.Errorf("module name %q must be a valid Go module name and not a reserved keyword", name) } - config, err := projectconfig.Load(ctx, "") - if err != nil { - return fmt.Errorf("failed to load project config: %w", err) - } - logger := log.FromContext(ctx) logger.Debugf("Creating FTL Go module %q in %s", name, path) @@ -84,8 +88,54 @@ func (i newGoCmd) Run(ctx context.Context) error { return nil } -func (i newKotlinCmd) Run(ctx context.Context) error { - return fmt.Errorf("kotlin scaffolinging temporarily removed") +func (i newJavaCmd) Run(ctx context.Context, config projectconfig.Config) error { + return RunJvmScaffolding(ctx, config, i.Dir, i.Name, i.Group, java.Files()) +} + +func (i newKotlinCmd) Run(ctx context.Context, config projectconfig.Config) error { + return RunJvmScaffolding(ctx, config, i.Dir, i.Name, i.Group, kotlin.Files()) +} + +func RunJvmScaffolding(ctx context.Context, config projectconfig.Config, dir string, name string, group string, source *zip.Reader) error { + name, path, err := validateModule(dir, name) + if err != nil { + return err + } + + logger := log.FromContext(ctx) + logger.Debugf("Creating FTL module %q in %s", name, path) + + packageDir := strings.ReplaceAll(group, ".", "/") + + javaContext := struct { + Dir string + Name string + Group string + PackageDir string + }{ + Dir: dir, + Name: name, + Group: group, + PackageDir: packageDir, + } + + if err := scaffold(ctx, config.Hermit, source, dir, javaContext); err != nil { + return err + } + + _, ok := internal.GitRoot(dir).Get() + if !config.NoGit && ok { + logger.Debugf("Adding files to git") + if config.Hermit { + if err := maybeGitAdd(ctx, dir, "bin/*"); err != nil { + return err + } + } + if err := maybeGitAdd(ctx, dir, filepath.Join(name, "*")); err != nil { + return err + } + } + return nil } func validateModule(dir string, name string) (string, string, error) { diff --git a/jvm-runtime/java/devel.go b/jvm-runtime/java/devel.go new file mode 100644 index 0000000000..6c09d47307 --- /dev/null +++ b/jvm-runtime/java/devel.go @@ -0,0 +1,12 @@ +//go:build !release + +package java + +import ( + "archive/zip" + + "github.com/TBD54566975/ftl/internal" +) + +// Files is the FTL Go runtime scaffolding files. +func Files() *zip.Reader { return internal.ZipRelativeToCaller("scaffolding") } diff --git a/jvm-runtime/java/release.go b/jvm-runtime/java/release.go new file mode 100644 index 0000000000..87bae32b32 --- /dev/null +++ b/jvm-runtime/java/release.go @@ -0,0 +1,21 @@ +//go:build release + +package java + +import ( + "archive/zip" + "bytes" + _ "embed" +) + +//go:embed scaffolding.zip +var archive []byte + +// Files is the FTL Go runtime scaffolding files. +func Files() *zip.Reader { + zr, err := zip.NewReader(bytes.NewReader(archive), int64(len(archive))) + if err != nil { + panic(err) + } + return zr +} diff --git a/jvm-runtime/java/scaffolding/bin/.ftl@latest.pkg b/jvm-runtime/java/scaffolding/bin/.ftl@latest.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/.ftl@latest.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/.maven-3.9.8.pkg b/jvm-runtime/java/scaffolding/bin/.maven-3.9.8.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/.maven-3.9.8.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/.openjdk@17.pkg b/jvm-runtime/java/scaffolding/bin/.openjdk@17.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/.openjdk@17.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/README.hermit.md b/jvm-runtime/java/scaffolding/bin/README.hermit.md new file mode 100644 index 0000000000..e889550ba4 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/README.hermit.md @@ -0,0 +1,7 @@ +# Hermit environment + +This is a [Hermit](https://github.com/cashapp/hermit) bin directory. + +The symlinks in this directory are managed by Hermit and will automatically +download and install Hermit itself as well as packages. These packages are +local to this environment. diff --git a/jvm-runtime/java/scaffolding/bin/activate-hermit b/jvm-runtime/java/scaffolding/bin/activate-hermit new file mode 100755 index 0000000000..fe28214d33 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/activate-hermit @@ -0,0 +1,21 @@ +#!/bin/bash +# This file must be used with "source bin/activate-hermit" from bash or zsh. +# You cannot run it directly +# +# THIS FILE IS GENERATED; DO NOT MODIFY + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +BIN_DIR="$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}")" +if "${BIN_DIR}/hermit" noop > /dev/null; then + eval "$("${BIN_DIR}/hermit" activate "${BIN_DIR}/..")" + + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then + hash -r 2>/dev/null + fi + + echo "Hermit environment $("${HERMIT_ENV}"/bin/hermit env HERMIT_ENV) activated" +fi diff --git a/jvm-runtime/java/scaffolding/bin/ftl b/jvm-runtime/java/scaffolding/bin/ftl new file mode 120000 index 0000000000..47611de9b6 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/ftl @@ -0,0 +1 @@ +.ftl@latest.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/hermit b/jvm-runtime/java/scaffolding/bin/hermit new file mode 100755 index 0000000000..7fef769248 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/hermit @@ -0,0 +1,43 @@ +#!/bin/bash +# +# THIS FILE IS GENERATED; DO NOT MODIFY + +set -eo pipefail + +export HERMIT_USER_HOME=~ + +if [ -z "${HERMIT_STATE_DIR}" ]; then + case "$(uname -s)" in + Darwin) + export HERMIT_STATE_DIR="${HERMIT_USER_HOME}/Library/Caches/hermit" + ;; + Linux) + export HERMIT_STATE_DIR="${XDG_CACHE_HOME:-${HERMIT_USER_HOME}/.cache}/hermit" + ;; + esac +fi + +export HERMIT_DIST_URL="${HERMIT_DIST_URL:-https://github.com/cashapp/hermit/releases/download/stable}" +HERMIT_CHANNEL="$(basename "${HERMIT_DIST_URL}")" +export HERMIT_CHANNEL +export HERMIT_EXE=${HERMIT_EXE:-${HERMIT_STATE_DIR}/pkg/hermit@${HERMIT_CHANNEL}/hermit} + +if [ ! -x "${HERMIT_EXE}" ]; then + echo "Bootstrapping ${HERMIT_EXE} from ${HERMIT_DIST_URL}" 1>&2 + INSTALL_SCRIPT="$(mktemp)" + # This value must match that of the install script + INSTALL_SCRIPT_SHA256="180e997dd837f839a3072a5e2f558619b6d12555cd5452d3ab19d87720704e38" + if [ "${INSTALL_SCRIPT_SHA256}" = "BYPASS" ]; then + curl -fsSL "${HERMIT_DIST_URL}/install.sh" -o "${INSTALL_SCRIPT}" + else + # Install script is versioned by its sha256sum value + curl -fsSL "${HERMIT_DIST_URL}/install-${INSTALL_SCRIPT_SHA256}.sh" -o "${INSTALL_SCRIPT}" + # Verify install script's sha256sum + openssl dgst -sha256 "${INSTALL_SCRIPT}" | \ + awk -v EXPECTED="$INSTALL_SCRIPT_SHA256" \ + '$2!=EXPECTED {print "Install script sha256 " $2 " does not match " EXPECTED; exit 1}' + fi + /bin/bash "${INSTALL_SCRIPT}" 1>&2 +fi + +exec "${HERMIT_EXE}" --level=fatal exec "$0" -- "$@" diff --git a/jvm-runtime/java/scaffolding/bin/hermit.hcl b/jvm-runtime/java/scaffolding/bin/hermit.hcl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jvm-runtime/java/scaffolding/bin/jar b/jvm-runtime/java/scaffolding/bin/jar new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jar @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jarsigner b/jvm-runtime/java/scaffolding/bin/jarsigner new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jarsigner @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/java b/jvm-runtime/java/scaffolding/bin/java new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/java @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/javac b/jvm-runtime/java/scaffolding/bin/javac new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/javac @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/javadoc b/jvm-runtime/java/scaffolding/bin/javadoc new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/javadoc @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/javap b/jvm-runtime/java/scaffolding/bin/javap new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/javap @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jcmd b/jvm-runtime/java/scaffolding/bin/jcmd new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jcmd @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jconsole b/jvm-runtime/java/scaffolding/bin/jconsole new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jconsole @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jdb b/jvm-runtime/java/scaffolding/bin/jdb new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jdb @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jdeprscan b/jvm-runtime/java/scaffolding/bin/jdeprscan new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jdeprscan @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jdeps b/jvm-runtime/java/scaffolding/bin/jdeps new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jdeps @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jfr b/jvm-runtime/java/scaffolding/bin/jfr new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jfr @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jhsdb b/jvm-runtime/java/scaffolding/bin/jhsdb new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jhsdb @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jimage b/jvm-runtime/java/scaffolding/bin/jimage new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jimage @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jinfo b/jvm-runtime/java/scaffolding/bin/jinfo new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jinfo @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jlink b/jvm-runtime/java/scaffolding/bin/jlink new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jlink @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jmap b/jvm-runtime/java/scaffolding/bin/jmap new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jmap @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jmod b/jvm-runtime/java/scaffolding/bin/jmod new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jmod @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jpackage b/jvm-runtime/java/scaffolding/bin/jpackage new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jpackage @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jps b/jvm-runtime/java/scaffolding/bin/jps new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jps @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jrunscript b/jvm-runtime/java/scaffolding/bin/jrunscript new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jrunscript @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jshell b/jvm-runtime/java/scaffolding/bin/jshell new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jshell @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jstack b/jvm-runtime/java/scaffolding/bin/jstack new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jstack @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jstat b/jvm-runtime/java/scaffolding/bin/jstat new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jstat @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/jstatd b/jvm-runtime/java/scaffolding/bin/jstatd new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/jstatd @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/keytool b/jvm-runtime/java/scaffolding/bin/keytool new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/keytool @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/mvn b/jvm-runtime/java/scaffolding/bin/mvn new file mode 120000 index 0000000000..9158f83b62 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/mvn @@ -0,0 +1 @@ +.maven-3.9.8.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/mvnDebug b/jvm-runtime/java/scaffolding/bin/mvnDebug new file mode 120000 index 0000000000..9158f83b62 --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/mvnDebug @@ -0,0 +1 @@ +.maven-3.9.8.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/rmiregistry b/jvm-runtime/java/scaffolding/bin/rmiregistry new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/rmiregistry @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/bin/serialver b/jvm-runtime/java/scaffolding/bin/serialver new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/java/scaffolding/bin/serialver @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/ftl.toml b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/ftl.toml new file mode 100644 index 0000000000..828a8b57ce --- /dev/null +++ b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/ftl.toml @@ -0,0 +1,2 @@ +module = "{{ .Name }}" +language = "java" diff --git a/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl new file mode 100644 index 0000000000..cf8d370b0c --- /dev/null +++ b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl @@ -0,0 +1,14 @@ + + + 4.0.0 + ftl.{{ .Group }} + {{ .Name }} + 1.0-SNAPSHOT + + + xyz.block.ftl + ftl-build-parent-java + 1.0-SNAPSHOT + + + diff --git a/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/src/main/java/{{ .PackageDir }}/EchoVerb.java b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/src/main/java/{{ .PackageDir }}/EchoVerb.java new file mode 100644 index 0000000000..29cd33c304 --- /dev/null +++ b/jvm-runtime/java/scaffolding/{{ .Name | camel | lower }}/src/main/java/{{ .PackageDir }}/EchoVerb.java @@ -0,0 +1,13 @@ +package {{ .Group }}; + +import xyz.block.ftl.Export; +import xyz.block.ftl.Verb; + +public class EchoVerb { + + @Export + @Verb + public String echo(String request) { + return "Hello, " + request + "!"; + } +} diff --git a/jvm-runtime/jvm_integration_test.go b/jvm-runtime/jvm_integration_test.go index e7411f31f2..ff291b26ee 100644 --- a/jvm-runtime/jvm_integration_test.go +++ b/jvm-runtime/jvm_integration_test.go @@ -14,6 +14,22 @@ import ( "github.com/alecthomas/repr" ) +func TestLifecycle(t *testing.T) { + in.Run(t, + in.WithLanguages("java", "kotlin"), + in.GitInit(), + in.Exec("rm", "ftl-project.toml"), + in.IfLanguage("kotlin", in.Exec("rm", "-r", "echo")), //horrible, but we need to do cleanup, I wonder if we should be running each test in a separate directory + in.Exec("ftl", "init", "test", "."), + in.IfLanguage("java", in.Exec("ftl", "new", "java", ".", "echo")), + in.IfLanguage("kotlin", in.Exec("ftl", "new", "kotlin", ".", "echo")), + in.Deploy("echo"), + in.Call("echo", "echo", "Bob", func(t testing.TB, response string) { + assert.Equal(t, "Hello, Bob!", response) + }), + ) +} + func TestJVMToGoCall(t *testing.T) { exampleObject := TestObject{ diff --git a/jvm-runtime/kotlin/devel.go b/jvm-runtime/kotlin/devel.go new file mode 100644 index 0000000000..b0cf1bb01f --- /dev/null +++ b/jvm-runtime/kotlin/devel.go @@ -0,0 +1,12 @@ +//go:build !release + +package kotlin + +import ( + "archive/zip" + + "github.com/TBD54566975/ftl/internal" +) + +// Files is the FTL Go runtime scaffolding files. +func Files() *zip.Reader { return internal.ZipRelativeToCaller("scaffolding") } diff --git a/jvm-runtime/kotlin/release.go b/jvm-runtime/kotlin/release.go new file mode 100644 index 0000000000..b757334241 --- /dev/null +++ b/jvm-runtime/kotlin/release.go @@ -0,0 +1,21 @@ +//go:build release + +package kotlin + +import ( + "archive/zip" + "bytes" + _ "embed" +) + +//go:embed scaffolding.zip +var archive []byte + +// Files is the FTL Go runtime scaffolding files. +func Files() *zip.Reader { + zr, err := zip.NewReader(bytes.NewReader(archive), int64(len(archive))) + if err != nil { + panic(err) + } + return zr +} diff --git a/jvm-runtime/kotlin/scaffolding/bin/.ftl@latest.pkg b/jvm-runtime/kotlin/scaffolding/bin/.ftl@latest.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/.ftl@latest.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/.maven-3.9.8.pkg b/jvm-runtime/kotlin/scaffolding/bin/.maven-3.9.8.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/.maven-3.9.8.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/.openjdk@17.pkg b/jvm-runtime/kotlin/scaffolding/bin/.openjdk@17.pkg new file mode 120000 index 0000000000..383f4511d4 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/.openjdk@17.pkg @@ -0,0 +1 @@ +hermit \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/README.hermit.md b/jvm-runtime/kotlin/scaffolding/bin/README.hermit.md new file mode 100644 index 0000000000..e889550ba4 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/README.hermit.md @@ -0,0 +1,7 @@ +# Hermit environment + +This is a [Hermit](https://github.com/cashapp/hermit) bin directory. + +The symlinks in this directory are managed by Hermit and will automatically +download and install Hermit itself as well as packages. These packages are +local to this environment. diff --git a/jvm-runtime/kotlin/scaffolding/bin/activate-hermit b/jvm-runtime/kotlin/scaffolding/bin/activate-hermit new file mode 100755 index 0000000000..fe28214d33 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/activate-hermit @@ -0,0 +1,21 @@ +#!/bin/bash +# This file must be used with "source bin/activate-hermit" from bash or zsh. +# You cannot run it directly +# +# THIS FILE IS GENERATED; DO NOT MODIFY + +if [ "${BASH_SOURCE-}" = "$0" ]; then + echo "You must source this script: \$ source $0" >&2 + exit 33 +fi + +BIN_DIR="$(dirname "${BASH_SOURCE[0]:-${(%):-%x}}")" +if "${BIN_DIR}/hermit" noop > /dev/null; then + eval "$("${BIN_DIR}/hermit" activate "${BIN_DIR}/..")" + + if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ]; then + hash -r 2>/dev/null + fi + + echo "Hermit environment $("${HERMIT_ENV}"/bin/hermit env HERMIT_ENV) activated" +fi diff --git a/jvm-runtime/kotlin/scaffolding/bin/ftl b/jvm-runtime/kotlin/scaffolding/bin/ftl new file mode 120000 index 0000000000..47611de9b6 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/ftl @@ -0,0 +1 @@ +.ftl@latest.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/hermit b/jvm-runtime/kotlin/scaffolding/bin/hermit new file mode 100755 index 0000000000..7fef769248 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/hermit @@ -0,0 +1,43 @@ +#!/bin/bash +# +# THIS FILE IS GENERATED; DO NOT MODIFY + +set -eo pipefail + +export HERMIT_USER_HOME=~ + +if [ -z "${HERMIT_STATE_DIR}" ]; then + case "$(uname -s)" in + Darwin) + export HERMIT_STATE_DIR="${HERMIT_USER_HOME}/Library/Caches/hermit" + ;; + Linux) + export HERMIT_STATE_DIR="${XDG_CACHE_HOME:-${HERMIT_USER_HOME}/.cache}/hermit" + ;; + esac +fi + +export HERMIT_DIST_URL="${HERMIT_DIST_URL:-https://github.com/cashapp/hermit/releases/download/stable}" +HERMIT_CHANNEL="$(basename "${HERMIT_DIST_URL}")" +export HERMIT_CHANNEL +export HERMIT_EXE=${HERMIT_EXE:-${HERMIT_STATE_DIR}/pkg/hermit@${HERMIT_CHANNEL}/hermit} + +if [ ! -x "${HERMIT_EXE}" ]; then + echo "Bootstrapping ${HERMIT_EXE} from ${HERMIT_DIST_URL}" 1>&2 + INSTALL_SCRIPT="$(mktemp)" + # This value must match that of the install script + INSTALL_SCRIPT_SHA256="180e997dd837f839a3072a5e2f558619b6d12555cd5452d3ab19d87720704e38" + if [ "${INSTALL_SCRIPT_SHA256}" = "BYPASS" ]; then + curl -fsSL "${HERMIT_DIST_URL}/install.sh" -o "${INSTALL_SCRIPT}" + else + # Install script is versioned by its sha256sum value + curl -fsSL "${HERMIT_DIST_URL}/install-${INSTALL_SCRIPT_SHA256}.sh" -o "${INSTALL_SCRIPT}" + # Verify install script's sha256sum + openssl dgst -sha256 "${INSTALL_SCRIPT}" | \ + awk -v EXPECTED="$INSTALL_SCRIPT_SHA256" \ + '$2!=EXPECTED {print "Install script sha256 " $2 " does not match " EXPECTED; exit 1}' + fi + /bin/bash "${INSTALL_SCRIPT}" 1>&2 +fi + +exec "${HERMIT_EXE}" --level=fatal exec "$0" -- "$@" diff --git a/jvm-runtime/kotlin/scaffolding/bin/hermit.hcl b/jvm-runtime/kotlin/scaffolding/bin/hermit.hcl new file mode 100644 index 0000000000..e69de29bb2 diff --git a/jvm-runtime/kotlin/scaffolding/bin/jar b/jvm-runtime/kotlin/scaffolding/bin/jar new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jar @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jarsigner b/jvm-runtime/kotlin/scaffolding/bin/jarsigner new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jarsigner @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/java b/jvm-runtime/kotlin/scaffolding/bin/java new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/java @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/javac b/jvm-runtime/kotlin/scaffolding/bin/javac new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/javac @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/javadoc b/jvm-runtime/kotlin/scaffolding/bin/javadoc new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/javadoc @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/javap b/jvm-runtime/kotlin/scaffolding/bin/javap new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/javap @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jcmd b/jvm-runtime/kotlin/scaffolding/bin/jcmd new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jcmd @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jconsole b/jvm-runtime/kotlin/scaffolding/bin/jconsole new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jconsole @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jdb b/jvm-runtime/kotlin/scaffolding/bin/jdb new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jdb @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jdeprscan b/jvm-runtime/kotlin/scaffolding/bin/jdeprscan new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jdeprscan @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jdeps b/jvm-runtime/kotlin/scaffolding/bin/jdeps new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jdeps @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jfr b/jvm-runtime/kotlin/scaffolding/bin/jfr new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jfr @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jhsdb b/jvm-runtime/kotlin/scaffolding/bin/jhsdb new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jhsdb @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jimage b/jvm-runtime/kotlin/scaffolding/bin/jimage new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jimage @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jinfo b/jvm-runtime/kotlin/scaffolding/bin/jinfo new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jinfo @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jlink b/jvm-runtime/kotlin/scaffolding/bin/jlink new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jlink @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jmap b/jvm-runtime/kotlin/scaffolding/bin/jmap new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jmap @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jmod b/jvm-runtime/kotlin/scaffolding/bin/jmod new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jmod @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jpackage b/jvm-runtime/kotlin/scaffolding/bin/jpackage new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jpackage @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jps b/jvm-runtime/kotlin/scaffolding/bin/jps new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jps @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jrunscript b/jvm-runtime/kotlin/scaffolding/bin/jrunscript new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jrunscript @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jshell b/jvm-runtime/kotlin/scaffolding/bin/jshell new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jshell @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jstack b/jvm-runtime/kotlin/scaffolding/bin/jstack new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jstack @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jstat b/jvm-runtime/kotlin/scaffolding/bin/jstat new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jstat @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/jstatd b/jvm-runtime/kotlin/scaffolding/bin/jstatd new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/jstatd @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/keytool b/jvm-runtime/kotlin/scaffolding/bin/keytool new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/keytool @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/mvn b/jvm-runtime/kotlin/scaffolding/bin/mvn new file mode 120000 index 0000000000..9158f83b62 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/mvn @@ -0,0 +1 @@ +.maven-3.9.8.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/mvnDebug b/jvm-runtime/kotlin/scaffolding/bin/mvnDebug new file mode 120000 index 0000000000..9158f83b62 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/mvnDebug @@ -0,0 +1 @@ +.maven-3.9.8.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/rmiregistry b/jvm-runtime/kotlin/scaffolding/bin/rmiregistry new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/rmiregistry @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/bin/serialver b/jvm-runtime/kotlin/scaffolding/bin/serialver new file mode 120000 index 0000000000..cf7b7e07ba --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/bin/serialver @@ -0,0 +1 @@ +.openjdk@17.pkg \ No newline at end of file diff --git a/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/ftl.toml b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/ftl.toml new file mode 100644 index 0000000000..c9bc601c3e --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/ftl.toml @@ -0,0 +1,2 @@ +module = "{{ .Name }}" +language = "kotlin" diff --git a/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl new file mode 100644 index 0000000000..a4ea755f42 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/pom.xml.tmpl @@ -0,0 +1,14 @@ + + + 4.0.0 + ftl.{{ .Group }} + {{ .Name }} + 1.0-SNAPSHOT + + + xyz.block.ftl + ftl-build-parent-kotlin + 1.0-SNAPSHOT + + + diff --git a/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/src/main/kotlin/{{ .PackageDir }}/EchoVerb.kt b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/src/main/kotlin/{{ .PackageDir }}/EchoVerb.kt new file mode 100644 index 0000000000..595bba72d7 --- /dev/null +++ b/jvm-runtime/kotlin/scaffolding/{{ .Name | camel | lower }}/src/main/kotlin/{{ .PackageDir }}/EchoVerb.kt @@ -0,0 +1,9 @@ +package {{ .Group }} + +import xyz.block.ftl.Export +import xyz.block.ftl.Verb + + +@Export +@Verb +fun echo(req: String): String = "Hello, $req!"