Visitar URL original
GitHub - knu/lockfile-maintenance-action: Maintain lockfiles with native minimum release ages and automated pull requests. Β· GitHub
Skip to content

About

Maintain lockfiles with native minimum release ages and automated pull requests.

Resources

Stars

1 star

Watchers

1 watching

Forks

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Latest commit

Β 

History

94 Commits

Folders and files

Repository files navigation

Lockfile Maintenance Action for GitHub Actions

This Action updates Git-tracked package and GitHub Actions lockfiles within their existing dependency constraints. Cargo, npm, pnpm, Yarn, uv, and Bundler receive a minimum release age through their native resolvers. GitHub Actions lockfiles use dated release candidates and the official lockfile verifier.

By default, all supported lockfiles in the repository, including subdirectories, are selected. Use gitignore-style patterns to limit the selection. Untracked files are never selected.

The Action creates or updates a pull request by default, committing only the selected lockfiles. Set create-pull-request: false to update files without committing or opening a PR. Run project tests in the consuming repository's PR CI.

Why use this alongside Renovate?

Renovate's minimumReleaseAge controls proposed dependency updates, but lockfile maintenance delegates resolution to a package manager. Newly resolved transitive dependencies need a resolver-level age policy too. Renovate documents this distinction.

  • Cargo cooldown support: as of September 2026, Renovate's Cargo maintenance command does not pass its minimum release age to Cargo. This Action supplies Cargo's native publish-age setting using a pinned nightly toolchain.
  • Maintenance independent of Renovate's status checks: we have observed a maintenance PR remain pending on renovate/stability-days even though every locked version met the configured age at the PR's last update. The cause was not established. This Action applies the age policy during resolution and creates its own PR, without waiting for that Renovate status. Do not require renovate/stability-days globally in branch protection; keep normal review and PR CI requirements.
  • One workflow for package and action dependencies: select Git-tracked package lockfiles and actions.lock with path patterns. Review per-file version or commit changes, including transitive dependencies, in the PR body.
  • No repository secrets with the App: install the Lockfile Maintenance App and use OIDC. App-authored PRs trigger the repository's CI and can join its existing dependency merge queue.

Renovate already forwards age limits to npm and Poetry; it is not missing this integration for every manager. This Action also supports npm and fails rather than retrying without its cutoff. Keep Renovate for manifest updates and security alerts, and disable its lockfile maintenance only for the lockfiles delegated here. Native package/source exceptions still apply; see release-age behavior.

Usage

For normal use, call the reusable workflow. Install the Lockfile Maintenance App and configure OIDC authorization first.

name: Lockfile maintenance
on:
  schedule:
    - cron: 0 0 * * 5
  workflow_dispatch:
permissions:
  contents: read
  id-token: write
jobs:
  maintenance:
    uses: knu/lockfile-maintenance-action/.github/workflows/maintenance.yml@v2 # zizmor: ignore[unpinned-uses] -- Follow the tested v2 release series.
    with:
      files: /pnpm-lock.yaml

The reusable workflow supplies Harden-Runner, automatic tool setup, and update serialization. It uses the same commit of its bundled action through GitHub's $/ syntax. See the complete caller example.

For checkbox and comment requests, enable App-based rebase handling. The App dispatches this workflow only for valid requests and tracks completion outside Actions. The caller needs only schedule and workflow_dispatch; unrelated PR activity creates no maintenance workflow runs.

Both the composite Action and the reusable workflow default to OIDC authentication. For token authentication, use auth: token and pass a write token as secrets.token; its GITHUB_TOKEN intentionally has only read access to contents. Tool selection, minimum release age, branch/base, title, labels, working directory, and setup options are available as workflow inputs. The outputs are pull-request-url and changed. GitHub.com is required for the self-repository syntax and dispatch run tracking.

Using the composite action directly

on:
  schedule:
    - cron: "0 0 * * 1"  # At 00:00 UTC on Mondays

  workflow_dispatch:

name: "Lockfile Maintenance"

concurrency:
  group: lockfile-maintenance
  cancel-in-progress: false

permissions:
  contents: read
  id-token: write

jobs:
  update:
    runs-on: ubuntu-latest
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
        with:
          egress-policy: audit

      - uses: knu/lockfile-maintenance-action@v2 # zizmor: ignore[unpinned-uses] -- Follow the v2 release series in this example.
        id: maintenance
        with:
          files: /Cargo.lock
          minimum-release-age: 3 days

Install the Lockfile Maintenance App for the default OIDC authentication. To use token authentication instead, set auth: token and pass token with a fine-grained personal access token or supply a GitHub App installation token with contents and pull requests write access. These allow the consuming repository's PR CI to run without the approval required for PR workflows triggered by GITHUB_TOKEN.

See the Cargo workflow and the multi-tool workflow for complete examples. With auth: token, the default token is github.token; when using it, grant contents: write and pull-requests: write, and enable GitHub Actions to create pull requests in repository settings.

@v2 follows the latest main commit that passes this repository's CI. The Action is tested on Linux runners.

Migrating from v1

Version 2 defaults to OIDC. Install the Lockfile Maintenance App and grant id-token: write, or add auth: token to keep using an existing token or github.token. A token input alone no longer selects token authentication. For local-only updates without the App, use auth: token with create-pull-request: false. The v1 branch stays on its last compatible commit.

Supported tools

Tool Lockfile Required manifest Setup
Cargo Cargo.lock Cargo.toml Installs rustup if missing and nightly-2026-09-10 if absent
npm package-lock.json package.json Requires npm >=11.10, available with the Action's Node.js 24 runtime
pnpm pnpm-lock.yaml package.json Prepared automatically; requires pnpm >=11
Yarn yarn.lock package.json Prepared automatically; requires Yarn >=4.10
uv uv.lock pyproject.toml Automatically installs uv 0.12.17; requires >=0.9.17
Bundler Gemfile.lock Gemfile Automatically installs Ruby 4.0 and Bundler 4.0.21; requires Bundler >=4.0.18
GitHub Actions .github/workflows/actions.lock Onboarded workflows Requires gh on PATH; prepares github/gh-actions-lock v0.4.0

Yarn support uses the modern Yarn npmMinimalAgeGate setting and is tested with Yarn 4. Yarn Classic (1.x) and Yarn versions below 4.10 are not supported.

Each package manifest must be in the same directory as its lockfile. Select workspace-root lockfiles for package-manager workspaces. Selecting multiple npm, pnpm, or Yarn lockfiles for the same manifest is an error. npm shrinkwrap and Poetry lockfiles are not supported. A sibling npm-shrinkwrap.json prevents npm maintenance because it takes precedence over package-lock.json.

GitHub Actions lockfile maintenance

Onboard workflows with the official gh actions-lock extension before selecting /.github/workflows/actions.lock. Only this canonical path in the checkout is supported, on github.com, using lockfile schema v0.0.3. Workflow YAML is not rewritten, and new workflows are not onboarded during maintenance.

  • Partial refs such as @v1 and @v1.2 select the highest stable release in that version family whose GitHub Release published_at meets minimum-release-age. If today's release is too young, an older eligible release can still be used. Candidate commits must descend from the current pin and remain reachable from the referenced tag. Updates never downgrade a current pin.
  • Exact tags, full SHAs, branches, and non-version refs keep their current pins. Branch commit timestamps are not treated as release publication dates. Use Renovate or Dependabot to change workflow version constraints.
  • Newly introduced transitive dependencies must also have eligible dated releases. Existing pins can be retained without rechecking their age. A parent whose dependency graph cannot meet the policy tries its next older candidate, then retains its current pin. Independent dependencies continue updating. Drafts, prereleases, and unknown dates are not eligible.
  • Candidate composites containing workspace-local or self-repository action references are retained at their current version; this resolver does not infer their changed graphs. Reusable workflow calls and container images remain outside lockfile coverage.

The official extension's cooldown only emits findings; it does not exclude young candidates. This Action selects candidates from GitHub metadata, generates their dependency graph, and runs gh actions-lock --verify before and after updating. API errors, changed repository identities, and verification failures fail the run and restore original files. Publication dates are upstream metadata, not proof that a dependency is safe. Review the PR diff and run consuming workflows in PR CI.

The same token used by this Action must read every referenced action repository. gh must already be installed. setup-actions-lock defaults to true and installs or replaces the extension with tested version v0.4.0 when needed; set it to false for a manually provisioned v0.4.0. On self-hosted runners this setup persists in the runner user's gh extension directory.

The Action sets up Node.js 24 for its own runtime and installs its runtime dependencies in a temporary directory, reusing an npm download cache. Cargo uses the pinned nightly without changing the default Rust toolchain.

Inputs

  • request-comment, request-pull-request (string, optional)

    Comment ID and PR number forwarded from the request job through workflow_dispatch inputs. Pass both to report the result on the command comment. Leave them empty for scheduled or ordinary manual runs.

  • reaction-token (string, optional)

    Token used to report rebase results on command comments. Requires issues: write. Defaults to github.token, independently of auth and token, so OIDC authentication failures can still be reported.

  • auth (string, optional)

    Authentication mode: token uses the supplied token or github.token; oidc exchanges a GitHub Actions identity token for a repository-scoped installation token from the Lockfile Maintenance App. OIDC requires id-token: write, an App installation, and authorization by the broker. It never falls back to another credential on failure.

    Default: oidc

  • create-pull-request (string, optional)

    Create or update a maintenance PR. Use false to only update files; this mode needs no write token or PR permissions. Existing file-change outputs remain available in either mode.

    Default: true

  • token (string, optional)

    Token used for automatic checkout and to push the maintenance branch and create or update its PR. Checkout requires contents read access; PR creation also requires contents and pull requests write access.

    Ignored when auth is oidc.

    Default: ${{ github.token }}

  • author, committer (string, optional)

    Author and committer of maintenance commits, each in Name <email@example.com> format. These apply in both authentication modes. The PR author is determined by the authentication token: with auth: oidc, PRs are created by lockfile-maintenance[bot] using the Lockfile Maintenance App's installation token.

    Default for both: lockfile-maintenance[bot] <331761537+lockfile-maintenance[bot]@users.noreply.github.com>

  • branch (string, optional)

    Branch used for the maintenance PR. Repeated runs update the same PR. Use distinct branches for independent file selections, and serialize workflow runs that use the same branch.

    Default: automation/lockfile-maintenance

  • base (string, optional)

    Target branch for the PR and automatic checkout. An existing checkout keeps its current ref; check out the desired base yourself when supplying an existing checkout.

    Default: the repository's default branch

  • title (string, optional)

    Title of the maintenance PR. Repeated runs reset the title to this value. Give each branch a distinct title when several maintenance PRs are open at once.

    Default: Lockfile maintenance

  • labels (string, optional)

    Comma or newline-separated labels applied to the PR.

    Default: dependencies

  • files (string, optional)

    Newline-separated gitignore-style patterns, relative to working-directory. Positive patterns include files, ! excludes them, and the last matching pattern wins. Only Git-tracked files with supported lockfile names are considered.

    A basename such as Cargo.lock matches at any depth; /Cargo.lock matches only the root. Patterns support *, **, directory names, # comments, and backslash escapes. Blank lines are ignored. Unlike gitignore's directory traversal rules, a later inclusion can re-include a file inside an excluded directory.

    Default: all supported lockfiles, including subdirectories.

    files: |
      Cargo.lock
      package-lock.json
      pnpm-lock.yaml
      yarn.lock
      uv.lock
      Gemfile.lock
      !vendor/
      vendor/example/Cargo.lock
  • setup-actions-lock (boolean, optional)

    Prepare the tested verifier when actions.lock is selected. Default: true. See Actions maintenance for the required gh version setup and the effect on self-hosted runners.

  • setup-pnpm (boolean, optional)

    Prepare pnpm for each selected lockfile in an isolated temporary directory. The adjacent package.json can select an exact pnpm version >=11 using packageManager or devEngines.packageManager. Without a declaration, use a compatible pnpm on PATH, or install the tested fallback, pnpm 12.4.2. Different lockfile directories can use different versions.

    Set to false to use a manually installed pnpm >=11. Use manual setup for version ranges or integrity-suffixed declarations. Automatic setup does not install project dependencies or modify manifests, and removes its temporary tools after the run.

    Default: true

  • setup-yarn (boolean, optional)

    Prepare Yarn using the same per-manifest version selection and isolation as pnpm. Requires an exact version >=4.10; the tested fallback is Yarn 4.18.0. Set to false for a custom installation, version range, or integrity-suffixed declaration.

    Default: true

  • setup-uv, setup-bundler, setup-rustup (boolean, optional)

    Set up these tools only when their lockfiles are selected. uv uses astral-sh/setup-uv; Ruby and Bundler use ruby/setup-ruby. Missing or unusable rustup is installed with actions-rust-lang/setup-rust-toolchain. Package caches and dependency installation are disabled in these setup steps. Set the corresponding option to false to preserve a manually prepared environment. Cargo still installs its pinned nightly if needed.

    Default: true

  • uv-version, ruby-version, bundler-version (string, optional)

    Versions passed to automatic setup. Defaults: 0.12.17, 4.0, and 4.0.21, respectively. Specify ruby-version when a project requires a different Ruby; the default does not infer it from repository files. All selected Gemfiles share that Ruby and Bundler installation, so use separate invocations for projects requiring different runtimes.

  • minimum-release-age (string, optional)

    Minimum age passed to each native package resolver and used to select dated Actions releases. Use a positive integer followed by seconds, minutes, hours, days, weeks, or months, for example 3 days. A month means 30 days. Values are rounded up to whole minutes for pnpm and Yarn, and whole days for Bundler.

    Default: 3 days

  • release-history-layout (string, optional)

    separate places collapsible release histories after the version-change tables, with links to move between them. inline embeds collapsible histories in table rows. Version numbers link to upstream releases or tags when available.

    Default: separate

  • working-directory (string, optional)

    Root for file selection, relative to the checkout. It must remain inside the checkout. Symlinked lockfiles and lockfile directories are rejected.

    Default: . (the repository root)

Outputs

  • pull-request-number

  • pull-request-url

    Number and URL of the maintenance PR. Empty when no PR exists or PR creation is disabled.

  • changed

    true if any selected lockfile changed, otherwise false.

  • lockfiles

    JSON array of selected lockfile paths, relative to the checkout.

  • changed-lockfiles

    JSON array of changed lockfile paths, relative to the checkout.

Pull request behavior

The PR body and Actions job summary include a version-change table for each changed lockfile. Each row shows a package's locked versions before and after the update, including transitive dependencies. Multiple versions are grouped under the package name; β€” marks additions or removals. Packages without a declared version are omitted. Metadata-only or source-only changes are identified when no package versions changed. Very large reports are truncated with a notice to stay within the PR body limit.

The Change column distinguishes major, minor, and patch changes, and marks downgrades, prereleases, additions, and removals. One- and two-component numeric versions are padded with zeroes for comparison. Non-SemVer versions are marked other; changes involving several removed and added versions are marked multiple rather than guessing version pairs.

The Action automatically checks out base when GITHUB_WORKSPACE has no .git entry. Existing checkouts, including Git worktrees, are preserved. To customize checkout options or manually install tools using repository files, run actions/checkout explicitly first. Node.js 24 is prepared internally. Additional tool setup is selected using the same tracked lockfiles, patterns, exclusions, and working directory as maintenance. Normal callers only need Harden-Runner followed by this Action. PR creation requires a clean tracked working tree and index, so unrelated staged or modified files cannot enter the maintenance commit. Files generated by package managers are excluded from the PR unless they are selected, Git-tracked lockfiles.

If no changes are needed, no new PR is created. The PR integration also closes an existing maintenance PR when its changes are no longer needed, and deletes its branch when appropriate. Reserve the configured branch for this Action.

The PR integration cannot accept commas or newlines in selected file paths. For these paths, or for a custom test/commit/PR workflow, disable PR creation:

- uses: knu/lockfile-maintenance-action@v2
  with:
    create-pull-request: false

A PR creation failure fails the Action; the file-update rollback applies to dependency-update failures, not to a later push or API failure.

Requesting a rebase

When creating or updating a maintenance PR, the Action reads the App policy and the calling workflow on the repository's default branch. It shows one rebase method: a checkbox when configured, otherwise a new /lockfile rebase comment when configured. With separate release histories, the guidance appears directly below the version tables. With inline release histories, it appears after the opening explanation, before the tables, so HTML lists inside the tables do not interfere with GitHub's checkbox positions. If neither method is configured or configuration cannot be read, the PR links to setup instead. Setup instructions are collapsed at the end of the PR body and linked from the checkbox item or comment guidance.

The check recognizes App handling for OIDC authentication with lockfile-maintenance.yml, matching branches, an authorized dispatch ref, and workflow_dispatch. For Actions handling, it looks for a request-rebase Action step and the corresponding event subscriptions in the calling workflow. This checks configuration, not App installation permissions or arbitrary job and step conditions.

Rebase requests regenerate the selected lockfiles from the latest base and update the same PR. Dependency versions may change during resolution. The reserved maintenance branch must not contain manual changes you need to preserve.

App-based rebase handling

For PRs created by the Lockfile Maintenance App, put this in .github/lockfile-maintenance-auth.yml on the default branch:

rebase: true

Keep workflow_dispatch in .github/workflows/lockfile-maintenance.yml. Remove issue_comment and pull_request_target subscriptions and the request job from the maintenance workflow before enabling App handling, so requests are not dispatched twice. Existing App installations must approve the added Actions and Issues write permissions.

The App accepts new /lockfile rebase comments and unchecked-to-checked transitions from users with repository write access. It checks the current PR state, author, repository, and branches before dispatch. Comments receive πŸ‘ before dispatch, then πŸŽ‰ on success or πŸ˜• on failure. Completion is checked about once per minute, for up to two hours; this does not keep an Actions runner waiting. If a dispatch result is unknown, the broker reports failure instead of retrying and risking a duplicate run. Submit a new request after checking the workflow runs.

The defaults are the automation/lockfile-maintenance PR branch and the repository default branch for both base and workflow execution. To match custom workflow inputs, use:

allowed_branches: [main, v1]
rebase:
  branch: automation/lockfile-maintenance-v1
  base: v1
  ref: v1

ref must be authorized by allowed_branches. This configuration supports one maintenance target per repository. Omit rebase or set it to false to disable App handling.

Actions-based rebase handling

For other bot identities or installations without App handling, use the composite action and a separate request job. Add these subscriptions to the consuming workflow's on section:

on:
  workflow_dispatch:
    inputs:
      request-comment:
        description: Rebase request comment ID (set by the request job).
        type: string
        default: ''
      request-pull-request:
        description: Rebase request PR number (set by the request job).
        type: string
        default: ''
  issue_comment:
    types: [created]
  pull_request_target:
    types: [edited]

Comments require issue_comment; checkbox edits require pull_request_target. Keep any existing schedule entry. The workflow must exist on the default branch. Event subscriptions alone are not enough: add a separate request job and restrict the maintenance job to scheduled and dispatched runs:

jobs:
  request-rebase:
    if: >-
      github.event.sender.type == 'User' &&
      (github.event_name == 'issue_comment' || github.event_name == 'pull_request_target')
    runs-on: ubuntu-latest
    permissions:
      actions: write
      issues: write
      pull-requests: read
    steps:
      - uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1
        with:
          egress-policy: audit
      - uses: knu/lockfile-maintenance-action/request-rebase@v2 # zizmor: ignore[unpinned-uses] -- Follow the v2 release series in this example.

  update:
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    runs-on: ubuntu-latest
    concurrency:
      group: lockfile-maintenance
      cancel-in-progress: false
    # Add issues: write to this job's existing permissions.
    # Keep existing setup steps, then forward the request inputs:
    steps:
      - uses: knu/lockfile-maintenance-action@v2 # zizmor: ignore[unpinned-uses] -- Follow the v2 release series in this example.
        with:
          request-comment: ${{ inputs.request-comment }}
          request-pull-request: ${{ inputs.request-pull-request }}
          # Keep existing maintenance inputs, including auth/token and files.

Move maintenance concurrency from the workflow level to the update job, so unrelated PR events cannot replace a pending update. See the complete OIDC example. Do not check out or execute PR code in the request job. It only validates the request and dispatches the maintenance workflow using GITHUB_TOKEN; the dispatched job uses its usual token or OIDC authentication. No broker changes or additional secrets are needed.

The request Action accepts these inputs:

Input Default Purpose
token github.token Requires actions write, issues write and pull requests read access.
branch automation/lockfile-maintenance Expected maintenance PR head branch.
base Repository default branch Expected maintenance PR base branch.
workflow Calling workflow's filename Workflow to dispatch.
ref Repository default branch Trusted branch on which to run that workflow.

Keep branch and base consistent with the maintenance Action's configuration. For maintenance on another branch, also set ref to the trusted branch containing its workflow and authorize that branch for OIDC as described below. Never derive these inputs from PR text or an unvalidated PR head. With several maintenance configurations, use a separate request Action invocation for each branch/base pair and dispatch the corresponding configured workflow. The target workflow must declare the two request inputs above. Other dispatch inputs use their defaults; additional required inputs without defaults are not supported.

A new comment with /lockfile rebase on its own line, or an unchecked-to-checked transition of the generated checkbox, requests a run. Other lines and whitespace around the command are allowed. The sender must be a user with write, maintain, or admin permission. The PR must still be open and use the configured branches in the same repository. Bot edits, ordinary body edits, edited comments, and fork PRs do not trigger maintenance. The dispatched output reports whether a run was requested, and the request job summary links to the workflow runs.

Accepted command comments receive πŸ‘ before dispatch. After maintenance succeeds for the requested PR, the Action adds πŸŽ‰; dispatch or maintenance failures add πŸ˜• (confused, one of GitHub's supported reactions). After adding the result, the handler removes its own acceptance reaction; reactions from other users remain. Result reactions use reaction-token, not the OIDC installation token, and verify that the comment belongs to the requested PR. A failure before the maintenance Action starts, runner termination, or unavailable GitHub API can prevent notification; follow the workflow link if only πŸ‘ remains. Queueing and tool setup mean acceptance and completion need not be immediate.

The checkbox resets when maintenance successfully updates the PR body. After a failure, uncheck and check it again, or post a new command comment if comment requests are configured. You can also select Run workflow on the maintenance workflow's Actions page, choosing the branch used for maintenance. Manual execution requires workflow_dispatch and repository write access.

OIDC authentication

Install the Lockfile Maintenance App and select the repositories to maintain. No registration with the broker operator is needed. Add .github/workflows/lockfile-maintenance.yml to the repository's default branch and grant id-token: write for the default OIDC authentication:

name: Lockfile maintenance

on:
  workflow_dispatch:
  schedule:
    - cron: "0 0 * * 5"

permissions:
  contents: read
  id-token: write

jobs:
  maintain:
    runs-on: ubuntu-latest
    steps:
      - uses: knu/lockfile-maintenance-action@v2
        with:
          files: /Cargo.lock
          minimum-release-age: 3 days

Only schedule and workflow_dispatch runs of this workflow on GitHub-hosted runners are accepted. Without a branch policy, only the current default branch is authorized. The configuration below can explicitly authorize other branches and restrict the default branch. The workflow must use GitHub's default branch-based OIDC subject (legacy or immutable); jobs with an environment or a customized OIDC subject are not supported.

The broker checks the App installation and the repository's current ID, owner, and default branch on each exchange. Removing the repository from the installation, uninstalling the App, or suspending it prevents new tokens from being issued. Limits apply independently to each repository: three exchanges per run attempt, ten per hour, and thirty per day. Failed exchanges after identity verification also count toward these limits.

The fixed broker endpoint is https://lockfile-maintenance-auth.idaemons.org/token. GitHub remains the identity provider; the broker validates the signed identity and returns an installation token restricted to the calling repository, with contents and pull requests write permissions. No App private key or token: input is needed in the consuming repository. The Action masks issued tokens and attempts to revoke the installation token on both success and failure. A terminated runner may leave it valid until its GitHub expiry (normally one hour).

OIDC identifies the workflow, not this composite Action or its version. Treat the authorized workflow and its repository configuration as trusted code. The installation token grants repository write access; GitHub does not restrict it to lockfiles.

Running from maintenance branches

To authorize OIDC authentication from additional branches, add .github/lockfile-maintenance-auth.yml to the repository's default branch:

allowed_branches:
  - main
  - v1
  - v2

When allowed_branches is present, only listed branches are authorized. Include your default branch explicitly (main or master, for example) if it should remain authorized. An empty list denies all branches. Use exact branch names, without refs/heads/; globs and regular expressions are not supported. Keep .github/workflows/lockfile-maintenance.yml on both the default branch and each branch you want to run. Then select an authorized branch when manually dispatching the workflow, for example:

gh workflow run lockfile-maintenance.yml --ref v1

On that branch, configure the Action to update the same base and use a separate PR branch:

- uses: knu/lockfile-maintenance-action@v2
  with:
    base: v1
    branch: automation/lockfile-maintenance-v1
    title: Lockfile maintenance (v1)

The broker checks the OIDC workflow ref, not the checkout ref or the base input. The base input still defaults to the repository's default branch. An existing checkout is preserved, so it must also point to the intended base. Serialize runs that share a maintenance PR branch.

The broker reads authorization from the current default branch's head commit on every exchange. Configuration on the calling branch cannot authorize it. When the file or allowed_branches key is absent, only the current default branch is authorized; an empty or comments-only file also uses this default. Invalid configuration, duplicate or unknown keys, or a branch absent from an explicit list deny authentication, including on the default branch. The file must be a single UTF-8 YAML document of at most 16 KiB. Comments are supported; aliases and unsupported tags are rejected. Removing an entry prevents new exchanges that read the updated configuration; tokens already issued remain valid until revoked or expired.

This configuration only authorizes authentication. It does not start or schedule workflows; GitHub's schedule event runs only on the default branch. Adding a branch trusts its workflow and the code it executes with the App token's repository-wide write permissions, not just permission to update that branch.

Release-age behavior

Package lockfiles use each tool's native policy, including its package and source exceptions. It is not a universal timestamp check: package-manager Git dependencies and Cargo/Bundler registry entries without publish timestamps are not covered. Named Cargo registries and uv package/index settings can override the general age policy. Bundler may retain already locked young gems, while Cargo may downgrade them. Actions lockfiles use the separate dated-release policy above.

npm regenerates package-lock.json with npm update --package-lock-only --ignore-scripts --before=<cutoff>, where the cutoff is the current time minus minimum-release-age. Using update also refreshes dependencies when node_modules already exists. It does not retry without the cutoff when resolution fails. npm's native source and package exceptions, including min-release-age-exclude, still apply. The CLI cutoff overrides .npmrc age settings; set the Action input to the policy you want enforced. Version reports read lockfile formats 1, 2, and 3; regeneration uses npm's configured output format.

Matching no supported lockfiles, missing manifests, and unsupported tool versions are errors. If an update fails or changes a protected manifest, configuration, or unselected lockfile, the Action attempts to restore the original files. Package-manager caches and other generated files are not rolled back.

Run this Action against trusted project configuration. Gemfiles, Yarn plugins, and uv workspace metadata can execute code even when install scripts are disabled.

Author

Copyright (c) 2026 Akinori MUSHA.

Licensed under the MIT license. See LICENSE for details.

Visit the GitHub Repository for the latest information.

About

Maintain lockfiles with native minimum release ages and automated pull requests.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages