Logofpack

Exit codes and JSON output

What every exit code means, and the machine-readable JSON result for scripts and CI.

退出码与 JSON 输出

每个退出码的含义,以及供脚本和 CI 使用的机器可读 JSON 结果。

Scripts and CI jobs should look at the exit code first, and at the JSON result for details.

Exit codes#

CodeMeaning
0success (--dry-run: the plan was produced)
1 at least one target failed to build/package, or a hook failed; fpack doctor : problems were found; fpack notarize : a submission was rejected or a query failed
2 usage or configuration error (unknown flag or target, no targets and no build.targets , invalid fpack.yaml, no Flutter project found)
3 prerequisites missing / artifact already exists / nothing buildable / Flutter SDK not found; fpack notarize : no notarization record found
130 interrupted by Ctrl-C (an interrupted notarization wait keeps processing on Apple's side)

Use them to react: 3 means a prerequisite is missing and nothing was built (fix the machine, do not retry blindly); 2 means your command or configuration is wrong; 1 means something was built or checked and failed.

fpack build apk aab || echo "fpack exited with $?"

JSON output#

--json prints exactly one JSON document to stdout; all human-readable output goes to stderr, so you can redirect safely:

fpack build apk aab --json > result.json
fpack doctor --json
fpack list --json

A successful web build looks like this (shortened):

{
  "fpackVersion": "1.1.16",
  "project": "my_app",
  "version": "1.0.0",
  "buildNumber": "1",
  "flutter": "3.47.7",
  "host": "linux/amd64",
  "mode": "release",
  "outputDir": "/work/my_app/dist/1.0.0+1",
  "checksumsFile": "/work/my_app/dist/1.0.0+1/SHA256SUMS",
  "logDir": "/work/my_app/build/fpack/logs",
  "targets": [
    {
      "target": "web",
      "platform": "web",
      "status": "success",
      "artifacts": [
        {
          "path": "/work/my_app/dist/1.0.0+1/my_app-1.0.0+1-web.zip",
          "file": "my_app-1.0.0+1-web.zip",
          "kind": "Web (zip)",
          "size": 14431167,
          "sha256": "7f78faa3…"
        }
      ],
      "durationMs": 22802
    }
  ],
  "exitCode": 0,
  "durationMs": 22813,
  "dryRun": false,
  "success": true
}

Fields of fpack build --json#

FieldMeaning
fpackVersion , project , projectRoot , version , buildNumber , flutter , flutterRoot , host , mode , flavor what was built, with which tools
outputDir, checksumsFile, logDir where artifacts, checksums and logs are
targets[]one entry per target
targets[].status success, failed, skipped or planned (dry run)
targets[].reason, fix why a target was skipped and how to make it buildable
targets[].error, hint, log, errorExcerpt[] failure details: message, suggested fix, full log path, key lines
targets[].warnings[], notes[], commands[] warnings, notes and the commands that ran or would run
targets[].artifacts[] path , file , kind , arch , size , sha256 (and sha512 )
targets[].artifacts[].notarization for notarized macOS files: state ( submitted , accepted , stapled , invalid ), id , status , record (the NOTARIZATION.md path)
targets[].durationMs, durationMstiming
hookErrorthe error of a failed hook
hooks[]the hook commands a dry run would execute
conflicts[] existing artifacts a real run would stop on (use --force to replace them)
exitCode, success, dryRun, interrupted the outcome

Examples#

# upload every artifact
jq -r '.targets[].artifacts[].path' result.json

# did every target succeed?
jq -e '.success' result.json

# list skipped targets and why
jq -r '.targets[] | select(.status=="skipped") | "\(.target): \(.reason)"' result.json

Next#

CI recipes put these to work; troubleshooting explains what to do for each failure.

脚本和 CI 任务应先看退出码,再看 JSON 结果了解细节。

退出码#

退出码含义
0成功(--dry-run:计划成功生成)
1 至少一个目标在构建/打包时失败,或钩子失败;fpack doctor:发现问题;fpack notarize:有提交被拒绝或查询失败
2用法或配置错误(未知参数或目标、未指定目标且没有 build.targets、fpack.yaml 有误、找不到 Flutter 项目)
3前置条件不满足 / 产物已存在 / 没有可构建的目标 / 找不到 Flutter SDK;fpack notarize:找不到公证记录
130被 Ctrl-C 中断(公证等待被中断时,Apple 端仍会继续处理)

据此做出反应:3 表示缺少前置条件,什么都没构建(修好机器,不要盲目重试);2 表示你的命令或配置有误;1 表示构建或检查已经运行但失败了。

fpack build apk aab || echo "fpack 退出码 $?"

JSON 输出#

--json 向 stdout 恰好输出一个 JSON 文档;所有人类可读的输出走 stderr,所以可以放心重定向:

fpack build apk aab --json > result.json
fpack doctor --json
fpack list --json

一次成功的 Web 构建大致如下(已缩短):

{
  "fpackVersion": "1.1.16",
  "project": "my_app",
  "version": "1.0.0",
  "buildNumber": "1",
  "flutter": "3.47.7",
  "host": "linux/amd64",
  "mode": "release",
  "outputDir": "/work/my_app/dist/1.0.0+1",
  "checksumsFile": "/work/my_app/dist/1.0.0+1/SHA256SUMS",
  "logDir": "/work/my_app/build/fpack/logs",
  "targets": [
    {
      "target": "web",
      "platform": "web",
      "status": "success",
      "artifacts": [
        {
          "path": "/work/my_app/dist/1.0.0+1/my_app-1.0.0+1-web.zip",
          "file": "my_app-1.0.0+1-web.zip",
          "kind": "Web (zip)",
          "size": 14431167,
          "sha256": "7f78faa3…"
        }
      ],
      "durationMs": 22802
    }
  ],
  "exitCode": 0,
  "durationMs": 22813,
  "dryRun": false,
  "success": true
}

fpack build --json 的字段#

字段含义
fpackVersion 、 project 、 projectRoot 、 version 、 buildNumber 、 flutter 、 flutterRoot 、 host 、 mode 、 flavor 构建了什么、用的什么工具
outputDir、checksumsFile、logDir产物、校验和与日志的位置
targets[]每个目标一项
targets[].status success、failed、skipped 或 planned(预演)
targets[].reason、fix目标为何被跳过,以及如何让它可以构建
targets[].error、hint、log、errorExcerpt[] 失败详情:错误信息、建议的修复、完整日志路径、关键行
targets[].warnings[]、notes[]、commands[] 警告、说明,以及已运行(或将运行)的命令
targets[].artifacts[] path 、 file 、 kind 、 arch 、 size 、 sha256 (以及 sha512 )
targets[].artifacts[].notarization 已公证的 macOS 文件: state ( submitted 、 accepted 、 stapled 、 invalid )、 id 、 status 、 record ( NOTARIZATION.md 路径)
targets[].durationMs、durationMs耗时
hookError失败钩子的错误
hooks[]预演中将会执行的钩子命令
conflicts[]真正运行时会因此停止的已有产物(用 --force 替换)
exitCode、success、dryRun、interrupted 结果

示例#

# 上传所有产物
jq -r '.targets[].artifacts[].path' result.json

# 所有目标都成功了吗?
jq -e '.success' result.json

# 列出被跳过的目标及原因
jq -r '.targets[] | select(.status=="skipped") | "\(.target): \(.reason)"' result.json

下一步#

CI 示例把这些用起来;故障排查说明每种失败该怎么办。