Skip to content

fix(python-sdk): Use README.md as single source of truth, fix CI compile#697

Merged
leggetter merged 1 commit into
mainfrom
fix/python-sdk-readme-single-source
Feb 11, 2026
Merged

fix(python-sdk): Use README.md as single source of truth, fix CI compile#697
leggetter merged 1 commit into
mainfrom
fix/python-sdk-readme-single-source

Conversation

@leggetter

Copy link
Copy Markdown
Collaborator

Summary

Speakeasy's Python generator sets readme = "README-PYPI.md" in pyproject.toml but does not generate that file, so poetry build and poetry install fail in CI.

This change makes README.md the single source of truth for the SDK in the repo and at build/test time; README-PYPI.md is only used ephemerally at publish time for PyPI (absolute links).

Changes

  • pyproject.toml: readme = "README.md" (so build/test work after generation).
  • patch_pyproject_readme.py: New script that replaces readme = "README-PYPI.md" with readme = "README.md" in pyproject.toml after generation. Idempotent; run before compile in CI.
  • .speakeasy/workflow.yaml: compileCommand for outpost-python set to python scripts/patch_pyproject_readme.py && poetry build so the patch runs before the default compile step during SDK generation.
  • publish.sh: For PyPI only: run prepare_readme.py (creates README-PYPI.md), temporarily point pyproject.toml at README-PYPI.md via sed, run poetry publish --build --skip-existing, then remove backup. PyPI still gets link-rewritten description.
  • README-PYPI.md: Removed from repo (generated only at publish).
  • .gitignore: Ignore README-PYPI.md.

Testing

  • Generation workflow will run compile (and tests) with the overridden compileCommand; patch runs first so poetry build sees README.md.
  • Publish workflow unchanged; publish.sh builds with README-PYPI.md only for the publish artifact.

Made with Cursor

- Speakeasy generates readme = "README-PYPI.md" in pyproject.toml but does
  not emit that file, causing poetry build/install to fail in CI.
- Use README.md as the only readme in repo; add patch_pyproject_readme.py
  to fix pyproject after generation (run via compileCommand in workflow).
- Publish: prepare_readme.py + temporary pyproject switch to README-PYPI.md
  only at publish time for PyPI absolute links; remove README-PYPI.md from
  repo and ignore in .gitignore.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings February 11, 2026 18:40
@vercel

vercel Bot commented Feb 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
outpost-docs Ready Ready Preview, Comment Feb 11, 2026 6:40pm
outpost-website Ready Ready Preview, Comment Feb 11, 2026 6:40pm

Request Review

@vercel
vercel Bot temporarily deployed to Preview – outpost-docs February 11, 2026 18:40 Inactive
@vercel
vercel Bot temporarily deployed to Preview – outpost-website February 11, 2026 18:40 Inactive
@leggetter
leggetter merged commit e3d146d into main Feb 11, 2026
8 checks passed
@leggetter
leggetter deleted the fix/python-sdk-readme-single-source branch February 11, 2026 18:42

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.

Pull request overview

Updates the generated Outpost Python SDK packaging workflow so poetry build/install succeeds in CI by making README.md the default package README, while still allowing a link-rewritten README to be used only for PyPI publishing.

Changes:

  • Switch pyproject.toml to use README.md and remove committed README-PYPI.md (now generated only at publish time).
  • Add a post-generation patch script and wire it into Speakeasy’s compileCommand before poetry build.
  • Update publish script to generate README-PYPI.md and temporarily point pyproject.toml at it for the publish build.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
sdks/outpost-python/pyproject.toml Uses README.md as the package readme to prevent build failures when README-PYPI.md is absent.
sdks/outpost-python/scripts/patch_pyproject_readme.py New helper to patch Speakeasy-generated pyproject.toml back to README.md before compile/build.
.speakeasy/workflow.yaml Overrides Python target compile command to run the patch before poetry build.
sdks/outpost-python/scripts/publish.sh Generates README-PYPI.md and switches pyproject.toml to use it for publishing.
sdks/outpost-python/README-PYPI.md Removes the file from the repo (generated only at publish time).
sdks/outpost-python/.gitignore Ignores the generated README-PYPI.md.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

pyrightconfig.json
# README-PYPI.md is committed as a temporary workaround for Speakeasy compile; overwritten by scripts/prepare_readme.py at publish.
README-PYPI.md
.DS_Store

Copilot AI Feb 11, 2026

Copy link

Choose a reason for hiding this comment

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

.gitignore contains a duplicate .DS_Store entry. Removing the duplicate reduces noise and makes the ignore list easier to maintain.

Suggested change
.DS_Store

Copilot uses AI. Check for mistakes.
Comment on lines 6 to +10
poetry run python scripts/prepare_readme.py

# Point pyproject at the link-rewritten readme for the publish build
sed -i.bak 's/readme = "README.md"/readme = "README-PYPI.md"/' pyproject.toml
poetry publish --build --skip-existing
rm -f pyproject.toml.bak

Copilot AI Feb 11, 2026

Copy link

Choose a reason for hiding this comment

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

publish.sh edits pyproject.toml to point at README-PYPI.md but never restores it back to README.md. After a local publish (or a failed publish), the working tree will be left in a state where normal builds/tests may fail unless README-PYPI.md is present. Consider restoring pyproject.toml from the backup on exit (e.g., via a trap) and/or explicitly switching it back to README.md after poetry publish completes.

Copilot uses AI. Check for mistakes.
poetry run python scripts/prepare_readme.py

# Point pyproject at the link-rewritten readme for the publish build
sed -i.bak 's/readme = "README.md"/readme = "README-PYPI.md"/' pyproject.toml

Copilot AI Feb 11, 2026

Copy link

Choose a reason for hiding this comment

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

The sed replacement assumes the pyproject line is exactly readme = "README.md". If the generated/edited TOML uses different whitespace/quotes or already has README-PYPI.md, this command will silently do nothing and the publish build may use the wrong README. Consider making this replacement resilient (match the readme key regardless of current value/spacing) and fail fast if no change was applied.

Suggested change
sed -i.bak 's/readme = "README.md"/readme = "README-PYPI.md"/' pyproject.toml
sed -i.bak -E 's/^[[:space:]]*readme[[:space:]]*=[[:space:]]*".*"/readme = "README-PYPI.md"/' pyproject.toml
if cmp -s pyproject.toml pyproject.toml.bak; then
echo "Error: failed to update readme in pyproject.toml" >&2
exit 1
fi

Copilot uses AI. Check for mistakes.
#!/usr/bin/env bash
# README.md is the source of truth. For PyPI we need absolute links, so we
# generate README-PYPI.md and point pyproject at it only for this build.
export POETRY_PYPI_TOKEN_PYPI=${PYPI_TOKEN}

Copilot AI Feb 11, 2026

Copy link

Choose a reason for hiding this comment

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

export POETRY_PYPI_TOKEN_PYPI=${PYPI_TOKEN} is unquoted and does not guard against an unset token. If PYPI_TOKEN is empty/unset, the script will attempt to publish without credentials (and may be confusing to debug). Consider using a safer pattern that errors when the token is missing and preserves any special characters in the token value.

Suggested change
export POETRY_PYPI_TOKEN_PYPI=${PYPI_TOKEN}
: "${PYPI_TOKEN:?PYPI_TOKEN environment variable must be set}"
export POETRY_PYPI_TOKEN_PYPI="${PYPI_TOKEN}"

Copilot uses AI. Check for mistakes.
Comment on lines +11 to +13
PYPROJECT = "pyproject.toml"
OLD = 'readme = "README-PYPI.md"'
NEW = 'readme = "README.md"'

Copilot AI Feb 11, 2026

Copy link

Choose a reason for hiding this comment

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

This script patches pyproject.toml using an exact string match (OLD = 'readme = "README-PYPI.md"'). If Speakeasy changes whitespace/quoting or uses the table form for readme, the patch will fail CI. Consider matching the readme key more flexibly (e.g., regex on the assignment) so the patch is resilient to generator formatting changes.

Copilot uses AI. Check for mistakes.
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