feat(ruby): Ruby language bindings#5178
Draft
omarqureshi wants to merge 9 commits into
Draft
Conversation
Adds Ruby as a jsii target language: - jsii-pacmak Ruby target (lib/targets/ruby.ts): generates idiomatic Ruby gems from .jsii assemblies — snake_case members, PascalCase modules with configurable acronyms, struct value classes with hash-to-struct coercion (recursive through collections and unambiguous union arms), Jsii::Enum constants, YARD documentation, runtime type checking, reserved-word and runtime-API name protection, statics emitted on their defining class (ES6 semantics), and complete gemspec metadata. Covered by unit tests and generated-code snapshots in the cross-language harness. - @jsii/ruby-runtime: the Ruby runtime gem — thread-safe JSON-RPC kernel client (re-entrant Monitor, stderr drain thread), object registry with allocate-based hydration and reference identity, guarded method_missing fallback with respond_to? discipline, explicit Jsii::Serializer (no core-class monkey-patching), structural type validation, diamond-struct conformance for is_a?/case dispatch, and callback dispatch matching the generator's name mapping (enforced by a consistency spec). - @jsii/ruby-runtime-test: 123/123 standard compliance suite tests (reported via tools/jsii-compliance into the shared compliance matrix) plus unit suites — 240 examples total. - CI: Ruby toolchain in build/test jobs; alternate-Ruby matrix row (3.4; 3.3 is the baseline). Supported: MRI >= 3.3 (3.1/3.2 EOL). Note: jsii-calc pins jsii ^6.0.0 — the targets.ruby schema lands in the compiler via aws/jsii-compiler#2663. Until a release carrying it exists, yarn.lock intentionally lags package.json (it still resolves the development-fork compiler); the lockfile will be regenerated as part of the final rebase. The working development branch is ruby-language-bindings-self-publish. Tracking issue: aws#5129 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 4, 2026
The Ruby pacmak target emitted jsii @example docs verbatim, leaving TypeScript snippets in generated Ruby docstrings. Wire in RosettaTabletReader and translate each example to Ruby (TargetLanguage.RUBY), mirroring the Python target. Examples degrade to the original source if translation fails. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
omarqureshi
force-pushed
the
ruby-language-bindings
branch
from
July 15, 2026 08:12
0ea38eb to
d2c88dd
Compare
Mirror the Python target's emitModuleDocumentation: for the assembly and each submodule that has a README, translate its TypeScript samples to Ruby via Rosetta (translateSnippetsInMarkdown, same tablet path as @example) and emit the result as the module's YARD docstring in a doc-only `_readme.rb` inside the module's directory, so YARD renders it on the module page. This surfaces CDK's real usage docs — which live in module READMEs, not per-type @example tags — in the Ruby API reference. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
22182fe added jsii-calc / @scope/jsii-calc-base-of-base@^2.1.1 devDeps to @jsii/ruby-runtime and @jsii/ruby-runtime-test but left yarn.lock lagging. A plain install tolerates that, but CI's `yarn install --immutable` forbids any lockfile modification, so Main failed at "Install Dependencies" on this branch. Record the resolutions (workspace-only; no new registry deps). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The committed snapshot predated the autoload + RBS refactor, so it no longer matched the generated code (Unit Tests failed). Regenerate it: this captures the current per-type autoload layout, the sig/*.rbs signatures, and the new per-submodule _readme.rb module-docstring files. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
`@example` tags were translated to Ruby, but fenced code blocks inside a
member's `remarks` prose were emitted verbatim — so e.g. CfnResource#addOverride
showed a TypeScript sample (`cfnResource.addOverride('Properties…', […])`) in
the Ruby docs. Run `remarks` through convertMarkdown when an apiLocation is
present, mirroring the Python target, so embedded ```ts samples translate too.
Regenerate the ruby snapshot: the change relabels a remarks fence ts->ruby and
normalizes some markdown (unescaping, bullet style) in jsii-calc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…s, requires) Three display-layer fixes for translated docs prose: - rubifyInlineRefs: translate inline `code` API references in prose to snake_case (`bucketArn` -> `bucket_arn`, `arnForObjects(pattern)` -> `arn_for_objects(pattern)`), matching the real member names. Literals/types/enums are left alone. - Strip HTML comments (CDK's `<!--BEGIN STABILITY BANNER-->` / CFNONLY markers), which YARD's Markdown renderer would otherwise show as visible text. - Strip `require` boilerplate from examples: it comes from the snippet fixture and, after import translation, collapses to duplicate `require 'aws-cdk-lib'` lines. Applied to @example (convertExample) and README/remarks fenced blocks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Requires: keep a single `require 'aws-cdk-lib'` per code block instead of stripping them entirely. Stripping left import-only blocks empty, and YARD's highlighter renders an empty ```ruby block as a literal `</code>` — the stray tag seen in the ACMPCA README. Deduping keeps the block non-empty. - normalizeFences: some READMEs put a fenced block's first line on the fence-open line (e.g. EKSv2's ASCII diagram `\`\`\`text +---`). redcarpet then renders it as a paragraph (CommonMark/GitHub opens the fence but drops that line). Split the trailing content to its own line so the fence opens and the line is kept. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Objective
Introduces comprehensive Ruby language bindings for the jsii ecosystem, enabling AWS CDK (and other jsii-based libraries) to be packaged as gems and consumed idiomatically from Ruby. It adds the code-generation target (
jsii-pacmak) and the core Ruby runtime (@jsii/ruby-runtime), with strict type-safety, careful object lifecycle management, and thread-safe IPC with the jsii Node kernel.Implements RFC 0935: Ruby language bindings. The change is strictly additive — no breaking changes to existing languages and no assembly-format change beyond an additive
targets.rubyschema extension.Warning
CI is expected to be red on this branch, by design. Ruby code generation requires a jsii-compiler release with Ruby target support, which is not yet published. Until it is, the following failures are expected and are not indicative of broken work:
jsii-pacmaktarget-rubysnapshot test — this branch builds with the stock compiler (no Ruby support), so the committed assemblies carry notargets.rubyand generated names won't match the snapshot.@jsii/ruby-runtime-test(generate.sh+ rspec) — cannot generate the Rubylib/without the Ruby-capable compiler.Once the Ruby-capable compiler is released, the committed fixtures (assemblies with
targets.ruby+ the Ruby snapshot) are regenerated against it and CI goes green. End-to-end regeneration + publish has already been validated against the fork compiler.Key Components
1. Code Generation (
jsii-pacmak)RubyTarget&RubyGenerator(packages/jsii-pacmak/lib/targets/ruby.ts): translate jsii types into idiomatic Ruby —class < Jsii::Object, behavioral interfaces as mixinmodules, datatype structs as kwargs value-classes (< Jsii::Struct), enums asJsii::Enumwrapper constants, async + sync methods, and property/method overrides..rbs; output validates clean underrbs validateacrossjsii-calcand its dependency closure.next→_next). Root namespaceAWSCDKwith AWS-prefix de-duplication (aws-s3→AWSCDK::S3::Bucket).module X; end) in dependency order to preventNameErrorduring nested type generation.Jsii::Type.check_typefor runtime enforcement, and embeds type metadata as Base64-encoded JSON literals so no jsii-supplied identifier or docstring can inject into generated source via string interpolation.version-utils.tstranslates npm semver (incl. pre-release.alpha.1/.dev.1) to RubyGems ranges.2. Ruby Runtime Core (
@jsii/ruby-runtime)Monitormakes the bidirectional JSON-RPC stdio pipe safe under concurrency and re-entrant callbacks; an isolated stderr-draining thread prevents pipe deadlocks.supercrossing back to the JS implementation), with user subclasses detected at construction time..allocate, mapped by$jsii.byref; deliberately never issues a guest-initiateddel(matching the Python/Go runtimes) — cleanup is wholesale on kernel shutdown, which suits short-livedsynthworkloads.Jsii::Serializer(rather than monkey-patching core types) handles by-value structs vs by-reference objects, avoiding leakage of host application state.3. Compliance & Testing (
@jsii/ruby-runtime-test)rbs validate. No skipped/pending tests.4. CI / Build
buildspec.yamlCodeBuild runtime added.tools/jsii-compliance).Compatibility & Known Limitations
required_ruby_version >= 3.3.0(3.1/3.2 are EOL). JRuby/TruffleRuby are out of scope for the initial release.beginAPI only accepts object references — a limitation shared by all bindings).Notes & Next Steps
jsii-rosettatranslation backend for Ruby is not included here and will follow in a subsequent PR.mainand do not yet carrytargets.ruby(it's compiler-generated). They — and thetarget-rubysnapshot — will be regenerated against the released Ruby-capable compiler before merge. See the warning above.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.