Stacktower Dependency Diff Action

June 25, 2026 · View on GitHub

Dependencies

Codecov for dependencies — Visualize dependency changes on every pull request with before/after tower diffs.

Dependency Tower

Most dependency updates are merged blind. You see a lockfile diff with 200 changed lines and hope nothing breaks. This Action makes dependency changes reviewable: it renders before/after tower visualizations, surfaces new vulnerabilities and license issues, and gives your team confidence to merge.

What It Does

On every PR that touches a dependency file:

  1. Detects which manifests changed (auto-detection or explicit path)
  2. Renders before and after dependency towers via the Stacktower Cloud API
  3. Computes a structured diff: added, removed, updated packages + vulnerability changes
  4. Posts a PR comment with health comparison, package changes, and side-by-side tower images
  5. Optionally fails the check on new vulnerabilities, license issues, or brittle dependencies

When multiple manifests change in the same PR (for example, package-lock.json and go.mod), the action processes each manifest and posts/updates a dedicated comment per manifest path.

Why

  • Catch supply-chain risks before merge — new vulns, copyleft licenses, abandoned packages
  • Replace unreadable lockfile diffs — see +3 added / -1 removed / 2 updated at a glance
  • 5-minute setup, zero maintenance — auto-detects manifests across 7 languages
  • Works with branch protection — fail gates integrate directly with required status checks

Usage

# .github/workflows/dependency-diff.yml
name: Dependency Diff
on:
  pull_request:
    paths:
      - 'package.json'
      - 'package-lock.json'
      - 'yarn.lock'
      - 'pnpm-lock.yaml'
      - 'poetry.lock'
      - 'pyproject.toml'
      - 'uv.lock'
      - 'requirements.txt'
      - 'Cargo.toml'
      - 'Cargo.lock'
      - 'go.mod'
      - 'Gemfile'
      - 'Gemfile.lock'
      - 'composer.json'
      - 'composer.lock'
      - 'pom.xml'
      - 'build.gradle'
      - 'build.gradle.kts'

jobs:
  tower-diff:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
      - uses: stacktower-io/stacktower-action@v1
        with:
          api-key: ${{ secrets.STACKTOWER_API_KEY }}
          fail-on-vuln: true

Setup

Free to use with any Stacktower account — API keys, CI dependency diffs, before/after towers, PR comments, and fail gates are available on the free tier. Triage AI investigations (investigate: true) require a Pro plan. Your key needs visualizations:write and visualizations:read scopes. Add investigations:write and investigations:read if using investigate: true.

  1. Sign up at app.stacktower.io (free account, no credit card)
  2. Create an API key at Settings > API Keys
  3. Add the key as a repository secret named STACKTOWER_API_KEY

Inputs

InputDescriptionRequiredDefault
api-keyStacktower Cloud API keyYes
manifestPath to manifest file (auto-detected if omitted)No
fail-on-vulnFail the check if new vulnerabilities are introducedNofalse
fail-on-licenseFail the check if copyleft, proprietary, or unknown licenses are detectedNofalse
fail-on-brittleFail the check if brittle (archived/abandoned/undermaintained) deps are detectedNofalse
security-scanRun vulnerability scan on dependenciesNotrue
investigateRun Triage AI agent for health grade + recommendations (requires Pro)Nofalse
commentPost a PR comment with the diffNotrue
tokenGitHub token for PR comments and investigation repo accessNo${{ github.token }}
api-base-urlStacktower API base URL (override for testing/self-hosted)Nohttps://api.stacktower.io/v1
app-base-urlStacktower app base URL (used for links in PR comments)Nohttps://app.stacktower.io

Outputs

OutputDescription
has-changesWhether dependency changes were detected
diff-jsonJSON diff result
new-vulnsNumber of new vulnerabilities introduced
license-issuesNumber of license issues (copyleft + proprietary + unknown)
brittle-depsNumber of brittle dependencies (archived/abandoned/undermaintained)
before-render-idRender ID for the before tower
after-render-idRender ID for the after tower
before-urlURL to the before tower on app.stacktower.io
after-urlURL to the after tower on app.stacktower.io
health-gradeDependency health grade (A-F) from the Triage AI investigation
investigation-jsonFull Triage AI investigation report as JSON

Supported Languages

LanguageManifests
JavaScriptpackage.json, package-lock.json, yarn.lock, pnpm-lock.yaml
Pythonpyproject.toml, poetry.lock, uv.lock, requirements.txt
RustCargo.toml, Cargo.lock
Gogo.mod
RubyGemfile, Gemfile.lock
PHPcomposer.json, composer.lock
Javapom.xml, build.gradle, build.gradle.kts

When both a lockfile and manifest change for the same language, the lockfile is preferred (it has fully resolved versions).

PR Comment

The action posts a comment with:

  • Summary bar — counts of added, removed, updated, and unchanged dependencies
  • Health comparison — before/after stats table (total deps, direct, transitive, max depth, vulnerabilities, licenses)
  • Package changes — detailed lists of added, removed, and updated packages with version info
  • New vulnerabilities — highlighted with severity badges
  • License issues (when fail-on-license is set) — copyleft, proprietary, and unknown licenses
  • Brittle dependencies (when fail-on-brittle is set) — archived, abandoned, or undermaintained packages
  • Tower visualizations — side-by-side before/after tower images linking to the interactive viewer
  • Investigation report (optional) — Triage AI health grade (A-F) and prioritized recommendations

Each manifest comment is automatically updated on subsequent pushes (no duplicate comments for the same manifest path).

Multi-language PR example

If a PR updates both JavaScript and Go dependencies:

  • frontend/package-lock.json
  • backend/go.mod

the action will post two Stacktower comments (one per manifest path), and each one is updated independently on later pushes.

Monorepo note: Auto-detection picks one manifest per language (the highest-priority lockfile). If your repo has multiple package.json or lockfiles for the same language in different directories, use the manifest input to target a specific file, or run the action multiple times with different manifest values via a matrix strategy.

Fail Gates

The action supports three fail gates that integrate with branch protection rules, letting you require clean dependency updates before merge. When multiple gates are enabled and triggered, all failures are reported together.

Fail on Vulnerabilities

Set fail-on-vuln: true to fail the check when new vulnerabilities are introduced in the PR diff.

Fail on License Issues

Set fail-on-license: true to fail the check when the after-PR dependency tree contains copyleft, proprietary, or unknown licenses.

Fail on Brittle Dependencies

Set fail-on-brittle: true to fail the check when the after-PR dependency tree contains archived, abandoned, or undermaintained packages.

- uses: stacktower-io/stacktower-action@v1
  with:
    api-key: ${{ secrets.STACKTOWER_API_KEY }}
    fail-on-vuln: true
    fail-on-license: true
    fail-on-brittle: true

Triage AI Investigation

Set investigate: true to get an AI-powered dependency health grade directly in your PR comment. The Triage AI agent goes beyond static analysis — it clones your repository, understands how you use each dependency, and produces:

  • Health grade (A-F) — an at-a-glance signal for reviewers
  • Prioritized recommendations — Do Now / Should Do / Nice to Have
  • Context-aware advice — knows whether a vulnerable package is in your hot path or an unused transitive dep

Note: Triage AI investigations require a Pro plan. The token input must have read access to the repository.

- uses: stacktower-io/stacktower-action@v1
  with:
    api-key: ${{ secrets.STACKTOWER_API_KEY }}
    investigate: true
    fail-on-vuln: true

The health grade is also available as an output:

- uses: stacktower-io/stacktower-action@v1
  id: deps
  with:
    api-key: ${{ secrets.STACKTOWER_API_KEY }}
    investigate: true

- run: echo "Health grade: ${{ steps.deps.outputs.health-grade }}"

More from Stacktower

  • Web App — Interactive tower viewer, dependency history, team dashboards
  • CLI — Open-source CLI for local parsing, rendering, and analysis
  • Blog — The story behind tower visualizations and XKCD 2347

Development

Prerequisites

  • Node.js >= 20
  • act for local Docker-based testing (brew install act)

Build & Test

make help          # show all targets
make all           # lint + unit tests + build (same as CI)
make build         # compile & bundle with ncc
make test          # run unit tests (vitest)
make lint          # type-check

Local Integration Test (Docker)

Run the full action in a Docker container using act, no push required.

1. Create a secrets file:

cp test/.secrets.example test/.secrets
# Edit test/.secrets with your real STACKTOWER_API_KEY and GITHUB_TOKEN

2. Run against the default API:

make test-act

3. Point to a custom API (e.g. local dev server):

make test-act API_URL=http://localhost:8080/v1 APP_URL=http://localhost:3000

The test workflow (.github/workflows/test-local.yml) exercises the action in-repo using uses: ./ with comment: false (so it won't try to post to a real PR). It prints all outputs to stdout for verification.

Note: test/.secrets is git-ignored. Never commit real API keys.

License

MIT