End-to-end SDK generation and publishing with Bitbucket Pipelines
Supported SDK languages:
TypeScript / Javascript | Java / Kotlin | Python | C# | Go | PHP |
---|---|---|---|---|---|
✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
This tutorial shows you how to use Bitbucket Pipelines with liblab to automate the SDK generation and publishing process for an existing project. You'll learn how to configure CI/CD workflows that automatically generate and release SDKs to public package managers like npm, PyPI, NuGet, Maven, Go Packages, and Packagist.
Ensure that you:
- Have a working liblab project with a valid OpenAPI spec and
liblab.config.json
file. - Have a Bitbucket account.
- Have an account on the package management platform(s) you want to deploy your SDKs to (ex. NPM, PyPi, Maven). This guide will help you with all of the other deployment details.
If you're new to Bitbucket Pipelines, you can find more information in Bitbucket's documentation.
This guide doesn't cover setting up a new liblab SDK project.
If you don't have a liblab SDK project yet then you'll first want to follow one of our framework guides or general getting started guide.
Structural Overview
Your completed project will consist of:
- Your existing liblab project repository which we'll refer to as the "Control Repo"
- One SDK repository per SDK language you want to publish which are your "SDK Repos"
When you complete the tutorial, the project repository structure will look like the example below.
Where each SDK repo will have the following organization:
- TypeScript
- Python
- C#
- Java
- Go
- PHP
Any change to the API spec or liblab configuration in the Control Repo will trigger SDK builds and create pull requests (PRs) in the respective SDK repositories.
Set up the Control Repo
First, you'll need to set up your Bitbucket pipeline. Run the following command from the root of your project. This command downloads the official liblab Bitbucket pipeline file (bitbucket-pipelines.yml
) and places it in the root of your Control Repo.
cd your-liblab-project
curl -o bitbucket-pipelines.yml https://raw.githubusercontent.com/liblaber/control-repo-template/main/bitbucket-pipelines.yml
bitbucket-pipelines.yml
This file automates SDK generation and pull request (PR) creation when changes occur in specified files and directories, such as liblab.config.json
, spec/
, hooks
, and customPlanModifiers
. It triggers on pushes to the main
branch and on pull requests. You can customize it to your own project's needs.
This is what you should have so far:
Create SDK Repos
Each generated SDK lives in its own repository, one per SDK language. Therefore, you need to create a new repository for each SDK language you plan to publish. In each repository, you must include a CI/CD configuration file (bitbucket-pipelines.yml
) to ensure the SDK is automatically published to the correct package manager always it's updated.
You don’t need to write the pipeline configuration yourself, we’ve already done that for you. Use the links below to access the most up-to-date bitbucket-pipelines.yml
files from the official liblab SDK template repositories:
This is what you should have so far:
Create liblab and Bitbucket tokens
The Bitbucket pipeline in the Control Repo, which generates SDKs, requires two tokens that you'll create in the next steps.
- A
LIBLAB_TOKEN
for authenticating the liblab CLI. - A
LIBLAB_BITBUCKET_TOKEN
to let the liblab CLI to push to your SDK repos.
Create a liblab token
By default, this token will expire after 90 days. You can increase this to up to 364 days by passing the --durationInDays
parameter.
Read more on the liblab token
command in the CLI documentation.
For guidance on setting up variables in Bitbucket, refer to the variables and secrets documentation.
To generate a liblab token, run the following command from your terminal:
liblab token create LIBLAB_TOKEN
You can replace LIBLAB_TOKEN
with any name you prefer. If you're generating SDKs for multiple APIs, you can either share the token between them or create separate tokens for each API.
Token successfully generated, it will be valid for 90 days
-TOKEN-----------------------------------------
liblab_HYeJzYb5CO3t7JaW4I6ZWKNKbOGp01MqqYSTS6yG
-----------------------------------------------
Copy the token (e.g., liblab_HYeJzYb5CO3t7JaW4I6ZWKNKbOGp01MqqYSTS6yG
) and save it somewhere safe.
Then, add the token to your Bitbucket Control Repo project.
- Access your Bitbucket project.
- Navigate to Settings > CI/CD > Variables and click Add variable.
- Set Key to
LIBLAB_TOKEN
and paste the token in the Value field, then click Add variable.
Create a Bitbucket access token
To enable the Bitbucket pipeline to run the liblab CLI and push changes to your SDK repos, you need a Bitbucket access token. Follow these steps to create a project access token:
liblab recommends using a Project access token. If the Control Repo and SDK repos are in the same project, this limits the token's access scope to necessary repos.
For non-premium accounts, consider creating a repository access token for the SDK repo. However, this restricts usage to one SDK repo.
- In Bitbucket, go to Projects and select the project containing the Control Repo and SDK repos.
- In the left sidebar, choose Project settings.
- Select Access tokens.
- Set Label to
LIBLAB_BITBUCKET_TOKEN
. - Assign the following permissions:
- Repositories:
- Read
- Write
- Pull Request:
- Read
- Write
- Repositories:
- Click Create and copy the generated token. This token will authenticate and push SDK code to your SDK repos from the Control Repo.
- Add the token as a repository variable in your Control Repo, with the name
LIBLAB_BITBUCKET_TOKEN
.
This is what you should have set up so far:
Create package manager tokens
Depending on what SDK language you are using, you will need to create additional secrets.
- TypeScript
- Python
- C#
- Java
- Go
- PHP
To publish to npm, you will need an npm access token. You can generate a new access token from your user settings on npm.
-
Select the Access Tokens tab, drop down the Generate New Token button, then select Granular Access Token.
-
Fill in all the required details for the token such as the name and expiry.
-
Make sure that this token has read and write permission to publish packages. If the package already exists, you can scope this token to just that package, otherwise this token needs read and write for all packages.
-
Once the token has been created, make a copy of it.
-
In your TypeScript SDK repo, add this token as a repository variable named
NPM_TOKEN
.
You can learn more about creating npm tokens in the npm access tokens documentation.
To publish to PyPI you will need an API token. You can generate a new API token from your account settings page on PyPI.
-
Select Account settings, scroll to the API tokens section, then select the Add API token button.
-
Give the token a name.
-
Select the scope for the token. If the package already exists, select that package for the scope, otherwise select Entire account (all packages).
-
Select the Create token button.
-
Once the token has been created, make a copy of it.
-
In your Python SDK repo, add this token as a repository variable named
PYPI_TOKEN
.
You can learn more about creating PyPI tokens in the PyPI API tokens documentation.
To publish to NuGet, you will need a NuGet API key. You can generate an API key from your account on NuGet.
-
Select your name on the top right, then select the API Keys.
-
From the API Keys page, expand the Create section.
-
Give your API Key a name, and set the required expiry and package owner.
-
Set the scope for this API Key.
- If the package already exists, select Push and Push only new package versions. Then in the Select Packages section, select the package you want to publish updates for.
- If the package does not exist, select Push and Push new packages and package versions, then in the Glob pattern, put
*
. This will allow you to push a new package.
-
Select the Create button.
-
Once the API Key has been created, expand the Manage section, and make a copy of it using the Copy button.
-
In your C# SDK repo, add this token a repository variable named
NUGET_TOKEN
.
You can learn more about creating NuGet API Keys in the NuGet API Keys documentation.
To publish to the Maven Central Repository, you will need Maven credentials and a GPG key with a passphrase to sign your artifacts.
As of March 12th, 2024, the Central Portal became the default publishing server for Maven packages. At the moment, we do not support automatic publishing through the Legacy OSSRH.
Central Portal Setup
The Central Portal Account Documentation explains how to create an account. An account is required for claiming namespaces, generating credentials and managing package deployments.
Namespace Registration
Your namespace is the crucial prerequisite for publishing a package to the Central Repository as it is the groupId
of the package. The Central Repository Namespace Documentation provides detailed instructions for claiming a namespace.
The namespace verification process is not instant.
- For own domain namespaces (e.g.
com.liblab
), an additional step is required, which involves setting up the verification key as a DNS record in order for the domain name to be verified by the Central Repository.
Once your namespace is verified, the next step is to generate your Maven credentials.
Generate Maven Credentials
-
Head to the Central Portal at central.sonatype.com, and either create an account, or sign in.
-
Select your email on the top right, then select View Account.
-
From the Account page, select the Generate User Token button.
-
When the dialog appears, confirm that you want to generate a new token, and credentials will be generated.
-
In your Java SDK repo, add value of the
Username
field as a new repository variable calledMAVEN_USERNAME
and the value of thePassword
field as a repository variable calledMAVEN_PASSWORD
.
You can learn more about creating Central Portal credentials in the Central Portal Documentation.
Generate GPG Key
The Central Repository requires all artifacts to be signed with PGP, such as using a GPG key. You will need to generate your own key pair, distribute it to the key server and obtain the private key, then set this as an other repository variable.
The following steps will guide you through the process of creating a GPG key using GnuPG. If you already have a GPG key, you can skip this step. If you want to use a different tool to generate your GPG key, you will need to follow the relevant documentation for that tool.
-
Install GnuPG if you don't have it installed.
-
Initialize the key generation prompt by running:
Terminalgpg --gen-key
-
Follow the instructions from
gpg
, and choose a passphrase -
Once the key is generated, you will need to get the key id. This is the 40-character hex string on the second line of the
pub
section in the output from generating the key:Terminalpublic and secret key created and signed.
pub ed25519 2024-05-07 [SC] [expires: 2027-05-07]
AB1C2D3456EF78A90BC12D34567890123456789E
uid Exciting Soda <[email protected]>
sub cv25519 2024-05-07 [E] [expires: 2027-05-07] -
Send the key to your key server, such as
openpgp
by running the following command:Terminalgpg --keyserver keys.openpgp.org --send-keys <key-id>
Replace
<key-id>
with the key id you obtained in the previous step. -
Get the private key using the following command:
Terminalgpg --export-secret-keys --armour <key-id>
Replace
<key-id>
with your key id.Terminal➜ ~ gpg --export-secret-keys --armour AB1C2D3456EF78A90BC12D34567890123456789E
-----BEGIN PGP PRIVATE KEY BLOCK-----
mDMEXEcE6RYJKwYBBAHaRw8BAQdArjWwk3FAqyiFbFBKT4TzXcVBqPTB3gmzlC/U
b7O1u120JkFsaWNlIExvdmVsYWNlIDxhbGljZUBvcGVucGdwLmV4YW1wbGU+iJAE
ExYIADgCGwMFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AWIQTrhbtfozp14V6UTmPy
MVUMT0fjjgUCXaWfOgAKCRDyMVUMT0fjjukrAPoDnHBSogOmsHOsd9qGsiZpgRnO
dypvbm+QtXZqth9rvwD9HcDC0tC+PHAsO7OTh1S1TC9RiJsvawAfCPaQZoed8gK4
OARcRwTpEgorBgEEAZdVAQUBAQdAQv8GIa2rSTzgqbXCpDDYMiKRVitCsy203x3s
E9+eviIDAQgHiHgEGBYIACAWIQTrhbtfozp14V6UTmPyMVUMT0fjjgUCXEcE6QIb
DAAKCRDyMVUMT0fjjlnQAQDFHUs6TIcxrNTtEZFjUFm1M0PJ1Dng/cDW4xN80fsn
0QEA22Kr7VkCjeAEC08VSTeV+QFsmz55/lntWkwYWhmvOgE=
=iIGO
-----END PGP PRIVATE KEY BLOCK----- -
Copy the output from this command, and add it to a new repository variable called
GPG_PRIVATE_KEY
. -
Create another repository variable called
GPG_PASSPHRASE
, and set this to the passphrase you chose when generating the key.
Go package management differs from many other languages in that it does not require API tokens for publishing to the Go Packages repository. Unlike some ecosystems where API tokens are necessary to interact with package registries, Go relies on its module proxy system, which integrates seamlessly with GitHub.
As explained in the official publishing tutorial on Go's website, packages are published to the Go Packages repository by tagging a release on GitHub. The Create a release in GitHub section later in this tutorial provides a step-by-step guide on how to create a release in GitHub which will automatically trigger the publishing of the package to the Go Packages repository. Upon creating a release, it should not take longer than one hour for the package to become available on the Go Packages repository.
To publish your PHP SDK to Packagist, you will first need an account on Packagist and your Packagist API Token.
-
Create an Account on Packagist or login to Packagist using your GitHub account.
-
Obtain your Packagist API Token from your profile settings
-
In your PHP SDK repo, add this token as an repository variable named
PACKAGIST_TOKEN
and set the repository variablePACKAGIST_USERNAME
to your packagist username as it appears on your profile. -
Submit your package
- Log in to your Packagist account.
- Go to the Submit tab.
- Enter the URL of your SDK's repository.
- Select Check to validate the repository and Submit to add your package to Packagist.
At this point, you should have a complete setup.
Update the config file
Now that all your repositories are set up, you'll need to update the liblab.config.json
file. Make sure to configure the publishing information and update the settings for each SDK language you plan to publish.
-
In the
publishing
section, set thegithubOrg
option to the Bitbucket workspace that contains the SDK repos. -
In the
languageOptions
section:-
Update the
githubRepoName
for each SDK. This should be the name of the corresponding Bitbucket SDK repo (e.g.,typescript-sdk
). -
Set the
sdkVersion
to match your desired version number. This should be updated for each new release. -
Configure details for each package manager:
- TypeScript
- Python
- C#
- Java
- Go
- PHP
- Set the
pypiPackageName
option to the name of your PyPI package. This needs to be unique.
- Set the
packageId
option to the name of your NuGet package.
- Set the
groupId
option to your namespace verified by the Maven Central Portal. - Set the
homepage
option to the valid public URL of your SDK homepage. - Add at least one developer to the
developers
option. - (Recommended) Set the
artifactId
option. If not set, it defaults to the kebab-cased version ofsdkName
.
-
Set the
goModuleName
option to the name of your Go module. This should match the SDK repo name, for examplegithub.com/myorg/go-sdk
. -
Ensure your license is set.
noteThe Go Packages License Policy requires that all packages published to the Go Packages repository must include a recognized license file. It is important to note that if the package does not include a recognized license file, only limited package information will be displayed on the Go Packages repository.
For more information on how to specify a license for your SDK, see the license config file option.
- Set the
packageName
option to the name of your PHP package. It must be in the formatvendor/packageName
.
-
There are many other options you can configure for SDK deployment but these are optional. Refer to the config file documentation to learn more.
The following code snippet shows an example of a liblab.config.json
file, where SDKs for C#, Python, TypeScript, Go, PHP, and Java are configured for generation and publishing:
Example liblab.config.json configured for SDK deployment
{
"sdkName": "test-sdk",
"apiVersion": "1.0.0",
"apiName": "test-api",
"specFilePath": "spec.json",
"languages": [
"csharp",
"python",
"typescript",
"go",
"php",
"java"
],
"languageOptions": {
"csharp": {
"liblabVersion": "2",
"packageId": "Test.SDK",
"githubRepoName": "csharp-sdk",
"sdkVersion": "1.0.0"
},
"python": {
"liblabVersion": "2",
"pypiPackageName": "test-sdk",
"githubRepoName": "python-sdk",
"sdkVersion": "1.0.0"
},
"typescript": {
"npmName": "test-sdk",
"npmOrg": "myorg",
"githubRepoName": "typescript-sdk",
"sdkVersion": "1.0.0"
},
"java": {
"groupId": "com.myorg",
"artifactId": "test-sdk",
"homepage": "https://myorg.com",
"githubRepoName": "java-sdk",
"sdkVersion": "1.0.0",
"developers": [
{
"name": "John Doe",
"email": "[email protected]",
"organization": "My Organization",
"organizationUrl": "https://myorg.com"
}
]
},
"go": {
"goModuleName": "bitbucket.org/myorg/go-sdk",
"githubRepoName": "go-sdk",
"sdkVersion": "1.0.0",
},
"php": {
"packageName": "myorg/test-sdk",
"githubRepoName": "php-sdk",
"sdkVersion": "1.0.0"
},
},
"publishing": {
"githubOrg": "myorg"
}
}
Finally, commit and push your changes to your Control Repo. This will trigger the pipeline to generate your SDKs and create PRs in your SDK repos. To check the progress, access the pipeline view to check the pipeline and job status.
Merge SDK PRs
Once the Control Repo pipeline completes successfully, a PR will be created in each SDK repo. To view these PRs, select Pull requests in each SDK repo.
If you don't see the PRs, check the Pipelines tab in your Control Repo for any errors. Refer to the common errors section section for troubleshooting tips.
To complete the process:
- Review the PRs to ensure the SDKs were generated correctly.
- Once you're happy, approve and merge the PRs.
Create a release in Bitbucket
Bitbucket does not provide a native way of automatically generating release notes. You can use a third-party solution or create release notes using Jira. Access the Atlassian tutorial page for more information.
Confirm SDK publication
After completing the publishing process, check the package manager services related to the SDKs you have created, such as npm, PyPI, and Maven, to verify that your SDK has been successfully published.
You're now fully set up to automatically generate and publish SDKs with liblab and Bitbucket pipelines, ensuring your latest API updates reach users as quickly as possible.
If you don't see the SDK in the package manager, check the Pipelines section in each SDK repo to troubleshoot any errors during the publishing process.
Common errors
If your repos are not configured correctly, you may see one of the following errors:
-
If the generate SDKs Action fails with this error:
Bitbucket pipeline outputError: Secrets LIBLAB_TOKEN and LIBLAB_BITBUCKET_TOKEN are required
Then you haven't set up the
LIBLAB_TOKEN
orLIBLAB_BITBUCKET_TOKEN
secrets correctly. Check that the tokens are set correctly, and that the tokens are valid. -
If the pipeline generates the SDKs but fails to create a pull request in the SDK repo, presenting an error similar to the next one:
Bitbucket pipeline outputError occurred while creating PR for Python: Access to push changes to branch v1.0.0-1730738768515 is forbidden
Then, your
LIBLAB_BITBUCKET_TOKEN
access token does not have the necessary permissions. Remember, you have to create a workspace or project access token. Only use the Repository access token if you are using the free account. Don't use the Bitbucket app password in the access token place.