Skip to content

fix(sites): flag consistency - #135

Merged
jamie-at-bunny merged 11 commits into
mainfrom
fix/sites-flag-consistency
Jul 28, 2026
Merged

fix(sites): flag consistency#135
jamie-at-bunny merged 11 commits into
mainfrom
fix/sites-flag-consistency

Conversation

@jamie-at-bunny

Copy link
Copy Markdown
Member

No description provided.

`confirm()` blocks forever when stdin isn't a TTY, so `sites delete`,
`sites deployments publish`, `sites deployments prune` and the shared
`domains remove` would hang in CI, and print the prompt to stdout ahead
of the `--output json` payload. Add `requireConfirmable()` next to
`isInteractive()` and call it before each of those confirmations, so an
unattended run fails fast with a `--force` hint.
`--force` already skips the confirmation, so `sites delete --force` with
nothing linked would open the picker and delete whichever site was
highlighted, unprompted. Thread `force` into `selectSite` from delete,
deployments publish/prune and the domains resolver (only `remove`
defines the flag) so those runs error with the same hint a
non-interactive run gets. `deploy --force` means "redeploy unchanged
content" and still gets the picker.
yargs coerces `--keep abc` to NaN, and NaN passes straight through
pruneVictims' `Math.max(0, keep)` into `slice(NaN)`, which behaves like
`slice(0)`: every deploy but current and previous gets deleted. Negative
counts did the same. Validate the count in the handler via
resolveKeepCount so it fails before any state is touched.
`sitePositionalBuilder`/`siteOptionBuilder` bundled `--link` with the
site target, so `open`, `ssl`, `delete` and `deployments prune`
advertised a flag none of them acts on: they never call `offerLink`, and
delete/prune hardcode `link: false`. Split the flag into its own
`siteLinkOption` and mount it only where offerLink runs.

An explicit `--link` was also dropped whenever the site came from
`--site` or `bunny.jsonc`, so `deploy --site my-site --link` never wrote
the manifest. Those paths now link on request; the picker keeps
prompting unless the flag already decided it.
`prune` used the `--site` flag builder despite having no positionals of
its own, so `bunny sites deployments prune my-site` failed with "Unknown
argument" while `deployments list my-site` worked. Declare `[site]` like
the sibling subcommands; yargs keeps accepting the `--site` form.
The scaffold only ever used the framework preset, so a project with
`sites.dir: "build"` deployed `build/` locally and the preset's `dist/`
from CI, and a configured `sites.build` was dropped entirely. Thread the
`sites` block through scaffoldSitesWorkflow into renderSitesWorkflow
(both for `ci init` and the offer inside `sites create`), report the
effective directory in the detection and success lines, and quote a
configured build command that a bare YAML scalar couldn't carry.
Every other sites command resolves the site through `sites.name`, but
create never read the config, so `bunny sites create --output json` in a
configured project failed with "Site name is required." Use the
configured name when no positional is passed, and say where it came from
in text output.
@bogdan-at-bunny

Copy link
Copy Markdown

@codex review

@changeset-bot

changeset-bot Bot commented Jul 28, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 222ce65

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 Patch
@bunny.net/cli-linux-x64 Patch
@bunny.net/cli-linux-arm64 Patch
@bunny.net/cli-darwin-x64 Patch
@bunny.net/cli-darwin-arm64 Patch
@bunny.net/cli-windows-x64 Patch

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

Comment thread packages/cli/src/commands/sites/ci/init.ts
@greptile-apps

greptile-apps Bot commented Jul 28, 2026

Copy link
Copy Markdown

Greptile Summary

This PR standardizes Sites command flags and makes generated CI workflows honor project configuration.

  • Resolves configured sites.build and sites.dir relative to nested bunny.jsonc files in generated workflows.
  • Restricts --link and destructive --force behavior to commands that can safely act on them.
  • Adds non-interactive confirmation guards and validates deployment-pruning inputs.
  • Aligns site creation, command documentation, tests, and release notes with the updated behavior.

Confidence Score: 5/5

The PR appears safe to merge.

The previously reported nested-config workflow-root issue is addressed by running build steps from the configured project directory and passing the correspondingly prefixed directory to the deployment action; no blocking failure remains.

Important Files Changed

Filename Overview
packages/cli/src/commands/sites/ci/init.ts Loads Sites configuration and passes its root, build command, and output directory into workflow scaffolding.
packages/cli/src/commands/sites/ci/scaffold.ts Computes the nested project prefix, performs project-relative framework detection, and configures workflow paths and dependency caching.
packages/cli/src/commands/sites/ci/workflow.ts Renders configured build commands, working directories, cache paths, and repository-relative deployment directories into GitHub Actions YAML.
packages/cli/src/commands/sites/interactive.ts Centralizes Sites link-option handling and prevents forced destructive commands from falling through to an interactive site picker.
packages/cli/src/core/ui.ts Adds a confirmation guard so unattended destructive commands require an explicit force flag.
packages/cli/src/commands/sites/deployments/prune.ts Adds positional site selection and validates that the deployment retention count is a non-negative integer.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Config["Nested bunny.jsonc"] --> Scaffold["CI scaffold"]
  Scaffold --> WorkingDir["defaults.run.working-directory"]
  Scaffold --> DeployDir["Repository-relative deploy directory"]
  WorkingDir --> Build["Build in configured project root"]
  Build --> Action["deploy-site action"]
  DeployDir --> Action
Loading

Reviews (3): Last reviewed commit: "fix(sites): apply an explicit --link dur..." | Re-trigger Greptile

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

Copy link
Copy Markdown

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: 5fd2a7d423

ℹ️ 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 thread packages/cli/src/commands/sites/ci/init.ts Outdated
Comment thread packages/cli/src/commands/sites/ci/workflow.ts Outdated
Comment thread packages/cli/src/commands/sites/interactive.ts Outdated
Comment thread packages/cli/src/commands/sites/ci/workflow.ts Outdated
`ci init` writes the workflow at the git root, but `sites.dir` and
`sites.build` resolve against the bunny.jsonc directory. With the config
in a monorepo package, CI ran the build from the checkout root and
deployed `<repo>/dist` instead of `<repo>/packages/site/dist`.

Pass the config directory through as `projectRoot`: framework and
package-manager detection now run there, run steps get
`defaults.run.working-directory`, the action's `directory` input takes
the prefix (its inputs aren't affected by run defaults), and a lockfile
of the project's own becomes `cache-dependency-path` so setup-node still
finds one. Paths are compared through realpath, and a bunny.jsonc above
the git root can't be expressed in a repo-rooted workflow, so its paths
are dropped with a warning.
The unsafe-token regex let YAML-typed commands through: `run: true`
parses as a boolean, `run: null` as null and `run: 1.5` as a number, and
Actions rejects a `run` that isn't a string. Drop the pattern list and
emit `sites.build` as a quoted scalar unconditionally; preset commands
come from our own table and stay readable.
… preset

An unrecognized bundler falls back to the static preset, so a configured
`sites.build` of `npm run build` emitted a lone run step: the runner had
no dependencies and the workflow failed on a build that works locally.
When the project has a package.json, that branch now gets the detected
package manager's setup and install steps first.
offerLink() runs at the end of a handler, but every command returns from
its `--output json` branch before reaching it, so `--link --output json`
reported success and left `.bunny/site.json` unwritten. Link during
resolution instead, where the flag is unambiguous, and keep offerLink for
the picker's prompt. The confirmation line is suppressed under json so
the payload stays clean.
@jamie-at-bunny
jamie-at-bunny merged commit 009d9e8 into main Jul 28, 2026
3 checks passed
@jamie-at-bunny
jamie-at-bunny deleted the fix/sites-flag-consistency branch July 28, 2026 12:24
@github-actions github-actions Bot mentioned this pull request Jul 28, 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.

3 participants