Skip to content

Commit 8528b6e

Browse files
committed
feat: add crates.io publish workflow and complete publishing metadata
Bring the Rust client into compliance with the new "## Publishing" section of client_requirements.md (orchestration PR #7): - Add manually triggered (workflow_dispatch) `.github/workflows/rust-publish.yml` that publishes the crate to crates.io. It gates on fmt/clippy/build, runs a `cargo publish --dry-run` packaging check, then `cargo publish`. The registry token is read only from the CARGO_REGISTRY_TOKEN repository secret, with an early-fail guard; a `dry_run` input allows packaging-only runs. - Cargo.toml: add the strongly recommended `homepage` field so the crates.io listing carries complete publishing metadata. Also addresses documentation compliance items surfaced by review-client: - Add the required "experimental, AI-generated and AI-maintained" disclaimer to the crate rustdoc (src/lib.rs), README.md and docs/README.md, and reword the "official" wording (including the crates.io Cargo.toml `description`) to match. - Document `ApifyClientError::as_api_error` in the docs/README.md error-handling section with a runnable snippet. - Remove dangling reference-style Markdown link brackets around `apify_client::models` and `futures_util::StreamExt`. Bump version 0.2.1 -> 0.2.2 (non-breaking; packaging/CI/docs only) and add the CHANGELOG entry. All integration tests, 7 example smoke tests and 22 doctests pass; cargo fmt/clippy clean; cargo publish --dry-run packages cleanly.
1 parent 3cc4e81 commit 8528b6e

7 files changed

Lines changed: 138 additions & 6 deletions

File tree

.github/workflows/rust-publish.yml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
name: Publish Rust client to crates.io
2+
3+
# Language-specific publish workflow for the Rust client. It is triggered manually only
4+
# (workflow_dispatch) so a maintainer deliberately decides when a release is cut. Publishing
5+
# to the crates.io registry is the language-specific distribution standard for Rust.
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
dry_run:
10+
description: 'Run `cargo publish --dry-run` only (no actual release).'
11+
type: boolean
12+
default: false
13+
14+
# Never allow two publish runs to race; a half-finished publish to a registry is hard to undo.
15+
concurrency:
16+
group: rust-publish
17+
cancel-in-progress: false
18+
19+
jobs:
20+
publish:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
26+
- name: Install Rust toolchain
27+
uses: dtolnay/rust-toolchain@stable
28+
with:
29+
components: rustfmt, clippy
30+
31+
- name: Cache cargo registry and build
32+
uses: actions/cache@v4
33+
with:
34+
path: |
35+
~/.cargo/registry
36+
~/.cargo/git
37+
target
38+
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }}
39+
40+
# Gate the release on the same quality bar as CI so a broken build can never be published.
41+
- name: Check formatting
42+
run: cargo fmt --all -- --check
43+
44+
- name: Clippy (deny warnings)
45+
run: cargo clippy --all-targets -- -D warnings
46+
47+
- name: Build
48+
run: cargo build --verbose
49+
50+
# Fail early with a clear message if the registry token is not configured, instead of
51+
# letting `cargo publish` fail later with a less obvious authentication error.
52+
- name: Require CARGO_REGISTRY_TOKEN secret
53+
env:
54+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
55+
run: |
56+
if [ -z "${CARGO_REGISTRY_TOKEN}" ]; then
57+
echo "::error::CARGO_REGISTRY_TOKEN secret is empty or missing; cannot publish to crates.io."
58+
exit 1
59+
fi
60+
61+
# Always verify packaging works (this also runs as part of `cargo publish`, but doing it
62+
# explicitly surfaces packaging problems before any registry interaction).
63+
- name: Verify package (dry run)
64+
env:
65+
# The crates.io registry token is stored as a repository secret.
66+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
67+
run: cargo publish --dry-run --verbose
68+
69+
- name: Publish to crates.io
70+
# Skip the actual publish when the run was dispatched as a dry run.
71+
if: ${{ github.event.inputs.dry_run != 'true' }}
72+
env:
73+
# The crates.io registry token is stored as a repository secret.
74+
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
75+
run: cargo publish --verbose

CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@ All notable changes to the Rust Apify API client are documented here. The format
44
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres
55
to [Semantic Versioning](https://semver.org/).
66

7+
## [0.2.2] - 2026-06-22
8+
9+
Publishing compliance for the updated client requirements (apify-client-orchestration PR #7).
10+
No changes to the public interface; packaging metadata and a release workflow only.
11+
12+
### Added
13+
- CI: a manually triggered (`workflow_dispatch`) `Publish Rust client to crates.io` workflow
14+
(`.github/workflows/rust-publish.yml`) that publishes the crate to crates.io — the
15+
language-specific distribution standard for Rust. It runs the format/clippy/build quality gate,
16+
performs a `cargo publish --dry-run` packaging check, then `cargo publish`. The registry token
17+
is read exclusively from the `CARGO_REGISTRY_TOKEN` repository secret, and the run fails early
18+
with a clear message if that secret is missing. A `dry_run` input allows a packaging-only run
19+
with no actual release.
20+
21+
### Changed
22+
- Packaging: added the strongly recommended `homepage` field (`https://apify.com`) to
23+
`Cargo.toml` so the crates.io listing carries complete publishing metadata.
24+
- Documentation: added the required "experimental, AI-generated and AI-maintained" disclaimer to
25+
the crate-level rustdoc (`src/lib.rs`), `README.md` and `docs/README.md`, and softened the
26+
"official" wording accordingly. The crates.io package `description` in `Cargo.toml` was likewise
27+
reworded to "An experimental, AI-generated and AI-maintained Rust client …" so the published
28+
one-line summary matches the disclaimer.
29+
- Documentation: documented `ApifyClientError::as_api_error` (used in the README error-handling
30+
example) in the `docs/README.md` error-handling section, with a runnable snippet.
31+
- Documentation: removed dangling reference-style Markdown link brackets around
32+
`apify_client::models` (`docs/README.md`) and `futures_util::StreamExt` (`docs/misc.md`) so
33+
they render as plain inline code rather than broken links on GitHub.
34+
735
## [0.2.1] - 2026-06-19
836

937
Compliance fix for the updated client/test requirements (apify-client-orchestration PR #4).

Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
[package]
22
name = "apify-client"
3-
version = "0.2.1"
3+
version = "0.2.2"
44
authors = ["Apify Technologies <support@apify.com>"]
5-
description = "The official Rust client for the Apify API (https://apify.com)."
5+
description = "An experimental, AI-generated and AI-maintained Rust client for the Apify API (https://apify.com)."
66
license = "Apache-2.0"
77
edition = "2021"
88
repository = "https://github.com/apify/apify-client-rust"
9+
homepage = "https://apify.com"
910
documentation = "https://docs.rs/apify-client"
1011
readme = "README.md"
1112
keywords = ["apify", "api", "client", "scraping", "automation"]

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Apify API client for Rust
22

3-
The official, idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
3+
> **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
4+
> generated and maintained by AI, and is not (yet) an officially supported Apify product. Review
5+
> the code before relying on it in production and report issues on the repository.
6+
7+
An idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
48
It provides a resource-oriented, async interface that mirrors the official
59
[JavaScript](https://github.com/apify/apify-client-js) and
610
[Python](https://github.com/apify/apify-client-python) clients.

docs/README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Apify Rust client — documentation
22

3+
> **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
4+
> generated and maintained by AI, and is not (yet) an officially supported Apify product. Review
5+
> the code before relying on it in production and report issues on the repository.
6+
37
This directory documents the public API of the Apify Rust client. The same descriptions
48
are available as rustdoc comments and can be browsed with `cargo doc --open`.
59

@@ -66,7 +70,7 @@ way to import them.
6670

6771
API resource/response **models** (`Actor`, `ActorRun`, `Build`, `Dataset`, `KeyValueStore`,
6872
`RequestQueue`, `RequestQueueRequest`, `RequestQueueHead`, `RequestQueueOperationInfo`,
69-
`KeyValueStoreKeysPage`, `ActorStoreListItem`, `User`, …) live in the [`apify_client::models`]
73+
`KeyValueStoreKeysPage`, `ActorStoreListItem`, `User`, …) live in the `apify_client::models`
7074
module and are imported from there:
7175

7276
```rust,no_run
@@ -117,6 +121,22 @@ Every fallible method returns `Result<T, ApifyClientError>`. The variants are:
117121

118122
`get`/`delete` map a missing resource to `Ok(None)` / a no-op.
119123

124+
To inspect the API-level details of an error without matching every variant, use
125+
`ApifyClientError::as_api_error`, which returns `Some(&ApiError)` for the `Api` variant and
126+
`None` for any other (transport, timeout, serde, …):
127+
128+
```rust,no_run
129+
# use apify_client::ApifyClient;
130+
# async fn run() {
131+
# let client = ApifyClient::new("t");
132+
if let Err(err) = client.actor("nonexistent~actor").get().await {
133+
if let Some(api) = err.as_api_error() {
134+
eprintln!("API error {}: {}", api.status_code, api.message);
135+
}
136+
}
137+
# }
138+
```
139+
120140
## Examples
121141

122142
Each example in [`../examples`](../examples) is runnable with

docs/misc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Also reachable via `run.log()` and `build.log()`.
112112
| `get()` || `Option<String>` | The entire log as text. |
113113
| `stream()` || `Stream<Item = Result<Vec<u8>>>` | Streams log chunks live (log redirection). |
114114

115-
Consuming `stream()` requires the [`futures_util::StreamExt`] trait (from the `futures-util`
115+
Consuming `stream()` requires the `futures_util::StreamExt` trait (from the `futures-util`
116116
crate) in scope to call `.next()` on the returned stream. Add it to your `Cargo.toml`:
117117

118118
```toml

src/lib.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
//! # apify-client
22
//!
3-
//! The official, idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
3+
//! **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
4+
//! generated and maintained by AI, and is not (yet) an officially supported Apify product.
5+
//! Review the code before relying on it in production and report issues on the repository.
6+
//!
7+
//! An idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
48
//!
59
//! It provides a resource-oriented interface that mirrors the official
610
//! [JavaScript](https://github.com/apify/apify-client-js) and Python clients: start from

0 commit comments

Comments
 (0)