Skip to content

Backport #458 to development: fix publish crash with embedded db credentials - #467

Merged
jacalata merged 7 commits into
developmentfrom
jac/fix-publish-embed-creds
Sep 10, 2026
Merged

Backport #458 to development: fix publish crash with embedded db credentials#467
jacalata merged 7 commits into
developmentfrom
jac/fix-publish-embed-creds

Conversation

@jacalata

@jacalata jacalata commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Direct backport of #458 (Mauro Fujihara's fix, already merged to main) to the development branch. Preserves Mauro's authorship on bbfaf4c.

What this PR does

Backports Mauro's two-line fix for the publish-with-embedded-credentials crash:

  • Wraps the workbook ConnectionItem in a list on the server.workbooks.publish(..., connections=...) call (fixes TypeError: object of type 'ConnectionItem' has no len()).
  • Adds a --db-server CLI flag so users can populate ConnectionItem.server_address (fixes the downstream ValueError: Connection must have a server address).

Scope

Intentionally scoped to just #458's cherry-pick — no follow-up validation, no follow-up tests, no i18n regeneration. Those ship as separate PRs stacked on top of this one:

  • PR B (follow-up): regenerate tabcmd/locales/en/LC_MESSAGES/tabcmd.mo — needed because the cherry-pick updated .properties but the English .mo binary wasn't refreshed, so English users would see raw msgid keys.
  • PR C (follow-up): --db-server guard, e2e coverage, and review polish (helper extraction, silent-drop caveat in help text).

The four revert commits at the tip cancel out earlier follow-up work — net diff is exactly what #458 landed on main.

Test plan

🤖 Generated with Claude Code

fujihara and others added 3 commits September 8, 2026 18:01
* Require --db-server for embedded credentials/oauth workbook publishing, fix connections payload

* Translations for publish.options.db-server message

* Simplify changes

* Adjust tests
PR #458 fixed the two publish crashes when using --db-username /
--db-password / --save-db-password, but callers who omit --db-server
still hit a raw ValueError from tableauserverclient's
_add_connections_element. Fail fast in run_command with a clear,
localizable message before we build the ConnectionItem so users get
an actionable error instead of an internal stack trace.

Update the existing no-db-server test to assert the exit path and add
the parallel coverage for the --oauth-username branch.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Extend the online publish suite with:

- A positive assertion for the happy path: test_wb_publish_embedded now
  passes --db-server matching the connection host baked into
  EmbeddedCredentials.twb (see-internal-slack). Without a matching
  server_address, tableauserverclient silently drops the embedded
  credentials at publish time, so covering the match is what actually
  proves the fix.
- A negative assertion: test_wb_publish_embedded_missing_db_server_fails
  runs publish with --db-username but no --db-server and expects a
  non-zero exit. The check now fires in run_command before any network
  work, so hardcoded placeholder creds are sufficient.

Threads a db_server keyword through the _publish_creds_args helper and
records the workbook's connection host as a class constant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Coverage

Coverage Report
FileStmtsMissCoverMissing
tabcmd
   __main__.py121212 0%
   _version.py111111 0%
   tabcmd.py151515 0%
   version.py955 44%
tabcmd/commands
   commands.py101010 0%
   constants.py771818 77%
   server.py1351818 87%
tabcmd/commands/auth
   session.py3945050 87%
tabcmd/commands/datasources_and_workbooks
   datasources_and_workbooks_command.py1571818 89%
   datasources_workbooks_views_url_parser.py14255 96%
   delete_command.py601616 73%
   export_command.py1202525 79%
   get_url_command.py1274747 63%
   publish_command.py1252929 77%
   runschedule_command.py2177 67%
tabcmd/commands/extracts
   create_extracts_command.py4288 81%
   decrypt_extracts_command.py2722 93%
   delete_extracts_command.py3766 84%
   encrypt_extracts_command.py2722 93%
   extracts.py2022 90%
   reencrypt_extracts_command.py2722 93%
   refresh_extracts_command.py481010 79%
tabcmd/commands/group
   create_group_command.py2955 83%
   delete_group_command.py2722 93%
tabcmd/commands/project
   create_project_command.py4688 83%
   delete_project_command.py3544 89%
   publish_samples_command.py3044 87%
tabcmd/commands/site
   create_site_command.py3455 85%
   delete_site_command.py2722 93%
   edit_site_command.py3822 95%
   list_command.py771212 84%
   list_sites_command.py2922 93%
tabcmd/commands/user
   add_users_command.py2955 83%
   create_site_users.py581111 81%
   create_users_command.py5999 85%
   delete_site_users_command.py4355 88%
   user_data.py2223131 86%
tabcmd/execution
   _version.py222 0%
   global_options.py12688 94%
   localize.py661111 83%
   logger_config.py6066 90%
   tabcmd_controller.py4277 83%
TOTAL287645984% 

jacalata and others added 4 commits September 8, 2026 22:24
Scope the guard to workbook publishes only. Datasource publishes go
through _add_credentials_element on the TSC side, which never requires
server_address, so the previous unconditional check was a regression
for `tabcmd publish live_mysql.tds --db-username ...` and similar.
The guard now checks the target filename extension early (before auth,
for fast failure) and repeats per-file inside the workbook branch of
the loop for the folder-publish case.

Rename the `credentials` parameter of `publish_workbook_file` to
`connection` — it holds a single ConnectionItem, not a list.

Tests:
- Add test_publish_with_oauth_creds covering the oauth branch's
  server_address assignment (previously untested).
- Add test_publish_datasource_with_db_username_no_db_server verifying
  datasource publishes are not blocked when --db-server is omitted.
- Strengthen the e2e negative test to run tabcmd via subprocess.run,
  capture stdout/stderr, and assert on the localized guard message
  (or the raw key when .mo has not been regenerated). Any earlier
  unrelated failure — bad auth, missing asset, session expiry — now
  fails the test rather than passing it.
- Trim the misleading class-constant comment on TWB_FILE_EMBEDDED_
  CONNECTION_SERVER; reword the "before we touch the database" comment
  to reference the guard's contract instead of a specific location.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 10, 2026 20:07
@jacalata jacalata changed the title Fix tabcmd publish crash with embedded db credentials (backport #458 + follow-up) Backport #458 to development: fix publish crash with embedded db credentials Sep 10, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The publish path still allows --db-username/--oauth-username with no --db-server (risking the original runtime failure) and the new locale keys appear not to be propagated into the checked-in .mo catalogs.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the publish command to better support publishing workbooks with embedded database credentials by adding a --db-server CLI option and passing workbook connection credentials in the shape expected by tableauserverclient.

Changes:

  • Add --db-server publish CLI argument and wire it into the workbook ConnectionItem.server_address.
  • Fix workbook publish call to pass connections as a list ([ConnectionItem]) instead of a single ConnectionItem.
  • Add/adjust unit tests and add localized help text for the new option across supported locales.
File summaries
File Description
tabcmd/commands/datasources_and_workbooks/publish_command.py Sets server_address from --db-server and wraps publish connections in a list.
tabcmd/execution/global_options.py Adds the --db-server argument to the publish command parser.
tests/commands/test_publish_command.py Extends publish credential tests to assert connections list handling and server_address propagation.
tabcmd/locales/en/tabcmd_messages_en.properties Adds help text for publish.options.db-server.
tabcmd/locales/de/tabcmd_messages_de.properties Adds help text for publish.options.db-server.
tabcmd/locales/es/tabcmd_messages_es.properties Adds help text for publish.options.db-server.
tabcmd/locales/fr/tabcmd_messages_fr.properties Adds help text for publish.options.db-server.
tabcmd/locales/ga/tabcmd_messages_ga.properties Adds help text for publish.options.db-server.
tabcmd/locales/it/tabcmd_messages_it.properties Adds help text for publish.options.db-server.
tabcmd/locales/ja/tabcmd_messages_ja.properties Adds help text for publish.options.db-server.
tabcmd/locales/ko/tabcmd_messages_ko.properties Adds help text for publish.options.db-server.
tabcmd/locales/pt/tabcmd_messages_pt.properties Adds help text for publish.options.db-server (with a Portuguese grammar fix suggested in review).
tabcmd/locales/sv/tabcmd_messages_sv.properties Adds help text for publish.options.db-server.
tabcmd/locales/zh/tabcmd_messages_zh.properties Adds help text for publish.options.db-server.
Review details
  • Files reviewed: 14/24 changed files
  • Comments generated: 4
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines 69 to 73
if args.db_username:
creds = TSC.models.ConnectionCredentials(args.db_username, args.db_password, embed=args.save_db_password)
workbook_connections = TSC.ConnectionItem()
workbook_connections.server_address = args.db_server
workbook_connections.connection_credentials = creds
Comment on lines +89 to +93
mock_args.db_username = "username"
mock_args.db_password = "oauth_u"
mock_args.db_server = None
mock_args.save_db_password = True
mock_args.oauth_username = None
publish.errors.server_resource_not_found=The resource you specified does not exist, or you do not have permission to see it. Check your project name and permissions
publish.options.append=Append extract file to existing data source
publish.options.db-password=Database password for all data sources
publish.options.db-server=Server address of the database to associate with the embedded connection credentials. Required when using --db-username or --oauth-username to publish a workbook.
publish.errors.server_resource_not_found=O recurso especificado não existe ou você não tem permissão para vê-lo. Verifique o nome e as permissões do projeto
publish.options.append=Anexe o arquivo de extração à fonte de dados existente
publish.options.db-password=Senha do banco de dados para todas as fontes de dados
publish.options.db-server=Endereço do servidor do banco de dado associado as credenciais. Obrigatório ao usar --db-username ou --oauth-username.
@jacalata

Copy link
Copy Markdown
Contributor Author

Note on the Copilot review above (2026-09-10 20:12 UTC):

This PR has been intentionally rescoped to a pure cherry-pick of #458 to unblock the crash fix, and the four Copilot findings all land in stacked follow-up PRs:

Stack: development#467 (this PR, backport) ← #469 (.mo regen) ← #470 (guard + tests + review polish).

@jacalata
jacalata merged commit f399979 into development Sep 10, 2026
23 checks passed
@jacalata
jacalata deleted the jac/fix-publish-embed-creds branch September 10, 2026 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants