Skip to content

Fix publish --build in non-interactive mode when dist already has artifacts#10768

Open
SergioChan wants to merge 3 commits intopython-poetry:mainfrom
SergioChan:fix-10760-publish-no-interaction
Open

Fix publish --build in non-interactive mode when dist already has artifacts#10768
SergioChan wants to merge 3 commits intopython-poetry:mainfrom
SergioChan:fix-10760-publish-no-interaction

Conversation

@SergioChan
Copy link

@SergioChan SergioChan commented Mar 11, 2026

Pull Request Check List

Resolves: #10760

  • Added tests for changed code.
  • Updated documentation for changed code.

Summary

  • Skip the publish pre-build confirmation prompt when running in non-interactive mode.
  • Keep the existing confirmation flow unchanged for interactive runs.
  • Add a regression test to ensure publish --build --no-interaction does not call confirm and still proceeds.

Testing

  • poetry run pytest tests/console/commands/test_publish.py -k "no_interaction or dist_dir_and_build_options"

Summary by Sourcery

Skip interactive confirmation when publishing with build in non-interactive mode and add regression coverage for this behavior.

Bug Fixes:

  • Avoid blocking non-interactive publish runs with a confirmation prompt when build artifacts already exist.

Tests:

  • Add a regression test ensuring publish --build --no-interaction skips confirmation but still builds and publishes.

@sourcery-ai
Copy link

sourcery-ai bot commented Mar 11, 2026

Reviewer's Guide

Ensures poetry publish --build behaves correctly in non-interactive mode by skipping the pre-build confirmation prompt when artifacts already exist in dist, while preserving the existing confirmation behavior for interactive runs and adding a regression test to lock in the new behavior.

Sequence diagram for publish_build_flow_in_interactive_and_non_interactive_modes

sequenceDiagram
    actor User
    participant PublishCommand
    participant IO
    participant Publisher

    User->>PublishCommand: run publish --build
    PublishCommand->>Publisher: inspect files
    Publisher-->>PublishCommand: files list
    alt build_option_enabled
        PublishCommand->>PublishCommand: check publisher.files
        alt files_exist_and_interactive
            PublishCommand->>IO: is_interactive()
            IO-->>PublishCommand: true
            PublishCommand->>User: confirm(Build anyway?)
            alt user_confirms
                PublishCommand->>Publisher: build()
                Publisher-->>PublishCommand: build complete
                PublishCommand->>Publisher: publish()
                Publisher-->>PublishCommand: publish complete
            else user_aborts
                PublishCommand->>User: line_error(Aborted!)
            end
        else non_interactive_or_no_files
            PublishCommand->>IO: is_interactive()
            IO-->>PublishCommand: false or not_called
            PublishCommand->>Publisher: build()
            Publisher-->>PublishCommand: build complete
            PublishCommand->>Publisher: publish()
            Publisher-->>PublishCommand: publish complete
        end
    else build_option_disabled
        PublishCommand->>Publisher: publish()
        Publisher-->>PublishCommand: publish complete
    end
Loading

File-Level Changes

Change Details Files
Gate the pre-build confirmation dialog on the session being interactive so non-interactive runs with existing dist artifacts skip the prompt but still build and publish.
  • Wrap the existing publisher.files confirmation check in an io.is_interactive() guard.
  • Preserve the abort behavior when the user declines the confirmation in interactive sessions.
src/poetry/console/commands/publish.py
Add a regression test to verify that publish --build --no-interaction skips the confirmation prompt while still invoking the build and publish steps.
  • Patch PublishCommand.confirm, PublishCommand.call, and Publisher.publish to assert they are invoked (or not) as expected.
  • Execute publish --build --no-interaction --dry-run via ApplicationTester and assert a zero exit code.
  • Assert that confirm is never called, call('build', args='--output dist') is called exactly once, and Publisher.publish is invoked once.
tests/console/commands/test_publish.py

Assessment against linked issues

Issue Objective Addressed Explanation
#10760 Ensure poetry publish --build --no-interaction does not prompt for confirmation when artifacts already exist in dist/ and instead proceeds with the operation.
#10760 Add automated test coverage to prevent regressions where non-interactive publish with build and existing dist/ artifacts blocks on a confirmation prompt.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've found 1 issue

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="tests/console/commands/test_publish.py" line_range="220-229" />
<code_context>
     assert "- Uploading simple_project-1.2.3-py2.py3-none-any.whl" in error
+
+
+def test_publish_build_no_interaction_skips_confirmation(
+    app_tester: ApplicationTester, mocker: MockerFixture
+) -> None:
+    confirm = mocker.patch("poetry.console.commands.publish.PublishCommand.confirm")
+    command_call = mocker.patch("poetry.console.commands.publish.PublishCommand.call")
+    publisher_publish = mocker.patch("poetry.publishing.Publisher.publish")
+
+    exit_code = app_tester.execute("publish --build --no-interaction --dry-run")
+
+    assert exit_code == 0
+    confirm.assert_not_called()
+    command_call.assert_called_once_with("build", args="--output dist")
+    assert publisher_publish.call_count == 1
</code_context>
<issue_to_address>
**issue (testing):** Test does not simulate pre-existing dist artifacts, so it doesn’t cover the regression scenario described in the PR

Because `Publisher.publish` is mocked and `publisher.files` is never set, `publisher.files` remains falsy and the `if publisher.files and self.io.is_interactive()` branch is never hit. This test only proves that `--no-interaction` skips `confirm` when there are no existing artifacts. To actually cover the regression, ensure the `Publisher` used by `PublishCommand` has a non-empty `files` list (e.g. via a fixture, a real `Publisher`, or by patching the constructor and setting `.files`), so the scenario with pre-existing `dist` artifacts is exercised.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +220 to +229
def test_publish_build_no_interaction_skips_confirmation(
app_tester: ApplicationTester, mocker: MockerFixture
) -> None:
confirm = mocker.patch("poetry.console.commands.publish.PublishCommand.confirm")
command_call = mocker.patch("poetry.console.commands.publish.PublishCommand.call")
publisher_publish = mocker.patch("poetry.publishing.Publisher.publish")

exit_code = app_tester.execute("publish --build --no-interaction --dry-run")

assert exit_code == 0
Copy link

Choose a reason for hiding this comment

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

issue (testing): Test does not simulate pre-existing dist artifacts, so it doesn’t cover the regression scenario described in the PR

Because Publisher.publish is mocked and publisher.files is never set, publisher.files remains falsy and the if publisher.files and self.io.is_interactive() branch is never hit. This test only proves that --no-interaction skips confirm when there are no existing artifacts. To actually cover the regression, ensure the Publisher used by PublishCommand has a non-empty files list (e.g. via a fixture, a real Publisher, or by patching the constructor and setting .files), so the scenario with pre-existing dist artifacts is exercised.

@SergioChan
Copy link
Author

Pushed a follow-up commit to tighten the regression coverage:

  • Updated the test to explicitly force a non-empty Publisher.files via a property mock, so the scenario includes pre-existing dist artifacts.
  • Kept --no-interaction in the execution path and still assert confirm() is not called, build is called once, and publish proceeds.

Validation run:

  • poetry run pytest tests/console/commands/test_publish.py -k "test_publish_build_no_interaction_skips_confirmation"

@SergioChan
Copy link
Author

Addressed in 5673d45.

  • Updated test_publish_build_no_interaction_skips_confirmation to explicitly simulate pre-existing dist artifacts by patching Publisher.files with a non-empty list.
  • Kept the existing assertions that confirm() is not called under --no-interaction and that build/publish still run.

Validation run locally:

  • python -m py_compile tests/console/commands/test_publish.py

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.

poetry publish --no-interaction still prompts when build artifacts exist in dist/, blocking CI pipelines

1 participant