End-to-end SDK generation and publishing with GitLab Pipelines
This tutorial includes the following SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
This tutorial will guide you through generating an SDK using liblab and automating the SDK publishing process using GitLab CI/CD pipelines. By combining liblab and GitLab's CI/CD features, you can manage the entire SDK lifecycle, from generation to publication on package managers such as npm, PyPI, and Maven.
By the end of this tutorial, you will have a GitLab CI/CD pipeline that automatically generates SDKs from your API specification and publishes them to package managers.
Prerequisites
To follow this tutorial, you’ll need the following:
- liblab CLI installed and logged in.
- A GitLab account.
- An API specification in OpenAPI or Swagger format.
- Package manager accounts with appropriate publishing permissions for npm, PyPI, Maven, etc.
Steps
This tutorial covers the following steps:
- Create a control repo
- Create SDK repos
- Create liblab and GitLab tokens
- Create package manager tokens
- Update your spec and config file
- Merge SDK PRs
- Create a release in GitLab
- Confirm SDK publication
1. Create a control repo
The first step is to create a control repo, which is used as the central repo to store your liblab config file, any hooks code, and the API spec.
You don't need to store the OpenAPI spec in the repo. You can link your OpenAPI spec from other repos directly to the liblab.config.json
file.
For this tutorial, you can use the control-repo-template. Access the control repo documentation for more information. The control-repo-template provided by liblab contains:
File | Description |
---|---|
.gitlab-ci.yml | It automates the SDK generation process and creates pull requests for changes in specific files, such as liblab.config.json and directories like hooks and customPlanModifiers . It triggers on pushes to the main branch or manual web actions, using a Node.js environment to execute the build. |
liblab.config.json | An example of liblab configuration file. It contains the configuration used by the liblab CLI to generate SDKs. |
spec.json | An OpenAPI spec example based on the Petstore. The liblab.config.json file is refering this OpenAPI spec. |
.github/workflows | Directory with two GitHub Actions. One creates PRs for your SDKs when your API spec or config file changes. The second GitHub Action polls for liblab updates and creates PRs for your SDKs when there is a liblab update. |
The control-repo-template is hosted in GitHub, therefore, you need to perform the following steps to use it with GitLab:
-
Create a new repo in GitLab. In your GitLab dashboard:
- Click New project.
- Select Create blank project.
- Set the Project name and Project slug and select Visibility Level as Public.
- Click Create project.
-
Clone the GitHub repo to your local machine:
git clone https://github.com/liblaber/control-repo-template
- Navigate to the cloned repo on your machine and add your new GitLab repo as a remote:
cd control-repo-template
git remote add gitlab https://gitlab.com/<your-gitlab-username>/<your-gitlab-repo>.git
- Push the control-repo-template to your GitLab repo:
git push gitlab main
This is what you should have on your GitLab project:
2. Create SDK repos
Each SDK you create needs its own repo for storage and publication. These SDK repos should be created before you can publish your SDKs. You can create these repos manually or use one of the liblab templates.
Create new GitLab projects for each SDK language or use liblab's templates:
If you're using a liblab template, follow the steps outlined in Step 1 to use the templates with GitLab.
Each liblab template includes a GitLab CI automation file that automates the build and deployment process of the SDK to the package manager service.
Learn more about the SDK repos by accessing the SDK repos documentation.
After creating the repos, this is what you should have:
3. Create liblab and GitLab tokens
The GitLab CI/CD pipeline used by the control repo that will generate SDKs requires two secrets:
- A liblab token that authenticates the liblab CLI.
- A GitLab token that allows the liblab CLI to push to your SDK repos.
3.1 Create a liblab token
To create the liblab token, follow the steps below:
-
Using the liblab CLI on your machine, run the following command to generate a liblab token:
Terminalliblab token create GITLAB_CI_TOKEN
You can replace
GITLAB_CI_TOKEN
with any name of your choice. If you're generating SDKs for multiple APIs, you can either use the same token for all of them or create separate tokens for each API.TerminalToken successfully generated, it will be valid for 90 days
-TOKEN-----------------------------------------
liblab_td7MY4WfsE6Df4BRfyhoma7uONeOrSWmvxtSRPDj
-----------------------------------------------noteBy default, the token expires after 90 days. You can extend this to up to 364 days by passing the
--durationInDays
parameter.Learn more about the
liblab token
command in the CLI documentation. -
Copy the generated token. You should copy only the string
liblab_...
at the central line. The token will allow liblab to authenticate during the CI/CD pipeline run. -
Add the token to your Gitlab control-repo project. Access your GitLab project, navigate to Settings > CI/CD > Variables and click Add variable. For Key, use
LIBLAB_TOKEN
and paste the liblab token into the Value field. After, click Add variable.
3.2 Create a GitLab token
To enable the GitLab pipeline to run the liblab CLI and push changes to your SDKs repos, you need to generate a GitLab personal access token:
-
In GitLab, click at your profile picture and select Preferences.
-
Access the Access tokens tab from the sidebar.
-
Select Add new token.
-
Enter a name (e.g.,
liblab-token
) and an expiration date based on your organization's security policy.tipIt's helpful to create a calendar reminder to refresh the token before it expires.
-
Select the following scopes:
- api
- read_repository
- write_repository
- read_user
-
Select Create personal access token and copy the generated token. This token will be used to authenticate and push SDKs to your SDK repos.
-
Add this token to your GitLab project's Settings > CI/CD > Variables as
LIBLAB_GITLAB_TOKEN
.
This is what you should have set up so far:
4. 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 an Actions secret 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 an Actions secret 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 as an Actions secret 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. - For GitHub namespaces (namespace in the form of
io.github.githuborgname
), though, verification process is automatic if the user is registered using the GitHub SSO.
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 GitHub Actions secret calledMAVEN_USERNAME
and the value of thePassword
field as a secret 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 GitHub Actions secret.
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 GitHub Actions secret called
GPG_PRIVATE_KEY
. -
Create another GitHub Actions secret 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 Actions secret named
PACKAGIST_TOKEN
and set the secretPACKAGIST_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 GitHub repository.
- Select Check to validate the repository and Submit to add your package to Packagist.
You should now have the following complete setup:
5. Update your spec and config file
After creating and configuring your SDK repos, the next step is to update your control repo with your API spec and configure the liblab.config.json
file.
Follow the steps below to update your API spec and trigger the release of new SDKs to the corresponding repos:
-
Clone your control repo and open it in your preferred code editor.
-
Replace the control repo API spec. The control repo includes a sample API spec (
spec.json
), which you can use to continue following this tutorial. However, you can replace the existingspec.json
with your API spec.- If you have a local API spec, replace the
spec.json
file with your own. - If your API spec is hosted remotely:
- Update the
specFilePath
field in theliblab.config.json
file with the URL of your remote API spec. - Delete the existing
spec.json
file from the repo if you are using a remote spec.
- Update the
- If you have a local API spec, replace the
-
Open the
liblab.config.json
file in your control repo and update the following fields:sdkName
: Set the name of your SDK.apiName
: Set the name of your API.apiVersion
: Specify the API version you're working with.languages
: List the SDK languages you want to generate, such as TypeScript, Python, Go, etc.
-
In the
liblab.config.json
, locate thelanguageOptions
section and update the options for each SDK language you are generating:-
Remove any unused languages. If there are languages you don't need, remove their configuration.
-
For each language, update the
githubRepoName
. liblab will use it to identify the GitLab project that matches the name of the corresponding SDK repo. -
Update the
sdkVersion
field to specify the version number for each SDK. -
Configure the specific fields 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 will default 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 example,github.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
.
-
In the
publishing
section, set thegithubOrg
as the GitLab group from the corresponding SDK repo.tipYou can configure additional optional settings. Access the liblab config file documentation to learn more.
After finishing, your
liblab.config.json
file should look like this:liblab.config.json{
"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": "github.com/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"
}
} -
-
Commit your changes to the
liblab.config.json
and API spec files. -
Push the changes to your control repo. This will trigger the pipeline that generates your SDKs and creates pull requests in your SDK repos.
6. Merge SDK PRs
After the control repo pipeline is complete, a pull request (PR) will be automatically created in each SDK repo.
Go to Build > Pipelines or Build > Jobs to check the pipeline and job status in the control repo.
When the pipeline starts a new job to build an SDK, the liblab CLI may require you to log in and confirm an authorization code. A link to the login page will be provided in the job logs within GitLab.
If you don't log in and confirm the code, the job may not be complete, and the SDK build will not be triggered.
After the job is completed successfully in the control repo, check the PRs generated by liblab in each SDK repo. To view the new PRs, access Code > Merge requests in each SDK repo.
If you don't see the PRs, check your control repo's CI/CD > Pipelines or Jobs section for any errors during the SDK generation process. You can also refer to the common errors section for troubleshooting.
To finish, follow the steps:
- Open each PR and review the changes to ensure the SDK was generated correctly.
- If everything looks correct, approve the PR and merge it into the main branch.
7. Create a release in GitLab
You need to create a release in the SDK repo to trigger the Action to publish your SDK to the package manager. To create a release, follow the steps below:
-
From each SDK repo, access Deploy > Releases and click Create a new release.
-
On the release page:
- Provide a Tag name. The tag should be a version number using semantic versioning, and it is common to prefix the version with
v
, such asv1.0.0
.
Note on Versioning Go PackagesIt is important to note that the release tag version will be used as the version of the package in the Go Packages repo. Therefore, it is important to follow semantic versioning and ensure that the version in the
liblab.config.json
file corresponds to the version of the release tag.- Give the release a Release title. The title can be the same as the tag.
- Add a Milestone. You can create one if necessary.
- Define the Release date and add the Release notes.
- Provide a Tag name. The tag should be a version number using semantic versioning, and it is common to prefix the version with
-
Click Create release
This will trigger the pipeline to publish the SDK to the relevant package manager.
8. 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.
Your setup is now fully automated to generate and publish SDKs with liblab and GitLab CI/CD, ensuring your latest API updates are quickly available to your users.
If you don’t see the SDK in the package manager, check the CI/CD > Pipelines or Jobs 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:
Error: Secrets LIBLAB_TOKEN and LIBLAB_GITLAB_TOKEN are required
Then you haven't set up the
LIBLAB_TOKEN
orLIBLAB_GITLAB_TOKEN
secrets correctly. Check that the tokens are set correctly, and that the tokens are valid.