Skip to content

Commit

Permalink
Migrate CI to GitHub actions (#186)
Browse files Browse the repository at this point in the history
Migrate CI to GitHub Actions now that Travis CI.org is inactive.

In addition to adding a basic `ci.yml` file, I needed to make several other changes:

1. Loosen the development dependency on `rake` to allow more recent versions
2. Wrap the use of `YAML::load` in the specs in a helper function that allows us to explicitly use `YAML::safe_load` with `OpenStruct` as a permitted class for Ruby 3.1 and up
3. Replace `File.exists?` with `File.exist?`

Ruby head is still failing because of a process start race condition between the `PatronTestServer` and the actual specs.  In the interest of getting something working quickly I temporarily removed `ruby-head`.  All other Rubies in the CI file are green.
  • Loading branch information
petergoldstein authored Mar 30, 2022
1 parent 1067878 commit 4bc6631
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 56 deletions.
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Tests

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
ruby-version: [2.4, 2.5, 2.6, 2.7, '3.0', 3.1]

name: Specs - Ruby ${{ matrix.ruby-version }}
steps:
- uses: actions/checkout@v2
- name: Install libcurl
run: |
sudo apt-get update
sudo apt-get -y install libcurl4 libcurl4-openssl-dev
- name: Set up Ruby ${{ matrix.ruby-version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby-version }}
bundler-cache: true # 'bundle install' and cache
- name: Run tests
run: bundle exec rake
4 changes: 2 additions & 2 deletions lib/patron/session.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ def handle_cookies(file_path = nil)
if file_path
path = Pathname(file_path).expand_path

if !File.exists?(file_path) && !File.writable?(path.dirname)
if !File.exist?(file_path) && !File.writable?(path.dirname)
raise ArgumentError, "Can't create file #{path} (permission error)"
elsif File.exists?(file_path) && !File.writable?(file_path)
elsif File.exist?(file_path) && !File.writable?(file_path)
raise ArgumentError, "Can't read or write file #{path} (permission error)"
end
else
Expand Down
2 changes: 1 addition & 1 deletion patron.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ SecureTransport-based builds might cause crashes in forking environment.
For more info see https://github.com/curl/curl/issues/788
}
spec.add_development_dependency "rake", "~> 12.3.3"
spec.add_development_dependency "rake", ">= 12.3.3"
spec.add_development_dependency "bundler"
spec.add_development_dependency "rspec", ">= 2.3.0"
spec.add_development_dependency "simplecov", "~> 0.10"
Expand Down
72 changes: 40 additions & 32 deletions spec/session_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@

describe Patron::Session do

def yaml_load(str)
if RUBY_VERSION >= '3.1.0'
YAML::safe_load(str, permitted_classes: [OpenStruct])
else
YAML::load(str)
end
end

before(:each) do
@session = Patron::Session.new
@session.base_url = "http://localhost:9001"
Expand Down Expand Up @@ -72,7 +80,7 @@

it "should retrieve a url with :get" do
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "GET"
end

Expand All @@ -91,7 +99,7 @@
tmpfile = "/tmp/patron_test.yaml"
response = @session.get_file "/test", tmpfile
expect(response.body).to be_nil
body = YAML::load_file(tmpfile)
body = yaml_load(File.open(tmpfile).read)
expect(body.request_method).to be == "GET"
FileUtils.rm tmpfile
end
Expand Down Expand Up @@ -143,33 +151,33 @@
it "should not send the user-agent if it has been deleted from headers" do
@session.headers.delete 'User-Agent'
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header["user-agent"]).to be_nil
end

it "should set the default User-agent" do
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header["user-agent"]).to be == [Patron.user_agent_string]
end

it "should include custom headers in a request" do
response = @session.get("/test", {"User-Agent" => "PatronTest"})
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header["user-agent"]).to be == ["PatronTest"]
end

it "should include default headers in a request, if they were defined" do
@session.headers = {"User-Agent" => "PatronTest"}
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header["user-agent"]).to be == ["PatronTest"]
end

it "should merge custom headers with session headers" do
@session.headers["X-Test"] = "Testing"
response = @session.get("/test", {"User-Agent" => "PatronTest"})
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header["user-agent"]).to be == ["PatronTest"]
expect(body.header["x-test"]).to be == ["Testing"]
end
Expand Down Expand Up @@ -252,7 +260,7 @@
it "should follow redirects by default" do
@session.max_redirects = 1
response = @session.get("/redirect")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(response.status).to be == 200
expect(body.path).to be == "/test"
end
Expand Down Expand Up @@ -285,34 +293,34 @@

it "should send a delete request with :delete" do
response = @session.delete("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "DELETE"
end

it "should send a COPY request with :copy" do
response = @session.copy("/test", "/test2")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "COPY"
end

it "should include a Destination header in COPY requests" do
response = @session.copy("/test", "/test2")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header['destination'].first).to be == "/test2"
end

it "should upload data with :get" do
data = "upload data"
response = @session.request(:get, "/test", {}, :data => data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "GET"
expect(body.header['content-length']).to be == [data.size.to_s]
end

it "should call to_s on the data being uploaded via GET if it is not already a String" do
data = 12345
response = @session.request(:get, "/test", {}, :data => data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "GET"
end

Expand All @@ -323,15 +331,15 @@
# you can have very deeply going queries, which are still technically GETs
data = Random.new.bytes(1024 * 24)
response = @session.request(:get, "/test", {}, :data => data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "GET"
expect(body.header['content-length']).to be == [data.size.to_s]
end

it "should upload data with :put" do
data = Random.new.bytes(1024 * 24)
response = @session.put("/test", data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "PUT"
expect(body.header['content-length']).to be == [data.size.to_s]
end
Expand All @@ -342,22 +350,22 @@
data.flush; data.rewind

response = @session.put("/test", data, {'Expect' => ''})
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "PUT"
expect(body.header['content-length']).to be == [data.size.to_s]
end

it "should upload data with :patch" do
data = "upload data"
response = @session.patch("/testpatch", data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.body).to eq("upload data")
end

it "should upload data with :delete" do
data = "upload data"
response = @session.request(:delete, "/test", {}, :data => data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "DELETE"
expect(body.header['content-length']).to be == [data.size.to_s]
end
Expand All @@ -368,7 +376,7 @@

it "should upload a file with :put" do
response = @session.put_file("/test", "LICENSE")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "PUT"
end

Expand All @@ -378,29 +386,29 @@

it "should use chunked encoding when uploading a file with :put" do
response = @session.put_file("/test", "LICENSE")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header['transfer-encoding'].first).to be == "chunked"
end

it "should call to_s on the data being uploaded via POST if it is not already a String" do
data = 12345
response = @session.post("/testpost", data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body['body']).to eq("12345")
end

it "should upload data with :post" do
data = "upload data"
response = @session.post("/test", data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "POST"
expect(body.header['content-length']).to be == [data.size.to_s]
end

it "should POST a hash of arguments as a urlencoded form" do
data = {:foo => 123, 'baz' => '++hello world++'}
response = @session.post("/testpost", data)
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body['content_type']).to be == "application/x-www-form-urlencoded"
expect(body['body']).to match(/baz=%2B%2Bhello%20world%2B%2B/)
expect(body['body']).to match(/foo=123/)
Expand All @@ -412,13 +420,13 @@

it "should upload a file with :post" do
response = @session.post_file("/test", "LICENSE")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "POST"
end

it "should upload a multipart with :post" do
response = @session.post_multipart("/test", { :test_data => "123" }, { :test_file => "LICENSE" } )
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.request_method).to be == "POST"
end

Expand All @@ -428,15 +436,15 @@

it "should use chunked encoding when uploading a file with :post" do
response = @session.post_file("/test", "LICENSE")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header['transfer-encoding'].first).to be == "chunked"
end

it "should pass credentials as http basic auth" do
@session.username = "foo"
@session.password = "bar"
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
expect(body.header['authorization']).to be == [encode_authz("foo", "bar")]
end

Expand All @@ -455,12 +463,12 @@
it "should handle cookies if set" do
@session.handle_cookies
response = @session.get("/setcookie").body
expect(YAML::load(response).header['cookie'].first).to be == "session_id=foo123"
expect(yaml_load(response).header['cookie'].first).to be == "session_id=foo123"
end

it "should not handle cookies by default" do
response = @session.get("/setcookie").body
expect(YAML::load(response).header).to_not include('cookie')
expect(yaml_load(response).header).to_not include('cookie')
end

it "should ignore a wrong Content-Length when asked to" do
Expand Down Expand Up @@ -505,7 +513,7 @@

expect {
response = @session.get("/test")
body = YAML::load(response.body)
body = yaml_load(response.body)
}.to_not raise_error

expect(body.request_method).to be == "GET"
Expand All @@ -524,13 +532,13 @@

it "should serialize query params and append them to the url" do
response = @session.request(:get, "/test", {}, :query => {:foo => "bar"})
request = YAML::load(response.body)
request = yaml_load(response.body)
expect(request.path + '?' + request.query_string).to be == "/test?foo=bar"
end

it "should merge parameters in the :query option with pre-existing query parameters" do
response = @session.request(:get, "/test?foo=bar", {}, :query => {:baz => "quux"})
request = YAML::load(response.body)
request = yaml_load(response.body)
expect(request.path + '?' + request.query_string).to be == "/test?foo=bar&baz=quux"
end

Expand Down
Loading

0 comments on commit 4bc6631

Please sign in to comment.