sifter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ Gemfile.lock
5
+ html
data/.rspec ADDED
File without changes
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source "http://rubygems.org"
2
+ gemspec
3
+
4
+ group :development, :test do
5
+ gem 'rspec', '~> 2.5.0'
6
+ gem 'fakeweb', '~> 1.3.0'
7
+ end
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # sifter-ruby
2
+
3
+ It's an API wrapper for the [Sifter API](http://sifterapp.com/developer). You
4
+ can use it to fetch projects, issues, milestones, and people from your Sifter
5
+ accounts.
6
+
7
+ ## Getting started
8
+
9
+ First you'll need to generate a Sifter API token. You can do this in your
10
+ Sifter account by going to "My Profile", clicking "Access Keys" and filling out
11
+ form. Once you've got that, you create an account object like so:
12
+
13
+ hostname = "example.sifterapp.com"
14
+ token = "abc123"
15
+ account = Sifter::Account.new(hostname, token)
16
+
17
+ All of the functionality in the Sifter API hangs off `Sifter::Account`. You can
18
+ fetch projects, issues, and milestones like so:
19
+
20
+ projects = account.projects
21
+ issues = projects.first.issues
22
+ milestones = projects.first.milestones
23
+
24
+ ## License
25
+
26
+ The MIT License
27
+
28
+ Copyright (c) 2011 Next Update
29
+
30
+ Permission is hereby granted, free of charge, to any person obtaining a copy
31
+ of this software and associated documentation files (the "Software"), to deal
32
+ in the Software without restriction, including without limitation the rights
33
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
34
+ copies of the Software, and to permit persons to whom the Software is
35
+ furnished to do so, subject to the following conditions:
36
+
37
+ The above copyright notice and this permission notice shall be included in
38
+ all copies or substantial portions of the Software.
39
+
40
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
41
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
42
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
43
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
44
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
45
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
46
+ THE SOFTWARE.
47
+
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ require 'bundler'
2
+ require 'rspec/core/rake_task'
3
+ require 'rake/rdoctask'
4
+
5
+ Bundler::GemHelper.install_tasks
6
+
7
+ task :default => :spec
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.rspec_opts = ["--format documentation"]
10
+ end
11
+
12
+ Rake::RDocTask.new do |t|
13
+ t.main = "README.md"
14
+ t.rdoc_files.include("README.md", "lib/**/*.rb")
15
+ t.options << "--accessor=property"
16
+ end
@@ -0,0 +1,52 @@
1
+ require "sifter"
2
+ require "optparse"
3
+
4
+ options = {}
5
+ opts = OptionParser.new do |opts|
6
+ opts.banner = <<-EOF
7
+ Usage:
8
+ milestones -t <token> -a <account> -p <project> [-m <name>]
9
+
10
+ Options:
11
+ EOF
12
+
13
+ opts.on("-tTOKEN", "--token TOKEN", "Sifter API token") do |t|
14
+ options[:token] = t
15
+ end
16
+
17
+ opts.on("-aACCOUNT", "--account ACCOUNT", "Account/subdomain to query") do |a|
18
+ options[:account] = a
19
+ end
20
+
21
+ opts.on("-mMILESTONE", "--milestone MILESTONE", "Milestone to query") do |m|
22
+ options[:milestone] = m
23
+ end
24
+
25
+ opts.on("-pPROJECT", "--project PROJECT", "Project to query") do |p|
26
+ options[:project] = p
27
+ end
28
+ end
29
+
30
+ opts.parse!
31
+
32
+ if __FILE__ == $PROGRAM_NAME
33
+ unless options.has_key?(:account) && options.has_key?(:token)
34
+ puts "Account and token parameters required."
35
+ exit 1
36
+ end
37
+
38
+ hostname = "#{options[:account]}.sifterapp.com"
39
+ token = options[:token]
40
+ account = Sifter::Account.new(hostname, token)
41
+ if options.has_key?(:project)
42
+ project = account.projects.select { |p|
43
+ p.name.downcase == options[:project].downcase
44
+ }.first
45
+
46
+ puts "Milestones:"
47
+ project.milestones.each { |m| puts " #{m.name}" }
48
+ else
49
+ puts "Projects:"
50
+ account.projects.each { |p| puts " #{p.name}" }
51
+ end
52
+ end
data/lib/sifter.rb ADDED
@@ -0,0 +1,50 @@
1
+ require "httparty"
2
+ require "hashie"
3
+
4
+ class Sifter
5
+
6
+ include HTTParty
7
+
8
+ autoload :Account, "sifter/account"
9
+ autoload :Project, "sifter/project"
10
+
11
+ # Wrapper around an issue.
12
+ class Issue < Hashie::Dash
13
+
14
+ property :number
15
+ property :subject
16
+ property :description
17
+ property :priority
18
+ property :status
19
+ property :assignee_name
20
+ property :category_name
21
+ property :milestone_name
22
+ property :opener_name
23
+ property :url
24
+ property :api_url
25
+
26
+ end
27
+
28
+ # Wrapper around a milestone.
29
+ class Milestone < Hashie::Dash
30
+
31
+ property :name
32
+ property :due_date
33
+ property :url
34
+ property :api_url
35
+ property :issues_url
36
+ property :api_issues_url
37
+
38
+ end
39
+
40
+ # Wrapper around a person.
41
+ class Person < Hashie::Dash
42
+
43
+ property :username
44
+ property :first_name
45
+ property :last_name
46
+ property :email
47
+
48
+ end
49
+
50
+ end
@@ -0,0 +1,40 @@
1
+ # Wrapper around an a Sifter account. Use this as the root for accessing the
2
+ # Sifter API.
3
+ class Sifter::Account
4
+
5
+ # Connect to a Sifter account. The host is the subdomain for your Sifter
6
+ # account (yourhost.sifterapp.com), you can get a token by going to
7
+ # Profile->Access Keys.
8
+ def initialize(host, token)
9
+ Sifter.default_options[:base_uri] = "https://" << host
10
+ Sifter.default_options[:headers] = {"X-Sifter-Token" => token}
11
+ end
12
+
13
+ # Fetch the possible issue statuses for this project. This is currently hardcoded
14
+ # in the app, so it's unlikely they'll change anytime soon.
15
+ def statuses
16
+ Sifter.
17
+ get("/api/statuses").
18
+ parsed_response["statuses"]
19
+ end
20
+
21
+
22
+ # Fetch the possible issue priorities for this project. This is currently hardcoded
23
+ # in the app, so it's unlikely they'll change anytime soon.
24
+ def priorities
25
+ Sifter.
26
+ get("/api/priorities").
27
+ parsed_response["priorities"]
28
+ end
29
+
30
+ # Fetch all projects that you have access to for this account. Returns an
31
+ # array of Sifter::Project objects.
32
+ def projects
33
+ Sifter.
34
+ get("/api/projects").
35
+ parsed_response["projects"].
36
+ map { |p| Sifter::Project.new(p) }
37
+ end
38
+
39
+ end
40
+
@@ -0,0 +1,44 @@
1
+ # Wrapper for a Sifter project. Fetch projects using Sifter::Account.
2
+ class Sifter::Project < Hashie::Dash
3
+
4
+ property :name
5
+ property :archived
6
+ property :primary_company_name
7
+ property :url
8
+ property :api_url
9
+ property :issues_url
10
+ property :milestones_url
11
+ property :people_url
12
+ property :api_milestones_url
13
+ property :api_people_url
14
+ property :api_issues_url
15
+ property :api_categories_url
16
+
17
+ # Fetch all the issues on this project. Returns an array of Sifter::Issue
18
+ # objects.
19
+ def issues
20
+ Sifter.
21
+ get(api_issues_url).
22
+ fetch("issues", []).
23
+ map { |i| Sifter::Issue.new(i) }
24
+ end
25
+
26
+ # Fetch all the milestones for this project. Returns an array of
27
+ # Sifter::Milestone objects.
28
+ def milestones
29
+ Sifter.
30
+ get(api_milestones_url).
31
+ fetch("milestones", []).
32
+ map { |m| Sifter::Milestone.new(m) }
33
+ end
34
+
35
+ # Fetch all the people linked to this project. Returns an array of
36
+ # Sifter::Person objects.
37
+ def people
38
+ Sifter.
39
+ get(api_people_url).
40
+ fetch("people", []).
41
+ map { |p| Sifter::Person.new(p) }
42
+ end
43
+
44
+ end
@@ -0,0 +1,3 @@
1
+ class Sifter
2
+ VERSION = "0.1.0"
3
+ end
data/sifter.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "sifter/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "sifter"
7
+ s.version = Sifter::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Adam Keys"]
10
+ s.email = ["adam@nextupdate.com"]
11
+ s.homepage = "http://github.com/nextupdate/sifter-ruby"
12
+ s.summary = %q{Wrapper for the Sifter API}
13
+ s.description = %q{Query, fetch, create and modify issues stored in Sifter.}
14
+
15
+ s.rubyforge_project = "sifter"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'httparty', '~> 0.6.1'
23
+ s.add_dependency 'hashie', '~> 0.4.0'
24
+ end
@@ -0,0 +1,36 @@
1
+ {
2
+ "issues": [
3
+ {
4
+ "number": 57,
5
+ "category_name": "Enhancement",
6
+ "priority": "Trivial",
7
+ "subject": "Donec vel neque",
8
+ "description": "Nam id libero quis ipsum feugiat elementum. Vivamus vitae mauris ut ipsum mattis malesuada. Sed vel massa. Mauris lobortis. Nunc egestas, massa id scelerisque dapibus, urna mi accumsan purus, vel aliquam nunc sapien eget nisi. Quisque vitae nibh. Proin interdum mollis leo. Fusce sed nisi. Integer ut tortor.",
9
+ "milestone_name": null,
10
+ "opener_name": "Adam Keys",
11
+ "assignee_name": "Garrett Dimon",
12
+ "status": "Open",
13
+ "url": "https://example.sifterapp.com/projects/189113590/issues/46809840",
14
+ "api_url": "https://example.sifterapp.com/api/projects/189113590/issues/46809840"
15
+ },
16
+ {
17
+ "number": 63,
18
+ "category_name": "Bug",
19
+ "priority": "Trivial",
20
+ "subject": "Sed lectus nunc, egestas tincidunt",
21
+ "description": "Proin dictum dignissim metus. Vivamus vel risus sed augue venenatis sodales. Quisque tempus dictum lorem. Sed a turpis eu turpis lobortis pellentesque. Nunc sem mi, ullamcorper non, dignissim eu, pellentesque eget, justo. Donec mollis neque quis tortor. In hac habitasse platea dictumst. Mauris at velit non erat scelerisque iaculis.",
22
+ "milestone_name": null,
23
+ "opener_name": "Adam Keys",
24
+ "assignee_name": null,
25
+ "status": "Open",
26
+ "url": "https://example.sifterapp.com/projects/189113590/issues/465769292",
27
+ "api_url": "https://example.sifterapp.com/api/projects/189113590/issues/465769292"
28
+ }
29
+ ],
30
+ "per_page": 10,
31
+ "page": 1,
32
+ "total_pages": 2,
33
+ "next_page_url": "https://example.sifterapp.com/api/projects/189113590/issues?per_page=10&page=1",
34
+ "previous_page_url": null
35
+ }
36
+
@@ -0,0 +1,18 @@
1
+ {
2
+ "milestones": [
3
+ {
4
+ "name": "Private Release",
5
+ "due_date": "2010/04/15",
6
+ "issues_url": "https://example.sifterapp.com/projects/189113590/issues?m=1",
7
+ "api_issues_url": "https://example.sifterapp.com/api/projects/189113590/issues?m=1"
8
+ },
9
+ {
10
+ "name": "Public Release",
11
+ "due_date": "2010/05/15",
12
+ "issues_url": "https://example.sifterapp.com/projects/189113590/issues?m=2",
13
+ "api_issues_url": "https://example.sifterapp.com/api/projects/189113590/issues?m=2"
14
+ }
15
+
16
+ ]
17
+ }
18
+
@@ -0,0 +1,22 @@
1
+ {
2
+ "people": [
3
+ {
4
+ "username": "gdimon",
5
+ "first_name": "Garrett",
6
+ "last_name": "Dimon",
7
+ "email": "garrett@nextupdate.com"
8
+ },
9
+ {
10
+ "username": "lpage",
11
+ "first_name": "Larry",
12
+ "last_name": "Page",
13
+ "email": "larry@garrettdimon.com"
14
+ },
15
+ {
16
+ "username": "sbrin",
17
+ "first_name": "Sergey",
18
+ "last_name": "Brin",
19
+ "email": "sergey@garrettdimon.com"
20
+ }
21
+ ]
22
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "priorities": {
3
+ "Trivial": 5,
4
+ "High": 2,
5
+ "Normal": 3,
6
+ "Critical": 1,
7
+ "Low": 4
8
+ }
9
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "projects": [
3
+ {
4
+ "name": "Elephant",
5
+ "primary_company_name": "Apple",
6
+ "archived": false,
7
+ "url": "https://example.sifterapp.com/projects/189113590",
8
+ "issues_url": "https://example.sifterapp.com/projects/189113590/issues",
9
+ "milestones_url": "https://example.sifterapp.com/projects/189113590/milestones",
10
+ "api_url": "https://example.sifterapp.com/api/projects/189113590",
11
+ "api_issues_url": "https://example.sifterapp.com/api/projects/189113590/issues",
12
+ "api_milestones_url": "https://example.sifterapp.com/api/projects/189113590/milestones",
13
+ "api_categories_url": "https://example.sifterapp.com/api/projects/189113590/categories",
14
+ "api_people_url": "https://example.sifterapp.com/api/projects/189113590/people"
15
+ },
16
+ {
17
+ "name": "Zebra",
18
+ "primary_company_name": "Google",
19
+ "archived": true,
20
+ "url": "https://example.sifterapp.com/projects/358047158",
21
+ "issues_url": "https://example.sifterapp.com/projects/358047158/issues",
22
+ "milestones_url": "https://example.sifterapp.com/projects/358047158/milestones",
23
+ "api_url": "https://example.sifterapp.com/api/projects/358047158",
24
+ "api_issues_url": "https://example.sifterapp.com/api/projects/358047158/issues",
25
+ "api_milestones_url": "https://example.sifterapp.com/api/projects/358047158/milestones",
26
+ "api_categories_url": "https://example.sifterapp.com/api/projects/358047158/categories",
27
+ "api_people_url": "https://example.sifterapp.com/api/projects/358047158/people"
28
+ }
29
+ ]
30
+ }
31
+
@@ -0,0 +1,9 @@
1
+ {
2
+ "statuses": {
3
+ "Open": 1,
4
+ "Closed": 4,
5
+ "Resolved": 3,
6
+ "Reopened": 2
7
+ }
8
+ }
9
+
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sifter::Account do
4
+
5
+ let(:account) { Sifter::Account.new("example.sifterapp.com", "abc123") }
6
+
7
+ it "fetches status codes" do
8
+ stub_get("/api/statuses", "statuses.json")
9
+
10
+ statuses = account.statuses
11
+
12
+ statuses["Open"].should == 1
13
+ statuses.length.should == 4
14
+ end
15
+
16
+ it "fetches priority codes" do
17
+ stub_get("/api/priorities", "priorities.json")
18
+
19
+ priorities = account.priorities
20
+
21
+ priorities["High"].should == 2
22
+ priorities.length.should == 5
23
+ end
24
+
25
+ it "fetches all projects" do
26
+ stub_get("/api/projects", "projects.json")
27
+
28
+ projects = account.projects
29
+
30
+ projects.length.should == 2
31
+ projects.first.should be_kind_of(Sifter::Project)
32
+ end
33
+
34
+ end
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe Sifter::Project do
4
+
5
+ before do
6
+ stub_get("/api/projects", "projects.json")
7
+ end
8
+
9
+ let(:account) { Sifter::Account.new("example.sifterapp.com", "abc123") }
10
+ let(:project) { account.projects.select { |p| p.name == "Elephant" }.first }
11
+
12
+ it "initializes from a hash" do
13
+ attrs = {
14
+ "name"=>"Elephant",
15
+ "issues_url"=>"https://example.sifterapp.com/projects/189113590/issues",
16
+ "api_milestones_url"=>
17
+ "https://example.sifterapp.com/api/projects/189113590/milestones",
18
+ "primary_company_name"=>"Apple",
19
+ "api_people_url"=>
20
+ "https://example.sifterapp.com/api/projects/189113590/people",
21
+ "url"=>"https://example.sifterapp.com/projects/189113590",
22
+ "archived"=>false,
23
+ "api_issues_url"=>
24
+ "https://example.sifterapp.com/api/projects/189113590/issues",
25
+ "api_categories_url"=>
26
+ "https://example.sifterapp.com/api/projects/189113590/categories",
27
+ "api_url"=>"https://example.sifterapp.com/api/projects/189113590",
28
+ "milestones_url"=>
29
+ "https://example.sifterapp.com/projects/189113590/milestones"
30
+ }
31
+
32
+ project = Sifter::Project.new(attrs)
33
+ attrs.each { |k, v| project[k].should == v }
34
+ end
35
+
36
+ it "fetches issues" do
37
+ stub_get(project.api_issues_url, "issues.json")
38
+
39
+ issues = project.issues
40
+
41
+ issues.length.should == 2
42
+ issues.first.should be_a(Sifter::Issue)
43
+ end
44
+
45
+ it "fetches milestones" do
46
+ stub_get(project.api_milestones_url, "milestones.json")
47
+
48
+ milestones = project.milestones
49
+
50
+ milestones.length.should == 2
51
+ milestones.first.should be_a(Sifter::Milestone)
52
+ end
53
+
54
+ it "fetches people" do
55
+ stub_get(project.api_people_url, "people.json")
56
+
57
+ people = project.people
58
+
59
+ people.length.should == 3
60
+ people.first.should be_a(Sifter::Person)
61
+ end
62
+
63
+ end
@@ -0,0 +1,29 @@
1
+ require "fakeweb"
2
+ require "sifter"
3
+
4
+ FakeWeb.allow_net_connect = false
5
+
6
+ RSpec.configure do
7
+
8
+ # Gratuitously borrowed from Wynn Netherland's gowalla gem
9
+ def stub_get(url, filename, options={})
10
+ opts = {
11
+ :body => fixture_file(filename),
12
+ :content_type => 'application/json; charset=utf-8'
13
+ }.merge(options)
14
+ FakeWeb.register_uri(:get, sifter_url(url), opts)
15
+ end
16
+
17
+ def fixture_file(filename)
18
+ return filename if filename == ''
19
+ file_path = File.expand_path(
20
+ File.dirname(__FILE__) + '/fixtures/' + filename
21
+ )
22
+ File.read(file_path)
23
+ end
24
+
25
+ def sifter_url(url)
26
+ url =~ /^http/ ? url : "https://example.sifterapp.com#{url}"
27
+ end
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,126 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sifter
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Adam Keys
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-10 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: httparty
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 0
32
+ - 6
33
+ - 1
34
+ version: 0.6.1
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: hashie
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 15
46
+ segments:
47
+ - 0
48
+ - 4
49
+ - 0
50
+ version: 0.4.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Query, fetch, create and modify issues stored in Sifter.
54
+ email:
55
+ - adam@nextupdate.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - .rspec
65
+ - Gemfile
66
+ - README.md
67
+ - Rakefile
68
+ - examples/listing.rb
69
+ - lib/sifter.rb
70
+ - lib/sifter/account.rb
71
+ - lib/sifter/project.rb
72
+ - lib/sifter/version.rb
73
+ - sifter.gemspec
74
+ - spec/fixtures/issues.json
75
+ - spec/fixtures/milestones.json
76
+ - spec/fixtures/people.json
77
+ - spec/fixtures/priorities.json
78
+ - spec/fixtures/projects.json
79
+ - spec/fixtures/statuses.json
80
+ - spec/sifter/account_spec.rb
81
+ - spec/sifter/project_spec.rb
82
+ - spec/spec_helper.rb
83
+ has_rdoc: true
84
+ homepage: http://github.com/nextupdate/sifter-ruby
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options: []
89
+
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ hash: 3
107
+ segments:
108
+ - 0
109
+ version: "0"
110
+ requirements: []
111
+
112
+ rubyforge_project: sifter
113
+ rubygems_version: 1.3.7
114
+ signing_key:
115
+ specification_version: 3
116
+ summary: Wrapper for the Sifter API
117
+ test_files:
118
+ - spec/fixtures/issues.json
119
+ - spec/fixtures/milestones.json
120
+ - spec/fixtures/people.json
121
+ - spec/fixtures/priorities.json
122
+ - spec/fixtures/projects.json
123
+ - spec/fixtures/statuses.json
124
+ - spec/sifter/account_spec.rb
125
+ - spec/sifter/project_spec.rb
126
+ - spec/spec_helper.rb