Skip to content

Instantly share code, notes, and snippets.

@renggli
Last active August 16, 2025 09:53
Show Gist options
  • Select an option

  • Save renggli/d33c4867e7fd78605892fb3350759049 to your computer and use it in GitHub Desktop.

Select an option

Save renggli/d33c4867e7fd78605892fb3350759049 to your computer and use it in GitHub Desktop.
Dart Package Publication Script
#!/bin/bash
#
# dart-publish -- Publishes a Dart package to pub.dev.
#
# Copyright (c) 2025 Lukas Renggli, renggli@gmail.com
# Helper to print a highlighted caption.
function highlight {
echo
echo -e "\\033[1m\\c"
echo -e "$1\\c"
echo -e "\\033[m"
}
# Helper to print a fatal error message and quit.
function fatal {
echo
echo -e "\\033[91m\\c"
echo -e "$1\\c"
echo -e "\\033[m"
exit 1
}
# Ask the user a yes / no question.
ask() {
local prompt default reply
if [[ ${2:-} = 'Y' ]]; then
prompt='Y/n'
default='Y'
elif [[ ${2:-} = 'N' ]]; then
prompt='y/N'
default='N'
else
prompt='y/n'
default=''
fi
while true; do
echo -n "$1 [$prompt] "
read -r reply </dev/tty
if [[ -z $reply ]]; then
reply=$default
fi
case "$reply" in
Y*|y*) return 0 ;;
N*|n*) return 1 ;;
esac
done
}
# Check if we are in the package root.
PUBSPEC_YAML="pubspec.yaml"
if [ ! -f "$PUBSPEC_YAML" ] ; then
fatal "No pubspec.yaml file found."
fi
# Get the package name.
highlight "Checking package name ..."
NAME=$(grep 'name: ' "$PUBSPEC_YAML" | head -n1 | awk '{ print $2 }')
if [ -z "$NAME" ] ; then
fatal "No package name found."
fi
# Get the version to be published.
highlight "Checking package version ..."
VERSION=$(grep 'version: ' "$PUBSPEC_YAML" | head -n1 | awk '{ print $2 }')
if [ -z "$VERSION" ] ; then
fatal "No package version found."
fi
# Check no dependency overrides.
highlight "Checking dependency overrides ..."
DEP_OVERRIDE=$(grep 'dependency_overrides:' "$PUBSPEC_YAML" | head -n1)
if [ ! -z "$DEP_OVERRIDE" ] ; then
fatal "Package has dependency overrides."
fi
# Check if the git repository is clean state.
highlight "Checking git status ..."
if [ ! -z "$(git status --untracked-files=no --porcelain)" ]; then
fatal $(git status --short)
fi
# Check if this is a not yet published version.
highlight "Checking package status ..."
URL="https://pub.dev/packages/$NAME/versions/$VERSION"
curl --output "/dev/null" --silent --head --fail "$URL"
if [ "$?" -eq 0 ]; then
fatal "Package version already exists at <$URL>."
fi
# Update to all the latest packages.
highlight "Update package dependencies ..."
dart pub upgrade
if [ "$?" -ne 0 ]; then
fatal "Unable to update packages."
fi
# Check if any packages are outdated.
highlight "Checking package dependencies ..."
dart pub outdated --no-show-all
if [ "$?" -ne 0 ]; then
fatal "Outdated package dependencies."
fi
# Check if the package is compatible with flutter.
highlight "Checking flutter compatibility ..."
FLUTTER_DIR=$(mktemp -d)/example
flutter create "$FLUTTER_DIR" > /dev/null 2>&1
if [ "$?" -ne 0 ]; then
fatal "Unable to create flutter stub."
fi
flutter pub add "$NAME:{path: $(pwd)}" --directory="$FLUTTER_DIR"
if [ "$?" -ne 0 ]; then
fatal "Package is not compatible with flutter."
fi
# Check if the formatter is happy.
highlight "Checking source formatting ..."
dart format --output=none --set-exit-if-changed .
if [ "$?" -ne 0 ]; then
fatal "Source code is not well formatted."
fi
# Check if the fixer is happy.
highlight "Checking source fixes ..."
dart fix --dry-run
if [ "$?" -ne 0 ]; then
fatal "Source code is not well fixed."
fi
# Check if the analyzer is happy.
highlight "Analyzing source code ..."
dart analyze --fatal-infos --fatal-warnings .
if [ "$?" -ne 0 ]; then
fatal "Source code has analysis issues."
fi
# Check if the documentation is happy.
highlight "Generating documentation ..."
dart doc --dry-run
if [ "$?" -ne 0 ]; then
fatal "Genearation of documentation failed."
fi
# Running the default tests.
highlight "Running tests ..."
dart test --test-randomize-ordering-seed=random --reporter=failures-only .
if [ "$?" -ne 0 ]; then
fatal "Tests are not passing."
fi
# Running the binary tests.
highlight "Running compiled tests ..."
dart test --test-randomize-ordering-seed=random --reporter=failures-only --compiler=exe .
if [ "$?" -ne 0 ]; then
fatal "Compiled tests are not passing."
fi
# Running the JavaScript tests.
WEB_INCOMPATIBLE=$(grep 'ffi: ' "$PUBSPEC_YAML" | head -n1)
if [ -z "$WEB_INCOMPATIBLE" ] ; then
highlight "Running JavaScript tests ..."
dart test --test-randomize-ordering-seed=random --reporter=failures-only --platform=chrome --compiler=dart2js .
if [ "$?" -ne 0 ]; then
fatal "JavaScript tests are not passing."
fi
else
highlight "Skipping JavaScript tests ..."
fi
# Running the WebAssembly tests.
if [ -z "$WEB_INCOMPATIBLE" ] ; then
highlight "Running WebAssembly tests ..."
dart test --test-randomize-ordering-seed=random --reporter=failures-only --platform=chrome --compiler=dart2wasm .
if [ "$?" -ne 0 ]; then
fatal "WebAssembly tests are not passing."
fi
else
highlight "Skipping WebAssembly tests ..."
fi
# Running package scoring.
highlight "Running pana ..."
dart pub global activate pana
pana --no-warning --exit-code-threshold=0 .
if [ "$?" -ne 0 ]; then
if ! ask "Pana failed or didn't grant all points. Continue?" N ; then
fatal "Pana failed."
fi
fi
# Performing the publishing.
highlight "Publishing ..."
dart pub publish
if [ "$?" -ne 0 ]; then
fatal "Publishing failed."
fi
# Adding the tag to remember the new version.
highlight "Updating Git tag ..."
git tag --force v$VERSION
git-remote push --tags
# Complete
highlight "The package was published to <$URL>."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment