From 3aff8715527b0cb6b6c78ee2941d4c91e47249e9 Mon Sep 17 00:00:00 2001 From: Azalea Date: Wed, 23 Sep 2026 01:08:20 +0000 Subject: [PATCH] [+] Publish crate to crates.io in release workflow and include README (#544) --- .github/workflows/release.yml | 53 ++++++++++++++++++++++++++++++++++- Cargo.toml | 1 + crates/hyfetch/Cargo.toml | 1 + tools/release.py | 11 ++++++++ 4 files changed, 65 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5c0fb321..b30555fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -31,6 +31,11 @@ on: required: true default: true type: boolean + publish_cargo: + description: "Publish crate to crates.io" + required: true + default: true + type: boolean permissions: contents: read @@ -49,6 +54,7 @@ jobs: version: ${{ steps.metadata.outputs.version }} python_package: ${{ steps.metadata.outputs.python_package }} npm_package: ${{ steps.metadata.outputs.npm_package }} + cargo_package: ${{ steps.metadata.outputs.cargo_package }} steps: - name: Resolve release refs id: release-refs @@ -80,6 +86,7 @@ jobs: outputs: pypi_exists: ${{ steps.state.outputs.pypi_exists }} npm_exists: ${{ steps.state.outputs.npm_exists }} + crates_exists: ${{ steps.state.outputs.crates_exists }} github_release_exists: ${{ steps.state.outputs.github_release_exists }} github_release_complete: ${{ steps.state.outputs.github_release_complete }} steps: @@ -97,6 +104,7 @@ jobs: --version "${{ needs.metadata.outputs.version }}" \ --python-package "${{ needs.metadata.outputs.python_package }}" \ --npm-package "${{ needs.metadata.outputs.npm_package }}" \ + --cargo-package "${{ needs.metadata.outputs.cargo_package }}" \ --repo "${{ github.repository }}" - name: Summarize release state @@ -108,6 +116,7 @@ jobs: echo "| --- | --- |" echo "| PyPI | ${{ steps.state.outputs.pypi_exists }} |" echo "| npm | ${{ steps.state.outputs.npm_exists }} |" + echo "| crates.io | ${{ steps.state.outputs.crates_exists }} |" echo "| GitHub Release assets | ${{ steps.state.outputs.github_release_complete }} |" } >> "$GITHUB_STEP_SUMMARY" @@ -123,6 +132,7 @@ jobs: CREATE_GITHUB_RELEASE: ${{ github.event_name != 'workflow_dispatch' || inputs.create_github_release }} PUBLISH_PYPI: ${{ github.event_name != 'workflow_dispatch' || inputs.publish_pypi }} PUBLISH_NPM: ${{ github.event_name != 'workflow_dispatch' || inputs.publish_npm }} + PUBLISH_CARGO: ${{ github.event_name != 'workflow_dispatch' || inputs.publish_cargo }} run: | pending=() skipped=() @@ -151,6 +161,14 @@ jobs: fi fi + if [[ "$PUBLISH_CARGO" == "true" ]]; then + if [[ "${{ needs.release-state.outputs.crates_exists }}" == "true" ]]; then + skipped+=("crates.io") + else + pending+=("crates.io") + fi + fi + { echo "## Preflight" echo @@ -163,7 +181,7 @@ jobs: if ((${#skipped[@]})); then printf 'Already complete: %s\n\n' "$(IFS=', '; echo "${skipped[*]}")" fi - echo "PyPI and npm publishing use trusted publishing/OIDC; no registry secrets are required." + echo "PyPI, npm, and crates.io publishing use trusted publishing/OIDC; no registry secrets are required." } >> "$GITHUB_STEP_SUMMARY" build-python-dist: @@ -374,3 +392,36 @@ jobs: - name: Publish package if: steps.npm-state.outputs.exists != 'true' run: npm publish --provenance + + publish-cargo: + name: Publish to crates.io + runs-on: ubuntu-22.04 + permissions: + contents: read + id-token: write + needs: + - metadata + - release-state + - preflight + if: >- + ${{ + always() + && needs.preflight.result == 'success' + && (github.event_name != 'workflow_dispatch' || inputs.publish_cargo) + && needs.release-state.outputs.crates_exists != 'true' + }} + steps: + - uses: actions/checkout@v6 + with: + ref: ${{ needs.metadata.outputs.source_ref }} + + - uses: dtolnay/rust-toolchain@stable + + - name: Authenticate with crates.io (Trusted Publishing / OIDC) + if: ${{ !secrets.CARGO_REGISTRY_TOKEN }} + uses: rust-lang/crates-io-auth-action@v1 + + - name: Publish crate + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN || env.CARGO_REGISTRY_TOKEN }} + run: cargo publish -p hyfetch diff --git a/Cargo.toml b/Cargo.toml index e4192d41..cb9978e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ rust-version = "1.75.0" description = "Neofetch with LGBTQ+ pride flags!" repository = "https://github.com/hykilpikonna/hyfetch" license = "MIT" +readme = "README.md" [workspace.dependencies] aho-corasick = { version = "1.1.3", default-features = false } diff --git a/crates/hyfetch/Cargo.toml b/crates/hyfetch/Cargo.toml index 8844a325..ff2e585b 100644 --- a/crates/hyfetch/Cargo.toml +++ b/crates/hyfetch/Cargo.toml @@ -7,6 +7,7 @@ rust-version = { workspace = true } description = { workspace = true } repository = { workspace = true } license = { workspace = true } +readme = { workspace = true } default-run = "hyfetch" [dependencies] diff --git a/tools/release.py b/tools/release.py index 4f95a2da..9b3bb6bc 100755 --- a/tools/release.py +++ b/tools/release.py @@ -166,6 +166,13 @@ def npm_version_exists(package: str, version: str) -> bool: return status == 200 +def crates_version_exists(package: str, version: str) -> bool: + package_path = urllib.parse.quote(package) + version_path = urllib.parse.quote(version) + status, _ = http_json_status(f"https://crates.io/api/v1/crates/{package_path}/{version_path}") + return status == 200 + + def github_release_state(repo: str, tag: str, version: str) -> Tuple[bool, bool]: repo_path = urllib.parse.quote(repo, safe="/") tag_path = urllib.parse.quote(tag, safe="") @@ -205,15 +212,18 @@ def command_metadata(args: argparse.Namespace) -> None: write_output("version", version) write_output("python_package", read_pyproject_name()) write_output("npm_package", package_json["name"]) + write_output("cargo_package", "hyfetch") def command_state(args: argparse.Namespace) -> None: pypi_exists = pypi_version_exists(args.python_package, args.version) npm_exists = npm_version_exists(args.npm_package, args.version) + crates_exists = crates_version_exists(args.cargo_package, args.version) github_release_exists, github_release_complete = github_release_state(args.repo, args.tag, args.version) write_output("pypi_exists", pypi_exists) write_output("npm_exists", npm_exists) + write_output("crates_exists", crates_exists) write_output("github_release_exists", github_release_exists) write_output("github_release_complete", github_release_complete) @@ -241,6 +251,7 @@ def build_parser() -> argparse.ArgumentParser: state.add_argument("--version", required=True) state.add_argument("--python-package", required=True) state.add_argument("--npm-package", required=True) + state.add_argument("--cargo-package", default="hyfetch") state.add_argument("--repo", required=True) state.set_defaults(func=command_state)