release-pub Skill
This skill is a specialized release workflow for Dart and Flutter packages published to pub.dev (including Dart CLI tools). It relies on a local helper script (release_helper) to safely manipulate pubspec.yaml and CHANGELOG.md.
Official Documentation
For detailed information on automated publishing, refer to the official Dart documentation:
Automated publishing of packages to pub.dev
[!CAUTION]
Immutable Tags: NEVER delete, modify, or re-push a Git tag that has already been published to pub.dev. Pub.dev entries are immutable. If a mistake is found after publishing, you must publish a new version (e.g., a patch release) instead of attempting to overwrite the existing tag.
Workflow Overview
Follow these steps precisely:
0. Initial Setup Verification (One-time only)
If this is the first time the package is being published via GitHub Actions, ensure the user has configured OIDC on pub.dev and added the workflow file:
Configure pub.dev:
- Advise the user to access
https://pub.dev/packages/<package_name>/admin.
- Find the Automated publishing section and click Enable publishing from GitHub Actions.
- Recommend setting the Repository to the current repository (
owner/repo).
- Set the Tag pattern:
- For single package repositories:
v{{version}} (recommended) or {{version}}.
- For monorepos:
package_name-v{{version}}.
- Security Hardening (Optional but recommended): Mention the Require GitHub Actions environment option to restrict publishing to specific users/approvers via GitHub Deployment Environments.
Add GitHub Actions Workflow:
- Ensure
.github/workflows/publish.yml exists with the following content (adjust the tag pattern if necessary):
name: Publish to pub.dev
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+*' # Align with the tag-pattern on pub.dev (e.g., 'v{{version}}')
jobs:
publish:
permissions:
id-token: write # Essential for OIDC authentication
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
# with:
# working-directory: path/to/package # Required if the package is not in the root
Wait for the user to confirm the setup is complete before proceeding with the first automated release.
1. Pre-release Checks
- Check if there are any uncommitted changes:
git status -s. If there are, tell the user to commit or stash them before proceeding.
- README / Docs Update Check: Scan the recent changes. If there are new features or changed options, remind the user to check if
README.md or other documentation needs updating before releasing.
- CRITICAL: Run the appropriate formatter, analyzer, and tests based on the project type:
- For Dart packages:
dart format ., dart analyze, and dart test
- For Flutter packages:
flutter format . (or dart format .), flutter analyze, and flutter test
- [MANDATORY]: Resolve ALL analyzer issues (errors, warnings, and info level lints) before proceeding. Do not ignore "info" level issues unless they are explicitly documented as unavoidable.
- If there are unresolved issues, report them and ask the user to fix them (or offer to fix them if they are straightforward).
- CRITICAL: Run the pre-publish dry-run:
- For Dart packages:
dart pub publish --dry-run
- For Flutter packages:
flutter pub publish --dry-run
If warnings or errors appear (other than expected ones that can be ignored), report them and ask for user confirmation to proceed.
2. Analyze Changes & Plan Release
- Find the last tag:
LAST_TAG=$(git tag --sort=-v:refname | head -1)
- Analyze the commits since the last tag:
git log ${LAST_TAG}..HEAD --oneline
- Determine if a tag prefix is used:
- Check the format of the
$LAST_TAG. If it starts with v (e.g., v1.2.3), use v as the prefix for the new tag.
- If no tags exist (first release), default to using the
v prefix (TAG_PREFIX="v").
- Otherwise, follow the existing pattern (no prefix if
$LAST_TAG is just a version string).
- Determine the bump type (
major, minor, patch) based on Conventional Commits:
BREAKING CHANGE: or <type>!: -> major (or minor if version is < 1.0.0 but follow the user's lead on pre-1.0.0 breaking changes).
feat: -> minor
fix:, docs:, chore:, refactor:, perf: etc. -> patch
- Generate markdown for
CHANGELOG.md notes describing the changes. Generate the notes entirely in English. DO NOT include the ## [version] - [date] title header in the notes as the script adds that automatically.
- Generate Preview (Dry-Run): Present a clear preview of the upcoming release to the user before making any file changes.
- Show the version bump recommendation (e.g.,
1.2.3 -> 1.3.0 (Recommended: feat=minor)) and offer other valid SemVer alternatives (e.g. 1.2.4, 2.0.0) in case they want a different bump.
- List the categorized commits that will be included in the release.
- Show the preview text of the upcoming
CHANGELOG.md entry.
3. Execution using Helper Script
Use the bundled Dart CLI script to apply changes safely. The script is located at .agents/skills/release-pub/scripts/release_helper.
Prepare Release (Version Bump & Changelog):
Determine the bump type (major, minor, patch) and the notes as analyzed in Step 2.
dart run .agents/skills/release-pub/scripts/release_helper/bin/release_helper.dart prepare <type> --notes "
### Features
- ...
### Bug Fixes
- ...
"
Extract New Version:
Read the pubspec.yaml to find the newly updated version string (e.g. 1.2.3). Let's call this $NEW_VERSION.
4. User Confirmation
Ask the user to confirm the prepared release based on the generated preview in Step 2:
- First present the version change options (e.g., "1.3.0 (Recommended)", "1.2.4", "2.0.0").
- Once the user chooses the version, proceed to update the files locally via Step 3.
- After running the execution helpers, show the user the Git diff (
git diff) and ask: "Ready to create release commit and tag (v$NEW_VERSION)?"
Wait for explicit confirmation.
5. Git & GitHub Operations
Once the user confirms:
- Stage the files:
git add pubspec.yaml CHANGELOG.md
- Commit:
git commit -m "chore: release v$NEW_VERSION"
Note: Do NOT add a Co-Authored-By line. This is a release commit, not a code contribution.
- Tag:
git tag ${TAG_PREFIX}$NEW_VERSION
- Push:
git push origin main
git push origin ${TAG_PREFIX}$NEW_VERSION
- Create GitHub Release:
Save the notes to a temporary file, e.g.,
/tmp/release_notes.md, then:gh release create ${TAG_PREFIX}$NEW_VERSION --title "${TAG_PREFIX}$NEW_VERSION" --notes-file /tmp/release_notes.md
env -u GITHUB_TOKEN -u GH_TOKEN gh release create ${TAG_PREFIX}$NEW_VERSION --title "${TAG_PREFIX}$NEW_VERSION" --notes-file /tmp/release_notes.md
rm /tmp/release_notes.md
Finally, report that the release is complete and that GitHub Actions will automatically handle pushing to pub.dev.
6. Monitor & Verify pub.dev Publishing
Do not stop after pushing the release. Actively monitor the automated publishing process until it completes, and promptly inform the user of the result:
Locate Workflow Run:
After pushing the tag, GitHub Actions takes a few seconds to register the run. Query GitHub CLI to locate the run ID triggered for the release commit:
COMMIT_SHA=$(git rev-parse HEAD)
RUN_ID=""
for i in {1..10}; do
RUN_ID=$(env -u GITHUB_TOKEN -u GH_TOKEN gh run list --workflow=publish.yml -c "$COMMIT_SHA" --json databaseId -q '.[0].databaseId')
if [ -n "$RUN_ID" ]; then
break
fi
sleep 3
done
(If --workflow=publish.yml does not yield results because a different workflow name or file is used, query without --workflow: env -u GITHUB_TOKEN -u GH_TOKEN gh run list -c "$COMMIT_SHA" --json databaseId,workflowName -q '.[0].databaseId'.)
Watch Workflow Progress:
Track the workflow run until it finishes:
env -u GITHUB_TOKEN -u GH_TOKEN gh run watch "$RUN_ID" --exit-status
Verify Package on pub.dev:
Once the workflow succeeds, verify that pub.dev is serving the newly released version:
PACKAGE_NAME=$(grep '^name:' pubspec.yaml | awk '{print $2}')
for i in {1..10}; do
STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pub.dev/packages/$PACKAGE_NAME/versions/$NEW_VERSION")
if [ "$STATUS" = "200" ]; then
break
fi
sleep 3
done
Notify the User:
As soon as the release is verified on pub.dev, report the successful completion to the user along with the direct pub.dev link:
"🎉 Successfully published $PACKAGE_NAME v$NEW_VERSION to pub.dev: https://pub.dev/packages/$PACKAGE_NAME/versions/$NEW_VERSION"
1---2name: release-pub3description: A specialized workflow for releasing Dart and Flutter packages to pub.dev. Use when the user asks to "release", "publish to pub.dev", or "create a release" for a Dart/Flutter project.4---56# `release-pub` Skill78This skill is a specialized release workflow for Dart and Flutter packages published to pub.dev (including Dart CLI tools). It relies on a local helper script (`release_helper`) to safely manipulate `pubspec.yaml` and `CHANGELOG.md`.910## Official Documentation1112For detailed information on automated publishing, refer to the official Dart documentation:13[Automated publishing of packages to pub.dev](https://dart.dev/tools/pub/automated-publishing)1415> [!CAUTION]16> **Immutable Tags**: NEVER delete, modify, or re-push a Git tag that has already been published to pub.dev. Pub.dev entries are immutable. If a mistake is found after publishing, you must publish a new version (e.g., a patch release) instead of attempting to overwrite the existing tag.1718## Workflow Overview1920Follow these steps precisely:2122### 0. Initial Setup Verification (One-time only)2324If this is the first time the package is being published via GitHub Actions, ensure the user has configured OIDC on pub.dev and added the workflow file:25261. **Configure pub.dev**:27 - Advise the user to access `https://pub.dev/packages/<package_name>/admin`.28 - Find the **Automated publishing** section and click **Enable publishing from GitHub Actions**.29 - Recommend setting the **Repository** to the current repository (`owner/repo`).30 - Set the **Tag pattern**:31 - For single package repositories: `v{{version}}` (recommended) or `{{version}}`.32 - For monorepos: `package_name-v{{version}}`.33 - **Security Hardening (Optional but recommended)**: Mention the **Require GitHub Actions environment** option to restrict publishing to specific users/approvers via GitHub Deployment Environments.34352. **Add GitHub Actions Workflow**:36 - Ensure `.github/workflows/publish.yml` exists with the following content (adjust the tag pattern if necessary):3738```yaml39name: Publish to pub.dev4041on:42 push:43 tags:44 - 'v[0-9]+.[0-9]+.[0-9]+*' # Align with the tag-pattern on pub.dev (e.g., 'v{{version}}')4546jobs:47 publish:48 permissions:49 id-token: write # Essential for OIDC authentication50 uses: dart-lang/setup-dart/.github/workflows/publish.yml@v151 # with:52 # working-directory: path/to/package # Required if the package is not in the root53```5455Wait for the user to confirm the setup is complete before proceeding with the first automated release.5657### 1. Pre-release Checks5859- Check if there are any uncommitted changes: `git status -s`. If there are, tell the user to commit or stash them before proceeding.60- **README / Docs Update Check**: Scan the recent changes. If there are new features or changed options, remind the user to check if `README.md` or other documentation needs updating before releasing.61- **CRITICAL**: Run the appropriate formatter, analyzer, and tests based on the project type:62 - For Dart packages: `dart format .`, `dart analyze`, and `dart test`63 - For Flutter packages: `flutter format .` (or `dart format .`), `flutter analyze`, and `flutter test`64 - **[MANDATORY]**: Resolve **ALL** analyzer issues (errors, warnings, and **info** level lints) before proceeding. Do not ignore "info" level issues unless they are explicitly documented as unavoidable.65 - If there are unresolved issues, report them and ask the user to fix them (or offer to fix them if they are straightforward).66- **CRITICAL**: Run the pre-publish dry-run:67 - For Dart packages: `dart pub publish --dry-run`68 - For Flutter packages: `flutter pub publish --dry-run`69 If warnings or errors appear (other than expected ones that can be ignored), report them and ask for user confirmation to proceed.7071### 2. Analyze Changes & Plan Release7273- Find the last tag: `LAST_TAG=$(git tag --sort=-v:refname | head -1)`74- Analyze the commits since the last tag: `git log ${LAST_TAG}..HEAD --oneline`75- Determine if a tag prefix is used:76 - Check the format of the `$LAST_TAG`. If it starts with `v` (e.g., `v1.2.3`), use `v` as the prefix for the new tag.77 - If no tags exist (first release), default to using the `v` prefix (`TAG_PREFIX="v"`).78 - Otherwise, follow the existing pattern (no prefix if `$LAST_TAG` is just a version string).79- Determine the bump type (`major`, `minor`, `patch`) based on Conventional Commits:80 - `BREAKING CHANGE:` or `<type>!:` -> major (or minor if version is `< 1.0.0` but follow the user's lead on pre-1.0.0 breaking changes).81 - `feat:` -> minor82 - `fix:`, `docs:`, `chore:`, `refactor:`, `perf:` etc. -> patch83- Generate markdown for `CHANGELOG.md` notes describing the changes. Generate the notes entirely in **English**. _DO NOT include the `## [version] - [date]` title header in the notes as the script adds that automatically._84- **Generate Preview (Dry-Run)**: Present a clear preview of the upcoming release to the user before making any file changes.85 - Show the version bump recommendation (e.g., `1.2.3 -> 1.3.0 (Recommended: feat=minor)`) and offer other valid SemVer alternatives (e.g. `1.2.4`, `2.0.0`) in case they want a different bump.86 - List the categorized commits that will be included in the release.87 - Show the preview text of the upcoming `CHANGELOG.md` entry.8889### 3. Execution using Helper Script9091Use the bundled Dart CLI script to apply changes safely. The script is located at `.agents/skills/release-pub/scripts/release_helper`.92931. **Prepare Release (Version Bump & Changelog)**:94 Determine the bump type (`major`, `minor`, `patch`) and the notes as analyzed in Step 2.9596 ```bash97 dart run .agents/skills/release-pub/scripts/release_helper/bin/release_helper.dart prepare <type> --notes "98 ### Features99 - ...100101 ### Bug Fixes102 - ...103 "104 ```1051062. **Extract New Version**:107 Read the `pubspec.yaml` to find the newly updated version string (e.g. `1.2.3`). Let's call this `$NEW_VERSION`.108109### 4. User Confirmation110111Ask the user to confirm the prepared release based on the generated preview in Step 2:112113- First present the version change options (e.g., "1.3.0 (Recommended)", "1.2.4", "2.0.0").114- Once the user chooses the version, proceed to update the files locally via Step 3.115- After running the execution helpers, show the user the Git diff (`git diff`) and ask: "Ready to create release commit and tag (v$NEW_VERSION)?"116 Wait for explicit confirmation.117118### 5. Git & GitHub Operations119120Once the user confirms:1211221. Stage the files:123 ```bash124 git add pubspec.yaml CHANGELOG.md125 ```1262. Commit:127 ```bash128 git commit -m "chore: release v$NEW_VERSION"129 ```130 _Note: Do NOT add a `Co-Authored-By` line. This is a release commit, not a code contribution._1313. Tag:132 ```bash133 git tag ${TAG_PREFIX}$NEW_VERSION134 ```1354. Push:136 ```bash137 git push origin main138 git push origin ${TAG_PREFIX}$NEW_VERSION139 ```1405. Create GitHub Release:141 Save the notes to a temporary file, e.g., `/tmp/release_notes.md`, then:142 ```bash143 gh release create ${TAG_PREFIX}$NEW_VERSION --title "${TAG_PREFIX}$NEW_VERSION" --notes-file /tmp/release_notes.md144 env -u GITHUB_TOKEN -u GH_TOKEN gh release create ${TAG_PREFIX}$NEW_VERSION --title "${TAG_PREFIX}$NEW_VERSION" --notes-file /tmp/release_notes.md145 rm /tmp/release_notes.md146 ```147148Finally, report that the release is complete and that GitHub Actions will automatically handle pushing to `pub.dev`.149150### 6. Monitor & Verify pub.dev Publishing151152Do not stop after pushing the release. Actively monitor the automated publishing process until it completes, and promptly inform the user of the result:1531541. **Locate Workflow Run**:155 After pushing the tag, GitHub Actions takes a few seconds to register the run. Query GitHub CLI to locate the run ID triggered for the release commit:156157 ```bash158 COMMIT_SHA=$(git rev-parse HEAD)159 RUN_ID=""160 for i in {1..10}; do161 RUN_ID=$(env -u GITHUB_TOKEN -u GH_TOKEN gh run list --workflow=publish.yml -c "$COMMIT_SHA" --json databaseId -q '.[0].databaseId')162 if [ -n "$RUN_ID" ]; then163 break164 fi165 sleep 3166 done167 ```168169 _(If `--workflow=publish.yml` does not yield results because a different workflow name or file is used, query without `--workflow`: `env -u GITHUB_TOKEN -u GH_TOKEN gh run list -c "$COMMIT_SHA" --json databaseId,workflowName -q '.[0].databaseId'`.)_1701712. **Watch Workflow Progress**:172 Track the workflow run until it finishes:173174 ```bash175 env -u GITHUB_TOKEN -u GH_TOKEN gh run watch "$RUN_ID" --exit-status176 ```177178 - **If the workflow fails**: Immediately fetch the error logs and alert the user:179 ```bash180 env -u GITHUB_TOKEN -u GH_TOKEN gh run view "$RUN_ID" --log-failed181 ```182 Explain what failed (e.g., pub.dev authentication/OIDC, package verification error, or environment protection rules) and suggest how to resolve it.1831843. **Verify Package on pub.dev**:185 Once the workflow succeeds, verify that pub.dev is serving the newly released version:186187 ```bash188 PACKAGE_NAME=$(grep '^name:' pubspec.yaml | awk '{print $2}')189 for i in {1..10}; do190 STATUS=$(curl -s -o /dev/null -w "%{http_code}" "https://pub.dev/packages/$PACKAGE_NAME/versions/$NEW_VERSION")191 if [ "$STATUS" = "200" ]; then192 break193 fi194 sleep 3195 done196 ```1971984. **Notify the User**:199 As soon as the release is verified on pub.dev, report the successful completion to the user along with the direct pub.dev link:200 "🎉 Successfully published `$PACKAGE_NAME` v`$NEW_VERSION` to pub.dev: https://pub.dev/packages/$PACKAGE_NAME/versions/$NEW_VERSION"