-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add Git::SearchCommits callable that sends backend API request to che…
…ck which commits are already known to the backend
- Loading branch information
1 parent
9716194
commit 6a57b34
Showing
11 changed files
with
325 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
# frozen_string_literal: true | ||
|
||
require "json" | ||
require "set" | ||
|
||
require_relative "../ext/transport" | ||
require_relative "../utils/git" | ||
|
||
module Datadog | ||
module CI | ||
module Git | ||
class SearchCommits | ||
class ApiError < StandardError; end | ||
|
||
attr_reader :api | ||
|
||
def initialize(api:) | ||
@api = api | ||
end | ||
|
||
def call(repository_url, commits) | ||
raise ApiError, "test visibility API is not configured" if api.nil? | ||
|
||
http_response = api.api_request( | ||
path: Ext::Transport::DD_API_GIT_SEARCH_COMMITS_PATH, | ||
payload: request_payload(repository_url, commits) | ||
) | ||
raise ApiError, "Failed to search commits: #{http_response.body}" unless http_response.ok? | ||
|
||
response_payload = parse_json_response(http_response) | ||
extract_commits(response_payload) | ||
end | ||
|
||
private | ||
|
||
def request_payload(repository_url, commits) | ||
{ | ||
meta: { | ||
repository_url: repository_url | ||
}, | ||
data: commits.filter_map do |commit| | ||
next unless Utils::Git.valid_commit_sha?(commit) | ||
|
||
{ | ||
id: commit, | ||
type: "commit" | ||
} | ||
end | ||
}.to_json | ||
end | ||
|
||
def parse_json_response(http_response) | ||
JSON.parse(http_response.payload) | ||
rescue JSON::ParserError => e | ||
raise ApiError, "Failed to parse search commits response: #{e}. Payload was: #{http_response.payload}" | ||
end | ||
|
||
def extract_commits(response_payload) | ||
result = Set.new | ||
|
||
response_payload.fetch("data").each do |commit_json| | ||
raise ApiError, "Invalid commit type response #{commit_json}" unless commit_json["type"] == "commit" | ||
|
||
commit_sha = commit_json["id"] | ||
raise ApiError, "Invalid commit SHA response #{commit_sha}" unless Utils::Git.valid_commit_sha?(commit_sha) | ||
|
||
result.add(commit_sha) | ||
end | ||
|
||
result | ||
rescue KeyError => e | ||
raise ApiError, "Malformed search commits response: #{e}. Payload was: #{response_payload}" | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
module Datadog | ||
module CI | ||
module Git | ||
class SearchCommits | ||
@api: Datadog::CI::Transport::Api::Base? | ||
|
||
attr_reader api: Datadog::CI::Transport::Api::Base? | ||
|
||
class ApiError < StandardError | ||
end | ||
|
||
def initialize: (api: Datadog::CI::Transport::Api::Base?) -> void | ||
|
||
def call: (String repository_url, Array[String] commits) -> Set[String] | ||
|
||
private | ||
|
||
def request_payload: (String repository_url, Array[String] commits) -> String | ||
|
||
def parse_json_response: (Datadog::Core::Transport::Response response) -> Hash[String, untyped] | ||
|
||
def extract_commits: (Hash[String, untyped] response) -> Set[String] | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# frozen_string_literal: true | ||
|
||
require_relative "../../../../lib/datadog/ci/git/search_commits" | ||
|
||
RSpec.describe Datadog::CI::Git::SearchCommits do | ||
let(:api) { double("api") } | ||
subject(:search_commits) { described_class.new(api: api) } | ||
|
||
describe "#call" do | ||
let(:repository_url) { "https://datadoghq.com/git/test.git" } | ||
let(:commits) { ["c7f893648f656339f62fb7b4d8a6ecdf7d063835"] } | ||
|
||
context "when the API is not configured" do | ||
let(:api) { nil } | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error(Datadog::CI::Git::SearchCommits::ApiError, "test visibility API is not configured") | ||
end | ||
end | ||
|
||
context "when the API is configured" do | ||
before do | ||
allow(api).to receive(:api_request).and_return(http_response) | ||
end | ||
|
||
context "when the API request fails" do | ||
let(:http_response) { double("http_response", ok?: false, body: "error message") } | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error(Datadog::CI::Git::SearchCommits::ApiError, "Failed to search commits: error message") | ||
end | ||
end | ||
|
||
context "when the API request is successful" do | ||
let(:http_response) { double("http_response", ok?: true, payload: response_payload) } | ||
let(:response_payload) do | ||
{ | ||
"data" => [ | ||
{ | ||
"id" => "c7f893648f656339f62fb7b4d8a6ecdf7d063835", | ||
"type" => "commit" | ||
} | ||
] | ||
}.to_json | ||
end | ||
|
||
it "returns the list of commit SHAs" do | ||
expect(api).to receive(:api_request).with( | ||
path: Datadog::CI::Ext::Transport::DD_API_GIT_SEARCH_COMMITS_PATH, | ||
payload: "{\"meta\":{\"repository_url\":\"https://datadoghq.com/git/test.git\"},\"data\":[{\"id\":\"c7f893648f656339f62fb7b4d8a6ecdf7d063835\",\"type\":\"commit\"}]}" | ||
).and_return(http_response) | ||
|
||
expect(search_commits.call(repository_url, commits)).to eq(Set.new(["c7f893648f656339f62fb7b4d8a6ecdf7d063835"])) | ||
end | ||
|
||
context "when the request contains an invalid commit SHA" do | ||
let(:commits) { ["INVALID_SHA", "c7f893648f656339f62fb7b4d8a6ecdf7d063835"] } | ||
|
||
it "does not include the invalid commit SHA in the request" do | ||
expect(api).to receive(:api_request).with( | ||
path: Datadog::CI::Ext::Transport::DD_API_GIT_SEARCH_COMMITS_PATH, | ||
payload: "{\"meta\":{\"repository_url\":\"https://datadoghq.com/git/test.git\"},\"data\":[{\"id\":\"c7f893648f656339f62fb7b4d8a6ecdf7d063835\",\"type\":\"commit\"}]}" | ||
).and_return(http_response) | ||
|
||
expect(search_commits.call(repository_url, commits)).to eq(Set.new(["c7f893648f656339f62fb7b4d8a6ecdf7d063835"])) | ||
end | ||
end | ||
|
||
context "when the response contains an invalid commit type" do | ||
let(:response_payload) do | ||
{ | ||
"data" => [ | ||
{ | ||
"id" => "c7f893648f656339f62fb7b4d8a6ecdf7d063835", | ||
"type" => "invalid" | ||
} | ||
] | ||
}.to_json | ||
end | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error( | ||
Datadog::CI::Git::SearchCommits::ApiError, | ||
"Invalid commit type response {\"id\"=>\"c7f893648f656339f62fb7b4d8a6ecdf7d063835\", \"type\"=>\"invalid\"}" | ||
) | ||
end | ||
end | ||
|
||
context "when the response contains an invalid commit SHA" do | ||
let(:response_payload) do | ||
{ | ||
"data" => [ | ||
{ | ||
"id" => "INVALID_SHA", | ||
"type" => "commit" | ||
} | ||
] | ||
}.to_json | ||
end | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error(Datadog::CI::Git::SearchCommits::ApiError, "Invalid commit SHA response INVALID_SHA") | ||
end | ||
end | ||
|
||
context "when the response is not a valid JSON" do | ||
let(:response_payload) { "invalid json" } | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error( | ||
Datadog::CI::Git::SearchCommits::ApiError, | ||
"Failed to parse search commits response: unexpected token at 'invalid json'. Payload was: invalid json" | ||
) | ||
end | ||
end | ||
|
||
context "when the response is missing the data key" do | ||
let(:response_payload) { {}.to_json } | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error( | ||
Datadog::CI::Git::SearchCommits::ApiError, | ||
"Malformed search commits response: key not found: \"data\". Payload was: {}" | ||
) | ||
end | ||
end | ||
|
||
context "when the response is missing the commit type" do | ||
let(:response_payload) do | ||
{ | ||
"data" => [ | ||
{ | ||
"id" => "c7f893648f656339f62fb7b4d8a6ecdf7d063835" | ||
} | ||
] | ||
}.to_json | ||
end | ||
|
||
it "raises an error" do | ||
expect { search_commits.call(repository_url, commits) } | ||
.to raise_error( | ||
Datadog::CI::Git::SearchCommits::ApiError, | ||
"Invalid commit type response {\"id\"=>\"c7f893648f656339f62fb7b4d8a6ecdf7d063835\"}" | ||
) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.