Skip to content

feat(scripts): manage custom hostnames for Edge Scripts#89

Merged
jamie-at-bunny merged 2 commits into
mainfrom
feat/scripts-hostnames
Jun 4, 2026
Merged

feat(scripts): manage custom hostnames for Edge Scripts#89
jamie-at-bunny merged 2 commits into
mainfrom
feat/scripts-hostnames

Conversation

@jamie-at-bunny
Copy link
Copy Markdown
Member

Add a scripts hostnames command group (add/ssl/list/remove) for managing a script's custom domains on its linked pull zone, via the core pull-zone API (addHostname/loadFreeCertificate/setForceSSL). SSL is opt-in on add; issuing a certificate forces HTTPS by default (--no-force-ssl to opt out). scripts deploy and scripts show now surface custom hostnames, deriving each URL's http/https scheme from its certificate / force-SSL state.

@bogdan-at-bunny
Copy link
Copy Markdown

@codex review

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Jun 4, 2026

🦋 Changeset detected

Latest commit: 52c2dca

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 6 packages
Name Type
@bunny.net/cli Minor
@bunny.net/cli-linux-x64 Minor
@bunny.net/cli-linux-arm64 Minor
@bunny.net/cli-darwin-x64 Minor
@bunny.net/cli-darwin-arm64 Minor
@bunny.net/cli-windows-x64 Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

* Defaults to the script's only linked pull zone. When several exist,
* requires `--pull-zone` to disambiguate.
*/
function resolvePullZoneId(script: EdgeScript, flag?: number): number {
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1368548a5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +46 to +48
await client.GET("/pullzone/loadFreeCertificate", {
params: { query: { hostname } },
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate hostname ownership before issuing SSL

When scripts hostnames ssl <hostname> --no-force-ssl runs, this account-wide /pullzone/loadFreeCertificate call is the only API request made; it is keyed only by hostname, not by the resolved pullZoneId. If the account has the hostname on a different pull zone, the command can issue/claim SSL for that other resource while reporting success for the selected script pull zone. Fetch the target pull zone's hostnames first, as remove does, or otherwise verify the hostname belongs to pullZoneId before calling this endpoint.

Useful? React with 👍 / 👎.

Comment on lines +278 to +279
if (args.output === "json") {
logger.log(JSON.stringify(hostnames, null, 2));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Redact certificate material from JSON output

When users run scripts hostnames list --output json, this serializes the raw HostnameModel objects returned by GET /pullzone/{id}; that model includes Certificate and CertificateKey, so any returned private-key material can be written to terminals or CI logs. scripts show --output json adds the same raw hostnames as well, so map hostnames to the safe fields used by the table output before JSON serialization.

Useful? React with 👍 / 👎.

Comment on lines +124 to +126
} catch (err) {
sslError = err instanceof Error ? err.message : String(err);
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Fail when requested SSL cannot be issued

When scripts hostnames add <host> --ssl is used and enableSsl() fails (for example, DNS is not pointed correctly), this catch records the error but the command still exits successfully after printing Added ..., and JSON output reports success unless callers inspect sslError. Automation that requests --ssl can therefore continue even though the certificate/Force SSL step did not happen; the ssl subcommand already treats the same failure as a command error.

Useful? React with 👍 / 👎.

Comment thread packages/cli/src/core/hostnames/commands.ts Outdated
@jamie-at-bunny
Copy link
Copy Markdown
Member Author

@greptile-apps review

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 4, 2026

Greptile Summary

This PR adds a scripts domains (alias: hostnames) command group for managing custom hostnames on an Edge Script's linked pull zone, backed by the core pull-zone API (addHostname / loadFreeCertificate / setForceSSL / removeHostname). It also surfaces custom domains in scripts deploy and scripts show output, strips private-key material from JSON via toSafeHostname, and introduces a reusable createHostnamesCommands factory parameterised by a pull-zone resolver so the same implementation can be mounted by apps later.

  • New core/hostnames/ moduleclient.ts houses hostnameUrl, fetchPullZoneHostnames, enableSsl, and toSafeHostname; commands.ts is the add/ssl/list/remove factory; client.test.ts covers URL-derivation logic and private-key-stripping.
  • scripts deploy + scripts show updated — both now fetch the full hostname list from the core API, with debug-level logging on failure instead of a silent swallow.
  • define-namespace wideneddescribe now accepts false to support hidden alias namespaces.

Confidence Score: 5/5

Safe to merge — the new hostname commands are well-scoped, the factory pattern is clean, and the previously flagged silent-swallow issues have been addressed with debug logging.

All changed paths follow established codebase conventions, errors are handled consistently, and private-key material is correctly stripped before any JSON serialization. No data-loss or incorrect-state paths were found in the changed code.

commands.ts — the process.exit(1) call in the JSON-mode SSL-failure path and the always-generic DNS-propagation hint are worth a second look before the factory is reused for apps.

Important Files Changed

Filename Overview
packages/cli/src/core/hostnames/client.ts New client helpers: hostnameUrl (scheme derivation), fetchPullZoneHostnames, enableSsl (cert + setForceSSL), and toSafeHostname to strip cert material from JSON output. Logic is sound and well-tested.
packages/cli/src/core/hostnames/commands.ts Factory for add/ssl/list/remove subcommands. The add command signals SSL failure in JSON mode via process.exit(1) while the text-mode path throws a UserError — a deliberate asymmetry worth noting.
packages/cli/src/commands/scripts/hostnames/index.ts Mounts createHostnamesCommands for Edge Scripts: resolves the linked pull zone via the compute client and passes a core client; handles the multi-zone disambiguation error correctly.
packages/cli/src/commands/scripts/deploy.ts Now fetches custom hostnames from the core API post-deploy and prints them; falls back to the system hostname; errors are debug-logged rather than swallowed silently.
packages/cli/src/commands/scripts/show.ts Adds a Hostnames table (system + custom, with SSL and Force-SSL columns) to the text output and merges hostnames into the JSON envelope via toSafeHostname; error path now debug-logs instead of swallowing.
packages/cli/src/core/define-namespace.ts Widens describe parameter to string

Sequence Diagram

sequenceDiagram
    participant User
    participant CLI
    participant ComputeAPI as Compute API
    participant CoreAPI as Core API

    Note over CLI,CoreAPI: scripts domains add domain --ssl

    User->>CLI: bunny scripts domains add shop.example.com --ssl
    CLI->>ComputeAPI: "GET /compute/script/{id}"
    ComputeAPI-->>CLI: EdgeScriptModel (LinkedPullZones)
    CLI->>CoreAPI: "POST /pullzone/{id}/addHostname"
    CoreAPI-->>CLI: 200 OK
    CLI->>CoreAPI: "GET /pullzone/{id} (fetch hostnames list)"
    CoreAPI-->>CLI: Hostname[]
    CLI->>CoreAPI: "GET /pullzone/loadFreeCertificate?hostname=..."
    CoreAPI-->>CLI: 200 OK
    CLI->>CoreAPI: "POST /pullzone/{id}/setForceSSL"
    CoreAPI-->>CLI: 200 OK
    CLI-->>User: Added + SSL issued

    Note over CLI,CoreAPI: scripts domains remove domain

    User->>CLI: bunny scripts domains remove shop.example.com
    CLI->>ComputeAPI: "GET /compute/script/{id}"
    ComputeAPI-->>CLI: EdgeScriptModel
    CLI->>CoreAPI: "GET /pullzone/{id} (verify ownership)"
    CoreAPI-->>CLI: Hostname[]
    CLI-->>User: Confirm remove?
    User->>CLI: yes
    CLI->>CoreAPI: "DELETE /pullzone/{id}/removeHostname"
    CoreAPI-->>CLI: 200 OK
    CLI-->>User: Removed shop.example.com
Loading

Fix All in Claude Code

Reviews (3): Last reviewed commit: "switch to domains" | Re-trigger Greptile

Comment thread packages/cli/src/core/hostnames/client.ts Outdated
Comment thread packages/cli/src/commands/scripts/deploy.ts
Comment thread packages/cli/src/commands/scripts/show.ts
@jamie-at-bunny
Copy link
Copy Markdown
Member Author

jamie-at-bunny commented Jun 4, 2026

@greptile-apps re-review

@jamie-at-bunny jamie-at-bunny merged commit f4bc85d into main Jun 4, 2026
1 check passed
@jamie-at-bunny jamie-at-bunny deleted the feat/scripts-hostnames branch June 4, 2026 15:39
@github-actions github-actions Bot mentioned this pull request Jun 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants