diff --git a/Cargo.lock b/Cargo.lock index 608d18cf..b4caaeb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -755,7 +755,7 @@ checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fbuild-build" -version = "2.1.20" +version = "2.1.21" dependencies = [ "async-trait", "fbuild-config", @@ -775,7 +775,7 @@ dependencies = [ [[package]] name = "fbuild-cli" -version = "2.1.20" +version = "2.1.21" dependencies = [ "blake3", "clap", @@ -798,7 +798,7 @@ dependencies = [ [[package]] name = "fbuild-config" -version = "2.1.20" +version = "2.1.21" dependencies = [ "fbuild-core", "include_dir", @@ -812,7 +812,7 @@ dependencies = [ [[package]] name = "fbuild-core" -version = "2.1.20" +version = "2.1.21" dependencies = [ "libc", "running-process-core", @@ -827,7 +827,7 @@ dependencies = [ [[package]] name = "fbuild-daemon" -version = "2.1.20" +version = "2.1.21" dependencies = [ "async-trait", "axum", @@ -864,7 +864,7 @@ dependencies = [ [[package]] name = "fbuild-deploy" -version = "2.1.20" +version = "2.1.21" dependencies = [ "async-trait", "espflash", @@ -886,7 +886,7 @@ dependencies = [ [[package]] name = "fbuild-packages" -version = "2.1.20" +version = "2.1.21" dependencies = [ "axum", "bzip2", @@ -913,14 +913,14 @@ dependencies = [ [[package]] name = "fbuild-paths" -version = "2.1.20" +version = "2.1.21" dependencies = [ "fbuild-core", ] [[package]] name = "fbuild-python" -version = "2.1.20" +version = "2.1.21" dependencies = [ "base64", "fbuild-core", @@ -940,7 +940,7 @@ dependencies = [ [[package]] name = "fbuild-serial" -version = "2.1.20" +version = "2.1.21" dependencies = [ "async-trait", "base64", @@ -962,7 +962,7 @@ dependencies = [ [[package]] name = "fbuild-test-support" -version = "2.1.20" +version = "2.1.21" dependencies = [ "tempfile", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 67ab025b..016fd846 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ members = [ ] [workspace.package] -version = "2.1.20" +version = "2.1.21" edition = "2021" rust-version = "1.75" license = "MIT OR Apache-2.0" diff --git a/ci/publish.py b/ci/publish.py index 56d76ecc..6332fb99 100644 --- a/ci/publish.py +++ b/ci/publish.py @@ -84,16 +84,23 @@ def run_capture(cmd: list[str]) -> str: return result.stdout.strip() -def read_project_meta() -> tuple[str, str, str, str]: - """Return (name, version, summary, requires_python) from pyproject.toml.""" +def read_project_meta() -> tuple[str, str, str, str, str]: + """Return (name, version, summary, requires_python, readme) from pyproject.toml.""" with open(ROOT / "pyproject.toml", "rb") as f: data = tomllib.load(f) proj = data["project"] + readme = "" + readme_field = proj.get("readme") + if readme_field: + readme_path = ROOT / (readme_field if isinstance(readme_field, str) else readme_field.get("file", "")) + if readme_path.exists(): + readme = readme_path.read_text(encoding="utf-8") return ( proj["name"], proj["version"], proj.get("description", ""), proj.get("requires-python", ">=3.10"), + readme, ) @@ -377,6 +384,7 @@ def build_wheel( version: str, summary: str, requires_python: str, + readme: str, platform_subdir: str, plat_tags: list[str], ) -> Path | None: @@ -417,6 +425,10 @@ def build_wheel( f"Summary: {summary}\n" f"Requires-Python: {requires_python}\n" ) + if readme: + # Per PEP 566: blank line separates headers from the description body, + # and Description-Content-Type declares the rendering format PyPI uses. + metadata += f"Description-Content-Type: text/markdown\n\n{readme}\n" wheel_meta = ( f"Wheel-Version: 1.0\n" @@ -426,8 +438,16 @@ def build_wheel( for pt in plat_tags: wheel_meta += f"Tag: {tag_prefix}-{pt}\n" + # S_IFREG is required — pip's wheel installer calls S_ISREG() on the + # upper 16 bits of external_attr and falls back to the umask default + # (0o644) if the file-type bit is missing, regardless of the mode + # bits set. That's how 2.1.20 shipped with mode=0o755 but still + # `/bin/fbuild: Permission denied` on every Linux/macOS install. + # Reference: uv/ruff wheels have external_attr 0x81ed0000 + # (S_IFREG | 0o755); 2.1.20 had 0x01ed0000. exec_perms = ( - stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR + stat.S_IFREG + | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH ) @@ -493,7 +513,7 @@ def add_file(whl: zipfile.ZipFile, arcname: str, data: bytes, executable: bool = return wheel_path -def build_all_wheels(name: str, version: str, summary: str, requires_python: str) -> list[Path]: +def build_all_wheels(name: str, version: str, summary: str, requires_python: str, readme: str) -> list[Path]: log(f"\n=== Step 4: Build wheels ({name} {version}) ===") if WHEEL_DIR.exists(): @@ -502,7 +522,7 @@ def build_all_wheels(name: str, version: str, summary: str, requires_python: str wheels: list[Path] = [] missing: list[str] = [] for subdir, plat_tags in PLATFORMS.items(): - whl = build_wheel(name, version, summary, requires_python, subdir, plat_tags) + whl = build_wheel(name, version, summary, requires_python, readme, subdir, plat_tags) if whl: wheels.append(whl) else: @@ -615,7 +635,7 @@ def main() -> None: ) args = parser.parse_args() - name, version, summary, requires_python = read_project_meta() + name, version, summary, requires_python, readme = read_project_meta() if args.upload_only: log(f"Publishing {name} {version} (upload-only, reusing dist/wheels/)") @@ -655,7 +675,7 @@ def main() -> None: download_artifacts(repo, run_id) # Step 4: Build platform wheels - wheels = build_all_wheels(name, version, summary, requires_python) + wheels = build_all_wheels(name, version, summary, requires_python, readme) # Step 5: Upload if args.dry_run: diff --git a/pyproject.toml b/pyproject.toml index 7b4e5b10..d55e98ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,9 +1,10 @@ [project] name = "fbuild" -version = "2.1.20" +version = "2.1.21" description = "PlatformIO-compatible embedded build tool (Rust implementation)" +readme = "README.md" requires-python = ">=3.10" -dependencies = ["zccache>=1.2.12"] +dependencies = ["zccache>=1.2.13"] [dependency-groups] dev = ["fbuild-dev-tools"] diff --git a/uv.lock b/uv.lock index 60019d17..53ac3336 100644 --- a/uv.lock +++ b/uv.lock @@ -4,7 +4,7 @@ requires-python = ">=3.10" [[package]] name = "fbuild" -version = "2.1.20" +version = "2.1.21" source = { editable = "." } dependencies = [ { name = "zccache" }, @@ -16,7 +16,7 @@ dev = [ ] [package.metadata] -requires-dist = [{ name = "zccache", specifier = ">=1.2.12" }] +requires-dist = [{ name = "zccache", specifier = ">=1.2.13" }] [package.metadata.requires-dev] dev = [{ name = "fbuild-dev-tools", editable = "ci/dev-tools" }] @@ -47,13 +47,13 @@ wheels = [ [[package]] name = "zccache" -version = "1.2.12" +version = "1.2.13" source = { registry = "https://pypi.org/simple" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/c7/a0e100342f30a928d027156046b3d510806b00abd70d3a780080fa18b753/zccache-1.2.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b26ca9fbd8c4ccd36023b657f9af699c5cbf5a805af7164cec5ed8b276e5e989", size = 11488714, upload-time = "2026-04-18T20:22:06.087Z" }, - { url = "https://files.pythonhosted.org/packages/b9/1a/860600f40f771244bd8bbecced9d6e356cb34cf6e0ce46aa580ab7bf1f9d/zccache-1.2.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:89d475e4ee11a0195b64da57c53f4b06376003da5d347891a12bfb363ad94269", size = 10978827, upload-time = "2026-04-18T20:22:34.72Z" }, - { url = "https://files.pythonhosted.org/packages/30/e2/d906f9184cfd403f6402826484cb4277af4a125a296f75c8abb3d1ffacef/zccache-1.2.12-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:e7096a9716764e094c09510445a25e3ce105341ed6c498aa203622fa53eec939", size = 10941646, upload-time = "2026-04-18T20:22:57.647Z" }, - { url = "https://files.pythonhosted.org/packages/04/7b/e3548c4b55296f6f08f35f3bddb1cf67ccb048cb354e7f411e6f23810333/zccache-1.2.12-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:0ebacaeb0ad3080ac81a02b00267b6d6f178ca8e6ab83f0d73a424a0e6323045", size = 11886978, upload-time = "2026-04-18T20:23:24.411Z" }, - { url = "https://files.pythonhosted.org/packages/0e/a9/c11a2f64f847d457536fc94c825dabae4a476b011c49086b53b398d70ae6/zccache-1.2.12-py3-none-win_amd64.whl", hash = "sha256:ada4bfd47c56f65aff5ce5db9e210f093bf90381705d1043ab1ad0ea5ff9d34d", size = 10714093, upload-time = "2026-04-18T20:23:46.504Z" }, - { url = "https://files.pythonhosted.org/packages/99/23/702306c7e5d8a55fc443acab81475f9469186527be577d51d9b2277b6197/zccache-1.2.12-py3-none-win_arm64.whl", hash = "sha256:d368addaa5b5bbd102406838e86b6621ec2a9451e653e1b64078a83b454e42f3", size = 9955945, upload-time = "2026-04-18T20:24:09.38Z" }, + { url = "https://files.pythonhosted.org/packages/87/73/4080b898921a865faff716717e1a198846c0ff256f38cbea54b28ea81fbb/zccache-1.2.13-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:25c01b6259118c226d7d9adb8fe854eca74e47d622023685553eb5d16afe69a9", size = 11488674, upload-time = "2026-04-19T09:12:46.718Z" }, + { url = "https://files.pythonhosted.org/packages/0c/3c/4d5f45dabb676bcfdc1f38945675ea8ce06ca47b057cdd755112cf393f5a/zccache-1.2.13-py3-none-macosx_11_0_arm64.whl", hash = "sha256:ca4b87d9110e23848a074a02887a3427868936915c387e9b9ffc7b39aaa38b30", size = 10981829, upload-time = "2026-04-19T09:13:03.894Z" }, + { url = "https://files.pythonhosted.org/packages/ea/1e/f4a222a3addc2227abc067459ad0128a5aaf0179c8d460c8872476bfe1f0/zccache-1.2.13-py3-none-manylinux_2_17_aarch64.whl", hash = "sha256:1cfc01e890ced64349a10ca7fa1973750fdadc6aad027c2a9eab1d5803b08f45", size = 10942113, upload-time = "2026-04-19T09:13:21.216Z" }, + { url = "https://files.pythonhosted.org/packages/f1/74/485a8c67a7a86fa4e7b1032266d761427d4d97de6a70da2e9cb6d4025e3e/zccache-1.2.13-py3-none-manylinux_2_17_x86_64.whl", hash = "sha256:9bdf895a0c24933adb28c57ef99948083d05adbf7220a5f643e4be7c504171c8", size = 11887723, upload-time = "2026-04-19T09:13:39.91Z" }, + { url = "https://files.pythonhosted.org/packages/ac/dc/7f8c8ced3eba832990bef18489bc5b419a4b3e5f1fe14727a5c123d6b9cb/zccache-1.2.13-py3-none-win_amd64.whl", hash = "sha256:7ed67d6bdf92b1e6f142aaf987c72f751824c8fcf9c18fd0401479f46d7ebca1", size = 10713286, upload-time = "2026-04-19T09:14:01.432Z" }, + { url = "https://files.pythonhosted.org/packages/6c/a3/95ebc437fbf581cee66484ccf455f2c0bf5729e264b800646ed1a06ec87c/zccache-1.2.13-py3-none-win_arm64.whl", hash = "sha256:117cd479adaa1c1aeca197fee7d86d9e59845807a82c03e3141bfd23815257cb", size = 9956694, upload-time = "2026-04-19T09:14:17.552Z" }, ]