Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 3 additions & 23 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -125,30 +125,10 @@ jobs:
if: steps.version_check.outputs.should_generate == 'true'
id: check_changes
env:
OPENAPI_VERSION: ${{ steps.version_check.outputs.openapi_version }}
SDK_VERSION: ${{ steps.version_check.outputs.openapi_version }}
run: |
# Move generated files to the correct locations and clean up
rm -Rf docs && mv java-client/docs .
rm -Rf gradle && mv java-client/gradle .
rm -Rf src/main && mv java-client/src/main src/
rm -Rf build.gradle && mv java-client/build.gradle .
rm -Rf build.sbt && mv java-client/build.sbt .
rm -Rf gradle.properties && mv java-client/gradle.properties .
rm -Rf gradlew && mv java-client/gradlew .
rm -Rf gradlew.bat && mv java-client/gradlew.bat .
rm -Rf pom.xml && mv java-client/pom.xml .
rm -Rf settings.gradle && mv java-client/settings.gradle .
rm -Rf README.md && mv java-client/README.md .
rm -Rf java-client

# Ensure gradlew is executable
chmod +x gradlew

# Move custom models
cp models/* src/main/java/ai/reveng/model/

# Store the SDK version
echo "$OPENAPI_VERSION" > .sdk-version
# Shared with scripts/generate-local.sh so the two cannot drift.
bash scripts/postprocess.sh

# Configure git
git config user.name "github-actions[bot]"
Expand Down
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,7 @@ build
.idea
.openapi-generator
out/
*.iml
*.iml
# Local generation scratch
.openapi-spec.json
java-client/
46 changes: 46 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Local generation and installation of the Java SDK.
#
# The released SDK is generated in CI (.github/workflows/check.yaml) and
# published by .github/workflows/publish.yaml. These targets exist to build an
# SDK from an arbitrary spec and install it into the local Maven repository,
# so downstream projects can be built against unreleased API changes. Nothing
# here publishes to a remote registry.

# Spec to generate from: a URL or a path to a local .json file.
SPEC ?= https://docs.reveng.ai/openapi.json

# Artifact version. Leave empty to derive it from the spec's info.version.
VERSION ?=

export SPEC
export VERSION

help: ## Show this help message
@printf "\nUsage: make [target]\n\n"
@printf "Targets:\n"
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk -F ':.*## ' '{printf " %-15s %s\n", $$1, $$2}'
@printf "\nVariables:\n"
@printf " %-15s %s\n" "SPEC" "OpenAPI spec URL or file path"
@printf " %-15s %s\n" "VERSION" "Artifact version override (default: derived from the spec)"
@printf "\n"

.DEFAULT_GOAL := help

generate: ## Regenerate the SDK source tree from SPEC
./scripts/generate-local.sh

build: ## Compile the current source tree
./gradlew build

install: ## Install the current source tree into ~/.m2 (publishToMavenLocal)
./gradlew publishToMavenLocal
@printf "\nInstalled:\n"
@ls -1 "$$HOME/.m2/repository/ai/reveng/sdk/$$(sed 's/^v//' .sdk-version)/"

sdk: generate install ## Regenerate from SPEC and install into ~/.m2

clean: ## Remove build output and any leftover generator output
./gradlew clean
rm -rf java-client .openapi-spec.json

.PHONY: help generate build install sdk clean
5 changes: 4 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,10 @@ test {

mavenPublishing {
publishToMavenCentral(true)
signAllPublications()

// CI sets ORG_GRADLE_PROJECT_signingInMemoryKey; publishToMavenLocal has no
// key, and signing without one fails the build.
if (project.hasProperty("signingInMemoryKey")) signAllPublications()

coordinates("ai.reveng", "sdk", "3.131.1")

Expand Down
122 changes: 122 additions & 0 deletions scripts/generate-local.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env bash
#
# Generate the Java SDK locally from an OpenAPI spec.
#
# This is the local-developer equivalent of .github/workflows/check.yaml. It
# uses the same generator version, the same config.yml, the same templates and
# the same post-processing (scripts/postprocess.sh), so local output does not
# drift from CI output. The only deliberate difference is that the spec source
# is configurable, so any spec URL or a saved .json file can be generated from
# as easily as the default.
#
# Usage:
# scripts/generate-local.sh [--spec <url|path>] [--version <x.y.z[-suffix]>]
# [--version-prefix <x.y.z>] [--generator <ver>]
#
# Env equivalents: SPEC, VERSION, VERSION_PREFIX, GENERATOR_VERSION
#
set -euo pipefail

REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"

# Spec to generate from: a URL or a path to a local .json file.
SPEC="${SPEC:-https://docs.reveng.ai/openapi.json}"

# Explicit artifact version. If empty it is derived from the spec (see below).
VERSION="${VERSION:-}"

# Used only when the spec's info.version is not semver, which is the case for
# unreleased builds. Maven needs a semver-shaped version, and consumers select
# an installed SDK by parsing a numeric X.Y.Z out of the artifact filename, so
# a locally built SDK must still start with one. The default sorts above any
# released version, so a local build is never mistaken for a release.
VERSION_PREFIX="${VERSION_PREFIX:-3.999.0}"

# Keep in lockstep with `generator-tag` in .github/workflows/check.yaml.
GENERATOR_VERSION="${GENERATOR_VERSION:-7.23.0}"

while [ $# -gt 0 ]; do
case "$1" in
--spec) SPEC="$2"; shift 2 ;;
--version) VERSION="$2"; shift 2 ;;
--version-prefix) VERSION_PREFIX="$2"; shift 2 ;;
--generator) GENERATOR_VERSION="$2"; shift 2 ;;
-h|--help) sed -n '2,17p' "$0"; exit 0 ;;
*) echo "unknown argument: $1" >&2; exit 2 ;;
esac
done

cd "$REPO_ROOT"

# --- 1. Resolve the spec to a file inside the repo -------------------------
# It has to live under REPO_ROOT because that is the only path bind-mounted
# into the generator container.
SPEC_FILE="$REPO_ROOT/.openapi-spec.json"
trap 'rm -f "$SPEC_FILE"' EXIT

case "$SPEC" in
http://*|https://*)
echo "==> Fetching spec from $SPEC"
curl -fsSL "$SPEC" -o "$SPEC_FILE"
;;
*)
echo "==> Using local spec $SPEC"
[ -f "$SPEC" ] || { echo "spec file not found: $SPEC" >&2; exit 1; }
cp "$SPEC" "$SPEC_FILE"
;;
esac

SPEC_VERSION="$(jq -r '.info.version // empty' "$SPEC_FILE")"
[ -n "$SPEC_VERSION" ] || { echo "spec has no info.version" >&2; exit 1; }
echo "==> Spec info.version: $SPEC_VERSION"

# --- 2. Resolve the artifact version --------------------------------------
if [ -z "$VERSION" ]; then
# Drop the `v` prefix: Maven versions do not use it. Note this makes
# .sdk-version differ from CI, which stores the tag-shaped version there.
# Local consumers read the file as the Maven version, so keep it stripped.
BASE="${SPEC_VERSION#v}"
if printf '%s' "$BASE" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; then
# Released spec: use its version verbatim, identical to CI.
VERSION="$BASE"
else
# Unreleased spec: prefix a synthetic semver and keep the spec's own
# version as a suffix, so the artifact stays traceable to its source.
VERSION="${VERSION_PREFIX}-${BASE}"
fi
fi

# Fail here rather than at consumer build time.
if ! printf '%s' "$VERSION" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+'; then
echo "version must start with a numeric X.Y.Z: got '$VERSION'" >&2
exit 1
fi
echo "==> Artifact version: $VERSION"

# --- 3. Generate ----------------------------------------------------------
# Pinned to the same image tag CI uses, so no local generator install is
# needed. Running as the invoking user keeps the generated tree owned by the
# developer rather than by root.
rm -rf "$REPO_ROOT/java-client"

echo "==> Running openapi-generator v${GENERATOR_VERSION}"
docker run --rm \
--user "$(id -u):$(id -g)" \
-v "$REPO_ROOT:/local" \
-w /local \
"openapitools/openapi-generator-cli:v${GENERATOR_VERSION}" \
generate \
-i /local/.openapi-spec.json \
-g java \
-o /local/java-client \
-c /local/config.yml \
-t /local/templates \
--additional-properties="artifactVersion=${VERSION}"

# --- 4. Post-process (shared with CI) -------------------------------------
echo "==> Post-processing"
SDK_VERSION="$VERSION" "$REPO_ROOT/scripts/postprocess.sh"

echo
echo "==> Done. Generated SDK version $(cat "$REPO_ROOT/.sdk-version")"
grep -n "^version = \|coordinates(" "$REPO_ROOT/build.gradle"
40 changes: 40 additions & 0 deletions scripts/postprocess.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
#
# Post-processing for a fresh openapi-generator run.
#
# This is shared by two callers and MUST stay identical for both:
# - CI: .github/workflows/check.yaml ("Check for changes" step)
# - local: scripts/generate-local.sh
#
# Precondition: openapi-generator has just written its output into ./java-client
# Inputs (env):
# SDK_VERSION - value written to .sdk-version
#
set -euo pipefail

cd "$(dirname "$0")/.."

: "${SDK_VERSION:?SDK_VERSION must be set}"

# Move generated files to the correct locations and clean up
rm -Rf docs && mv java-client/docs .
rm -Rf gradle && mv java-client/gradle .
rm -Rf src/main && mv java-client/src/main src/
rm -Rf build.gradle && mv java-client/build.gradle .
rm -Rf build.sbt && mv java-client/build.sbt .
rm -Rf gradle.properties && mv java-client/gradle.properties .
rm -Rf gradlew && mv java-client/gradlew .
rm -Rf gradlew.bat && mv java-client/gradlew.bat .
rm -Rf pom.xml && mv java-client/pom.xml .
rm -Rf settings.gradle && mv java-client/settings.gradle .
rm -Rf README.md && mv java-client/README.md .
rm -Rf java-client

# Ensure gradlew is executable
chmod +x gradlew

# Move custom models
cp models/* src/main/java/ai/reveng/model/

# Store the SDK version
echo "$SDK_VERSION" > .sdk-version
5 changes: 4 additions & 1 deletion templates/libraries/okhttp-gson/build.gradle.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,10 @@ test {

mavenPublishing {
publishToMavenCentral(true)
signAllPublications()

// CI sets ORG_GRADLE_PROJECT_signingInMemoryKey; publishToMavenLocal has no
// key, and signing without one fails the build.
if (project.hasProperty("signingInMemoryKey")) signAllPublications()

coordinates("{{groupId}}", "{{artifactId}}", "{{artifactVersion}}")

Expand Down