# Publishing to crates.io

> How to publish the Fern Rust SDK to crates.io.

Publish your public-facing Fern Rust SDK to the [crates.io
registry](https://crates.io/). After following the steps on this page,
you'll have a versioned crate published on crates.io.

<Frame>
  <img src="https://files.buildwithfern.com/fern.docs.buildwithfern.com/learn/afa0dae6fc8234651663611a198c26fe0d6984aef2cd4fe1e9286520a8b5b362/products/sdks/overview/rust/assets/published-crate.png" alt="Versioned package published on crates.io" />
</Frame>

<Info>
  This page assumes that you have:

  * An initialized `fern` folder. See [Set up the `fern`
    folder](/sdks/overview/quickstart).
  * A GitHub repository for your SDK. See [Project Structure](/sdks/overview/project-structure).
</Info>

## Configure `generators.yml`

<Steps>
  <Step title="Configure `output` location">
    Change the output location in `generators.yml` from `local-file-system` (the default) to `crates` to indicate that Fern should publish your crate directly to the crates.io registry:

    ```yaml title="generators.yml" {6-7}
    groups: 
      rust-sdk:
        generators:
          - name: fernapi/fern-rust-sdk
            version: 0.17.2
            output:
              location: crates

    ```
  </Step>

  <Step title="Add a unique crate name">
    Your crate name must be unique in the crates.io registry, otherwise publishing your SDK will fail. Update your crate name if you haven't done so already:

    ```yaml title="generators.yml" {8}
    groups: 
      rust-sdk:
        generators:
          - name: fernapi/fern-rust-sdk
            version: 0.17.2
            output:
              location: crates
              package-name: your-crate-name
    ```
  </Step>

  <Step title="Configure `clientClassName`">
    The `clientClassName` option controls the name of the generated client struct. This is the name users will use when instantiating your SDK client.

    ```yaml title="generators.yml" {9-10}
    groups: 
      rust-sdk:
        generators:
          - name: fernapi/fern-rust-sdk
            version: 0.17.2
            output:
              location: crates
              package-name: your-crate-name
            config:
              clientClassName: YourClientName # must be PascalCase
    ```
  </Step>

  <Step title="Add repository location">
    Add the path to your GitHub repository to `generators.yml`:

    ```yaml title="generators.yml" {11-12}
    groups: 
      rust-sdk:
        generators:
          - name: fernapi/fern-rust-sdk
            version: 0.17.2
            output:
              location: crates
              package-name: your-crate-name
            config:
              clientClassName: YourClientName
            github: 
              repository: your-org/your-rust-sdk
    ```
  </Step>
</Steps>

## Set up crates.io publishing authentication

<Steps>
  <Step title="Log into crates.io">
    Log into [crates.io](https://crates.io/) using your GitHub account.
  </Step>

  <Step title="Navigate to Account settings">
    1. Click on your profile picture in the top right corner.
    2. Select **Account Settings**.
    3. Go to the **API Tokens** section.
  </Step>

  <Step title="Create a new API token">
    1. Click **New Token**.
    2. Name your token (e.g., "Fern SDK Publishing").
    3. Under **Scopes**, select **publish-new** to publish new crates and **publish-update** to update existing crates.
    4. Click **Generate Token**.

    <Frame>
      <img src="https://files.buildwithfern.com/fern.docs.buildwithfern.com/learn/9f542492f52a6561b3134b301f83a5ac0f59be0df1859653778ac666e6ac9bcc/products/sdks/overview/rust/assets/api-token.png" alt="Create a new API token on crates.io" />
    </Frame>

    <Warning>
      Save your new token immediately. It won't be displayed again after you leave the page.
    </Warning>
  </Step>

  <Step title="Configure crates.io authentication token">
    Add `token: ${CRATES_IO_API_KEY}` to `generators.yml` to tell Fern to use the `CRATES_IO_API_KEY` environment variable for authentication when publishing to crates.io.

    ```yaml title="generators.yml" {9}
    groups: 
      rust-sdk:
        generators:
          - name: fernapi/fern-rust-sdk
            version: 0.17.2
            output:
              location: crates
              package-name: your-crate-name
              token: ${CRATES_IO_API_KEY}
            config:
              clientClassName: YourClientName
            github: 
              repository: your-org/your-rust-sdk
    ```
  </Step>
</Steps>

## Publish your SDK

Decide how you want to publish your SDK to crates.io. You can use GitHub workflows for automated releases or publish directly via the CLI.

<AccordionGroup>
  <Accordion title="Release via a GitHub workflow (recommended)">
    Set up a release workflow via [GitHub Actions](https://docs.github.com/en/actions/get-started/quickstart) so you can trigger new SDK releases directly from your source repository.

    <Steps>
      <Step title="Set up authentication">
        Open your source repository in GitHub. Click on the **Settings** tab in your repository. Then, under the **Security** section, open **Secrets and variables** > **Actions**.

        You can also use the url `https://github.com/<your-repo>/settings/secrets/actions`.
      </Step>

      <Step title="Add secret for your crates.io token">
        1. Select **New repository secret**.
        2. Name your secret `CRATES_IO_API_KEY`.
        3. Add the corresponding token you generated above.
        4. Click **Add secret**.
      </Step>

      <Step title="Add secret for your Fern token">
        1. Select **New repository secret**.
        2. Name your secret `FERN_TOKEN`.
        3. Add your Fern token. If you don't already have one, generate one by
           running `fern token`. By default, the `fern_token` is generated for the
           organization listed in `fern.config.json`.
        4. Click **Add secret**.
      </Step>

      <Step title="Set up a new workflow">
        Set up a CI workflow that you can manually trigger from the GitHub UI. In your repository, navigate to **Actions**. Select **New workflow**, then **Set up workflow yourself**. Add a workflow that's similar to this:

        ```yaml title=".github/workflows/publish.yml" maxLines=0
        name: Publish Rust SDK

        on:
        workflow_dispatch:
          inputs:
            version:
              description: "The version of the Rust SDK that you would like to release"
              required: true
              type: string

        jobs:
        release:
          runs-on: ubuntu-latest
          steps:
            - name: Checkout repo
              uses: actions/checkout@v4

            - name: Install Fern CLI
              run: npm install -g fern-api

            - name: Release Rust SDK
              env:
                FERN_TOKEN: ${{ secrets.FERN_TOKEN }}
                CRATES_IO_API_KEY: ${{ secrets.CRATES_IO_API_KEY }}
              run: |
                fern generate --group rust-sdk --version ${{ inputs.version }} --log-level debug
        ```
      </Step>

      <Step title="Regenerate and release your SDK">
        Navigate to the **Actions** tab, select the workflow you just created, specify a version number, and click **Run workflow**. This regenerates your SDK.

        The rest of the release process depends on your chosen mode:

        * **Release mode (default):** If you didn't specify a `mode` or set `mode: release`, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository.

        * **Pull request or push mode:** If you set `mode: pull-request` or `mode: push`, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (`pull-request`) or branch (`push`), then [tag a new release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

        Once the workflow completes, you can view your new release by logging into crates.io, navigating to **Dashboard**, and looking under **My Crates**.
      </Step>
    </Steps>
  </Accordion>

  <Accordion title="Release via CLI and environment variables">
    <Steps>
      <Step title="Set crates.io environment variable">
        Set the `CRATES_IO_API_KEY` environment variable on your local machine:

        ```bash
        export CRATES_IO_API_KEY=your-actual-rust-token
        ```
      </Step>

      <Step title="Regenerate and release your SDK">
        Regenerate your SDK, specifying the version:

        ```bash
        fern generate --group rust-sdk --version <version>
        ```

        The rest of the release process depends on your chosen mode:

        * **Release mode (default):** If you didn't specify a `mode` or set `mode: release`, no further action is required. Fern automatically tags the new release with your specified version number and initiates the publishing workflow in your SDK repository.

        * **Pull request or push mode:** If you set `mode: pull-request` or `mode: push`, Fern creates a pull request or pushes to a branch respectively. Review and merge the PR (`pull-request`) or branch (`push`), then [tag a new release](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository) to initiate the publishing workflow in your SDK repository.

        Once the workflow completes, you can view your new release by logging into crates.io, navigating to **Dashboard**, and looking under **My Crates**.
      </Step>
    </Steps>
  </Accordion>
</AccordionGroup>