Skip to content

parseMetadataLinks overwrites duplicate dependency names, causing incorrect update-type #699

@devantler

Description

@devantler

Bug Description

When the same dependency name appears multiple times in a grouped update commit (e.g., picomatch updated via multiple transitive dependency paths at different semver ranges), parseMetadataLinks() produces incorrect version pairs because it uses a Map<string, dependencyVersions> — the Map's .set() overwrites earlier entries for the same key.

Example

Consider a commit message where picomatch is updated at two different major versions:

Updates `picomatch` from 2.3.1 to 2.3.2
Updates `picomatch` from 4.0.1 to 4.0.2

With the current code, the Map stores only the last entry:

parseMetadataLinks result:
  picomatch → { prevVersion: "4.0.1", newVersion: "4.0.2" }   // 2.3.1→2.3.2 was overwritten!

When the YAML metadata lists both picomatch entries with dependency-version:

updated-dependencies:
- dependency-name: picomatch
  dependency-version: 2.3.2
  dependency-type: direct:production
- dependency-name: picomatch
  dependency-version: 4.0.2
  dependency-type: indirect

The consumer code does (for each dependency):

const lastVersion = updatedVersion?.prevVersion || ...   // from parseMetadataLinks Map
const nextVersion = dependency['dependency-version'] || ... // from YAML
const updateType = calculateUpdateType(lastVersion, nextVersion)

For the first YAML entry (the v2.x picomatch):

  • lastVersion = "4.0.1"wrong, pulled from the overwritten Map entry (v4 line)
  • nextVersion = "2.3.2" — correct, from YAML dependency-version
  • calculateUpdateType("4.0.1", "2.3.2") → major parts differ (4 ≠ 2) → version-update:semver-major

This should have been calculateUpdateType("2.3.1", "2.3.2")version-update:semver-patch.

Since the action's update-type output uses maxSemver() across all dependencies, this single incorrectly classified entry causes the entire PR to be reported as a semver-major update.

Root Cause

// src/dependabot/update_metadata.ts - parseMetadataLinks()
function parseMetadataLinks(commitMessage: string): Map<string, dependencyVersions> {
  const updates: Map<string, dependencyVersions> = new Map()
  // ...
  updates.set(dependencyName, { prevVersion, newVersion })  // overwrites on duplicate names
  // ...
}

Impact

  • update-type output is incorrect (e.g., semver-major instead of semver-patch)
  • previous-version output for the first dependency may show a version from the wrong entry
  • Downstream workflows that gate auto-approval on update-type will skip legitimate patch updates

Proposed Fix

Change parseMetadataLinks to return Map<string, dependencyVersions[]> and use a per-name counter in the consumer to retrieve the correct entry for each YAML dependency in order. See #700.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions