本文记录 Flutter 插件首次发布、GitHub Actions 自动发布、国内镜像处理和常见问题。
适用于:
- Flutter Plugin
- Flutter Package
- Dart Package
- macOS/Linux 开发环境
- GitHub Actions 自动发布
一、整体发布流程
首次发布
rust
完善插件资料
↓
本地检查
↓
切换到官方 pub.dev 源
↓
执行 dart pub publish
↓
使用 Google 账号完成授权
↓
在 pub.dev 配置 GitHub Actions 自动发布
pub.dev 目前只允许自动发布已经存在的包。因此,0.0.1 等第一个版本必须在本地使用 dart pub publish 发布,后续版本才能通过 GitHub Actions 自动发布。(Dart)
后续版本
修改代码
↓
更新版本号
↓
更新 CHANGELOG.md
↓
提交代码
↓
创建 Git Tag
↓
推送 Tag
↓
GitHub Actions 自动发布
二、发布前准备
2.1 必要文件
插件根目录建议至少包含:
bash
lib/
example/
test/
README.md
CHANGELOG.md
LICENSE
pubspec.yaml
analysis_options.yaml
其中:
| 文件 | 用途 |
|---|---|
README.md |
pub.dev 插件首页的主要内容 |
CHANGELOG.md |
展示每个版本的更新记录 |
LICENSE |
开源许可证,发布时必须提供 |
pubspec.yaml |
插件名称、版本、依赖和仓库信息 |
example/ |
插件使用示例 |
test/ |
自动化测试 |
pub.dev 会使用 README.md、CHANGELOG.md 和 pubspec.yaml 生成插件页面;发布包必须包含 LICENSE。(Dart)
2.2 检查 pubspec.yaml
示例:
yaml
name: ifl_table
description: A flexible and customizable table widget for Flutter applications.
version: 0.0.1
repository: https://github.com/your-name/ifl_table
issue_tracker: https://github.com/your-name/ifl_table/issues
environment:
sdk: ^3.5.0
flutter: ">=3.24.0"
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^5.0.0
重点检查:
name
description
version
repository
environment
dependencies
name
包名必须:
- 全部小写;
- 使用下划线分隔;
- 只能包含
[a-z0-9_]; - 不能以数字开头;
- 不能和 pub.dev 已有包重名。
例如:
makefile
name: ifl_table
description
描述需要使用英文,建议简洁说明插件解决的问题。
lua
description: A flexible and customizable table widget for Flutter applications.
version
使用语义化版本:
makefile
version: 主版本.次版本.修订版本
例如:
0.0.1
0.1.0
1.0.0
1.0.1
已经发布过的版本不能修改后重新覆盖,任何修改都必须增加版本号。(Dart)
repository
填写插件实际对应的 GitHub 仓库:
arduino
repository: https://github.com/your-name/ifl_table
如果没有单独配置 issue_tracker,且 repository 指向 GitHub,pub.dev 通常会使用仓库的 Issues 页面。(Dart)
2.3 不要配置错误的 publish_to
如果发布到官方 pub.dev,通常不要写 publish_to:
bash
# 不需要配置
# publish_to: ...
下面的配置会禁止发布:
makefile
publish_to: none
下面的配置会尝试发布到其他仓库:
arduino
publish_to: https://example.com
publish_to 用于指定非 pub.dev 仓库,或者通过 none 阻止包被发布。(Dart)
三、本地发布前检查
在插件根目录执行:
css
flutter pub get
dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test
dart pub publish --dry-run
3.1 dry-run 的作用
arduino
dart pub publish --dry-run
该命令不会真正发布,主要用于:
- 检查
pubspec.yaml; - 检查目录结构;
- 检查依赖;
- 显示即将上传的文件;
- 显示发布警告。
官方建议在真正上传前,认真检查 dry-run 输出的文件列表,避免上传无关文件或隐私文件。(Dart)
3.2 检查 Git 状态
执行:
lua
git status
建议确保:
vbnet
nothing to commit, working tree clean
如果还有改动,先提交:
sql
git add .
git commit -m "chore: prepare release 0.0.1"
git push
dart pub publish 会检查 Git 状态,并在存在未提交改动时给出警告。(Dart)
3.3 检查发布文件
dart pub publish --dry-run 会列出准备上传的所有文件。
不应上传的内容包括:
bash
.idea/
.vscode/
build/
.dart_tool/
*.jks
*.keystore
*.p12
*.mobileprovision
.env
私钥
Token
测试账号密码
无关截图或大型文件
一般情况下,pub 会忽略:
- 以
.开头的隐藏文件; .gitignore中忽略的文件;.pubignore中忽略的文件。
如果希望发布规则与 Git 忽略规则不同,可以创建 .pubignore。(Dart)
四、处理国内 pub 镜像
4.1 常见错误
发布时出现:
vbnet
Do you want to publish ifl_table 0.0.1 to
https://pub.flutter-io.cn (y/N)?
或者:
csharp
package repository requested authentication!
dart pub token add https://pub.flutter-io.cn
Authentication failed!
这说明当前终端配置了:
ini
PUB_HOSTED_URL=https://pub.flutter-io.cn
PUB_HOSTED_URL 会把 Dart 默认包仓库切换成指定的镜像服务器。(Dart)
这里不应该给国内镜像添加 Token,因为真正的发布目标应该是:
arduino
https://pub.dev
4.2 查看当前配置
macOS/Linux:
bash
echo $PUB_HOSTED_URL
如果输出:
arduino
https://pub.flutter-io.cn
说明当前使用的是国内镜像。
4.3 临时取消镜像
只对当前终端生效:
bash
unset PUB_HOSTED_URL
再次确认:
bash
echo $PUB_HOSTED_URL
没有任何输出即可。
然后重新执行:
rust
dart pub publish --dry-run
dart pub publish
确认提示中的地址为:
arduino
https://pub.dev
4.4 只在发布命令中取消镜像
也可以不修改当前终端环境,直接执行:
arduino
env -u PUB_HOSTED_URL dart pub publish --dry-run
正式发布:
bash
env -u PUB_HOSTED_URL dart pub publish
4.5 永久删除镜像配置
检查 Shell 配置文件:
bash
grep -n "PUB_HOSTED_URL" \
~/.zshrc \
~/.zprofile \
~/.bash_profile \
~/.bashrc \
2>/dev/null
找到:
arduino
export PUB_HOSTED_URL=https://pub.flutter-io.cn
删除或者注释:
shell
# export PUB_HOSTED_URL=https://pub.flutter-io.cn
然后重新加载:
bash
source ~/.zshrc
五、首次发布插件
5.1 正式发布
确保当前目录是插件根目录,然后执行:
rust
dart pub publish
正确的确认信息应该是:
vbnet
Do you want to publish ifl_table 0.0.1 to https://pub.dev (y/N)?
确认:
- 包名正确;
- 版本号正确;
- 地址是
https://pub.dev; - 上传文件没有问题。
然后输入:
y
5.2 登录授权
第一次发布时,终端通常会:
- 自动打开浏览器;或者
- 输出一个登录授权地址。
使用 Google 账号登录并授权。
首次成功发布包的账号,会成为该包最初的 uploader,并具有后续版本发布权限。(Dart)
5.3 发布成功后检查
发布完成后检查:
rust
插件首页
README 展示
CHANGELOG 展示
支持的平台
源码仓库链接
API 文档
示例代码
版本号
pub points
pub.dev 的分析可能不会立即完成,插件页面刚发布时部分评分和平台检测可能仍在处理中。
六、配置 GitHub Actions 自动发布
首次版本发布成功后,才能配置自动发布。(Dart)
6.1 在 pub.dev 配置仓库
进入插件的 Admin 页面:
bash
pub.dev/packages/ifl_table/admin
找到:
Automated publishing
点击:
csharp
Enable publishing from GitHub Actions
填写 GitHub 仓库:
GitHub用户名/仓库名
例如:
bash
your-name/ifl_table
Tag Pattern 填写:
v{{version}}
对应关系:
makefile
pubspec.yaml:version: 0.0.2
Git Tag: v0.0.2
仓库地址、Tag Pattern 和 pubspec.yaml 版本必须相互匹配。(Dart)
6.2 GitHub Actions 配置
创建:
bash
.github/workflows/publish.yml
内容:
yaml
name: Publish to pub.dev
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
jobs:
publish:
permissions:
id-token: write
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
该工作流使用 GitHub OIDC 临时凭证,不需要在 GitHub Secrets 中保存长期的 pub.dev Token。官方推荐优先使用 Dart 团队提供的 reusable workflow。(Dart)
6.3 插件不在仓库根目录
如果仓库结构是:
markdown
repository/
├── apps/
└── packages/
└── ifl_table/
├── pubspec.yaml
└── lib/
配置:
yaml
name: Publish ifl_table to pub.dev
on:
push:
tags:
- 'ifl_table-v[0-9]+.[0-9]+.[0-9]+'
jobs:
publish:
permissions:
id-token: write
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
with:
working-directory: packages/ifl_table
pub.dev 中的 Tag Pattern 对应设置为:
ifl_table-v{{version}}
一个仓库中包含多个包时,官方建议为不同的包使用独立 Tag Pattern 和独立发布工作流。(Dart)
七、发布后续版本
假设当前版本为:
makefile
version: 0.0.1
准备发布:
makefile
version: 0.0.2
7.1 修改版本号
makefile
version: 0.0.2
7.2 更新 CHANGELOG.md
markdown
## 0.0.2
- Fixed table layout issues.
- Improved documentation.
- Added new configuration options.
建议将最新版本放在最上面。
7.3 本地检查
css
flutter pub get
dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test
env -u PUB_HOSTED_URL dart pub publish --dry-run
7.4 提交代码
sql
git add .
git commit -m "chore: release 0.0.2"
git push origin main
7.5 创建并推送 Tag
perl
git tag v0.0.2
git push origin v0.0.2
推送 Tag 后,GitHub Actions 会自动运行并发布插件。pub.dev 要求自动发布工作流由 Git Tag push 触发,普通分支 push 或无 Tag 的工作流触发会被拒绝。(Dart)
可以在 GitHub 仓库的 Actions 页面查看发布日志。(Dart)
八、版本号规则
建议遵循:
MAJOR.MINOR.PATCH
主版本.次版本.修订版本
修复问题
例如:
0.0.1 → 0.0.2
1.0.0 → 1.0.1
适用于:
- 修复 Bug;
- 修改文档;
- 优化性能;
- 不破坏现有 API 的小改动。
新增兼容功能
例如:
0.1.0 → 0.2.0
1.1.0 → 1.2.0
适用于:
- 新增参数;
- 新增组件;
- 新增平台支持;
- 新增功能,同时保持向后兼容。
存在破坏性修改
例如:
1.4.0 → 2.0.0
适用于:
- 删除公开 API;
- 修改参数含义;
- 修改返回类型;
- 用户必须修改代码才能升级。
预发布版本
例如:
makefile
version: 1.0.0-dev.1
version: 1.0.0-alpha.1
version: 1.0.0-beta.1
version: 1.0.0-rc.1
适合测试尚未完全稳定的新版本。pub.dev 支持在版本号后添加 prerelease 后缀。(Dart)
九、常见问题
9.1 发布地址是 pub.flutter-io.cn
原因:
配置了 PUB_HOSTED_URL
处理:
bash
unset PUB_HOSTED_URL
dart pub publish
或者:
bash
env -u PUB_HOSTED_URL dart pub publish
9.2 Authentication failed
先检查发布地址。
如果地址是:
arduino
https://pub.flutter-io.cn
不要执行:
csharp
dart pub token add https://pub.flutter-io.cn
应取消国内镜像,重新发布到:
arduino
https://pub.dev
dart pub token 主要用于需要认证的第三方或私有包仓库。(Dart)
9.3 Package name already exists
说明包名已经被其他人占用。
需要修改:
makefile
name: 新的包名
包名在整个 pub.dev 中必须唯一。
9.4 Version already exists
例如 0.0.1 已发布,再次发布相同版本会失败。
修改:
makefile
version: 0.0.2
同时更新:
CHANGELOG.md
Git Tag
已经发布的版本不可覆盖。(Dart)
9.5 GitHub Action 没有触发
检查以下三处是否一致:
css
pubspec.yaml:
version: 0.0.2
pub.dev Tag Pattern:
v{{version}}
实际 Git Tag:
v0.0.2
再检查 workflow:
ini
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
如果推送的是:
0.0.2
而 workflow 只匹配:
v0.0.2
则不会触发。(Dart)
9.6 Action 触发但认证失败
检查工作流是否包含:
yaml
permissions:
id-token: write
以及是否使用:
arduino
uses: dart-lang/setup-dart/.github/workflows/publish.yml@v1
同时确认已经在 pub.dev 的 Admin 页面中绑定正确的 GitHub 仓库和 Tag Pattern。(Dart)
9.7 发布了错误版本怎么办
已发布版本通常不能直接删除。
如果只是普通 Bug,推荐:
- 修复问题;
- 增加版本号;
- 更新
CHANGELOG.md; - 发布新版本。
pub.dev 支持在发布后的七天内 retract 某个版本,但 retract 并不等于删除,且通常应该优先发布修复版本。(Dart)
十、Verified Publisher
个人插件可以直接使用 Google 账号发布。
公司或组织维护的插件,可以创建 Verified Publisher,用公司域名展示发布者身份。
当前新包不能直接通过命令发布到 Verified Publisher。通常流程是:
个人 Google 账号首次发布
↓
进入插件 Admin 页面
↓
将插件转移到 Verified Publisher
转移到 Verified Publisher 后不能再转回个人账号,因此操作前需要确认归属。(Dart)
十一、推荐发布命令
首次发布
css
flutter pub get
dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test
git status
env -u PUB_HOSTED_URL dart pub publish --dry-run
env -u PUB_HOSTED_URL dart pub publish
后续自动发布
以 0.0.2 为例:
sql
flutter pub get
dart format --output=none --set-exit-if-changed .
flutter analyze
flutter test
env -u PUB_HOSTED_URL dart pub publish --dry-run
git add .
git commit -m "chore: release 0.0.2"
git push origin main
git tag v0.0.2
git push origin v0.0.2
十二、发布检查清单
插件资料
- 包名没有被占用
-
description使用英文 -
README.md内容完整 -
CHANGELOG.md已更新 - 存在
LICENSE -
repository地址正确 -
example/可以运行 - 公开 API 有必要的注释
代码质量
-
dart format通过 -
flutter analyze通过 -
flutter test通过 - 没有密钥、密码和 Token
- 没有无关的大文件
- Git 工作区已提交
发布配置
-
pubspec.yaml版本号正确 - 没有
publish_to: none - 已取消
PUB_HOSTED_URL -
dry-run没有错误 - 发布地址是
https://pub.dev
自动发布
- 第一个版本已经手动发布
- pub.dev 已绑定 GitHub 仓库
- Tag Pattern 配置为
v{{version}} - workflow 包含
id-token: write - Git Tag 与版本号一致
-
CHANGELOG.md与版本号一致
十三、最简发布流程
以后发布新版本,只需要记住下面几步:
markdown
1. 修改 pubspec.yaml 版本号
2. 更新 CHANGELOG.md
3. 执行 flutter analyze 和 flutter test
4. 执行 dart pub publish --dry-run
5. 提交并推送代码
6. 创建与版本号一致的 Git Tag
7. 推送 Tag,等待 GitHub Actions 发布
示例:
perl
git add .
git commit -m "chore: release 0.0.2"
git push origin main
git tag v0.0.2
git push origin v0.0.2