ghl-generate
Wraps script/generate.rb. Idempotent: regenerating against the same spec SHA produces byte-identical output, which is the contract the ghl-drift-check skill relies on.
When to run
- After
bin/sync-specadvances the pinned OpenAPI SHA. - After editing
script/generate.rb(templates, method shapes, etc.). - As a sanity check before opening a PR that touches the generator.
Prerequisites
vendor/openapi/is populated (runbin/sync-specfirst if not).bundle installhas been run (the post-step shells out to rubocop autocorrect).
How to run
bin/generate # every app under vendor/openapi/apps/
bin/generate contacts # one app
bin/generate contacts blogs # several
bundle exec rake # always finish with a green test + lint run
What gets emitted
For each vendor/openapi/apps/<app>.json:
| Output | Shape |
|---|---|
lib/high_level/resources/<app>.rb |
HighLevel::Resources::<Pascal> < Resources::Base — one snake_case method per operation. |
lib/high_level/models/<app>/<schema_snake>.rb |
HighLevel::Models::<Pascal>::<Schema> = Data.define(...) — one file per schema with object-shape. |
Every emitted file carries the header:
# GENERATED FROM vendor/openapi/apps/<app>.json @ <sha>
# DO NOT EDIT — regenerate via bin/generate.
Conventions the generator applies
operationId(kebab-case) → method name (snake_case).search-contacts-advanced→search_contacts_advanced.- Path parameters (
{contactId}) → required kwargs (contact_id:) + Ruby interpolation in the path string ("/contacts/#{contact_id}"). - Query parameters → optional kwargs (default
nil), gathered into a.compact-edparams:hash with original (camelCase) keys. - Header parameters → optional kwargs, gathered into a
headers:hash with original key casing.Versionis skipped (the Authentication middleware injects it). requestBodypresent → requiredbody:kwarg.securitydeclarations → string array passed toResources::Base#request(security:), which the Authentication middleware reads via the request's:high_level_securitycontext.**_optscatch-all on every method so callers can forward Faraday options without the resource layer rejecting them.
Idempotency
Running the generator twice against the same vendor/openapi/VERSION produces no file changes. The ghl-drift-check skill relies on this.
Failure modes
- "no spec for app: X" — the spec file isn't in
vendor/openapi/apps/. Runbin/sync-specor check the app name. - rubocop autocorrect failed — the generator still wrote the files; review them and fix the template if a class of operations produces non-idiomatic Ruby.
- Generated file looks malformed — usually a template bug in
script/generate.rb; fix the template and re-run.