A GitHub Action that generates a formatted diff of npm package-lock.json changes for pull requests. Perfect for reviewing dependency updates at a glance.
✅ Works with reusable workflows - No complex workarounds needed
✅ Supports npm v6 and v7+ - Handles both dependencies and packages formats
✅ Clean table output - Formatted Markdown table matching composer-diff style
✅ Direct npm links - One-click access to package pages and version comparisons
✅ Detailed metrics - Outputs counts for added, removed, and upgraded packages
The action itself only requires read access to the repository contents to compare the lockfiles:
permissions:
contents: readHowever, if you use a separate action to post the diff as a comment (like in the example below), you will also need:
permissions:
pull-requests: writename: Dependency Check
on:
pull_request:
permissions:
contents: read
pull-requests: write
jobs:
npm-diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate npm lockfile diff
id: npm_diff
uses: stixx/npm-diff@v1
with:
base-ref: ${{ github.event.pull_request.base.ref || 'main' }}
- name: Comment PR
if: steps.npm_diff.outputs.has_changes == 'true'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: npm-diff
message: |
<details open>
<summary>NPM package changes</summary>
${{ steps.npm_diff.outputs.diff }}
</details>- name: Generate npm lockfile diff
id: npm_diff
uses: stixx/npm-diff@v1
with:
base-ref: develop
path: frontend/package-lock.json
- name: Comment with summary
if: steps.npm_diff.outputs.has_changes == 'true'
uses: marocchino/sticky-pull-request-comment@v2
with:
header: npm-diff
message: |
## 📦 NPM Dependency Changes
**Summary:** ${{ steps.npm_diff.outputs.added_count }} added, ${{ steps.npm_diff.outputs.removed_count }} removed, ${{ steps.npm_diff.outputs.updated_count }} upgraded
<details open>
<summary>View details</summary>
${{ steps.npm_diff.outputs.diff }}
</details># .github/workflows/reusable-dependency-check.yml
name: Dependency Check
on:
workflow_call:
jobs:
diff:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate npm diff
id: npm_diff
uses: stixx/npm-diff@v1
- uses: marocchino/sticky-pull-request-comment@v2
if: steps.npm_diff.outputs.has_changes == 'true'
with:
header: npm-diff
message: |
<details open>
<summary>NPM package changes</summary>
${{ steps.npm_diff.outputs.diff }}
</details>| Input | Description | Required | Default |
|---|---|---|---|
base-ref |
Base branch reference for comparison (e.g., main, develop) |
No | main |
path |
Path to package-lock.json file | No | package-lock.json |
include-transitive |
Include transitive dependencies in the diff | No | false |
| Output | Description | Example |
|---|---|---|
has_changes |
Whether package-lock.json has changes | true or false |
diff |
The formatted diff output as Markdown table | See example below |
added_count |
Number of packages added | 5 |
removed_count |
Number of packages removed | 2 |
updated_count |
Number of packages updated | 12 |
When used in a Pull Request, the action generates a summary and a detailed table of changes.
Summary: 1 added, 0 removed, 2 upgraded
View details
| Packages | Operation | Base | Target | Link |
|---|---|---|---|---|
| express | Upgraded | 4.17.1 |
4.18.2 |
Compare |
| lodash | Upgraded | 4.17.20 |
4.17.21 |
Compare |
| axios | Added | - | 1.4.0 |
Details |
actions/checkout@v4withfetch-depth: 0(or at leastfetch-depth: 2to access base branch)- Node.js is available by default in GitHub Actions runners
- Checks if
package-lock.jsonexists at the specified path - Compares the lockfile between the base branch and current HEAD
- Parses both versions (supports npm v6
dependenciesand npm v7+packagesformats) - Identifies added, removed, and upgraded packages
- Generates a formatted Markdown table with npm package links
- Outputs the diff and metrics for use in subsequent steps
Ensure you're using fetch-depth: 0 in your checkout step:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required to access base branchIf your package-lock.json is in a subdirectory:
- uses: stixx/npm-diff@v1
with:
path: frontend/package-lock.jsonTo compare against a branch other than main:
- uses: stixx/npm-diff@v1
with:
base-ref: developBy default, the action only shows changes for direct dependencies to keep the diff clean. To see all changes (including transitive dependencies):
- uses: stixx/npm-diff@v1
with:
include-transitive: trueContributions are welcome! Please feel free to submit a Pull Request.
To run tests locally:
npm testMIT License - see LICENSE file for details
Created by stixx
- IonBazan/composer-diff-action - Similar action for PHP Composer
- marocchino/sticky-pull-request-comment - For posting diff comments