spinnaker 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rspec +3 -0
- data/.rubocop.yml +15 -0
- data/CHANGELOG.md +19 -0
- data/README.md +47 -11
- data/Rakefile +3 -7
- data/config.ru +8 -0
- data/lib/spinnaker/api.rb +73 -0
- data/lib/spinnaker/migrate.rb +31 -0
- data/lib/spinnaker/models/helper.rb +23 -0
- data/lib/spinnaker/models/page.rb +57 -0
- data/lib/spinnaker/models/visit.rb +10 -0
- data/lib/spinnaker/version.rb +2 -2
- data/lib/spinnaker.rb +96 -2
- metadata +16 -9
- data/spinnaker.gemspec +0 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 29b7a91a929c2b0a3fce2b6b97059043b4c0522698d29da535e8b76189ccd4b5
|
4
|
+
data.tar.gz: 3d66013517a6a029006b5ca6ffc9cb6bac2ed685fd77a64b7b577eec97ddb1a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 217c7cfcb4403d8e055d1a5802566f0a14e3e427d24a740ffa383b93450366dddb8b62605cac851b1178662827bf8f8c9515311a3fa007baa2c84de90e119fbe
|
7
|
+
data.tar.gz: 5161e790d2e11ebf9dac1e60b33346da5f95f3bca185e613fe7b2a7313394cea249efba02f30f209af97a80b554b0152073f5bff6c4fa823827e5df888ab2beb
|
data/.rspec
ADDED
data/.rubocop.yml
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
AllCops:
|
2
2
|
TargetRubyVersion: 2.6
|
3
3
|
|
4
|
+
Metrics/AbcSize:
|
5
|
+
Enabled: true
|
6
|
+
Exclude:
|
7
|
+
- lib/spinnaker/api.rb
|
8
|
+
|
9
|
+
Metrics/MethodLength:
|
10
|
+
Enabled: true
|
11
|
+
Exclude:
|
12
|
+
- lib/spinnaker/api.rb
|
13
|
+
|
14
|
+
Style/ClassVars:
|
15
|
+
Enabled: true
|
16
|
+
Exclude:
|
17
|
+
- lib/spinnaker.rb
|
18
|
+
|
4
19
|
Style/StringLiterals:
|
5
20
|
Enabled: true
|
6
21
|
EnforcedStyle: double_quotes
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
## [0.1.0] - 2023-10-23
|
2
|
+
|
3
|
+
This is the initial release.
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Ability to track page visits
|
8
|
+
- Tracks the following info:
|
9
|
+
- Path
|
10
|
+
- Title
|
11
|
+
- Meta info (is it the index, a feed, etc.)
|
12
|
+
- Exists (whether or not the path is valid according to the site)
|
13
|
+
- Visits (the number of visits, as well as the time of each visit)
|
14
|
+
- Serves page data over an API
|
15
|
+
- Query the API over a specified time period:
|
16
|
+
- Default is to get page info for the last 24 hours
|
17
|
+
- /today: page data for the current day
|
18
|
+
- /week: page data for the current week
|
19
|
+
- /month: page data for the current month
|
data/README.md
CHANGED
@@ -1,34 +1,70 @@
|
|
1
1
|
# Spinnaker
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/spinnaker`. To experiment with that code, run `bin/console` for an interactive prompt.
|
3
|
+
Spinnaker is a drop-in tool for collecting and serving website page metrics. It's designed for use with [Jekyll](https://github.com/jekyll/jekyll) (and [Lanyon](https://github.com/stomar/lanyon)) in mind, but since it's just middleware for [Rack](https://github.com/rack/rack), it will work for any compatible frameworks. Spinnaker is quite private out of the box, as it only tracks what pages are being requested, and at what times those requests occur.
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
9
|
-
|
7
|
+
To add spinnaker to your project, run:
|
8
|
+
```sh
|
9
|
+
bundle add spinnaker
|
10
|
+
```
|
11
|
+
|
12
|
+
You could also install it manuall with `gem install spinnaker`.
|
13
|
+
|
14
|
+
Then `use` it in your config.ru file.
|
15
|
+
```ruby
|
16
|
+
# config.ru
|
17
|
+
|
18
|
+
require "lanyon"
|
19
|
+
require "spinnaker"
|
10
20
|
|
11
|
-
|
21
|
+
use Spinnaker
|
22
|
+
run Lanyon.application
|
23
|
+
```
|
12
24
|
|
13
|
-
|
25
|
+
If needed you can configure some settings before `use`ing it.
|
26
|
+
```ruby
|
27
|
+
# config.ru
|
14
28
|
|
15
|
-
|
29
|
+
require "lanyon"
|
30
|
+
require "spinnaker"
|
16
31
|
|
17
|
-
|
32
|
+
Spinnaker.new.tap do |s|
|
33
|
+
# Set the endpoint where spinnaker will serve metrics.
|
34
|
+
# The default value is '/spinnaker'.
|
35
|
+
s.endoint = "stats"
|
36
|
+
|
37
|
+
# Set the address (or address range) to listen on the metrics endpoint.
|
38
|
+
# Accepts CIDR range syntax (i.e. 192.168.1.0/24).
|
39
|
+
# Accepts an array of addresses, or simply a single string.
|
40
|
+
# The default value is ['127.0.0.1'].
|
41
|
+
s.listen = ["127.0.0.1", "192.168.1.0/24"]
|
42
|
+
end
|
43
|
+
|
44
|
+
use Spinnaker
|
45
|
+
run Lanyon.application
|
46
|
+
```
|
18
47
|
|
19
48
|
## Usage
|
20
49
|
|
21
|
-
|
50
|
+
Right now, you can query data over a specified time period on the API. Asumming the endpoint is '/spinnaker':
|
51
|
+
| Request Type | Path | Data |
|
52
|
+
| - | - | - |
|
53
|
+
| GET | /spinnaker{/latest} | Get page data for the last 24 hours |
|
54
|
+
| GET | /spinnaker/today | Get page data for the current day |
|
55
|
+
| GET | /spinnaker/week | Get page data for the current week |
|
56
|
+
| GET | /spinnaker/month | Get page data for the current month |
|
57
|
+
|
22
58
|
|
23
59
|
## Development
|
24
60
|
|
25
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake
|
61
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
26
62
|
|
27
63
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
28
64
|
|
29
65
|
## Contributing
|
30
66
|
|
31
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
67
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pinecat/spinnaker.
|
32
68
|
|
33
69
|
## License
|
34
70
|
|
data/Rakefile
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
|
-
require "
|
4
|
+
require "rspec/core/rake_task"
|
5
5
|
|
6
|
-
|
7
|
-
t.libs << "test"
|
8
|
-
t.libs << "lib"
|
9
|
-
t.test_files = FileList["test/**/test_*.rb"]
|
10
|
-
end
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
7
|
|
12
8
|
require "rubocop/rake_task"
|
13
9
|
|
14
10
|
RuboCop::RakeTask.new
|
15
11
|
|
16
|
-
task default: %i[
|
12
|
+
task default: %i[spec rubocop]
|
data/config.ru
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Spinnaker
|
4
|
+
# API endpoints for querying the page data.
|
5
|
+
class API
|
6
|
+
# Initializer to setup the the endpoints hash and define routes.
|
7
|
+
def initialize
|
8
|
+
@endpoints = {}
|
9
|
+
routes
|
10
|
+
end
|
11
|
+
|
12
|
+
# Called with a paht to retrieve data from one of the routes.
|
13
|
+
def handle(endpoint)
|
14
|
+
blk = @endpoints[endpoint]
|
15
|
+
return [404, {}, ["Not found"]] if blk.nil?
|
16
|
+
|
17
|
+
[200, {}, [blk.call]]
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Simple DSL to define an API route.
|
23
|
+
def route(*eps, &block)
|
24
|
+
eps.each do |ep|
|
25
|
+
@endpoints[ep] = block
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Define all API routes here (TODO: Need a better solution for this)
|
30
|
+
# TODO: These endpoints could be auto-generated with a list of timeframes/periods
|
31
|
+
def routes
|
32
|
+
# /latest, /
|
33
|
+
# Default API endpoint, serves metrics for the last 24 hours.
|
34
|
+
route "", "latest" do
|
35
|
+
period = :the_last_24_hours
|
36
|
+
{
|
37
|
+
visits: Visit.where("timestamp > ?", Helper.period(period)).count,
|
38
|
+
pages: Helper.latest(period)
|
39
|
+
}.to_json
|
40
|
+
end
|
41
|
+
|
42
|
+
# /today
|
43
|
+
# Serves metrics for the current day.
|
44
|
+
route "today" do
|
45
|
+
period = :today
|
46
|
+
{
|
47
|
+
visits: Visit.where("timestamp > ?", Helper.period(period)).count,
|
48
|
+
pages: Helper.latest(period).as_json(period)
|
49
|
+
}.to_json
|
50
|
+
end
|
51
|
+
|
52
|
+
# /week
|
53
|
+
# Serves metrics for the current day.
|
54
|
+
route "week" do
|
55
|
+
period = :this_week
|
56
|
+
{
|
57
|
+
visits: Visit.where("timestamp > ?", Helper.period(period)).count,
|
58
|
+
pages: Helper.latest(period).as_json(period)
|
59
|
+
}.to_json
|
60
|
+
end
|
61
|
+
|
62
|
+
# /month
|
63
|
+
# Serves metrics for the current day.
|
64
|
+
route "week" do
|
65
|
+
period = :this_month
|
66
|
+
{
|
67
|
+
visits: Visit.where("timestamp > ?", Helper.period(period)).count,
|
68
|
+
pages: Helper.latest(period).as_json(period)
|
69
|
+
}.to_json
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Spinnaker # :nodoc:
|
4
|
+
# return [String] The name of the pages table.
|
5
|
+
PAGES_TABLE = :spinnaker_pages
|
6
|
+
|
7
|
+
# return [String] The name of the visits table.
|
8
|
+
VISITS_TABLE = :spinnaker_visits
|
9
|
+
|
10
|
+
# Migrations for the Spinnaker table, which keeps track of page hits.
|
11
|
+
class SpinnakerMigrations < ActiveRecord::Migration[7.1]
|
12
|
+
def create_pages
|
13
|
+
create_table PAGES_TABLE do |t|
|
14
|
+
t.string :path, default: "", null: false
|
15
|
+
t.string :title, default: nil
|
16
|
+
t.string :meta, default: nil
|
17
|
+
t.boolean :exists, default: false
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index PAGES_TABLE, :path
|
21
|
+
end
|
22
|
+
|
23
|
+
def create_visits
|
24
|
+
create_table VISITS_TABLE do |t|
|
25
|
+
t.datetime :timestamp, null: false
|
26
|
+
end
|
27
|
+
|
28
|
+
add_reference VISITS_TABLE, :page, null: false, foreign_key: { to_table: PAGES_TABLE }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class Spinnaker # :nodoc:
|
2
|
+
# Helper methods for the models
|
3
|
+
module Helper
|
4
|
+
def self.latest(timeframe)
|
5
|
+
vs = Visit.where("timestamp > ?", period(timeframe))
|
6
|
+
pages = []
|
7
|
+
vs.each do |v|
|
8
|
+
pages << Page.find(v.page_id)
|
9
|
+
end
|
10
|
+
|
11
|
+
pages.uniq
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.period(timeframe)
|
15
|
+
case timeframe
|
16
|
+
when :today then Date.today.beginning_of_day
|
17
|
+
when :this_week then Date.today.beginning_of_week - 1.day
|
18
|
+
when :this_month then Date.today.beginning_of_month
|
19
|
+
else (Time.now - 1.day).beginning_of_hour
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Spinnaker # :nodoc:
|
4
|
+
# Model to access data from the 'spinnaker_pages' table.
|
5
|
+
class Page < ActiveRecord::Base
|
6
|
+
#
|
7
|
+
# Database info]
|
8
|
+
#
|
9
|
+
self.table_name = PAGES_TABLE
|
10
|
+
self.primary_key = "id"
|
11
|
+
|
12
|
+
#
|
13
|
+
# Relationships
|
14
|
+
#
|
15
|
+
|
16
|
+
# Visits track the specific time the page was requested.
|
17
|
+
has_many :visits
|
18
|
+
|
19
|
+
#
|
20
|
+
# Aliases
|
21
|
+
#
|
22
|
+
|
23
|
+
# Needed for the relation with visits to work properly.
|
24
|
+
alias_attribute :page_id, :id
|
25
|
+
|
26
|
+
#
|
27
|
+
# Functions
|
28
|
+
#
|
29
|
+
|
30
|
+
# Get when the last visit to the page was.
|
31
|
+
def last_visit
|
32
|
+
visits.last.timestamp.localtime.to_s
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get visits for a specified timeframe:
|
36
|
+
# :the_last_24_hours
|
37
|
+
# :today
|
38
|
+
# :this_week
|
39
|
+
# :this_month
|
40
|
+
# :this_year
|
41
|
+
def visits_for(timeframe)
|
42
|
+
visits.where("timestamp > ?", Helper.period(timeframe)).count
|
43
|
+
end
|
44
|
+
|
45
|
+
# Override the default as_json method.
|
46
|
+
def as_json(*options)
|
47
|
+
{
|
48
|
+
path: path,
|
49
|
+
title: title,
|
50
|
+
meta: meta,
|
51
|
+
exists: exists,
|
52
|
+
visits: visits_for(options[0]),
|
53
|
+
last: last_visit
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/spinnaker/version.rb
CHANGED
data/lib/spinnaker.rb
CHANGED
@@ -1,8 +1,102 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_record"
|
4
|
+
require "json"
|
5
|
+
require "nokogiri"
|
6
|
+
require "rack"
|
7
|
+
require "yaml"
|
8
|
+
|
9
|
+
require_relative "spinnaker/api"
|
10
|
+
require_relative "spinnaker/migrate"
|
11
|
+
require_relative "spinnaker/models/helper"
|
12
|
+
require_relative "spinnaker/models/page"
|
13
|
+
require_relative "spinnaker/models/visit"
|
3
14
|
require_relative "spinnaker/version"
|
4
15
|
|
5
|
-
|
16
|
+
# Spinnaker is a rack middleware used to log page hits to a SQL database.
|
17
|
+
class Spinnaker
|
18
|
+
# Error template.
|
6
19
|
class Error < StandardError; end
|
7
|
-
|
20
|
+
|
21
|
+
# return [String] CIDR range to listen on for the API, default is ['127.0.0.1'].
|
22
|
+
@@listen = [IPAddr.new("127.0.0.1")]
|
23
|
+
|
24
|
+
# return [String] Endpoint for the API, default is 'spinnaker'.
|
25
|
+
@@endpoint = "spinnaker"
|
26
|
+
|
27
|
+
def initialize(app = nil)
|
28
|
+
database
|
29
|
+
@api = API.new
|
30
|
+
@app = app
|
31
|
+
end
|
32
|
+
|
33
|
+
def call(env)
|
34
|
+
status, headers, body = @app.call(env)
|
35
|
+
req = Rack::Request.new(env)
|
36
|
+
|
37
|
+
if req.path.start_with? "/#{@@endpoint}"
|
38
|
+
return [403, {}, ["Forbidden"]] unless its_from_a_valid_ip(req.ip)
|
39
|
+
|
40
|
+
return @api.handle(req.path.delete_prefix("/#{@@endpoint}").delete_prefix("/"))
|
41
|
+
end
|
42
|
+
|
43
|
+
record(req.path, status, body)
|
44
|
+
[status, headers, body]
|
45
|
+
end
|
46
|
+
|
47
|
+
def listen=(val)
|
48
|
+
@@listen.clear
|
49
|
+
if val.instance_of?(Array)
|
50
|
+
val.each do |v|
|
51
|
+
@@listen << IPAddr.new(v)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
@@listen << IPAddr.new(val)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def endpoint=(val)
|
59
|
+
@@endpoint = val
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def database
|
65
|
+
conn = ENV.fetch("DATABASE_URL", { adapter: "sqlite3", database: "db/test.db" })
|
66
|
+
ActiveRecord::Base.establish_connection(conn)
|
67
|
+
SpinnakerMigrations.migrate(:create_pages) unless ActiveRecord::Base.connection.table_exists? PAGES_TABLE
|
68
|
+
SpinnakerMigrations.migrate(:create_visits) unless ActiveRecord::Base.connection.table_exists? VISITS_TABLE
|
69
|
+
end
|
70
|
+
|
71
|
+
def its_from_a_valid_ip(ip)
|
72
|
+
@@listen.each do |addr|
|
73
|
+
return true if addr.include? IPAddr.new(ip)
|
74
|
+
end
|
75
|
+
|
76
|
+
false
|
77
|
+
end
|
78
|
+
|
79
|
+
def record(path, status, body)
|
80
|
+
# Check if the page exists
|
81
|
+
exists = (status >= 400 && status < 500 ? false : true)
|
82
|
+
|
83
|
+
# Create an entry in the database
|
84
|
+
page = Page.find_or_create_by!(path: path)
|
85
|
+
page.update!(title: Nokogiri::HTML(body[0]).xpath("//title")&.text, exists: exists)
|
86
|
+
Visit.create(page: page, timestamp: Time.now)
|
87
|
+
|
88
|
+
# Determine if there is any meta data to add for the page
|
89
|
+
metainfo(page, path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def metainfo(page, path)
|
93
|
+
meta = nil
|
94
|
+
if ["/", ""].include?(path)
|
95
|
+
meta = "Index"
|
96
|
+
elsif path.include?(".xml") || path.include?(".atom")
|
97
|
+
meta = "Feed"
|
98
|
+
end
|
99
|
+
|
100
|
+
page.update!(meta: meta)
|
101
|
+
end
|
8
102
|
end
|
metadata
CHANGED
@@ -1,30 +1,37 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spinnaker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Rory Dudley
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-23 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description:
|
13
|
+
description: Track page hits for rack apps and store in a database.
|
14
14
|
email:
|
15
15
|
- rory.dudley@gmail.com
|
16
16
|
executables: []
|
17
17
|
extensions: []
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
|
+
- ".rspec"
|
20
21
|
- ".rubocop.yml"
|
22
|
+
- CHANGELOG.md
|
21
23
|
- LICENSE.txt
|
22
24
|
- README.md
|
23
25
|
- Rakefile
|
26
|
+
- config.ru
|
24
27
|
- lib/spinnaker.rb
|
28
|
+
- lib/spinnaker/api.rb
|
29
|
+
- lib/spinnaker/migrate.rb
|
30
|
+
- lib/spinnaker/models/helper.rb
|
31
|
+
- lib/spinnaker/models/page.rb
|
32
|
+
- lib/spinnaker/models/visit.rb
|
25
33
|
- lib/spinnaker/version.rb
|
26
34
|
- sig/spinnaker.rbs
|
27
|
-
- spinnaker.gemspec
|
28
35
|
homepage: https://github.com/pinecat/spinnaker
|
29
36
|
licenses:
|
30
37
|
- MIT
|
@@ -33,7 +40,7 @@ metadata:
|
|
33
40
|
homepage_uri: https://github.com/pinecat/spinnaker
|
34
41
|
source_code_uri: https://github.com/pinecat/spinnaker
|
35
42
|
changelog_uri: https://github.com/pinecat/spinnaker
|
36
|
-
post_install_message:
|
43
|
+
post_install_message:
|
37
44
|
rdoc_options: []
|
38
45
|
require_paths:
|
39
46
|
- lib
|
@@ -48,8 +55,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
48
55
|
- !ruby/object:Gem::Version
|
49
56
|
version: '0'
|
50
57
|
requirements: []
|
51
|
-
rubygems_version: 3.4.
|
52
|
-
signing_key:
|
58
|
+
rubygems_version: 3.4.21
|
59
|
+
signing_key:
|
53
60
|
specification_version: 4
|
54
|
-
summary:
|
61
|
+
summary: Track page hits for rack apps.
|
55
62
|
test_files: []
|
data/spinnaker.gemspec
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "lib/spinnaker/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = "spinnaker"
|
7
|
-
spec.version = Spinnaker::VERSION
|
8
|
-
spec.authors = ["Rory Dudley"]
|
9
|
-
spec.email = ["rory.dudley@gmail.com"]
|
10
|
-
|
11
|
-
spec.summary = "A server for Ruby/Duck applications."
|
12
|
-
spec.description = "A simple server that can serve Duck apps (https://rubygems.org/gems/duck)."
|
13
|
-
spec.homepage = "https://github.com/pinecat/spinnaker"
|
14
|
-
spec.license = "MIT"
|
15
|
-
spec.required_ruby_version = ">= 2.6.0"
|
16
|
-
|
17
|
-
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
18
|
-
|
19
|
-
spec.metadata["homepage_uri"] = spec.homepage
|
20
|
-
spec.metadata["source_code_uri"] = "https://github.com/pinecat/spinnaker"
|
21
|
-
spec.metadata["changelog_uri"] = "https://github.com/pinecat/spinnaker"
|
22
|
-
|
23
|
-
# Specify which files should be added to the gem when it is released.
|
24
|
-
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
-
spec.files = Dir.chdir(__dir__) do
|
26
|
-
`git ls-files -z`.split("\x0").reject do |f|
|
27
|
-
(File.expand_path(f) == __FILE__) ||
|
28
|
-
f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
|
29
|
-
end
|
30
|
-
end
|
31
|
-
spec.bindir = "exe"
|
32
|
-
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
33
|
-
spec.require_paths = ["lib"]
|
34
|
-
|
35
|
-
# Uncomment to register a new dependency of your gem
|
36
|
-
# spec.add_dependency "example-gem", "~> 1.0"
|
37
|
-
|
38
|
-
# For more information and examples about making a new gem, check out our
|
39
|
-
# guide at: https://bundler.io/guides/creating_gem.html
|
40
|
-
end
|