← Recipes

阅读中文版本

Freeze Dependency Updates Before a Release

Pin installs with a frozen lockfile and pause automated update pull requests during the release window, then unfreeze deliberately.

~25 mindependenciesreleaseci

Task

Guarantee the release artifact is built from exactly the dependency graph that passed testing.

When to use this

A release branch is cut on Friday. Over the weekend an automated bot merges four minor upgrades, and Monday's build contains code nobody tested. The release is delayed while the team bisects an unrelated failure.

Prerequisites

  • A committed lockfile managed by pnpm, npm, or yarn
  • Renovate or Dependabot configured on the repository
  • CI that installs from the lockfile

Steps

1. Make CI install strictly from the lockfile and fail when it is out of sync.

pnpm install --frozen-lockfile
# npm equivalent
npm ci
# yarn equivalent
yarn install --immutable

Expected output: The build fails if package.json and the lockfile disagree instead of silently resolving newer versions.

2. Pause automated dependency pull requests for the release window.

{
  "packageRules": [
    {
      "description": "Release freeze 2026-10-21 through 2026-10-28",
      "matchPackageNames": ["*"],
      "enabled": false
    }
  ]
}

Expected output: Renovate opens no new update pull requests until the rule is removed, while existing branches stop updating.

3. Verify the lockfile does not change during the release build.

git diff --exit-code pnpm-lock.yaml && echo 'lockfile unchanged'

Expected output: The command exits zero and prints lockfile unchanged before the artifact is published.

4. After the release, remove the freeze and merge upgrades one at a time with the full test suite.

git revert --no-edit 4f2c1ab && pnpm install && pnpm test

Expected output: Update pull requests resume, and each upgrade is validated in isolation before the next one merges.

Troubleshooting

Problem

pnpm install --frozen-lockfile fails on the release branch

Solution

The lockfile is out of sync; run pnpm install --lockfile-only intentionally, review the diff, and commit it as part of the release preparation.

Problem

A critical CVE lands during the freeze

Solution

Allow a documented exception with security approval, apply only that upgrade, and rerun the full test suite before shipping.

Limitations

  • Freezing delays security patches and should last days, not weeks.
  • The lockfile does not pin base container images, OS packages, or externally resolved peer dependencies.

Freeze the graph, not just the version

Pinning a direct dependency in package.json does not pin its transitive dependencies. Only the lockfile records the exact resolved graph. A frozen install fails loudly when package.json and the lockfile disagree, which is exactly what you want on a release branch: no silent resolution of a version that was never tested.

Pause the bots

Automated update tools are valuable most of the time and harmful during a release window. Disable their pull requests for the freeze period, either with a repository-level config rule or by pausing the app. Record the freeze dates in the release checklist so nobody wonders why updates stopped. Existing branches should be left alone rather than force-pushed.

packageRules:
  - description: Release freeze 2026-10-21 through 2026-10-28
    matchPackageNames: ["*"]
    enabled: false

Prove nothing moved

Run git diff --exit-code on the lockfile in the release pipeline. If it changes, the build resolved something new and should stop. Also compare the container image digest, not just the tag, because a mutable tag can point at a rebuilt image. Store the lockfile hash in the release notes for traceability.

Unfreeze with discipline

The risk you deferred does not disappear. After the release, re-enable updates and merge them in small batches with tests between. Prioritize security patches and runtime upgrades. If an emergency CVE appears during the freeze, treat it as a documented exception: one package, security approval, full regression, then back to the freeze.