Skip to content

deploy manifest/deploy bundle always resolve a default title, triggering an unwanted PATCH of the content title (breaks trusted publishing) #835

Description

@tdstein

deploy manifest and deploy bundle pre-resolve the title before constructing RSConnectExecutor:

  • main.py:1901: title = title or default_title_from_manifest(file)
  • main.py:1997: title = title or default_title_from_bundle(file)

Because the executor computes title_is_default = not title, these commands always hand deploy() a non-empty title with title_is_default=False. RSConnectClient.deploy then hits api.py:1145:

if app["title"] != app_title and not title_is_default:
    result = self.content_update(app_guid, {"title": app_title})  # PATCH v1/content/{guid}

So every redeploy to an existing --app-id where the derived default differs from the content's real title issues a PATCH /v1/content/{guid}. The derived default is usually junk: for a manifest with no metadata.entrypoint (e.g. anything from R's rsconnect::writeManifest()), _default_title_from_manifest falls back to dirname(manifest_file) — deploying manifest.json by relative path yields the cwd's basename (in our case, the title "inst").

Consequences:

  1. Trusted publishing is broken for manifest deploys. Connect machine identities are only permitted on the content-get/bundle/deploy/task endpoints; PATCH /v1/content/:guid is rejected with You don't have permission to perform this operation, failing the whole deploy at the "Deploying bundle" step. Since R content can only be deployed via manifest, every R + trusted-publishing deploy (e.g. through posit-dev/connect-actions) fails.
  2. With an API key, content is silently renamed to the derived default (our app would have been renamed to "inst").

Repro: create content on Connect with a title, then rsconnect deploy manifest --app-id <guid> manifest.json — observe the PATCH (403 under a trusted-publishing key; silent rename under an API key).

Suggested fix: don't pre-resolve the title in the command functions. Pass the user's --title (possibly None) into the executor so title_is_default stays accurate, and use the manifest/bundle-derived default only where a title is actually needed (content creation). Other deploy subcommands already behave this way, which is why source deploys work under trusted publishing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions