Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions .github/workflows/rust-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ name: Publish Rust client to crates.io
# matching GitHub release. The release tag is derived from the single source of truth (the
# `version` field in Cargo.toml, which is also what `CLIENT_VERSION` reads via CARGO_PKG_VERSION)
# so the published crate version, the git tag, and the in-code client version can never disagree.
#
# Authentication to crates.io uses Trusted Publishing (OIDC) via `rust-lang/crates-io-auth-action`,
# the registry's recommended mechanism — no long-lived crates.io API token is stored as a secret.
# A Trusted Publisher must be configured for the crate on crates.io (this repository + this
# workflow file). The only repository secret still used is the built-in GITHUB_TOKEN, for pushing
# the tag and creating the GitHub release.
on:
workflow_dispatch:
inputs:
Expand All @@ -23,9 +29,12 @@ concurrency:
cancel-in-progress: false

# The default GITHUB_TOKEN needs write access to push the release tag and create the GitHub
# release. The crates.io registry token is provided separately as a repository secret.
# release. `id-token: write` lets the job mint a short-lived OpenID Connect token that
# `rust-lang/crates-io-auth-action` exchanges for an ephemeral crates.io publish token
# (Trusted Publishing) — so no long-lived crates.io registry secret is stored in the repo.
permissions:
contents: write
id-token: write

jobs:
publish:
Expand Down Expand Up @@ -107,23 +116,11 @@ jobs:
exit 1
fi

# Fail early with a clear message if the registry token is not configured, instead of
# letting `cargo publish` fail later with a less obvious authentication error.
- name: Require CARGO_REGISTRY_TOKEN secret
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: |
if [ -z "${CARGO_REGISTRY_TOKEN}" ]; then
echo "::error::CARGO_REGISTRY_TOKEN secret is empty or missing; cannot publish to crates.io."
exit 1
fi

# Always verify packaging works (this also runs as part of `cargo publish`, but doing it
# explicitly surfaces packaging problems before any registry interaction or tag creation).
# No registry credentials are needed for `--dry-run`: it only packages and verifies the
# crate locally without contacting the registry for authentication.
- name: Verify package (dry run)
env:
# The crates.io registry token is stored as a repository secret.
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --dry-run --verbose

# Ordering rationale (deliberate): the git tag and GitHub release are created and pushed
Expand Down Expand Up @@ -200,10 +197,20 @@ jobs:
--notes "${RELEASE_NOTES}"
fi

# Trusted Publishing: exchange the GitHub Actions OIDC identity for a short-lived crates.io
# token instead of storing a long-lived registry secret. The action sets a `token` output
# and automatically revokes it in its post step when the job finishes. This requires a
# matching Trusted Publisher to be configured for the crate on crates.io (organization,
# repository and workflow file name).
- name: Authenticate to crates.io (Trusted Publishing)
id: auth
if: ${{ github.event.inputs.dry_run != 'true' }}
uses: rust-lang/crates-io-auth-action@v1

- name: Publish to crates.io
# Skip the actual publish when the run was dispatched as a dry run.
if: ${{ github.event.inputs.dry_run != 'true' }}
env:
# The crates.io registry token is stored as a repository secret.
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
# Short-lived token minted by Trusted Publishing (no stored registry secret).
CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
run: cargo publish --verbose
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,27 @@ All notable changes to the Rust Apify API client are documented here. The format
based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and the project adheres
to [Semantic Versioning](https://semver.org/).

## [0.4.1] - 2026-06-29

Compliance pass against the updated client requirements (no OpenAPI spec change; still
`v2-2026-06-25T142310Z`). No changes to the public API surface, so this is a patch release.

### Changed
- Documentation now states the client is **"official, but experimental"** (previously worded as
"not (yet) an officially supported Apify product"), keeping the AI-generated and AI-maintained
disclaimer. Updated consistently in the crate-level rustdoc (`src/lib.rs`), `README.md`,
`docs/README.md`, and the crate `description` in `Cargo.toml`, per the documentation requirement
that the docs clearly state the clients are official, but experimental and AI-generated/maintained.
- The crates.io publish workflow (`.github/workflows/rust-publish.yml`) now authenticates with
**Trusted Publishing** (OIDC) via `rust-lang/crates-io-auth-action@v1` instead of a stored
`CARGO_REGISTRY_TOKEN` secret, per the publishing requirement to use a Trusted Publisher when the
language's distribution process supports it (crates.io does). The job gains `id-token: write`
permission to mint the OIDC token, which the action exchanges for a short-lived crates.io token
(auto-revoked at job end); the `cargo publish --dry-run` verification step needs no credentials.
A Trusted Publisher must be configured for the crate on crates.io (this repository + workflow
file). The only remaining repository secret used for publishing is the built-in `GITHUB_TOKEN`
(tag push and GitHub release creation).

## [0.4.0] - 2026-06-26

Updated to Apify OpenAPI specification `v2-2026-06-25T142310Z` (previously
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "apify-client"
version = "0.4.0"
version = "0.4.1"
authors = ["Apify Technologies <support@apify.com>"]
description = "An experimental, AI-generated and AI-maintained Rust client for the Apify API (https://apify.com)."
description = "An official, but experimental, AI-generated and AI-maintained Rust client for the Apify API (https://apify.com)."
license = "Apache-2.0"
edition = "2021"
repository = "https://github.com/apify/apify-client-rust"
Expand Down
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Apify API client for Rust

> **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
> generated and maintained by AI, and is not (yet) an officially supported Apify product. Review
> the code before relying on it in production and report issues on the repository.
> **Official, but experimental — AI-generated and AI-maintained.** This is an official Apify
> client, but it is experimental: it is generated and maintained by AI. Review the code before
> relying on it in production and report issues on the repository.

An idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
It provides a resource-oriented, async interface that mirrors the official
Expand Down Expand Up @@ -129,14 +129,20 @@ GitHub release whose notes are the corresponding `CHANGELOG.md` section (falling
one-liner if that section is missing), and finally runs `cargo publish`.

The workflow **only runs from `master`** — it hard-fails on any other ref — and refuses to run if
the resolved tag already exists, so a release can never clobber a prior one. It also fails early
with a clear message if the `CARGO_REGISTRY_TOKEN` secret is missing. A `dry_run` input runs all
checks but performs no publish, tag, or release.
the resolved tag already exists, so a release can never clobber a prior one. A `dry_run` input runs
all checks but performs no publish, tag, or release.

Authentication to crates.io uses **Trusted Publishing** (OIDC): the job has `id-token: write`
permission and `rust-lang/crates-io-auth-action@v1` exchanges the GitHub Actions identity for a
short-lived crates.io token at publish time (auto-revoked when the job ends). No long-lived
crates.io API token is stored as a repository secret; the only publishing secret used is the
built-in `GITHUB_TOKEN` (for the tag push and GitHub release).

Prerequisites and steps to cut a release:

1. Configure the `CARGO_REGISTRY_TOKEN` repository secret with a crates.io API token (one-time
setup). The tag and GitHub release use the default `GITHUB_TOKEN`, so no other secret is needed.
1. Configure a **Trusted Publisher** for the `apify-client` crate on crates.io (one-time setup),
pointing at this repository and the `rust-publish.yml` workflow. No `CARGO_REGISTRY_TOKEN` secret
is needed; the tag and GitHub release use the default `GITHUB_TOKEN`.
2. Bump `version` in `Cargo.toml` and add a matching dated entry to `CHANGELOG.md` (the release
notes are extracted from that section), then merge to `master`.
3. Trigger the workflow from `master`.
Expand Down
6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Apify Rust client — documentation

> **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
> generated and maintained by AI, and is not (yet) an officially supported Apify product. Review
> the code before relying on it in production and report issues on the repository.
> **Official, but experimental — AI-generated and AI-maintained.** This is an official Apify
> client, but it is experimental: it is generated and maintained by AI. Review the code before
> relying on it in production and report issues on the repository.

This directory documents the public API of the Apify Rust client. The same descriptions
are available as rustdoc comments and can be browsed with `cargo doc --open`.
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! # apify-client
//!
//! **Experimental — AI-generated and AI-maintained.** This client is experimental. It is
//! generated and maintained by AI, and is not (yet) an officially supported Apify product.
//! Review the code before relying on it in production and report issues on the repository.
//! **Official, but experimental — AI-generated and AI-maintained.** This is an official Apify
//! client, but it is experimental: it is generated and maintained by AI. Review the code before
//! relying on it in production and report issues on the repository.
//!
//! An idiomatic Rust client for the [Apify API](https://docs.apify.com/api/v2).
//!
Expand Down
Loading