Skip to content

Commit 15a8d32

Browse files
committed
fix(github_actions): use most specific version tag when updating comments
When a pinned SHA has multiple version tags (e.g. v1, v1.0, v1.0.1), the version comment update logic used .find to pick the first tag whose version string was a suffix of the comment. Because tags are sorted ascending, this could pick a short version like "1" that is a substring of the actual comment version "1.0.1". The subsequent gsub("1", "1.1") then mangled the entire comment, e.g. "# v1.0.1" became "# v1.1.0.1.1". Fix by selecting the longest (most specific) matching version string instead of the first match. This ensures gsub replaces the correct substring. Fixes an issue observed in cli/cli#12918 where the comment was incorrectly updated to "# v1.1.0.1.1" instead of "# v1.1".
1 parent fb51f94 commit 15a8d32

3 files changed

Lines changed: 75 additions & 1 deletion

File tree

github_actions/lib/dependabot/github_actions/file_updater.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,12 @@ def updated_version_comment(comment, old_ref, new_ref)
110110
previous_version_tags = git_checker.most_specific_version_tags_for_sha(old_ref)
111111
return unless previous_version_tags.any? # There's no tag for this commit
112112

113+
# Use the most specific (longest) matching version to avoid partial replacements.
114+
# Tags are sorted ascending, so ["v1", "v1.0", "v1.0.1"] maps to ["1", "1.0", "1.0.1"].
115+
# Without this, "1" could match the end of "v1.0.1", causing gsub("1", "1.1") => "v1.1.0.1.1".
113116
previous_version = previous_version_tags.map { |tag| version_class.new(tag).to_s }
114-
.find { |version| comment.end_with? version }
117+
.select { |version| comment.end_with?(version) }
118+
.max_by(&:length)
115119
return unless previous_version
116120

117121
new_version_tag = git_checker.most_specific_version_tag_for_sha(new_ref)

github_actions/spec/dependabot/github_actions/file_updater_spec.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,69 @@
485485
end
486486
end
487487

488+
context "with pinned SHA where shorter tag version is a suffix of comment version" do
489+
let(:git_checker) { instance_double(Dependabot::GitCommitChecker) }
490+
let(:workflow_file_body) do
491+
fixture("workflow_files", "pinned_source_multiple_tags_substring_versions.yml")
492+
end
493+
let(:dependency) do
494+
Dependabot::Dependency.new(
495+
name: "advanced-security/filter-sarif",
496+
version: "1.1",
497+
package_manager: "github_actions",
498+
previous_version: "1.0.1",
499+
previous_requirements: [{
500+
requirement: nil,
501+
groups: [],
502+
file: ".github/workflows/workflow.yml",
503+
source: {
504+
type: "git",
505+
url: "https://github.com/advanced-security/filter-sarif",
506+
ref: "f3b8118a9349d88f7b1c0c488476411145b6270d",
507+
branch: nil
508+
},
509+
metadata: {
510+
declaration_string:
511+
"advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d"
512+
}
513+
}],
514+
requirements: [{
515+
requirement: nil,
516+
groups: [],
517+
file: ".github/workflows/workflow.yml",
518+
source: {
519+
type: "git",
520+
url: "https://github.com/advanced-security/filter-sarif",
521+
ref: "2da736ff05ef065cb2894ac6892e47b5eac2c3c0",
522+
branch: nil
523+
},
524+
metadata: {
525+
declaration_string:
526+
"advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0"
527+
}
528+
}]
529+
)
530+
end
531+
532+
it "uses the most specific matching tag to avoid partial gsub replacements" do
533+
allow(Dependabot::GitCommitChecker).to receive(:new).and_return(git_checker)
534+
allow(git_checker).to receive(:ref_looks_like_commit_sha?).and_return(true)
535+
# The old SHA has multiple tags where "1" (from v1) is a suffix of "1.0.1"
536+
allow(git_checker).to receive(:most_specific_version_tags_for_sha)
537+
.with("f3b8118a9349d88f7b1c0c488476411145b6270d")
538+
.and_return(["v1", "v1.0", "v1.0.1"])
539+
allow(git_checker).to receive(:most_specific_version_tag_for_sha)
540+
.with("2da736ff05ef065cb2894ac6892e47b5eac2c3c0")
541+
.and_return("v1.1")
542+
543+
expect(updated_workflow_file.content).to include(
544+
"advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1"
545+
)
546+
# Must NOT contain the buggy result where gsub("1", "1.1") mangled the comment
547+
expect(updated_workflow_file.content).not_to include("v1.1.0.1.1")
548+
end
549+
end
550+
488551
context "with pinned SHA hash matching multiple tags and version in comment different from latest matching tag" do
489552
let(:service_pack_url) do
490553
"https://github.com/github/codeql-action.git/info/refs" \
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
on: [push]
2+
3+
name: Integration
4+
jobs:
5+
chore:
6+
steps:
7+
- uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0.1

0 commit comments

Comments
 (0)