Publishing a library to pub.dev

Today I published my first ever library to pub.dev. Here's how it went.

Creating a verified publisher

I went to pub.dev and signed in. Once signed in, you can create a verified publisher. Verified publishers are based on a domain name and packages listed by a publisher will show up with a little blue badge.

The process is simple, they verify ownership of your domain by sending you a TXT value to set up there. On Google Domains, it took 10 minutes for the change to propagate and for pub.dev to verify my ownership.

Preparing the package for publishing

My very first step was to publish the package to GitHub. Then I went over to Dart's page on how to publish a package: https://dart.dev/tools/pub/publishing.

They require publishers to choose a license. I went for the recommended BSD license. However, the formatting of the LICENSE file is a bit odd. It has no extension and is commented out:

// Copyright <YEAR> <COPYRIGHT HOLDER>. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//    * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//    * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

I also had to complete pubspec.yaml by following https://dart.dev/tools/pub/pubspec.

It didn't take long.

Publishing

Once ready, I ran a dry run of the publication.

% pub publish --dry-run
Publishing google_sign_in_mocks 0.1.0 to https://pub.dartlang.org:
|-- .gitignore
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- analysis_options.yaml
|-- lib
|   |-- google_sign_in_mocks.dart
|   '-- src
|       '-- google_sign_in_mocks_base.dart
|-- pubspec.yaml
'-- test
    '-- google_sign_in_mocks_test.dart
Missing requirements:
* Your pubspec.yaml's "homepage" field must be an "http:" or "https:" URL, but it was "blog.wafrat.com".
Sorry, your package is missing a requirement and can't be published yet.
For more information, see: https://dart.dev/tools/pub/cmd/pub-lish.

The dry run is nice, it warns you of issues before you actually try to publish it for real. This time I was missing the http or https field to my homepage. After fixing this, it told me it was ready for publishing.

% pub publish
Publishing google_sign_in_mocks 0.1.0 to https://pub.dartlang.org:
|-- .gitignore
|-- CHANGELOG.md
|-- LICENSE
|-- README.md
|-- analysis_options.yaml
|-- lib
|   |-- google_sign_in_mocks.dart
|   '-- src
|       '-- google_sign_in_mocks_base.dart
|-- pubspec.yaml
'-- test
    '-- google_sign_in_mocks_test.dart

Looks great! Are you ready to upload your package (y/n)? y
Pub needs your authorization to upload packages on your behalf.
In a web browser, go to https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=force...
Then click "Allow access".

Waiting for your authorization...
Authorization received, processing...
Successfully authorized.
Uploading... (5.1s)
Successfully uploaded package.
% 

Right after this was done, the package was available in search and by direct link. However, they appeared as uploaded by my email address, not my publisher.

Transferring to the verified publisher

It turns out it is a limitation of the publishing tool. https://dart.dev/tools/pub/publishing#transferring-a-package-to-a-verified-publisher explains that you then have to go to your package and transfer ownership to your own publisher. Here's how it looks after being transferred:

If you go to Versions, you have access to the different versions uploaded to pub.dev. Each version has a link to the documentation. It takes a few minutes for pub.dev to generate the documentation.

Follow-ups

One feature I didn't know about is that if you click on the score chip, you can see how the score was computed.

In my case maintenance only scored 65 because:

  • The package description is too short. (-20 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

  • Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package.

Common filename patterns include main.dart, example.dart, and google_sign_in_mocks.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

  • Homepage URL is insecure. (-5 points)

Update the homepage field and use a secure (https) URL.

I won't write an example just yet but fixing the description is easy enough!

I tried publishing again under the same version name, and expectedly it told me that version already existed. Then I updated the version in pubspec.yaml and published again. This time it warned me that CHANGELOG didn't mention this version. This is quite polished!

After adding the version to the CHANGELOG, it accepted my update.

As you can see, popularity accounts for half the score.

Last note, pub.dev runs a linter and gives hint on bad quality code. This is what the health score represents.