How to publish an SDK

Publishing turns a packed SDK into something other Workshop users can pull from the SDK Store. If the SDK isn’t yet packed, tested, and tried locally, go through How to build an SDK first.

The publishing flow has four steps:

  1. Pack the SDK into one .sdk artifact per platform.

  2. Register the SDK name on the SDK Store.

  3. Upload a revision.

  4. Release the revision to one or more channels.

The first step runs on your machine. The last three talk to the live SDK Store at api.charmhub.io and require an authenticated account.

Prerequisites

Before starting:

  • SDKcraft is installed.

  • LXD 6.6 or later is running on the host.

  • An Ubuntu One account that’s allowed to publish SDKs.

  • The SDK source tree is clean and ready to build.

  • The SDK passes sdkcraft try end-to-end in at least one workshop.

There is no local-only or dry-run mode for the Store-side commands. Plan to publish from a workstation with a stable network connection.

Pack the SDK

sdkcraft pack builds the SDK and packs it into one artifact per platform declared in sdkcraft.yaml:

$ sdkcraft pack

The resulting filenames follow the pattern <NAME>_<ARCH>_<BASE>.sdk, for example <NAME>_amd64_ubuntu@24.04.sdk. sdkcraft pack differs from sdkcraft try in one respect: the artifacts stay in the working directory rather than being copied into the try area.

If a previous build left state behind, clean and rebuild from scratch:

$ sdkcraft clean && sdkcraft pack

Test the SDK

If the SDK ships a tests/ directory with spread tests, run them against the freshly packed artifacts:

$ sdkcraft test

SDKcraft provisions a clean LXD container for each test, installs the packed SDK into a workshop, and runs the declared scenarios end-to-end.

sdkcraft init scaffolds a starter test under tests/main/launch/ and a tests/spread.yaml declaring the suites that sdkcraft test should pick up. Add more tests next to the starter, each in its own subdirectory of the same suite:

tests/main/smoke/task.yaml
summary: SDK installs and reports healthy
execute: |
  workshop launch --verbose --wait-on-error
  workshop info | grep -E 'status:\s+okay'

Try the SDK

The final pre-publish step is to install the packed SDK in a real workshop and use it the way an end user would:

$ sdkcraft try

sdkcraft try packs the SDK and copies it into the try area. Add it to a workshop with the try- prefix:

workshop.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: try-<NAME>

Then launch the workshop and exercise the SDK:

$ workshop launch --verbose --wait-on-error

This is the last chance to catch problems before the SDK is on the Store. Pay particular attention to:

  • Hook output in workshop changes and workshop tasks.

  • The SDK’s status in workshop info; a waiting or error state is the SDK telling you something is wrong.

  • The interaction between this SDK and any other SDKs it’s meant to be installed alongside.

Register the SDK name

Each SDK on the Store has a unique name. Reserve yours once per SDK, ever.

Authenticate first:

$ sdkcraft login

Confirm the right account is active:

$ sdkcraft whoami

Then register the SDK name:

$ sdkcraft register <NAME>

Names are global to the SDK Store and normally cannot be re-registered after release. Pick a name that matches the SDK’s name field in sdkcraft.yaml and that you intend to keep.

Upload a revision

Each sdkcraft upload invocation pushes one .sdk file and assigns it a revision number on the Store:

$ sdkcraft upload <NAME>_amd64_ubuntu@24.04.sdk

The output reports the revision number. At this point, the revision is on the Store but isn’t released to any channel yet, so sdk find won’t return it.

To upload and release in one step, pass --release with one or more channels:

$ sdkcraft upload <NAME>_amd64_ubuntu@24.04.sdk --release latest/edge

Upload one artifact per platform. If sdkcraft pack produced <NAME>_amd64_ubuntu@22.04.sdk and <NAME>_amd64_ubuntu@24.04.sdk, upload both; the Store tracks revisions per platform.

Automate uploads from CI

The .github/workflows/ files that ship with the canonical/template-sdk repository run sdkcraft upload --release automatically on push to the version branch that renovate.json maintains. After the one-time sdkcraft register, upstream releases land as automated revisions without further manual commands: Renovate opens a PR bumping VERSION, the merge of that PR triggers the upload workflow, and the new revision shows up in the configured channels.

The workflow expects Store credentials in the repository’s GitHub Actions secrets; configure them once. For what else the template ships, see How to build an SDK.

Release a revision

When a revision is on the Store but not yet released, or when promoting an existing revision from one channel to another, use sdkcraft release:

$ sdkcraft release <NAME> <REVISION> <CHANNELS>

Channels follow the [<TRACK>/]<RISK>[/<BRANCH>] shape:

  • <TRACK> is optional and groups related revisions, typically along major-version lines or variations in supported platforms (for example, 1.x or nvidia). Omitting it targets the default latest track.

    Caution

    Do not use the base (for example, 24.04) as the track name. The SDK Store tracks revisions per platform automatically (see the platforms listed in sdkcraft.yaml), so a per-base track only duplicates that and limits how revisions can be grouped meaningfully.

  • <RISK> is one of stable, candidate, beta, or edge.

  • <BRANCH> is optional and creates a short-lived channel with a one-month expiration.

Plain stable and comma-separated lists like beta,edge are valid channel arguments.

For example, to promote revision 8 to latest/stable:

$ sdkcraft release <NAME> 8 latest/stable

sdkcraft release is idempotent and never rebuilds or re-uploads; it only adjusts the channel map.

Consume the published SDK

Once a revision is released to a channel, any Workshop user can pull it by referencing the SDK in workshop.yaml:

workshop.yaml
name: dev
base: ubuntu@24.04
sdks:
  - name: <NAME>
    channel: latest/stable

The workshop’s base must match one of the SDK’s supported platforms.

See also

Explanation:

How-to guides:

Reference:

Tutorial: