release

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
  • Kill any
    turbo
    processes that might be running with SIGKILL
  • Before beginning the release, verify that gcloud is logged in by running
    gcloud auth print-access-token >/dev/null
    . If it fails, run
    gcloud auth login
    , then repeat the check. Do not continue with the release until the check succeeds.
  • Codex-specific: Before running release commands, make sure rbenv wins over the macOS system Ruby. Codex may start non-interactive shells with
    /usr/bin
    before
    ~/.rbenv/shims
    , causing Ruby 2.6 to be used even though the user's terminal uses Ruby 3.3.x. Run release commands that may invoke Ruby/Bundler with:
    PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" <command>
    Verify with
    PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" ruby --version
    ; it should use the user's rbenv Ruby, not
    /usr/bin/ruby
    . This matters because the lambda Ruby package currently resolves gems such as
    json
    that require Ruby >= 2.7.
  • Check
    npm whoami
    . Only if it fails, run
    npm login
    (I will manually do 2FA in the browser)
  • Use
    op item get "Npmjs" --fields password --reveal --account remotiondev.1password.com
    to get the password for NPM.
  • Use
    op item get "Npmjs" --otp --account remotiondev.1password.com
    to get a one-time password for 2FA.
  • Run
    npm token create --name="PublishRemotionXXXXXX" --packages "remotion" --packages "create-video" --packages-and-scopes-permission read-write --bypass-2fa --scopes "@remotion" --otp=<otp>
    . Replace XXXXXX with a random string so we have a unique name. Use
    op item get "Npmjs" --otp --account remotiondev.1password.com
    to get the OTP and pass it via
    --otp=
    . It will ask for a password, pipe in the password using
    echo "$PASSWORD" |
    .
    • Do not pass
      --json
      : npm masks the token as
      npm_***
      in JSON output, making it unusable. Redirect the plain output to a file in the scratchpad and extract the token with
      grep -oE 'npm_[A-Za-z0-9]{20,}'
      into a scratchpad file (e.g.
      $SP/npm_token
      ). Never print the token. If a token turned out unusable, revoke it with
      npm token revoke <id> --otp=<otp>
      (find the id with
      npm token list
      ).
  • Run
    bun i
  • Run
    bun run build
  • Run
    npm view remotion version
    to get the current version number
  • Run
    bun set-version.ts <version>
    , where <version> is the current version plus 1. If the exit code is not 0, abort the entire release process immediately. Do not pipe its output (e.g. into
    tail
    ): the shell is zsh, so
    $PIPESTATUS
    is unavailable and the exit code gets lost. Redirect to a log file instead, then confirm the
    v<version>
    commit and tag exist.
  • Run
    cd packages/example && sh runlambda.sh && cd ../..
    . If this fails, abort the release.
  • Publish the public packages under a temporary npm dist-tag, then promote
    latest
    only after every package is installable.
    validating
    is npm's automatic scan for ordinary publishes, not a reason to use
    npm stage
    . Do not run
    bun run release
    : its current script publishes directly to
    latest
    and starts private publishing and Git pushes before the availability gate.
    • From the repository root, after
      set-version.ts
      , run:
      bash
      releaseVersion=$(node -p "require('./packages/core/package.json').version")
      releaseTag="remotion-release-$(printf '%s' "$releaseVersion" | tr . -)"
      releaseManifest="/tmp/remotion-release-${releaseVersion}-packages.txt"
      bun publish.ts --list > "$releaseManifest"
      The manifest is the exact package list to check and promote. Record each package's previous
      latest
      tag so a partial promotion can be rolled back.
    • Check whether any package in the manifest is being published to npm for the first time. Bun adds
      latest
      to a package's initial publish even with
      --tag
      . If there are new packages, stop before the bulk publish and plan their first publication separately; this flow cannot keep their first version off
      latest
      .
    • Run
      NPM_CONFIG_TOKEN=<token> bun publish.ts --tag="$releaseTag"
      with the token created above. Bun still packs the packages and rewrites
      workspace:
      and
      catalog:
      dependencies. This tagged path does not tolerate republish errors. A successful upload is not proof that npm's scan is finished: check the manifest, exact package versions, and temporary tags. Do not upload the same version again while its scan is pending. If a publish attempt failed and the version is confirmed absent, resume that package alone with
      bun publish.ts --tag="$releaseTag" --only=<package>
      using the same token; never rerun the entire manifest blindly.
    • For each package in the manifest, require
      npm view <package>@<version> version --json
      and a successful
      npm pack <package>@<version> --pack-destination <temporary-directory>
      before promotion. The pack check confirms the tarball can actually be fetched. Run the per-package checks with a
      while read -r p; do ( ... ) & done < "$releaseManifest"; wait
      loop (not
      xargs -I
      , which fails with "command line cannot be assembled"). Right after publishing, expect roughly a third of the packages to still be
      validating
      ; this has taken ~15 minutes. Write the polling loop as a script and run it in the background, and draft the changelog meanwhile. Poll unresolved packages about once per minute; use the npm lifecycle status API where available:
      GET https://registry.npmjs.org/-/package/<encoded-package-name>/version/<version>/status
      , authenticated with publish access. URL-encode scoped names, such as
      @remotion%2Fwhisper-web
      , and keep credentials out of logs. If a package remains
      validating
      after an hour, report the release as pending and leave every
      latest
      tag on the prior release. Blocked, rejected, manual-review, missing, and unknown states also stop promotion; investigate them rather than treating them as scanning delays.
    • Once all packages are installable, use the release token to run
      npm dist-tag add <package>@<version> latest
      for every package in the manifest. The npm CLI ignores
      NPM_CONFIG_TOKEN
      (only
      bun publish
      respects it) and falls back to the login session, failing with
      EOTP
      . Pass the token like this instead:
      env "npm_config_//registry.npmjs.org/:_authToken=$TOKEN" npm dist-tag add ...
      . This is one registry operation per package; npm has no atomic multi-package promotion. Verify that
      npm view <package> dist-tags.latest --prefer-online
      equals the release version for every package. Parallel checks can return stale cached tags for a few packages; recheck mismatches sequentially before treating them as failures. If promotion fails partway, restore the recorded previous
      latest
      tags for packages already changed and report the incomplete release. After a successful promotion, remove the temporary tag from each package and verify the final tags. The release token gets
      E403
      on
      dist-tag rm
      , so use the logged-in session with a fresh OTP per call:
      npm dist-tag rm <package> <releaseTag> --otp=$(op item get "Npmjs" --otp --account remotiondev.1password.com)
      . If a call fails because the OTP rolled over, wait 30 seconds and retry once.
    • If npm explicitly returns
      E_STAGE_REQUIRED
      , direct publishing is unavailable for that package. Stop this release and assess a staged workflow separately; staged approval requires a 2FA action per package. Do not silently mix a staged package into this direct-publish flow.
  • Only after all public
    latest
    tags are verified, run
    bunx turbo run publishprivate --concurrency=1
    , then
    git push --tags
    and
    git push
    from the repository root. If any step fails, stop and report the affected release state.
  • Run
    bun run publishtemplates
    from the repository root to republish every template after the public packages have been promoted. If any template fails to publish, stop the release workflow and report the failure.
  • Generate a changelog in markdown and save it to
    /tmp/release-<version>.md
    :
    • Run
      git log v<previous_version>..v<new_version> --oneline
      to get all commits
    • Extract PR numbers from merge commits
    • For each PR, run
      gh pr view <number> --json title,author,number,url --jq '"* \(.title) by @\(.author.login) in \(.url)"'
    • Categorize PRs into sections: "What's Changed", "Templates", "Docs", "Internal"
    • Also use the "Elements" and "Internal and Experimental" sections when previous releases do
    • In "What's Changed", put headline features (especially ones with new docs pages) first, then sort items so that entries for the same package are adjacent (no subheadings, just sorted order). Changes to the
      remotion
      core package should appear first
    • Strip redundant prefixes from PR titles (e.g. remove "Docs:" from items in the Docs section)
    • Linkify items whose PR added a new documentation page: run
      git diff --diff-filter=A --name-only v<previous_version>..v<new_version> -- 'packages/docs/docs/**/*.mdx' 'packages/docs/docs/**/*.md'
      to list added docs pages, map each added page to the PR that introduced it, and wrap that item's title in a markdown link to the page (e.g.
      * [<title>](https://remotion.dev/docs/<slug>) by @author in <url>
      ). Determine the URL from the page's
      slug:
      frontmatter if present, otherwise from its file path relative to
      packages/docs/docs/
      . Leave items without a new docs page unlinked.
    • "Templates" is a separate section for any template-* changes
    • Check for genuinely new contributors by running
      gh api repos/remotion-dev/remotion/contributors --paginate --jq '.[].login'
      and comparing against PR authors. Only add a "New Contributors" section for authors not in that list
    • Add
      **Full Changelog**: https://github.com/remotion-dev/remotion/compare/v<previous_version>...v<new_version>
      at the bottom
    • Use the same format as previous GitHub releases (check with
      gh release view v<previous_version>
      )
    • Don't release until you get approval. Allow me to edit it before. This does not block the npm steps: draft the changelog while npm scans packages, and continue with promotion, private publishing, pushes and templates without waiting.
    • After approval, re-read
      /tmp/release-<version>.md
      (I may have edited it) and run
      gh release create v<version> --title v<version> --notes-file /tmp/release-<version>.md --verify-tag
      .
  • Finally, delete the local copies of the npm token from the scratchpad. It expires by itself after 7 days.
  • 使用 SIGKILL 终止任何可能正在运行的
    turbo
    进程
  • 在开始发布前,通过运行
    gcloud auth print-access-token >/dev/null
    验证 gcloud 是否已登录。如果失败,运行
    gcloud auth login
    ,然后重复检查。在检查成功前不要继续发布。
  • Codex 专属:运行发布命令前,确保 rbenv 优先于 macOS 系统 Ruby。Codex 可能会在
    ~/.rbenv/shims
    之前以
    /usr/bin
    启动非交互式 shell,导致使用 Ruby 2.6,即使用户终端使用的是 Ruby 3.3.x。对于可能调用 Ruby/Bundler 的发布命令,请使用:
    PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" <command>
    使用
    PATH="$HOME/.rbenv/shims:$HOME/.rbenv/bin:$PATH" ruby --version
    验证;它应使用用户的 rbenv Ruby,而不是
    /usr/bin/ruby
    。这一点很重要,因为 lambda Ruby 包当前解析的
    json
    等 gem 要求 Ruby >= 2.7。
  • 检查
    npm whoami
    。仅当该命令失败时,才运行
    npm login
    (我会在浏览器中手动完成 2FA)
  • 使用
    op item get "Npmjs" --fields password --reveal --account remotiondev.1password.com
    获取 NPM 密码。
  • 使用
    op item get "Npmjs" --otp --account remotiondev.1password.com
    获取用于 2FA 的一次性密码。
  • 运行
    npm token create --name="PublishRemotionXXXXXX" --packages "remotion" --packages "create-video" --packages-and-scopes-permission read-write --bypass-2fa --scopes "@remotion" --otp=<otp>
    。将 XXXXXX 替换为随机字符串,以获得唯一名称。使用
    op item get "Npmjs" --otp --account remotiondev.1password.com
    获取 OTP,并通过
    --otp=
    传入。它会要求输入密码,使用
    echo "$PASSWORD" |
    通过管道传入。
    • 不要传入
      --json
      :npm 会在 JSON 输出中将 token 掩码为
      npm_***
      ,使其无法使用。将纯文本输出重定向到 scratchpad 中的文件,并使用
      grep -oE 'npm_[A-Za-z0-9]{20,}'
      将 token 提取到 scratchpad 文件(例如
      $SP/npm_token
      )。绝不打印 token。如果某个 token 最终不可用,使用
      npm token revoke <id> --otp=<otp>
      撤销它(使用
      npm token list
      查找 id)。
  • 运行
    bun i
  • 运行
    bun run build
  • 运行
    npm view remotion version
    获取当前版本号
  • 运行
    bun set-version.ts <version>
    ,其中
    <version>
    为当前版本加 1。如果退出码不是 0,立即中止整个发布流程。不要对输出进行管道处理(例如传入
    tail
    ):shell 为 zsh,因此
    $PIPESTATUS
    不可用,退出码会丢失。改为重定向到日志文件,然后确认
    v<version>
    commit 和 tag 均存在。
  • 运行
    cd packages/example && sh runlambda.sh && cd ../..
    。如果失败,中止发布。
  • 先使用临时 npm dist-tag 发布公共包,只有在每个包都可安装后,才能将
    latest
    提升到新版本。
    validating
    是 npm 对普通发布执行的自动扫描,不是使用
    npm stage
    的理由。不要运行
    bun run release
    :当前脚本会直接发布到
    latest
    ,并在可用性检查通过前启动私有包发布和 Git push。
    • 从仓库根目录运行
      set-version.ts
      后,执行:
      bash
      releaseVersion=$(node -p "require('./packages/core/package.json').version")
      releaseTag="remotion-release-$(printf '%s' "$releaseVersion" | tr . -)"
      releaseManifest="/tmp/remotion-release-${releaseVersion}-packages.txt"
      bun publish.ts --list > "$releaseManifest"
      manifest 是需要检查和提升的精确包列表。记录每个包原先的
      latest
      tag,以便在部分提升失败时回滚。
    • 检查 manifest 中是否有包将首次发布到 npm。Bun 即使使用
      --tag
      ,也会在包首次发布时添加
      latest
      。如果存在新包,请在批量发布前停止,并单独规划其首次发布;此流程无法让这些包的首个版本避开
      latest
      。
    • 使用上述创建的 token 运行
      NPM_CONFIG_TOKEN=<token> bun publish.ts --tag="$releaseTag"
      。Bun 仍会打包这些包,并重写
      workspace:
      和
      catalog:
      依赖。这个带 tag 的发布路径无法容忍重复发布错误。上传成功并不能证明 npm 扫描已经完成:请检查 manifest、精确的包版本和临时 tag。扫描待处理期间,不要再次上传同一版本。如果某次发布尝试失败且已确认该版本不存在,仅使用
      bun publish.ts --tag="$releaseTag" --only=<package>
      恢复该包;绝不要盲目重跑整个 manifest。
    • 对于 manifest 中的每个包,在提升前必须要求
      npm view <package>@<version> version --json
      和
      npm pack <package>@<version> --pack-destination <temporary-directory>
      成功。pack 检查可确认 tarball 确实能够获取。使用
      while read -r p; do ( ... ) & done < "$releaseManifest"; wait
      循环执行逐包检查(不要使用
      xargs -I
      ,后者会报 "command line cannot be assembled")。发布后不久,预计约三分之一的包仍会处于
      validating
      ;整个过程可能持续约 15 分钟。将轮询循环编写为脚本并在后台运行,同时起草更新日志。每隔约一分钟轮询一次尚未解决的包;在可用时使用 npm lifecycle status API:以发布权限进行认证后,执行
      GET https://registry.npmjs.org/-/package/<encoded-package-name>/version/<version>/status
      。对 scoped 名称进行 URL 编码,例如
      @remotion%2Fwhisper-web
      ,并确保凭据不出现在日志中。如果某个包在一小时后仍为
      validating
      ,将发布报告为 pending,并让所有
      latest
      tag 保持在上一版本。
      blocked
      、
      rejected
      、
      manual-review
      、
      missing
      和
      unknown
      状态也会阻止提升;应调查这些状态,而不是将其视为扫描延迟。
    • 一旦所有包都可安装,就使用发布 token 对 manifest 中的每个包运行
      npm dist-tag add <package>@<version> latest
      。npm CLI 会忽略
      NPM_CONFIG_TOKEN
      (只有
      bun publish
      会读取它),转而使用登录会话,并因
      EOTP
      而失败。请改为以下方式传入 token:
      env "npm_config_//registry.npmjs.org/:_authToken=$TOKEN" npm dist-tag add ...
      。这是每个包一次 registry 操作;npm 不支持多包原子提升。验证每个包的
      npm view <package> dist-tags.latest --prefer-online
      均等于发布版本。并行检查时,少数包可能返回过期的缓存 tag;在将不匹配项视为失败前,应顺序重新检查。如果提升在中途失败,为已更改的包恢复已记录的上一版
      latest
      tag,并报告发布不完整。成功提升后,从每个包移除临时 tag,并验证最终 tag。发布 token 在执行
      dist-tag rm
      时会收到
      E403
      ,因此改用已登录会话,并为每次调用获取新的 OTP:
      npm dist-tag rm <package> <releaseTag> --otp=$(op item get "Npmjs" --otp --account remotiondev.1password.com)
      。如果调用因 OTP 已轮换而失败,等待 30 秒后重试一次。
    • 如果 npm 明确返回
      E_STAGE_REQUIRED
      ,则该包无法直接发布。停止本次发布,并单独评估 staged 流程;staged 审批要求为每个包执行一次 2FA 操作。不要将 staged 包悄悄混入此直接发布流程。
  • 仅在所有公共包的
    latest
    tag 都验证无误后,运行
    bunx turbo run publishprivate --concurrency=1
    ,然后在仓库根目录执行
    git push --tags
    和
    git push
    。如果任一步骤失败,停止操作并报告受影响的发布状态。
  • 在仓库根目录运行
    bun run publishtemplates
    ,在公共包完成提升后重新发布每个 template。如果任何 template 发布失败,停止发布流程并报告失败。
  • 使用 Markdown 生成更新日志,并保存到
    /tmp/release-<version>.md
    :
    • 运行
      git log v<previous_version>..v<new_version> --oneline
      获取所有 commit
    • 从 merge commit 中提取 PR 编号
    • 对于每个 PR,运行
      gh pr view <number> --json title,author,number,url --jq '"* \(.title) by @\(.author.login) in \(.url)"'
    • 将 PR 分类到以下栏目:"What's Changed"、"Templates"、"Docs"、"Internal"
    • 当之前的 release 使用相应栏目时,也使用 "Elements" 和 "Internal and Experimental" 栏目
    • 在 "What's Changed" 中,将重点功能(尤其是带新增文档页面的功能)放在最前,然后排序条目,使同一包的条目相邻(不使用子标题,只调整顺序)。对
      remotion
      核心包的更改应排在最前
    • 去除 PR 标题中冗余的前缀(例如,在 Docs 栏目中移除 "Docs:")
    • 对于其 PR 新增了文档页面的条目,添加 Markdown 链接:运行
      git diff --diff-filter=A --name-only v<previous_version>..v<new_version> -- 'packages/docs/docs/**/*.mdx' 'packages/docs/docs/**/*.md'
      列出新增文档页面,将每个新增页面映射到引入它的 PR,并把条目标题包装为指向页面的 Markdown 链接(例如
      * [<title>](https://remotion.dev/docs/<slug>) by @author in <url>
      )。如果 frontmatter 中有
      slug:
      ,则使用它确定 URL;否则根据文件相对于
      packages/docs/docs/
      的路径确定。没有新增文档页面的条目不要添加链接。
    • "Templates" 是单独栏目,用于放置所有 template-* 更改
    • 运行
      gh api repos/remotion-dev/remotion/contributors --paginate --jq '.[].login'
      并与 PR 作者比较,以检查真正的新贡献者。仅为此列表中不存在的作者添加 "New Contributors" 栏目
    • 在底部添加
      **Full Changelog**: https://github.com/remotion-dev/remotion/compare/v<previous_version>...v<new_version>
    • 使用与之前 GitHub release 相同的格式(通过
      gh release view v<previous_version>
      查看)
    • 获得批准前不要发布。允许我编辑它。这不会阻塞 npm 步骤:在 npm 扫描包时起草更新日志,并在无需等待的情况下继续提升、私有包发布、push 和模板发布。
    • 获得批准后,重新读取
      /tmp/release-<version>.md
      (我可能已编辑),并运行
      gh release create v<version> --title v<version> --notes-file /tmp/release-<version>.md --verify-tag
  • 最后,删除 scratchpad 中保存的本地 npm token 副本。该 token 会在 7 天后自动过期。