diff --git a/.cursor/rules/cloudinary.mdc b/.cursor/rules/cloudinary.mdc new file mode 100644 index 0000000..278b42b --- /dev/null +++ b/.cursor/rules/cloudinary.mdc @@ -0,0 +1,8 @@ +--- +description: Cloudinary cloudinary-go — agent guide +alwaysApply: true +--- + +Read and follow `AGENTS.md` in the repository root. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..ba1d307 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,5 @@ +# Cloudinary cloudinary-go — instructions for AI coding agents + +Read `AGENTS.md` in the repository root and follow it. It is the single +authoritative guide for this package: build/test commands, conventions, +gotchas, and when to use this SDK versus a sibling Cloudinary package. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..138f027 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,81 @@ +# AGENTS.md — cloudinary-go + +## What this package is (one line) +Official Cloudinary Go **server-side** SDK: upload assets, build transformation/delivery URLs, and call the Admin API from your backend — the SDK that holds your `API_SECRET`. + +## When to use this / when NOT to use this +- **Use this when:** you are in a Go server runtime (HTTP handlers, workers, CLIs, build scripts) and need to upload assets, sign delivery URLs, or administer assets — anything that requires the `API_SECRET` to stay off the client. +- **Do NOT use this when:** you only need the **AI Content Analysis API** as a focused typed client → use [`analysis-go`](https://github.com/cloudinary/analysis-go); or you're doing **account provisioning** (sub-accounts, users, access keys) → use [`account-provisioning-go`](https://github.com/cloudinary/account-provisioning-go); or you want a no-code/autonomous-agent path → use the Cloudinary MCP server. +- **Sibling packages:** `analysis-go` and `account-provisioning-go` are narrow clients for a single API surface. This package is the **full server SDK** (upload + transform URLs + Admin API together) and is the default for general Cloudinary work in Go. + +## Setup +```bash +go get github.com/cloudinary/cloudinary-go/v2 +``` +Required configuration / credentials: +```bash +export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME +``` +`cloudinary.New()` reads `CLOUDINARY_URL` from the environment automatically. + +## Minimal runnable example +```go +package main + +import ( + "context" + "fmt" + + "github.com/cloudinary/cloudinary-go/v2" + "github.com/cloudinary/cloudinary-go/v2/api/uploader" +) + +func main() { + cld, _ := cloudinary.New() // reads CLOUDINARY_URL + ctx := context.Background() + + resp, _ := cld.Upload.Upload(ctx, "my_picture.jpg", uploader.UploadParams{}) + fmt.Println(resp.SecureURL) + + image, _ := cld.Image("sample.jpg") + image.Transformation = "c_fill,h_150,w_100" + url, _ := image.String() + fmt.Println(url) +} +``` + +## Build / test commands (run these after editing) +```bash +go mod download # fetch dependencies +go build ./... # compile everything +go test ./... # run the suite (CI uses gotestsum ./..., equivalent) +go vet ./... # static checks +``` +Notes: +- **Tests need `CLOUDINARY_URL`** — much of the suite hits the live Upload/Admin APIs, so set it to a real (test) cloud before running. CI allocates one via `scripts/get_test_cloud.sh`; locally, export your own. See `TEST.md` for test-writing conventions. +- If you edit param/option structs, regenerate fluent setters: `make generate`. Don't hand-edit generated `*_setters.go` files. +- CI (`.github/workflows/test.yaml`) matrix runs Go 1.20–1.24, tests only (via `gotestsum`). There is no golangci-lint step and no `.golangci.yml` in the repo — `go vet` and `gofmt` are the de-facto gate. + +## Conventions & gotchas +- **The `/v2` import path is mandatory.** Module is `github.com/cloudinary/cloudinary-go/v2`; importing without `/v2` resolves to the unmaintained 1.x and will not compile against current code. +- Format with `gofmt` / `go fmt ./...` before committing. +- Public entry point is the `cloudinary` package (`cloudinary.New()`); upload lives under `api/uploader`, admin under `api/admin`. Import these subpackages explicitly rather than reaching into deep internal paths. +- Generated setters: edit the generator under `gen/generate_setters/`, not the output. Run `make generate` after changing option structs. +- Signed uploads and the Admin API require the `API_SECRET` — keep it server-side; never embed it in a client binary or browser bundle. +- **Version support:** SDK 2.8+ requires **Go 1.20+**; SDK 2.7 / 1.x support Go 1.13–1.19. See the table in `README.md`. + +## Canonical docs (leave the repo for depth) +- Go SDK guide: https://cloudinary.com/documentation/go_integration +- Transformations: https://cloudinary.com/documentation/go_media_transformations +- Upload: https://cloudinary.com/documentation/go_image_and_video_upload +- Admin API: https://cloudinary.com/documentation/go_asset_administration +- API reference (pkg.go.dev): https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2 +- MCP server (agent/no-code path): https://github.com/cloudinary/mcp-servers + +## Agent / MCP note +If the capability you need is also exposed via the Cloudinary MCP servers, prefer the MCP tool for autonomous task execution and use this SDK for generated Go code. See cloudinary/mcp-servers. + +## Commit / PR conventions +- Branch off `main`; rebase on `upstream/main` before opening a PR (see `CONTRIBUTING.md`). +- PR description must clearly state the bug/feature and reference the related issue number. +- Provide tests covering new code (`TEST.md`), and ensure CI tests pass before requesting review. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..56d2862 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,27 @@ +@AGENTS.md + +# CLAUDE.md — cloudinary-go + +## What this repo is + +Official Cloudinary Go **server-side** SDK: upload assets, build transformation/delivery URLs, and call the Admin API from backend code. Module path: `github.com/cloudinary/cloudinary-go/v2` (the `/v2` suffix is mandatory — dropping it resolves to the unmaintained 1.x line). + +## Key constraints / gotchas + +- **`/v2` import path is mandatory.** Import `github.com/cloudinary/cloudinary-go/v2` everywhere; subpackages are `api/uploader` and `api/admin`. +- **`API_SECRET` stays server-side.** Never embed it in a client binary or browser bundle; use the signed-upload pattern for browser-direct flows. +- **Tests need `CLOUDINARY_URL`.** Most of the suite hits the live Upload/Admin APIs; set `export CLOUDINARY_URL=cloudinary://API_KEY:API_SECRET@CLOUD_NAME` before running. CI uses `scripts/get_test_cloud.sh`. +- **Do not hand-edit `*_setters.go` files.** They are generated. Edit the generator under `gen/generate_setters/`, then run `make generate`. +- **Go floor:** SDK 2.8+ requires Go 1.20+. SDK 2.7 / 1.x support Go 1.13–1.19. +- **CI gate:** `.github/workflows/test.yaml` runs `gotestsum ./...` on Go 1.20–1.24. There is no golangci-lint step; `go vet` and `gofmt` are the de-facto gate. +- **Format before committing:** `go fmt ./...` + +## Verified build / test commands + +```bash +go mod download # fetch dependencies +go build ./... # compile everything +go vet ./... # static checks +go test ./... # full suite (requires CLOUDINARY_URL pointing at a real test cloud) +make generate # regenerate fluent setters after editing param/option structs +``` diff --git a/README.md b/README.md index f3904dd..b5aeaa7 100644 --- a/README.md +++ b/README.md @@ -1,137 +1,165 @@ -[![Tests](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml/badge.svg)](https://github.com/cloudinary/cloudinary-go/actions) -[![Go Report Card](https://goreportcard.com/badge/github.com/cloudinary/cloudinary-go/v2)](https://goreportcard.com/report/github.com/cloudinary/cloudinary-go/v2) -[![PkgGoDev](https://pkg.go.dev/badge/github.com/cloudinary/cloudinary-go/v2)](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2) - -Cloudinary Go SDK -================== - -## About - -The Cloudinary Go SDK allows you to quickly and easily integrate your application with Cloudinary. -Effortlessly optimize, transform, upload and manage your cloud's assets. - -#### Note +# Cloudinary Go SDK -This Readme provides basic installation and usage information. -For the complete documentation, see the [Go SDK Guide](https://cloudinary.com/documentation/go_integration). - -## Table of Contents - -- [Key Features](#key-features) -- [Version Support](#Version-Support) -- [Installation](#installation) -- [Usage](#usage) - - [Setup](#Setup) - - [Transform and Optimize Assets](#Transform-and-Optimize-Assets) +[![PkgGoDev](https://pkg.go.dev/badge/github.com/cloudinary/cloudinary-go/v2)](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2) +[![License](https://img.shields.io/github/license/cloudinary/cloudinary-go)](https://github.com/cloudinary/cloudinary-go/blob/main/LICENSE) +[![Tests](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml/badge.svg)](https://github.com/cloudinary/cloudinary-go/actions/workflows/test.yaml) -## Key Features +The Cloudinary Go SDK is the server-side SDK for Go. Use it to upload assets, build transformation and delivery URLs, and call the Admin API from backend code. The module path is `github.com/cloudinary/cloudinary-go/v2` (the `/v2` suffix is required); SDK 2.8 and later require Go 1.20 or later. -- [Transform](https://cloudinary.com/documentation/go_media_transformations) assets. -- [Asset Management](https://cloudinary.com/documentation/go_asset_administration). -- [Secure URLs](https://cloudinary.com/documentation/video_manipulation_and_delivery#generating_secure_https_urls_using_sdks). +## Installation -## Version Support +```bash +go get github.com/cloudinary/cloudinary-go/v2 +``` -| **SDK Version** | **Go 1.13 - 1.19** | **Go 1.20** | **Go 1.21** | **Go 1.22** | **Go 1.23** | -|-----------------|--------------------|-------------|-------------|-------------|-------------| -| **2.8 & Up** | ❌ | ✔️ | ✔️ | ✔️ | ✔️ | -| **2.7** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| **1.x** | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +## Configuration -## Installation +The SDK reads credentials from the `CLOUDINARY_URL` environment variable: ```bash -go get github.com/cloudinary/cloudinary-go/v2 +export CLOUDINARY_URL=cloudinary://:@ ``` -# Usage +```go +import "github.com/cloudinary/cloudinary-go/v2" + +cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment +``` -### Setup +To pass credentials in code instead, use `NewFromParams`: ```go -import ( - "github.com/cloudinary/cloudinary-go/v2" -) +import "github.com/cloudinary/cloudinary-go/v2" -cld, _ := cloudinary.New() +cld, err := cloudinary.NewFromParams("my_cloud_name", "my_key", "my_secret") ``` -- [See full documentation](https://cloudinary.com/documentation/go_integration#configuration). +`New`, `NewFromParams`, and `NewFromURL` all return an error when the credentials are missing or malformed — check it. Keep the API secret on the server: don't put it in a distributed binary, client-side code, or version control. -### Transform and Optimize Assets +## Quick examples -- [See full documentation](https://cloudinary.com/documentation/go_media_transformations). +### Upload a file + +`cld.Upload.Upload(ctx, file, uploader.UploadParams{...})` returns a `*uploader.UploadResult`. The `file` argument accepts a local path, a remote URL, a base64 string, an `*os.File`, a `*multipart.FileHeader`, or any `io.Reader`. The result includes `PublicID` and `SecureURL`: ```go -image, err := cld.Image("sample.jpg") -if err != nil {...} +package main + +import ( + "context" + "fmt" + "log" -image.Transformation = "c_fill,h_150,w_100" + "github.com/cloudinary/cloudinary-go/v2" + "github.com/cloudinary/cloudinary-go/v2/api/uploader" +) -imageURL, err := image.String() +func main() { + cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment + if err != nil { + log.Fatal(err) + } + + resp, err := cld.Upload.Upload(context.Background(), "my_image.jpg", uploader.UploadParams{ + PublicID: "cms/hero", // optional: where the asset lives in your media library + }) + if err != nil { + log.Fatal(err) + } + fmt.Println(resp.PublicID, resp.SecureURL) +} ``` -### Upload +### Build and optimize a delivery URL -- [See full documentation](https://cloudinary.com/documentation/go_image_and_video_upload). -- [Learn more about configuring your uploads with upload presets](https://cloudinary.com/documentation/upload_presets). +`cld.Image(publicID)` returns an `*asset.Asset` whose `String()` method serializes a delivery URL — no network call. Set the `Transformation` field with raw transformation syntax. This one scales to 500px wide and lets Cloudinary pick the format and quality for the requesting browser (`f_auto`, `q_auto`): ```go -resp, err := cld.Upload.Upload(ctx, "my_picture.jpg", uploader.UploadParams{}) -``` - -### Security options +package main -- [See full documentation](https://cloudinary.com/documentation/solution_overview#security). - -### Logging +import ( + "fmt" + "log" -Cloudinary SDK logs errors using standard `go log` functions. + "github.com/cloudinary/cloudinary-go/v2" +) -For details on redefining the logger or adjusting the logging level, see [Logging](logger/README.md). +func main() { + cld, err := cloudinary.NewFromParams("demo", "my_key", "my_secret") + if err != nil { + log.Fatal(err) + } + + image, err := cld.Image("sample") + if err != nil { + log.Fatal(err) + } + image.Transformation = "c_scale,w_500/f_auto/q_auto" + + url, err := image.String() + if err != nil { + log.Fatal(err) + } + fmt.Println(url) + // https://res.cloudinary.com/demo/image/upload/c_scale,w_500/f_auto/q_auto/sample +} +``` -### Complete SDK Example +### Retrieve asset details with the Admin API -See [Complete SDK Example](example/example.go). +`cld.Admin.Assets(ctx, admin.AssetsParams{...})` returns an `*admin.AssetsResult`. Its `Assets` field is a slice of assets, each with `PublicID` and `SecureURL`: -## Contributions +```go +package main -- Ensure tests run locally -- Open a PR and ensure Travis tests pass -- For more information on how to contribute, take a look at the [contributing](CONTRIBUTING.md) page. +import ( + "context" + "fmt" + "log" -## Get Help + "github.com/cloudinary/cloudinary-go/v2" + "github.com/cloudinary/cloudinary-go/v2/api/admin" +) -If you run into an issue or have a question, you can either: +func main() { + cld, err := cloudinary.New() // reads CLOUDINARY_URL from the environment + if err != nil { + log.Fatal(err) + } + + res, err := cld.Admin.Assets(context.Background(), admin.AssetsParams{ + Prefix: "cms/", + MaxResults: 30, + }) + if err != nil { + log.Fatal(err) + } + for _, a := range res.Assets { + fmt.Println(a.PublicID, a.SecureURL) + } +} +``` -- Issues related to the SDK: [Open a GitHub issue](https://github.com/cloudinary/cloudinary-go/issues). -- Issues related to your account: [Open a support ticket](https://cloudinary.com/contact) +## For AI agents -## About Cloudinary +`cloudinary-go` is the Go server-side SDK — upload, transformation and delivery URLs, and the Admin API, where the API secret stays private. Construct a client with `cloudinary.New()` (reads `CLOUDINARY_URL`), `cloudinary.NewFromURL`, or `cloudinary.NewFromParams`. Upload lives under `api/uploader`, admin under `api/admin`. For tasks this package doesn't cover, use a sibling package: -Cloudinary is a powerful media API for websites and mobile apps alike, Cloudinary enables developers to efficiently -manage, transform, optimize, and deliver images and videos through multiple CDNs. Ultimately, viewers enjoy responsive -and personalized visual-media experiences—irrespective of the viewing device. +| Task | Package | +|---|---| +| Only the AI Content Analysis API, as a typed client | [`analysis-go`](https://github.com/cloudinary/analysis-go) | +| Provisioning — product environments, users, access keys | [`account-provisioning-go`](https://github.com/cloudinary/account-provisioning-go) | +| Run Cloudinary operations as agent tools | [Cloudinary MCP servers](https://github.com/cloudinary/mcp-servers) | -## Additional Resources +Go has no first-party browser runtime, so there is no Go equivalent of the JavaScript `url-gen` split — URL building and credential handling both live in this SDK. -- [Cloudinary Transformation and REST API References](https://cloudinary.com/documentation/cloudinary_references): - Comprehensive references, including syntax and examples for all SDKs. -- [MediaJams.dev](https://mediajams.dev/): Bite-size use-case tutorials written by and for Cloudinary Developers -- [DevJams](https://www.youtube.com/playlist?list=PL8dVGjLA2oMr09amgERARsZyrOz_sPvqw): Cloudinary developer podcasts on - YouTube. -- [Cloudinary Academy](https://training.cloudinary.com/): Free self-paced courses, instructor-led virtual courses, and - on-site courses. -- [Code Explorers and Feature Demos](https://cloudinary.com/documentation/code_explorers_demos_index): A one-stop shop - for all code explorers, Postman collections, and feature demos found in the docs. -- [Cloudinary Roadmap](https://cloudinary.com/roadmap): Your chance to follow, vote, or suggest what Cloudinary should - develop next. -- [Cloudinary Facebook Community](https://www.facebook.com/groups/CloudinaryCommunity): Learn from and offer help to - other Cloudinary developers. -- [Cloudinary Account Registration](https://cloudinary.com/users/register/free): Free Cloudinary account registration. -- [Cloudinary Website](https://cloudinary.com): Learn about Cloudinary's products, partners, customers, pricing, and - more. +## Links -## Licence +- [Go SDK guide](https://cloudinary.com/documentation/go_integration) +- [Upload](https://cloudinary.com/documentation/go_image_and_video_upload) +- [Asset administration (Admin API)](https://cloudinary.com/documentation/go_asset_administration) +- [Media transformations](https://cloudinary.com/documentation/go_media_transformations) +- [Transformation and API references](https://cloudinary.com/documentation/cloudinary_references) +- [Documentation llms.txt index](https://cloudinary.com/documentation/llms.txt) +- [Package on pkg.go.dev](https://pkg.go.dev/github.com/cloudinary/cloudinary-go/v2) Released under the MIT license.