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
14 changes: 14 additions & 0 deletions .github/workflows/docs-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: Docs check

on:
pull_request:
push:
branches: [main]

jobs:
check-docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- run: ./scripts/check-docs.sh
7 changes: 7 additions & 0 deletions .github/workflows/update-and-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ jobs:
-g rust \
-o . \
--skip-validate-spec \
--git-host github.com \
--git-user-id linkbreakers-com \
--git-repo-id linkbreakers-rust \
--global-property apiTests=false,modelTests=false,apiDocs=false,modelDocs=false \
--additional-properties=packageName=linkbreakers,packageVersion=$NEW_VERSION,library=reqwest

Expand Down Expand Up @@ -123,6 +126,10 @@ jobs:
cargo test || echo "⚠️ Tests failed or no tests found"
echo "✅ Build completed"

- name: Check README against the generated SDK
if: steps.compare.outputs.needs_update == 'true'
run: ./scripts/check-docs.sh

- name: Configure Git
if: steps.compare.outputs.needs_update == 'true'
run: |
Expand Down
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Add this to your `Cargo.toml`:

```toml
[dependencies]
linkbreakers = "1.32.0"
linkbreakers = "1"
tokio = { version = "1", features = ["full"] }
```

Expand All @@ -21,16 +21,29 @@ tokio = { version = "1", features = ["full"] }
### Async Example

```rust
use linkbreakers::{apis::configuration::Configuration, apis::links_api};
use linkbreakers::{apis::configuration::Configuration, apis::links_api, models::CreateLinkRequest};

#[tokio::main]
async fn main() {
// Create configuration with authentication
let mut config = Configuration::new();
config.bearer_access_token = Some("your-api-token".to_string());

// Example: List links
match links_api::links_list(&config, Some(10), None, None, None, None, None, None, None, None).await {
// Create a shortened link
let mut request = CreateLinkRequest::new("https://example.com".to_string());
request.name = Some("My Link".to_string());

match links_api::links_service_create(&config, request, None).await {
Ok(response) => {
let shortlink = response.link.and_then(|link| link.shortlink).unwrap_or_default();
println!("Short link: {}", shortlink);
}
Err(e) => eprintln!("Error: {:?}", e),
}

// List links: page_size, then the optional page_token, include, tags,
// search, sort_by, sort_direction, view, directory_id and cursor
match links_api::links_service_list(&config, 10, None, None, None, None, None, None, None, None, None).await {
Ok(response) => {
println!("Found {} links", response.links.unwrap_or_default().len());
}
Expand All @@ -39,6 +52,8 @@ async fn main() {
}
```

Each API is a module under `linkbreakers::apis` (`links_api`, `visitors_api`, ...) and each operation is a function named after the API's operation ID (`links_service_create`, `links_service_list`, `visitors_service_identify`, ...). It takes the configuration, then the path parameters, request body and query parameters in order, with optional ones as `Option`.

### Blocking Example

```rust
Expand All @@ -52,7 +67,7 @@ fn main() {
// Example: List links (blocking)
let runtime = tokio::runtime::Runtime::new().unwrap();
let result = runtime.block_on(async {
links_api::links_list(&config, Some(10), None, None, None, None, None, None, None, None).await
links_api::links_service_list(&config, 10, None, None, None, None, None, None, None, None, None).await
});

match result {
Expand Down Expand Up @@ -85,7 +100,7 @@ For Rust-specific docs, run: `cargo doc --open`

## Auto-Generated

This SDK is automatically generated from the Linkbreakers OpenAPI specification and published when the API is updated.
This SDK is automatically generated from the Linkbreakers OpenAPI specification and published when the API is updated. This README is written by hand: `scripts/check-docs.sh` compiles every Rust block in it against the generated code, on pull requests and before every release.

Current API version: See [OPENAPI_VERSION](./OPENAPI_VERSION)

Expand Down
4 changes: 2 additions & 2 deletions git_push.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ if [ "$git_host" = "" ]; then
fi

if [ "$git_user_id" = "" ]; then
git_user_id="GIT_USER_ID"
git_user_id="linkbreakers-com"
echo "[INFO] No command line input provided. Set \$git_user_id to $git_user_id"
fi

if [ "$git_repo_id" = "" ]; then
git_repo_id="GIT_REPO_ID"
git_repo_id="linkbreakers-rust"
echo "[INFO] No command line input provided. Set \$git_repo_id to $git_repo_id"
fi

Expand Down
37 changes: 37 additions & 0 deletions scripts/check-docs.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env bash
# Compiles every Rust block in README.md against the generated crate, so the
# hand-written README cannot call functions the generator does not produce.
# A block without `fn main` is compiled as the body of one.
set -euo pipefail

root="$(cd "$(dirname "$0")/.." && pwd)"
examples="$root/examples"
prefix="docscheck_readme_"
trap 'rm -f "$examples"/${prefix}*.rs; rmdir "$examples" 2>/dev/null || true' EXIT
mkdir -p "$examples"

awk -v dir="$examples" -v prefix="$prefix" '
/^```rust$/ { n++; inside = 1; body = ""; next }
/^```$/ && inside {
inside = 0
file = sprintf("%s/%s%d.rs", dir, prefix, n)
if (body ~ /fn main/) { printf "%s", body > file }
else { printf "#![allow(unused)]\nfn main() {\n%s}\n", body > file }
close(file)
next
}
inside { body = body $0 "\n" }
' "$root/README.md"

count=$(find "$examples" -name "${prefix}*.rs" | wc -l | tr -d ' ')
if [ "$count" = "0" ]; then
echo "No Rust blocks found in README.md" >&2
exit 1
fi

cd "$root"
if ! cargo check --quiet --examples; then
echo "A README.md Rust block no longer compiles against the generated SDK." >&2
exit 1
fi
echo "Compiled $count README.md Rust blocks against the generated SDK."
Loading