diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0bff3f94c0..df042fa1bc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -49,7 +49,7 @@ jobs:
permissions:
contents: read
packages: write
- needs: [build-runner, build-controller]
+ needs: [ build-runner, build-controller ]
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -109,8 +109,8 @@ jobs:
server-password: OSSRH_PASSWORD
gpg-passphrase: SIGN_KEY_PASS
gpg-private-key: ${{ secrets.GPG_PRIVATE_KEY }}
- cache: "maven"
- - name: Publish JARs # Snapshots are published first, then the tagged release
+ cache: 'maven'
+ - name: Publish JARs to Staging # Snapshots are published first, then the tagged release is published to staging.
run: |
mvn -U --batch-mode clean deploy -P release
mvn --batch-mode versions:set -DnewVersion=$(git describe --tags --abbrev=0 | cut -c2-) -DprocessAllModules -DgenerateBackupPoms=false
@@ -121,10 +121,12 @@ jobs:
OSSRH_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
GITHUB_TOKEN: ${{ github.token }}
+ - name: Run Staging Tests
+ run: staging-tests $(git describe --tags --abbrev=0 | cut -c2-)
create-release:
name: Release Go Binaries
runs-on: ubuntu-latest
- needs: [release-docker, release-jars]
+ needs: [ release-docker, release-jars ]
steps:
- name: Checkout code
uses: actions/checkout@v4
@@ -144,3 +146,18 @@ jobs:
goreleaser release
env:
GITHUB_TOKEN: ${{ github.token }}
+ - name: Promote JARs to Release
+ if: ${{ success() }}
+ run: |
+ mvn nexus-staging:release -DserverId=ossrh -DnexusUrl=https://s01.oss.sonatype.org
+ env:
+ OSSRH_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
+ OSSRH_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
+ GITHUB_TOKEN: ${{ github.token }}
+ - name: Rollback Staging JARs
+ if: ${{ failure() }}
+ run: |
+ mvn nexus-staging:drop -DserverId=ossrh -DnexusUrl=https://s01.oss.sonatype.org
+ env:
+ OSSRH_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
+ OSSRH_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
diff --git a/pom.xml b/pom.xml
index 674423a9b2..56268a2297 100644
--- a/pom.xml
+++ b/pom.xml
@@ -411,8 +411,7 @@
${maven.deploy.skip}
ossrh
https://s01.oss.sonatype.org/
- true
- 10
+ true
diff --git a/scripts/staging-tests b/scripts/staging-tests
new file mode 100755
index 0000000000..82fcafe447
--- /dev/null
+++ b/scripts/staging-tests
@@ -0,0 +1,101 @@
+#!/bin/bash
+set -euo pipefail
+export PATH="$PWD/build/release:$PATH"
+
+info() {
+ echo -e "\033[1;32m$*\033[0m"
+}
+
+error() {
+ echo -e "\033[1;31m$*\033[0m"
+ exit 1
+}
+
+pull_staging_release() {
+ info "Pulling release JARs from Sonatype OSSRH Staging"
+ local version=$1
+
+ mvn dependency:get \
+ -DremoteRepositories=ossrh::default::https://s01.oss.sonatype.org/content/repositories/staging/ \
+ -Dartifact=xyz.block:ftl-runtime:${version}:jar -Dtransitive=false \
+ -Ddest=kotlin-runtime/ftl-runtime/target/ftl-runtime-${version}.jar
+
+ mvn dependency:get \
+ -DremoteRepositories=ossrh::default::https://s01.oss.sonatype.org/content/repositories/staging/ \
+ -Dartifact=xyz.block:ftl-generator:${version}:jar:jar-with-dependencies -Dtransitive=false \
+ -Ddest=kotlin-runtime/ftl-generator/target/ftl-generator-${version}.jar
+}
+
+wait_for() {
+ info "Waiting for $1"
+ for _ in {1..240}; do
+ if eval "$2"; then
+ info "Success!"
+ return 0
+ fi
+ sleep 1
+ done
+ error "Timed out waiting for $1"
+}
+
+stop_cluster() {
+ kill %1
+ wait
+}
+
+start_cluster() {
+ info "Starting cluster"
+ ftl serve --recreate &
+ wait_for "cluster to become ready" "ftl status"
+ trap stop_cluster EXIT INT TERM
+}
+
+deploy_echo_kotlin() (
+ info "Deploying echo-kotlin"
+ ftl deploy examples/kotlin/ftl-module-echo
+)
+
+deploy_fresh_kotlin() (
+ info "Deploying newly initialised Kotlin module"
+ IT_MODULES=build/modules
+ rm -rf "${IT_MODULES}"
+ ftl init kotlin "${IT_MODULES}" echo2
+ ftl init kotlin "${IT_MODULES}" echo3
+ cd "${IT_MODULES}"
+ ftl deploy ftl-module-echo2
+ ftl deploy ftl-module-echo3
+)
+
+deploy_time_go() (
+ info "Deploying time"
+ cd examples
+ # Pull a supported platforms from the cluster.
+ platform="$(ftl status | jq -r '(.runners // [])[].labels | "\(.os)-\(.arch)"' | sort | uniq | head -1)"
+ ftl-go --os "${platform%-*}" --arch "${platform#*-}" deploy time
+)
+
+wait_for_deploys() {
+ wait_for "deployments to come up" 'ftl status | jq -r "(.routes // [])[].module" | sort | paste -sd " " - | grep -q "echo echo2 echo3 time"'
+}
+
+pull_staging_release $1
+start_cluster
+
+# Cluster is up, start interacting with it.
+deploy_time_go
+deploy_echo_kotlin
+deploy_fresh_kotlin
+
+wait_for_deploys
+
+info "Calling echo"
+message="$(ftl call echo.echo '{"name": "Alice"}' | jq -r .message)"
+[[ "$message" =~ "Hello, Alice! The time is " ]] || error "Unexpected response from echo: $message"
+
+message="$(ftl call echo2.echo '{"name": "Alice"}' | jq -r .message)"
+[[ "$message" =~ "Hello, Alice!" ]] || error "Unexpected response from echo2: $message"
+
+message="$(ftl call echo3.echo '{"name": "Alice"}' | jq -r .message)"
+[[ "$message" =~ "Hello, Alice!" ]] || error "Unexpected response from echo2: $message"
+
+info "Success!"