Files
hatchet/sdks/ruby/generate.sh
Gabe Ruttner 2fdc47a6af feat: multiple slot types (#2927)
* feat: adds support for multiple slot types, primarily motivated by durable slots

---------

Co-authored-by: mrkaye97 <mrkaye97@gmail.com>
2026-02-17 05:43:47 -08:00

165 lines
5.9 KiB
Bash
Executable File

#!/bin/bash
#
# Single entry point for all Ruby SDK code generation.
#
# Generates:
# 1. Protobuf/gRPC stubs (from api-contracts/*.proto)
# 2. REST API client (from bin/oas/openapi.yaml via openapi-generator)
#
# Usage:
# cd sdks/ruby && bash generate.sh # generate everything
# cd sdks/ruby && bash generate.sh proto # protobuf only
# cd sdks/ruby && bash generate.sh rest # REST client only
#
# Prerequisites:
# - grpc-tools gem (gem install grpc-tools)
# - openapi-generator-cli (npm install -g @openapitools/openapi-generator-cli)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
# ── Protobuf / gRPC generation ──────────────────────────────────────────────
generate_proto() {
echo "==> Generating protobuf/gRPC stubs..."
local contracts_dir="$REPO_ROOT/api-contracts"
local output_dir="$SCRIPT_DIR/src/lib/hatchet/contracts"
mkdir -p "$output_dir/dispatcher"
mkdir -p "$output_dir/events"
mkdir -p "$output_dir/workflows"
mkdir -p "$output_dir/v1/shared"
local proto_files=(
"dispatcher/dispatcher.proto"
"events/events.proto"
"workflows/workflows.proto"
"v1/shared/condition.proto"
"v1/dispatcher.proto"
"v1/workflows.proto"
)
for proto_file in "${proto_files[@]}"; do
echo " $proto_file"
grpc_tools_ruby_protoc \
--proto_path="$contracts_dir" \
--ruby_out="$output_dir" \
--grpc_out="$output_dir" \
"$proto_file"
done
echo " Done."
}
# ── REST API client generation ───────────────────────────────────────────────
generate_rest() {
echo "==> Generating REST API client from OpenAPI spec..."
local openapi_spec="$REPO_ROOT/bin/oas/openapi.yaml"
local output_dir="$SCRIPT_DIR/src/lib/hatchet/clients/rest"
local config_file="$SCRIPT_DIR/src/config/openapi_generator_config.json"
if [ ! -f "$openapi_spec" ]; then
echo "ERROR: OpenAPI spec not found at $openapi_spec" >&2
exit 1
fi
# Install openapi-generator-cli if missing
if ! command -v openapi-generator-cli &>/dev/null; then
echo " Installing openapi-generator-cli..."
npm install -g @openapitools/openapi-generator-cli
fi
# Generate
local additional_props="gemName=hatchet-sdk-rest,moduleName=HatchetSdkRest,gemVersion=0.0.1,gemDescription=HatchetRubySDKRestClient,gemAuthor=HatchetTeam,gemHomepage=https://github.com/hatchet-dev/hatchet,gemLicense=MIT,library=faraday"
# TODO-RUBY: we can generate docs here :wow:
local cmd=(
openapi-generator-cli generate
-i "$openapi_spec"
-g ruby
-o "$output_dir"
--skip-validate-spec
--global-property "apiTests=false,modelTests=false,apiDocs=false,modelDocs=false"
--additional-properties "$additional_props"
)
if [ -f "$config_file" ]; then
cmd+=(-c "$config_file")
fi
"${cmd[@]}"
# ── Post-generation patches ──────────────────────────────────────────────
echo " Applying patches..."
apply_cookie_auth_patch "$output_dir"
echo " Done."
}
# Patch the generated client to support cookie-based auth and skip nil values.
apply_cookie_auth_patch() {
local output_dir="$1"
# 1. Fix configuration.rb: fill in empty 'in:' for cookie auth
local config_rb="$output_dir/lib/hatchet-sdk-rest/configuration.rb"
if [ -f "$config_rb" ]; then
sed -i.bak "s/in: ,/in: 'cookie',/g" "$config_rb" && rm -f "$config_rb.bak"
fi
# 2. Fix api_client.rb: add cookie support + nil guard
local api_client_rb="$output_dir/lib/hatchet-sdk-rest/api_client.rb"
if [ -f "$api_client_rb" ]; then
ruby -e '
path = ARGV[0]
content = File.read(path)
# Match the auth switch block regardless of indentation
old_pattern = /^(\s*)case auth_setting\[:in\]\n\s*when '\''header'\'' then header_params\[auth_setting\[:key\]\] = auth_setting\[:value\]\n\s*when '\''query'\'' then query_params\[auth_setting\[:key\]\] = auth_setting\[:value\]\n\s*else fail ArgumentError, '\''Authentication token must be in `query` or `header`'\''\n\s*end/
if content.match(old_pattern)
indent = content.match(old_pattern)[1]
new_auth = "#{indent}next if auth_setting[:value].nil? || auth_setting[:value].to_s.empty?\n" \
"#{indent}case auth_setting[:in]\n" \
"#{indent}when '\''header'\'' then header_params[auth_setting[:key]] = auth_setting[:value]\n" \
"#{indent}when '\''query'\'' then query_params[auth_setting[:key]] = auth_setting[:value]\n" \
"#{indent}when '\''cookie'\'' then header_params['\''Cookie'\''] = \"\#{auth_setting[:key]}=\#{auth_setting[:value]}\"\n" \
"#{indent}else next\n" \
"#{indent}end"
content.sub!(old_pattern, new_auth)
File.write(path, content)
puts " Patched api_client.rb"
else
puts " api_client.rb already patched (skipping)"
end
' "$api_client_rb"
fi
}
# ── Main ─────────────────────────────────────────────────────────────────────
case "${1:-all}" in
proto) generate_proto ;;
rest) generate_rest ;;
all)
generate_proto
generate_rest
;;
-h|--help)
echo "Usage: $0 [proto|rest|all]"
echo " proto Generate protobuf/gRPC stubs only"
echo " rest Generate REST API client only"
echo " all Generate everything (default)"
exit 0
;;
*)
echo "Unknown command: $1. Use --help for usage." >&2
exit 1
;;
esac
echo "==> All generation complete."