├── log └── .keep ├── .ruby-version ├── .ruby-gemset ├── img ├── diagram.jpg └── diagram-original.jpg ├── Procfile ├── config.ru ├── config ├── travis.example.yml └── puma.rb ├── .dockerignore ├── .travis.yml ├── CONTRIBUTING.md ├── spec ├── fixtures │ └── github │ │ └── api.github.com │ │ └── users │ │ └── svenfuchs.json ├── spec_helper.rb ├── payloads │ ├── installation.json │ ├── installation_repositories.json │ ├── release.json │ ├── release_created.json │ ├── branch_deleted.json │ ├── repo_created.json │ ├── repo_deleted.json │ ├── repo_privatized.json │ ├── repo_publicized.json │ ├── tag_created.json │ ├── tag_deleted.json │ ├── branch_created.json │ ├── member.json │ ├── member_removed.json │ ├── push.json │ ├── bot_push.json │ ├── rerequested_check_suite_tag_ref_type.json │ ├── rerequested_check_suite.json │ ├── rerequested_check_run.json │ └── pull_request.json └── travis │ └── listener │ ├── app_spec.rb │ └── events_spec.rb ├── .gitignore ├── Dockerfile ├── .rubocop.yml ├── .github └── workflows │ └── trivy-analysis.yml ├── LICENSE ├── README.mdown ├── Gemfile ├── lib └── travis │ ├── listener.rb │ ├── sidekiq.rb │ └── listener │ ├── schemas.rb │ └── app.rb ├── Makefile └── Gemfile.lock /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.2 2 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | travis-listener 2 | -------------------------------------------------------------------------------- /img/diagram.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travis-ci/travis-listener/HEAD/img/diagram.jpg -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec puma -C config/puma.rb 2 | console: bundle exec irb -I lib -r travis/listener 3 | -------------------------------------------------------------------------------- /img/diagram-original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/travis-ci/travis-listener/HEAD/img/diagram-original.jpg -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path('lib', __dir__) 4 | 5 | require 'travis/listener' 6 | 7 | Travis::Listener.setup 8 | 9 | use Sentry::Rack::CaptureExceptions if Travis.config.sentry.dsn 10 | run Travis::Listener::App 11 | -------------------------------------------------------------------------------- /config/travis.example.yml: -------------------------------------------------------------------------------- 1 | production: 2 | log_level: info 3 | sentry: 4 | dsn: https://tok:en@app.getsentry.com/app_id 5 | redis: 6 | url: redis://tok:en@url.com:12345 7 | 8 | staging: 9 | sentry: 10 | dsn: https://tok:en@app.getsentry.com/app_id 11 | redis: 12 | url: redis://tok:en@url.com:12345 -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | workers Integer(ENV.fetch('WEB_CONCURRENCY', nil) || 2) 4 | threads_count = Integer(ENV.fetch('RAILS_MAX_THREADS', nil) || 5) 5 | threads threads_count, threads_count 6 | 7 | preload_app! 8 | 9 | port ENV.fetch('PORT', nil) || 3000 10 | environment ENV.fetch('RACK_ENV', nil) || 'development' 11 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # Ignore docker files 2 | .dockerignore 3 | Dockerfile* 4 | docker-compose* 5 | 6 | # Ignore .git 7 | /.git 8 | .gitignore 9 | 10 | # Ignore bundler config. 11 | /.bundle 12 | vendor/bundle 13 | 14 | /.env 15 | .travis.yml 16 | 17 | # Ignore all logfiles. 18 | /log/* 19 | !/log/.keep 20 | 21 | # Ignore Rubocop files 22 | .rubocop-* 23 | 24 | # Ignore coverage reports 25 | /coverage/* 26 | 27 | # Ignore editor specific configs 28 | /.idea 29 | /.vscode 30 | .project 31 | .classpath 32 | .c9/ 33 | *.launch 34 | .settings/ 35 | *.sublime-workspace 36 | .generators 37 | .rakeTasks 38 | 39 | # System Files 40 | .DS_Store 41 | Thumbs.db 42 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | dist: bionic 3 | 4 | rvm: 3.2.2 5 | 6 | services: 7 | - redis 8 | 9 | env: 10 | global: 11 | - PATH=/snap/bin:$PATH 12 | 13 | cache: bundler 14 | 15 | before_install: 16 | - gem update --system 3.4.19 > /dev/null 2>&1 17 | 18 | bundler_args: --without development --jobs 3 --retry 3 --deployment 19 | 20 | jobs: 21 | include: 22 | - stage: "rspec" 23 | script: bundle exec rspec spec 24 | - stage: ":ship: it" 25 | install: skip 26 | before_install: skip 27 | script: make ship 28 | if: (branch = master and type = push ) OR commit_message =~ /ship:docker/ OR env(SHIP_DOCKER) = true 29 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Travis CI 2 | 3 | Issues for any Travis CI repo should be submitted to https://github.com/travis-ci/travis-ci/issues 4 | 5 | ## Security Issues 6 | 7 | ***Any security issues should be submitted directly to [security@travis-ci.org](mailto:security@travis-ci.org)*** 8 | 9 | ## Reporting Issues 10 | 11 | - Explain what you expected to happen vs the actual results 12 | - Include a screenshot if it helps illustrate the issue. https://github.com/blog/1347-issue-attachments 13 | - What steps are required to reproduce the issue 14 | - An example build that shows the issue 15 | 16 | ## Submitting a PR to Travis-Listener 17 | 18 | See testing and setup notes in the base [README](https://github.com/travis-ci/travis-listener) -------------------------------------------------------------------------------- /spec/fixtures/github/api.github.com/users/svenfuchs.json: -------------------------------------------------------------------------------- 1 | { 2 | "public_repos": 86, 3 | "type": "User", 4 | "public_gists": 79, 5 | "location": "Germany/Berlin", 6 | "url": "https://api.github.com/users/svenfuchs", 7 | "company": null, 8 | "html_url": "https://github.com/svenfuchs", 9 | "hireable": false, 10 | "avatar_url": "https://secure.gravatar.com/avatar/402602a60e500e85f2f5dc1ff3648ecb?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png", 11 | "created_at": "2008-03-04T20:38:09Z", 12 | "email": "me@svenfuchs.com", 13 | "bio": "", 14 | "name": "Sven Fuchs", 15 | "gravatar_id": "402602a60e500e85f2f5dc1ff3648ecb", 16 | "followers": 276, 17 | "following": 90, 18 | "blog": "http://svenfuchs.com", 19 | "id": 2208, 20 | "login": "svenfuchs" 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | vendor/bundle 10 | 11 | config/travis.yml 12 | 13 | # Ignore all logfiles. 14 | /log/* 15 | !/log/.keep 16 | 17 | # Ignore Rubocop files 18 | .rubocop-* 19 | 20 | # Ignore coverage reports 21 | /coverage/* 22 | 23 | # Ignore editor specific configs 24 | /.idea 25 | /.vscode 26 | .project 27 | .classpath 28 | .c9/ 29 | *.launch 30 | .settings/ 31 | *.sublime-workspace 32 | .generators 33 | .rakeTasks 34 | 35 | # System Files 36 | .DS_Store 37 | Thumbs.db 38 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3.2.2-slim 2 | 3 | LABEL maintainer Travis CI GmbH 4 | 5 | # packages required for bundle install 6 | RUN ( \ 7 | apt-get update ; \ 8 | apt-get upgrade -y ; \ 9 | apt-get install -y --no-install-recommends git make gcc \ 10 | && rm -rf /var/lib/apt/lists/* \ 11 | ) 12 | 13 | WORKDIR /app 14 | 15 | RUN gem update --system 3.4.19 > /dev/null 2>&1 16 | 17 | # Bundle config 18 | RUN bundle config set --global no-cache 'true' && \ 19 | bundle config set --global frozen 'true' && \ 20 | bundle config set --global jobs `expr $(cat /proc/cpuinfo | grep -c 'cpu cores')` && \ 21 | bundle config set --global retry 3 && \ 22 | bundle config set --local deployment 'true' && \ 23 | bundle config set --local without 'development test' 24 | 25 | COPY Gemfile Gemfile.lock ./ 26 | 27 | RUN bundle install 28 | 29 | COPY . ./ 30 | 31 | CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"] 32 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-performance 3 | - rubocop-rake 4 | - rubocop-rspec 5 | 6 | AllCops: 7 | NewCops: enable 8 | Exclude: 9 | - vendor/**/* 10 | TargetRubyVersion: 3.2 11 | 12 | Layout/LineLength: 13 | Enabled: true 14 | Max: 160 15 | 16 | Metrics/ModuleLength: 17 | Enabled: false 18 | 19 | Metrics/ClassLength: 20 | Enabled: false 21 | 22 | Metrics/MethodLength: 23 | Enabled: false 24 | 25 | Metrics/BlockLength: 26 | Enabled: false 27 | 28 | Metrics/AbcSize: 29 | Enabled: false 30 | 31 | Metrics/CyclomaticComplexity: 32 | Enabled: false 33 | 34 | Style/Documentation: 35 | Enabled: false 36 | 37 | Style/ClassVars: 38 | Enabled: false 39 | 40 | Bundler/OrderedGems: 41 | Enabled: false 42 | 43 | RSpec/FilePath: 44 | Enabled: false 45 | 46 | RSpec/MultipleExpectations: 47 | Enabled: false 48 | 49 | RSpec/MultipleMemoizedHelpers: 50 | Enabled: false 51 | 52 | RSpec/ExampleLength: 53 | Enabled: false 54 | 55 | RSpec/AnyInstance: 56 | Enabled: false 57 | -------------------------------------------------------------------------------- /.github/workflows/trivy-analysis.yml: -------------------------------------------------------------------------------- 1 | name: build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ master ] 9 | schedule: 10 | - cron: '36 19 * * 5' 11 | 12 | jobs: 13 | build: 14 | name: Build 15 | runs-on: "ubuntu-18.04" 16 | steps: 17 | - name: Checkout code 18 | uses: actions/checkout@v2 19 | 20 | - name: Build an image from Dockerfile 21 | run: | 22 | docker build -t travis-ci/travis-listener:${{ github.sha }} . 23 | 24 | - name: Run Trivy vulnerability scanner 25 | uses: aquasecurity/trivy-action@master 26 | with: 27 | image-ref: 'travis-ci/travis-listener:${{ github.sha }}' 28 | format: 'template' 29 | template: '@/contrib/sarif.tpl' 30 | output: 'trivy-results.sarif' 31 | severity: 'CRITICAL,HIGH' 32 | 33 | - name: Upload Trivy scan results to GitHub Security tab 34 | uses: github/codeql-action/upload-sarif@v1 35 | with: 36 | sarif_file: 'trivy-results.sarif' 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT LICENSE 2 | 3 | Copyright (c) 2010 Travis CI GmbH 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.mdown: -------------------------------------------------------------------------------- 1 | # Travis Listener 2 | ************************** 3 | 4 | [![Build Status](https://travis-ci.org/travis-ci/travis-listener.svg?branch=master)](https://travis-ci.org/travis-ci/travis-listener) 5 | 6 | Travis Listener is a small Sinatra app which receives service hook notifications from GitHub and queues them for processing by Travis Gatekeeper (a private repo) using [Sidekiq](http://sidekiq.org). 7 | 8 | Although the Travis service hook listens for several different events when activated for a repository, currently Travis Listener only processes `push` and `pull_request` events and discards the rest. 9 | 10 | It's important to note that if the sender.type in the received event is marked as a bot, the listener will also mark the sender as a bot, and this designation receives special treatment later in the system. 11 | 12 | This is the first point of entry for build events from GitHub, and over time support for responding to user sync related events is planned. 13 | 14 | ![Travis Listener Diagram](/img/diagram.jpg) 15 | 16 | ## License & copyright information ## 17 | 18 | See LICENSE file. 19 | 20 | Copyright (c) 2011 [Travis CI development team](https://github.com/travis-ci). 21 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'simplecov' 4 | require 'simplecov-console' 5 | 6 | SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new( 7 | [ 8 | SimpleCov::Formatter::Console, 9 | SimpleCov::Formatter::HTMLFormatter 10 | ] 11 | ) 12 | 13 | # Code Coverage check 14 | SimpleCov.start do 15 | add_filter 'spec' 16 | add_filter 'vendor/' 17 | end 18 | 19 | ENV['RACK_ENV'] ||= 'test' 20 | 21 | require 'rack/test' 22 | require 'logger' 23 | require 'travis/listener' 24 | require 'sidekiq/testing' 25 | require 'pry' 26 | 27 | Travis.logger = Logger.new(StringIO.new) 28 | 29 | Travis::Listener.setup 30 | 31 | RSpec.configure do |c| 32 | c.include Rack::Test::Methods 33 | 34 | c.alias_example_to :fit, focused: true 35 | c.filter_run focus: true 36 | c.run_all_when_everything_filtered = true 37 | end 38 | 39 | require 'timecop' 40 | Timecop.freeze('2022-01-01 00:02:00 +0200') 41 | 42 | module Payloads 43 | def self.load(path) 44 | File.read(File.expand_path("../payloads/#{path}.json", __FILE__)) 45 | end 46 | end 47 | 48 | QUEUE_PAYLOAD = { 49 | type: 'push', 50 | uuid: Travis.uuid, 51 | github_guid: 'abc123', 52 | github_event: 'push', 53 | received_at: Time.now 54 | }.freeze 55 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 5 | 6 | ruby '3.2.2' 7 | 8 | gem 'activesupport', '~> 7' 9 | gem 'sinatra', '~> 4.2' 10 | gem 'rake', '~> 13' 11 | gem 'puma', '~> 6.4', '>= 6.4.3' 12 | 13 | gem 'travis-support', github: 'travis-ci/travis-support' 14 | gem 'travis-config', github: 'travis-ci/travis-config' 15 | gem 'travis-metrics', github: 'travis-ci/travis-metrics' 16 | 17 | gem 'sidekiq', '~> 7', '>= 7.1.3' 18 | 19 | gem 'sentry-ruby' 20 | 21 | gem 'metriks', github: 'travis-ci/metriks', branch: 'prd-ruby-upgrade-dev' 22 | gem 'metriks-librato_metrics', github: 'travis-ci/metriks-librato_metrics' 23 | 24 | gem 'yajl-ruby', '~> 1.4' 25 | 26 | # Security: constrain transitive deps to patched versions 27 | gem 'rack', '>= 2.2.20' 28 | gem 'rexml', '>= 3.3.9' 29 | 30 | gem 'jemalloc', github: 'travis-ci/jemalloc-rb', branch: 'jemalloc-5.0' 31 | 32 | group :development, :test do 33 | gem 'pry' 34 | gem 'rspec', '~> 3' 35 | end 36 | 37 | group :development do 38 | gem 'foreman', '~> 0.87' 39 | gem 'rubocop', require: false 40 | gem 'rubocop-performance', require: false 41 | gem 'rubocop-rake', require: false 42 | gem 'rubocop-rspec', require: false 43 | end 44 | 45 | group :test do 46 | gem 'rack-test' 47 | gem 'timecop' 48 | gem 'simplecov', require: false 49 | gem 'simplecov-console', require: false 50 | end 51 | -------------------------------------------------------------------------------- /lib/travis/listener.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'travis/config' 4 | require 'travis/support' 5 | require 'travis/metrics' 6 | require 'travis/listener/app' 7 | require 'logger' 8 | 9 | $stdout.sync = true 10 | 11 | module Travis 12 | class << self 13 | def config 14 | @config ||= Listener::Config.load 15 | end 16 | end 17 | 18 | module Listener 19 | class Config < Travis::Config 20 | define redis: { url: ENV.fetch('REDIS_URL', 'redis://localhost:6379'), network_timeout: 5, ssl: ENV['REDIS_SSL'] || false }, 21 | redis_gatekeeper: { url: ENV.fetch('REDIS_GATEKEEPER_URL', 'redis://localhost:6379'), network_timeout: 5, ssl: ENV['REDIS_GATEKEEPER_SSL'] || false }, 22 | gator: { queue: ENV.fetch('SIDEKIQ_GATEKEEPER_QUEUE', 'build_requests') }, 23 | sync: { queue: ENV.fetch('SIDEKIQ_SYNC_QUEUE', 'sync.gh_apps') }, 24 | sentry: {}, 25 | metrics: { reporter: 'librato' } 26 | end 27 | 28 | class << self 29 | def setup 30 | if Travis.config.sentry.dsn 31 | require 'sentry-ruby' 32 | 33 | ::Sentry.init do |config| 34 | config.dsn = Travis.config.sentry.dsn 35 | config.excluded_exceptions = %w[Sinatra::NotFound] 36 | end 37 | end 38 | 39 | return unless ENV.fetch('RACK_ENV', nil) == 'production' 40 | 41 | Travis::Metrics.setup(Travis.config.metrics, Travis::Logger.new($stdout)) 42 | end 43 | 44 | def disconnect 45 | # empty for now 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := bash 2 | 3 | VERSION_VALUE ?= $(shell git rev-parse --short HEAD 2>/dev/null) 4 | DOCKER_IMAGE_REPO ?= travisci/travis-listener 5 | DOCKER_DEST ?= $(DOCKER_IMAGE_REPO):$(VERSION_VALUE) 6 | QUAY ?= quay.io 7 | QUAY_IMAGE ?= $(QUAY)/$(DOCKER_IMAGE_REPO) 8 | GCR ?= gcr.io/travis-ci-prod-services-1 9 | GCR_IMAGE ?= $(GCR)/$(DOCKER_IMAGE_REPO) 10 | 11 | ifdef $$QUAY_ROBOT_HANDLE 12 | QUAY_ROBOT_HANDLE := $$QUAY_ROBOT_HANDLE 13 | endif 14 | ifdef $$QUAY_ROBOT_TOKEN 15 | QUAY_ROBOT_TOKEN := $$QUAY_ROBOT_TOKEN 16 | endif 17 | ifdef $$GCR_ACCOUNT_JSON_ENC 18 | GCR_ACCOUNT_JSON_ENC := $$GCR_ACCOUNT_JSON_ENC 19 | endif 20 | ifndef $$TRAVIS_BRANCH 21 | TRAVIS_BRANCH ?= $(shell git rev-parse --abbrev-ref HEAD) 22 | endif 23 | ifneq ($(TRAVIS_BRANCH),master) 24 | BRANCH := $(shell echo "$(TRAVIS_BRANCH)" | sed 's/\//_/') 25 | VERSION_VALUE := $(VERSION_VALUE)-$(BRANCH) 26 | endif 27 | ifdef $$TRAVIS_PULL_REQUEST 28 | TRAVIS_PULL_REQUEST := $$TRAVIS_PULL_REQUEST 29 | endif 30 | 31 | DOCKER ?= docker 32 | 33 | .PHONY: docker-build 34 | docker-build: 35 | $(DOCKER) build -t $(DOCKER_DEST) . 36 | 37 | .PHONY: docker-push 38 | docker-push: 39 | @echo $(QUAY_ROBOT_TOKEN) | $(DOCKER) login -u $(QUAY_ROBOT_HANDLE) --password-stdin $(QUAY) 40 | $(shell echo ${GCR_ACCOUNT_JSON_ENC} | openssl enc -d -base64 -A > ./gce-account.json) 41 | cat ./gce-account.json | $(DOCKER) login -u _json_key --password-stdin https://gcr.io 42 | rm -f ./gce-account.json 43 | $(DOCKER) tag $(DOCKER_DEST) $(QUAY_IMAGE):$(VERSION_VALUE) 44 | $(DOCKER) tag $(DOCKER_DEST) $(GCR_IMAGE):$(VERSION_VALUE) 45 | $(DOCKER) push $(QUAY_IMAGE):$(VERSION_VALUE) 46 | $(DOCKER) push $(GCR_IMAGE):$(VERSION_VALUE) 47 | 48 | .PHONY: docker-latest 49 | docker-latest: 50 | $(DOCKER) tag $(DOCKER_DEST) $(QUAY_IMAGE):latest 51 | $(DOCKER) push $(QUAY_IMAGE):latest 52 | 53 | .PHONY: ship 54 | ship: docker-build docker-push 55 | 56 | ifeq ($(TRAVIS_BRANCH),master) 57 | ifeq ($(TRAVIS_PULL_REQUEST),false) 58 | ship: docker-latest 59 | endif 60 | endif 61 | -------------------------------------------------------------------------------- /spec/payloads/installation.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "deleted", 3 | "installation": { 4 | "id": 2, 5 | "account": { 6 | "login": "octocat", 7 | "id": 1, 8 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 9 | "gravatar_id": "", 10 | "url": "https://api.github.com/users/octocat", 11 | "html_url": "https://github.com/octocat", 12 | "followers_url": "https://api.github.com/users/octocat/followers", 13 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 14 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 15 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 16 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 17 | "organizations_url": "https://api.github.com/users/octocat/orgs", 18 | "repos_url": "https://api.github.com/users/octocat/repos", 19 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 20 | "received_events_url": "https://api.github.com/users/octocat/received_events", 21 | "type": "User", 22 | "site_admin": false 23 | }, 24 | "repository_selection": "selected", 25 | "access_tokens_url": "https://api.github.com/installations/2/access_tokens", 26 | "repositories_url": "https://api.github.com/installation/repositories" 27 | }, 28 | "sender": { 29 | "login": "octocat", 30 | "id": 1, 31 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 32 | "gravatar_id": "", 33 | "url": "https://api.github.com/users/octocat", 34 | "html_url": "https://github.com/octocat", 35 | "followers_url": "https://api.github.com/users/octocat/followers", 36 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 37 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 38 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 39 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 40 | "organizations_url": "https://api.github.com/users/octocat/orgs", 41 | "repos_url": "https://api.github.com/users/octocat/repos", 42 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 43 | "received_events_url": "https://api.github.com/users/octocat/received_events", 44 | "type": "User", 45 | "site_admin": false 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /spec/payloads/installation_repositories.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "removed", 3 | "installation": { 4 | "id": 2, 5 | "account": { 6 | "login": "octocat", 7 | "id": 1, 8 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 9 | "gravatar_id": "", 10 | "url": "https://api.github.com/users/octocat", 11 | "html_url": "https://github.com/octocat", 12 | "followers_url": "https://api.github.com/users/octocat/followers", 13 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 14 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 15 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 16 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 17 | "organizations_url": "https://api.github.com/users/octocat/orgs", 18 | "repos_url": "https://api.github.com/users/octocat/repos", 19 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 20 | "received_events_url": "https://api.github.com/users/octocat/received_events", 21 | "type": "User", 22 | "site_admin": false 23 | }, 24 | "repository_selection": "selected", 25 | "access_tokens_url": "https://api.github.com/installations/2/access_tokens", 26 | "repositories_url": "https://api.github.com/installation/repositories", 27 | "html_url": "https://github.com/settings/installations/2" 28 | }, 29 | "repository_selection": "selected", 30 | "repositories_added": [ 31 | 32 | ], 33 | "repositories_removed": [ 34 | { 35 | "id": 1296269, 36 | "name": "Hello-World", 37 | "full_name": "octocat/Hello-World" 38 | } 39 | ], 40 | "sender": { 41 | "login": "octocat", 42 | "id": 1, 43 | "avatar_url": "https://github.com/images/error/octocat_happy.gif", 44 | "gravatar_id": "", 45 | "url": "https://api.github.com/users/octocat", 46 | "html_url": "https://github.com/octocat", 47 | "followers_url": "https://api.github.com/users/octocat/followers", 48 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 49 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 50 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 51 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 52 | "organizations_url": "https://api.github.com/users/octocat/orgs", 53 | "repos_url": "https://api.github.com/users/octocat/repos", 54 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 55 | "received_events_url": "https://api.github.com/users/octocat/received_events", 56 | "type": "User", 57 | "site_admin": false 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /lib/travis/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'sidekiq' 4 | 5 | module Travis 6 | module Sidekiq 7 | 8 | def self.redis_get_ssl_params(is_gatekeeper) 9 | gk_string = is_gatekeeper ? '_GATEKEEPER' : '' 10 | ssl = is_gatekeeper ? Travis.config.redis_gatekeeper.ssl : Travis.config.redis.ssl 11 | return nil unless ssl 12 | 13 | value = {} 14 | value[:ca_path] = ENV["REDIS#{gk_string}_SSL_CA_PATH"] if ENV["REDIS#{gk_string}_SSL_CA_PATH"] 15 | value[:cert] = OpenSSL::X509::Certificate.new(File.read(ENV["REDIS#{gk_string}_SSL_CERT_FILE"])) if ENV["REDIS#{gk_string}_SSL_CERT_FILE"] 16 | value[:key] = OpenSSL::PKEY::RSA.new(File.read(ENV["REDIS#{gk_string}_SSL_KEY_FILE"])) if ENV["REDIS#{gk_string}_SSL_KEY_FILE"] 17 | value[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if Travis.config.ssl_verify == false 18 | value 19 | end 20 | 21 | class Gatekeeper 22 | def self.client 23 | config = Travis.config.redis_gatekeeper.to_h 24 | config = config.merge(ssl_params: redis_ssl_params) if config[:ssl] 25 | @@client ||= ::Sidekiq::Client.new( 26 | pool: ::Sidekiq::RedisConnection.create( 27 | config 28 | ) 29 | ) 30 | end 31 | 32 | def self.redis_ssl_params 33 | @redis_ssl_param ||= Travis::Sidekiq::redis_get_ssl_params(true) 34 | end 35 | 36 | def self.push(queue, *args) 37 | client.push( 38 | 'queue' => queue, 39 | 'class' => 'Travis::Gatekeeper::Worker', 40 | 'args' => args.map! { |arg| arg.to_json } 41 | ) 42 | end 43 | end 44 | 45 | class GithubSync 46 | def self.gh_app_install(data) 47 | Metriks.meter('listener.event.gh_apps_install').mark 48 | 49 | push('sync.gh_apps', :gh_app_install, data) 50 | end 51 | 52 | def self.gh_app_repos(data) 53 | Metriks.meter('listener.event.gh_apps_repos').mark 54 | 55 | push('sync.gh_apps', :gh_app_repos, data) 56 | end 57 | 58 | def self.gh_app_member(data) 59 | Metriks.meter('listener.event.gh_apps_member').mark 60 | 61 | push('sync', :gh_app_member, data) 62 | end 63 | 64 | def self.organization(data) 65 | Metriks.meter('listener.event.organization').mark 66 | 67 | push('sync', :organization, data) 68 | end 69 | 70 | def self.client 71 | config = Travis.config.redis.to_h 72 | config = config.merge(ssl_params: redis_ssl_params) if config[:ssl] 73 | @@client ||= ::Sidekiq::Client.new( 74 | pool: ::Sidekiq::RedisConnection.create(config) 75 | ) 76 | end 77 | 78 | def self.redis_ssl_params 79 | @redis_ssl_param ||= Travis::Sidekiq::redis_get_ssl_params(false) 80 | end 81 | 82 | def self.push(queue, *args) 83 | client.push( 84 | 'queue' => queue, 85 | 'class' => 'Travis::GithubSync::Worker', 86 | 'args' => args.map! { |arg| arg.to_json } 87 | ) 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /spec/travis/listener/app_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Travis::Listener::App do 6 | let(:app) { subject } 7 | let(:auth) { %w[user 12345] } 8 | let(:payload) { Payloads.load('push') } 9 | let(:queue) { Travis::Sidekiq::Gatekeeper } 10 | 11 | before do 12 | authorize(*auth) 13 | allow(queue).to receive(:push) 14 | end 15 | 16 | def create(opts = {}) 17 | params = {} 18 | 19 | if (params_payload = (opts[:payload] || payload)) 20 | params[:payload] = params_payload 21 | end 22 | 23 | headers = { 'HTTP_X_GITHUB_EVENT' => 'push', 'HTTP_X_GITHUB_GUID' => 'abc123' } 24 | headers.merge!(opts.delete(:headers) || {}) 25 | 26 | post(opts[:url] || '/', params, headers) 27 | end 28 | 29 | it 'results in a 204 if the hook is accepted' do 30 | create 31 | expect(last_response.status).to be(204) 32 | end 33 | 34 | describe 'without a payload' do 35 | let(:payload) { nil } 36 | 37 | it 'does not accept a hook' do 38 | create 39 | expect(last_response.status).to be(422) 40 | end 41 | end 42 | 43 | it 'returns 200 when checking if the app is still running' do 44 | get '/uptime' 45 | expect(last_response.status).to be(200) 46 | end 47 | 48 | it 'pushes the message to sidekiq' do 49 | create 50 | expect(queue).to have_received(:push).with('build_requests', QUEUE_PAYLOAD.merge(payload: Payloads.load('push'))) 51 | end 52 | 53 | it 'passes the given request ID on' do 54 | create(headers: { 'HTTP_X_REQUEST_ID' => 'abc-def-ghi' }) 55 | expect(queue).to have_received(:push).with('build_requests', 56 | QUEUE_PAYLOAD.merge(payload: Payloads.load('push'), uuid: 'abc-def-ghi')) 57 | end 58 | 59 | context 'with valid_ips provided' do 60 | before do 61 | allow_any_instance_of(described_class).to receive(:valid_ips).and_return(['1.2.3.4']) 62 | end 63 | 64 | context 'when ip_validation is turned off' do 65 | it 'accepts a request from an invalid IP' do 66 | expect_any_instance_of(described_class).to receive(:report_ip_validity) 67 | create headers: { 'REMOTE_ADDR' => '1.2.3.1' } 68 | expect(last_response.status).to be(204) 69 | end 70 | end 71 | 72 | context 'when ip_validation is turned on' do 73 | before do 74 | allow_any_instance_of(described_class).to receive(:ip_validation?).and_return(true) 75 | end 76 | 77 | it 'accepts a request from valid IP' do 78 | create headers: { 'REMOTE_ADDR' => '1.2.3.4' } 79 | expect(last_response.status).to be(204) 80 | end 81 | 82 | it 'rejects a request without a valid IP' do 83 | create headers: { 'REMOTE_ADDR' => '1.1.1.1' } 84 | expect(last_response.status).to be(403) 85 | end 86 | end 87 | end 88 | 89 | context 'with valid_ips provided as a range' do 90 | before do 91 | allow_any_instance_of(described_class).to receive(:valid_ips).and_return(['1.1.1.0/30']) 92 | allow_any_instance_of(described_class).to receive(:ip_validation?).and_return(true) 93 | end 94 | 95 | it 'accepts a request from valid IP' do 96 | create headers: { 'REMOTE_ADDR' => '1.1.1.0' } 97 | expect(last_response.status).to be(204) 98 | 99 | create headers: { 'REMOTE_ADDR' => '1.1.1.1' } 100 | expect(last_response.status).to be(204) 101 | 102 | create headers: { 'REMOTE_ADDR' => '1.1.1.2' } 103 | expect(last_response.status).to be(204) 104 | 105 | create headers: { 'REMOTE_ADDR' => '1.1.1.3' } 106 | expect(last_response.status).to be(204) 107 | end 108 | 109 | it 'rejects a request without a valid IP' do 110 | create headers: { 'REMOTE_ADDR' => '1.1.1.4' } 111 | expect(last_response.status).to be(403) 112 | 113 | create headers: { 'REMOTE_ADDR' => '1.1.1.10' } 114 | expect(last_response.status).to be(403) 115 | end 116 | end 117 | end 118 | -------------------------------------------------------------------------------- /spec/payloads/release.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "released", 3 | "release": { 4 | "url": "https://api.github.com/repos/AndriiMysko/TestRepo/releases/154920917", 5 | "assets_url": "https://api.github.com/repos/AndriiMysko/TestRepo/releases/154920917/assets", 6 | "upload_url": "https://uploads.github.com/repos/AndriiMysko/TestRepo/releases/154920917/assets{?name,label}", 7 | "html_url": "https://github.com/AndriiMysko/TestRepo/releases/tag/v1.06", 8 | "id": 154920917, 9 | "author": { 10 | "login": "AndriiMysko", 11 | "id": 69478317, 12 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 13 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 14 | "gravatar_id": "", 15 | "url": "https://api.github.com/users/AndriiMysko", 16 | "html_url": "https://github.com/AndriiMysko", 17 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 18 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 19 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 20 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 21 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 22 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 23 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 24 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 25 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 26 | "type": "User", 27 | "site_admin": false 28 | }, 29 | "node_id": "RE_kwDOESKnMc4JO-fV", 30 | "tag_name": "v1.06", 31 | "target_commitish": "2fc000b754572313afffc903fb304228e43d87a7", 32 | "name": "Test tag 7", 33 | "draft": false, 34 | "prerelease": false, 35 | "created_at": "2023-08-16T10:48:17Z", 36 | "published_at": "2024-05-09T11:08:45Z", 37 | "assets": [], 38 | "tarball_url": "https://api.github.com/repos/AndriiMysko/TestRepo/tarball/v1.06", 39 | "zipball_url": "https://api.github.com/repos/AndriiMysko/TestRepo/zipball/v1.06", 40 | "body": "" 41 | }, 42 | "repository": { 43 | "id": 287483697, 44 | "node_id": "MDEwOlJlcG9zaXRvcnkyODc0ODM2OTc=", 45 | "name": "TestRepo", 46 | "full_name": "AndriiMysko/TestRepo", 47 | "private": false, 48 | "owner": { 49 | "login": "AndriiMysko", 50 | "id": 69478317, 51 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 52 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 53 | "gravatar_id": "", 54 | "url": "https://api.github.com/users/AndriiMysko", 55 | "html_url": "https://github.com/AndriiMysko", 56 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 57 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 58 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 59 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 60 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 61 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 62 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 63 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 64 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 65 | "type": "User", 66 | "site_admin": false 67 | }, 68 | "html_url": "https://github.com/AndriiMysko/TestRepo", 69 | "description": null, 70 | "fork": false, 71 | "homepage": null, 72 | "size": 39, 73 | "stargazers_count": 0, 74 | "watchers_count": 0, 75 | "language": null, 76 | "has_issues": true, 77 | "has_projects": true, 78 | "has_downloads": true, 79 | "has_wiki": true, 80 | "has_pages": false, 81 | "has_discussions": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "archived": false, 85 | "disabled": false, 86 | "open_issues_count": 1, 87 | "license": null, 88 | "allow_forking": true, 89 | "is_template": false, 90 | "web_commit_signoff_required": false, 91 | "topics": [], 92 | "visibility": "public", 93 | "forks": 0, 94 | "open_issues": 1, 95 | "watchers": 0, 96 | "default_branch": "master" 97 | }, 98 | "sender": { 99 | "login": "AndriiMysko", 100 | "id": 69478317, 101 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 102 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 103 | "gravatar_id": "", 104 | "url": "https://api.github.com/users/AndriiMysko", 105 | "html_url": "https://github.com/AndriiMysko", 106 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 107 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 108 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 109 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 110 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 111 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 112 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 113 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 114 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 115 | "type": "User", 116 | "site_admin": false 117 | }, 118 | "installation": { 119 | "id": 48311564, 120 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDgzMTE1NjQ=" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /spec/payloads/release_created.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "release": { 4 | "url": "https://api.github.com/repos/AndriiMysko/TestRepo/releases/154920917", 5 | "assets_url": "https://api.github.com/repos/AndriiMysko/TestRepo/releases/154920917/assets", 6 | "upload_url": "https://uploads.github.com/repos/AndriiMysko/TestRepo/releases/154920917/assets{?name,label}", 7 | "html_url": "https://github.com/AndriiMysko/TestRepo/releases/tag/v1.06", 8 | "id": 154920917, 9 | "author": { 10 | "login": "AndriiMysko", 11 | "id": 69478317, 12 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 13 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 14 | "gravatar_id": "", 15 | "url": "https://api.github.com/users/AndriiMysko", 16 | "html_url": "https://github.com/AndriiMysko", 17 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 18 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 19 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 20 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 21 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 22 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 23 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 24 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 25 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 26 | "type": "User", 27 | "site_admin": false 28 | }, 29 | "node_id": "RE_kwDOESKnMc4JO-fV", 30 | "tag_name": "v1.06", 31 | "target_commitish": "2fc000b754572313afffc903fb304228e43d87a7", 32 | "name": "Test tag 7", 33 | "draft": false, 34 | "prerelease": false, 35 | "created_at": "2023-08-16T10:48:17Z", 36 | "published_at": "2024-05-09T11:08:45Z", 37 | "assets": [], 38 | "tarball_url": "https://api.github.com/repos/AndriiMysko/TestRepo/tarball/v1.06", 39 | "zipball_url": "https://api.github.com/repos/AndriiMysko/TestRepo/zipball/v1.06", 40 | "body": "" 41 | }, 42 | "repository": { 43 | "id": 287483697, 44 | "node_id": "MDEwOlJlcG9zaXRvcnkyODc0ODM2OTc=", 45 | "name": "TestRepo", 46 | "full_name": "AndriiMysko/TestRepo", 47 | "private": false, 48 | "owner": { 49 | "login": "AndriiMysko", 50 | "id": 69478317, 51 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 52 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 53 | "gravatar_id": "", 54 | "url": "https://api.github.com/users/AndriiMysko", 55 | "html_url": "https://github.com/AndriiMysko", 56 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 57 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 58 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 59 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 60 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 61 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 62 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 63 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 64 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 65 | "type": "User", 66 | "site_admin": false 67 | }, 68 | "html_url": "https://github.com/AndriiMysko/TestRepo", 69 | "description": null, 70 | "fork": false, 71 | "homepage": null, 72 | "size": 39, 73 | "stargazers_count": 0, 74 | "watchers_count": 0, 75 | "language": null, 76 | "has_issues": true, 77 | "has_projects": true, 78 | "has_downloads": true, 79 | "has_wiki": true, 80 | "has_pages": false, 81 | "has_discussions": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "archived": false, 85 | "disabled": false, 86 | "open_issues_count": 1, 87 | "license": null, 88 | "allow_forking": true, 89 | "is_template": false, 90 | "web_commit_signoff_required": false, 91 | "topics": [], 92 | "visibility": "public", 93 | "forks": 0, 94 | "open_issues": 1, 95 | "watchers": 0, 96 | "default_branch": "master" 97 | }, 98 | "sender": { 99 | "login": "AndriiMysko", 100 | "id": 69478317, 101 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 102 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 103 | "gravatar_id": "", 104 | "url": "https://api.github.com/users/AndriiMysko", 105 | "html_url": "https://github.com/AndriiMysko", 106 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 107 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 108 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 109 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 110 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 111 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 112 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 113 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 114 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 115 | "type": "User", 116 | "site_admin": false 117 | }, 118 | "installation": { 119 | "id": 48311564, 120 | "node_id": "MDIzOkludGVncmF0aW9uSW5zdGFsbGF0aW9uNDgzMTE1NjQ=" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /spec/travis/listener/events_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe Travis::Listener::App do 6 | let(:app) { subject } 7 | let(:auth) { %w[user 12345] } 8 | let(:payload) { Payloads.load(type) } 9 | let(:gatekeeper_queue) { Travis::Sidekiq::Gatekeeper } 10 | let(:gh_sync_queue) { Travis::Sidekiq::GithubSync } 11 | 12 | before do 13 | allow(gatekeeper_queue).to receive(:push) 14 | allow(gh_sync_queue).to receive(:push) 15 | authorize(*auth) 16 | create 17 | end 18 | 19 | def create(opts = {}) 20 | params = if %w[installation installation_repositories].include? type 21 | payload 22 | else 23 | { payload: (opts[:payload] || payload) } 24 | end 25 | 26 | headers = { 'HTTP_X_GITHUB_EVENT' => event, 'HTTP_X_GITHUB_DELIVERY' => 'abc123' } 27 | headers.merge!(opts.delete(:headers) || {}) 28 | 29 | post(opts[:url] || '/', params, headers) 30 | end 31 | 32 | shared_examples_for 'queues gatekeeper event' do 33 | it { expect(gatekeeper_queue).to have_received(:push).with('build_requests', hash_including(type: event)) } 34 | end 35 | 36 | shared_examples_for 'does not queue gatekeeper event' do 37 | it { expect(gatekeeper_queue).not_to have_received(:push).with('build_requests', hash_including(type: event)) } 38 | end 39 | 40 | describe 'a push event' do 41 | let(:type) { 'push' } 42 | let(:event) { 'push' } 43 | 44 | include_examples 'queues gatekeeper event' 45 | end 46 | 47 | describe 'a pull_request event' do 48 | let(:type) { 'pull_request' } 49 | let(:event) { 'pull_request' } 50 | 51 | include_examples 'queues gatekeeper event' 52 | end 53 | 54 | describe 'a branch_created event' do 55 | let(:type) { 'branch_created' } 56 | let(:event) { 'create' } 57 | 58 | include_examples 'queues gatekeeper event' 59 | end 60 | 61 | describe 'a branch_deleted event' do 62 | let(:type) { 'branch_deleted' } 63 | let(:event) { 'delete' } 64 | 65 | include_examples 'queues gatekeeper event' 66 | end 67 | 68 | describe 'a tag_created event' do 69 | let(:type) { 'tag_created' } 70 | let(:event) { 'create' } 71 | 72 | include_examples 'queues gatekeeper event' 73 | end 74 | 75 | describe 'a tag_deleted event' do 76 | let(:type) { 'tag_deleted' } 77 | let(:event) { 'delete' } 78 | 79 | include_examples 'queues gatekeeper event' 80 | end 81 | 82 | describe 'a repo_created event' do 83 | let(:type) { 'repo_created' } 84 | let(:event) { 'create' } 85 | 86 | include_examples 'queues gatekeeper event' 87 | end 88 | 89 | describe 'a repo_deleted event' do 90 | let(:type) { 'repo_deleted' } 91 | let(:event) { 'delete' } 92 | 93 | include_examples 'queues gatekeeper event' 94 | end 95 | 96 | describe 'a repo_privatized event' do 97 | let(:type) { 'repo_privatized' } 98 | let(:event) { 'repository' } 99 | 100 | include_examples 'queues gatekeeper event' 101 | end 102 | 103 | describe 'a repo_publicized event' do 104 | let(:type) { 'repo_publicized' } 105 | let(:event) { 'repository' } 106 | 107 | include_examples 'queues gatekeeper event' 108 | end 109 | 110 | describe 'a create_run event' do 111 | let(:type) { 'rerequested_check_run' } 112 | let(:event) { 'check_run' } 113 | 114 | include_examples 'queues gatekeeper event' 115 | end 116 | 117 | describe 'a create_suite event : ref_type branch' do 118 | let(:type) { 'rerequested_check_suite' } 119 | let(:event) { 'check_suite' } 120 | 121 | include_examples 'queues gatekeeper event' 122 | end 123 | 124 | describe 'a create_suite tag : ref_type event' do 125 | let(:type) { 'rerequested_check_suite_tag_ref_type' } 126 | let(:event) { 'check_suite' } 127 | 128 | include_examples 'does not queue gatekeeper event' 129 | end 130 | 131 | describe 'an installation event' do 132 | let(:type) { 'installation' } 133 | let(:event) { 'installation' } 134 | 135 | it { 136 | expect(gh_sync_queue) 137 | .to have_received(:push) 138 | .with('sync.gh_apps', :gh_app_install, hash_including(type: event)) 139 | } 140 | end 141 | 142 | describe 'an installation_repositories event' do 143 | let(:type) { 'installation_repositories' } 144 | let(:event) { 'installation_repositories' } 145 | 146 | it { 147 | expect(gh_sync_queue) 148 | .to have_received(:push) 149 | .with('sync.gh_apps', :gh_app_repos, hash_including(type: event)) 150 | } 151 | end 152 | 153 | describe 'a member event' do 154 | let(:type) { 'member' } 155 | let(:event) { 'member' } 156 | 157 | it { 158 | expect(gh_sync_queue) 159 | .to have_received(:push) 160 | .with('sync', :gh_app_member, hash_including(type: event)) 161 | } 162 | end 163 | 164 | describe 'a bot push' do 165 | let(:type) { 'bot_push' } 166 | let(:event) { 'push' } 167 | 168 | include_examples 'queues gatekeeper event' 169 | end 170 | 171 | describe 'an organization member removed' do 172 | let(:type) { 'member_removed' } 173 | let(:event) { 'organization' } 174 | 175 | it { 176 | expect(gh_sync_queue) 177 | .to have_received(:push) 178 | .with('sync', :organization, hash_including(type: event)) 179 | } 180 | end 181 | 182 | describe 'a release event' do 183 | let(:type) { 'release' } 184 | let(:event) { 'release' } 185 | 186 | include_examples 'queues gatekeeper event' 187 | end 188 | 189 | describe 'a release event that is not a released action' do 190 | let(:type) { 'release_created' } 191 | let(:event) { 'release' } 192 | 193 | include_examples 'does not queue gatekeeper event' 194 | end 195 | end 196 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: https://github.com/travis-ci/jemalloc-rb.git 3 | revision: e9528e26aff663efa2c124cdeca47700e389097d 4 | branch: jemalloc-5.0 5 | specs: 6 | jemalloc (1.0.2) 7 | 8 | GIT 9 | remote: https://github.com/travis-ci/metriks-librato_metrics.git 10 | revision: e876ca2f0e1abcc745260c3772118e63fb946c8a 11 | specs: 12 | metriks-librato_metrics (1.0.6) 13 | 14 | GIT 15 | remote: https://github.com/travis-ci/metriks.git 16 | revision: 6292ce11b8d22888bd9947b9f38d104834268fa7 17 | branch: prd-ruby-upgrade-dev 18 | specs: 19 | metriks (0.9.9.8) 20 | HDRHistogram (~> 0.1) 21 | atomic (~> 1.0) 22 | avl_tree (~> 1.2) 23 | hitimes (~> 1.3) 24 | 25 | GIT 26 | remote: https://github.com/travis-ci/travis-config.git 27 | revision: 601e9a6dcb799dc14944c40153c60aaf935629ee 28 | specs: 29 | travis-config (2.0.0) 30 | hashr (~> 2.0) 31 | 32 | GIT 33 | remote: https://github.com/travis-ci/travis-metrics.git 34 | revision: 0b6a8accc70685a1cb65f1ec5305bceab41ad777 35 | specs: 36 | travis-metrics (3.0.0) 37 | metriks-librato_metrics (~> 1.0) 38 | 39 | GIT 40 | remote: https://github.com/travis-ci/travis-support.git 41 | revision: 8b566a94502267b3115c901f8409dc2165b6539b 42 | specs: 43 | travis-support (0.1.0) 44 | 45 | GEM 46 | remote: https://rubygems.org/ 47 | specs: 48 | HDRHistogram (0.1.11) 49 | activesupport (7.0.7.2) 50 | concurrent-ruby (~> 1.0, >= 1.0.2) 51 | i18n (>= 1.6, < 2) 52 | minitest (>= 5.1) 53 | tzinfo (~> 2.0) 54 | ansi (1.5.0) 55 | ast (2.4.2) 56 | atomic (1.1.101) 57 | avl_tree (1.2.1) 58 | atomic (~> 1.1) 59 | base64 (0.1.2) 60 | coderay (1.1.3) 61 | concurrent-ruby (1.2.2) 62 | connection_pool (2.5.5) 63 | diff-lcs (1.5.0) 64 | docile (1.4.0) 65 | foreman (0.87.2) 66 | hashr (2.0.1) 67 | hitimes (1.3.1) 68 | i18n (1.14.1) 69 | concurrent-ruby (~> 1.0) 70 | json (2.6.3) 71 | language_server-protocol (3.17.0.3) 72 | logger (1.7.0) 73 | method_source (1.0.0) 74 | minitest (5.19.0) 75 | mustermann (3.0.4) 76 | ruby2_keywords (~> 0.0.1) 77 | nio4r (2.7.5) 78 | parallel (1.23.0) 79 | parser (3.2.2.3) 80 | ast (~> 2.4.1) 81 | racc 82 | pry (0.14.2) 83 | coderay (~> 1.1) 84 | method_source (~> 1.0) 85 | puma (6.6.1) 86 | nio4r (~> 2.0) 87 | racc (1.7.1) 88 | rack (3.2.4) 89 | rack-protection (4.2.1) 90 | base64 (>= 0.1.0) 91 | logger (>= 1.6.0) 92 | rack (>= 3.0.0, < 4) 93 | rack-session (2.1.1) 94 | base64 (>= 0.1.0) 95 | rack (>= 3.0.0) 96 | rack-test (2.1.0) 97 | rack (>= 1.3) 98 | rainbow (3.1.1) 99 | rake (13.0.6) 100 | redis-client (0.26.1) 101 | connection_pool 102 | regexp_parser (2.8.1) 103 | rexml (3.4.4) 104 | rspec (3.12.0) 105 | rspec-core (~> 3.12.0) 106 | rspec-expectations (~> 3.12.0) 107 | rspec-mocks (~> 3.12.0) 108 | rspec-core (3.12.2) 109 | rspec-support (~> 3.12.0) 110 | rspec-expectations (3.12.3) 111 | diff-lcs (>= 1.2.0, < 2.0) 112 | rspec-support (~> 3.12.0) 113 | rspec-mocks (3.12.6) 114 | diff-lcs (>= 1.2.0, < 2.0) 115 | rspec-support (~> 3.12.0) 116 | rspec-support (3.12.1) 117 | rubocop (1.56.1) 118 | base64 (~> 0.1.1) 119 | json (~> 2.3) 120 | language_server-protocol (>= 3.17.0) 121 | parallel (~> 1.10) 122 | parser (>= 3.2.2.3) 123 | rainbow (>= 2.2.2, < 4.0) 124 | regexp_parser (>= 1.8, < 3.0) 125 | rexml (>= 3.2.5, < 4.0) 126 | rubocop-ast (>= 1.28.1, < 2.0) 127 | ruby-progressbar (~> 1.7) 128 | unicode-display_width (>= 2.4.0, < 3.0) 129 | rubocop-ast (1.29.0) 130 | parser (>= 3.2.1.0) 131 | rubocop-capybara (2.18.0) 132 | rubocop (~> 1.41) 133 | rubocop-factory_bot (2.23.1) 134 | rubocop (~> 1.33) 135 | rubocop-performance (1.19.0) 136 | rubocop (>= 1.7.0, < 2.0) 137 | rubocop-ast (>= 0.4.0) 138 | rubocop-rake (0.6.0) 139 | rubocop (~> 1.0) 140 | rubocop-rspec (2.23.2) 141 | rubocop (~> 1.33) 142 | rubocop-capybara (~> 2.17) 143 | rubocop-factory_bot (~> 2.22) 144 | ruby-progressbar (1.13.0) 145 | ruby2_keywords (0.0.5) 146 | sentry-ruby (5.10.0) 147 | concurrent-ruby (~> 1.0, >= 1.0.2) 148 | sidekiq (7.3.9) 149 | base64 150 | connection_pool (>= 2.3.0) 151 | logger 152 | rack (>= 2.2.4) 153 | redis-client (>= 0.22.2) 154 | simplecov (0.22.0) 155 | docile (~> 1.1) 156 | simplecov-html (~> 0.11) 157 | simplecov_json_formatter (~> 0.1) 158 | simplecov-console (0.9.1) 159 | ansi 160 | simplecov 161 | terminal-table 162 | simplecov-html (0.12.3) 163 | simplecov_json_formatter (0.1.4) 164 | sinatra (4.2.1) 165 | logger (>= 1.6.0) 166 | mustermann (~> 3.0) 167 | rack (>= 3.0.0, < 4) 168 | rack-protection (= 4.2.1) 169 | rack-session (>= 2.0.0, < 3) 170 | tilt (~> 2.0) 171 | terminal-table (3.0.2) 172 | unicode-display_width (>= 1.1.1, < 3) 173 | tilt (2.6.1) 174 | timecop (0.9.8) 175 | tzinfo (2.0.6) 176 | concurrent-ruby (~> 1.0) 177 | unicode-display_width (2.4.2) 178 | yajl-ruby (1.4.3) 179 | 180 | PLATFORMS 181 | ruby 182 | 183 | DEPENDENCIES 184 | activesupport (~> 7) 185 | foreman (~> 0.87) 186 | jemalloc! 187 | metriks! 188 | metriks-librato_metrics! 189 | pry 190 | puma (~> 6.4, >= 6.4.3) 191 | rack (>= 2.2.20) 192 | rack-test 193 | rake (~> 13) 194 | rexml (>= 3.3.9) 195 | rspec (~> 3) 196 | rubocop 197 | rubocop-performance 198 | rubocop-rake 199 | rubocop-rspec 200 | sentry-ruby 201 | sidekiq (~> 7, >= 7.1.3) 202 | simplecov 203 | simplecov-console 204 | sinatra (~> 4.2) 205 | timecop 206 | travis-config! 207 | travis-metrics! 208 | travis-support! 209 | yajl-ruby (~> 1.4) 210 | 211 | RUBY VERSION 212 | ruby 3.2.2p53 213 | 214 | BUNDLED WITH 215 | 2.4.19 216 | -------------------------------------------------------------------------------- /spec/payloads/branch_deleted.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref":"test-branch", 3 | "ref_type":"branch", 4 | "pusher_type":"user", 5 | "repository":{ 6 | "id":1, 7 | "name":"test", 8 | "full_name":"svenfuchs/test", 9 | "owner":{ 10 | "login":"svenfuchs", 11 | "id":2208, 12 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 13 | "gravatar_id":"", 14 | "url":"https://api.github.com/users/svenfuchs", 15 | "html_url":"https://github.com/svenfuchs", 16 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 17 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 18 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 19 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 20 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 21 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 22 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 23 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 24 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 25 | "type":"User", 26 | "site_admin":false 27 | }, 28 | "private":false, 29 | "html_url":"https://github.com/svenfuchs/test", 30 | "description":"", 31 | "fork":false, 32 | "url":"https://api.github.com/repos/svenfuchs/test", 33 | "forks_url":"https://api.github.com/repos/svenfuchs/test/forks", 34 | "keys_url":"https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 35 | "collaborators_url":"https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 36 | "teams_url":"https://api.github.com/repos/svenfuchs/test/teams", 37 | "hooks_url":"https://api.github.com/repos/svenfuchs/test/hooks", 38 | "issue_events_url":"https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 39 | "events_url":"https://api.github.com/repos/svenfuchs/test/events", 40 | "assignees_url":"https://api.github.com/repos/svenfuchs/test/assignees{/user}", 41 | "branches_url":"https://api.github.com/repos/svenfuchs/test/branches{/branch}", 42 | "tags_url":"https://api.github.com/repos/svenfuchs/test/tags", 43 | "blobs_url":"https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 44 | "git_tags_url":"https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 45 | "git_refs_url":"https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 46 | "trees_url":"https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 47 | "statuses_url":"https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 48 | "languages_url":"https://api.github.com/repos/svenfuchs/test/languages", 49 | "stargazers_url":"https://api.github.com/repos/svenfuchs/test/stargazers", 50 | "contributors_url":"https://api.github.com/repos/svenfuchs/test/contributors", 51 | "subscribers_url":"https://api.github.com/repos/svenfuchs/test/subscribers", 52 | "subscription_url":"https://api.github.com/repos/svenfuchs/test/subscription", 53 | "commits_url":"https://api.github.com/repos/svenfuchs/test/commits{/sha}", 54 | "git_commits_url":"https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 55 | "comments_url":"https://api.github.com/repos/svenfuchs/test/comments{/number}", 56 | "issue_comment_url":"https://api.github.com/repos/svenfuchs/test/issues/comments{/number}", 57 | "contents_url":"https://api.github.com/repos/svenfuchs/test/contents/{+path}", 58 | "compare_url":"https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 59 | "merges_url":"https://api.github.com/repos/svenfuchs/test/merges", 60 | "archive_url":"https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 61 | "downloads_url":"https://api.github.com/repos/svenfuchs/test/downloads", 62 | "issues_url":"https://api.github.com/repos/svenfuchs/test/issues{/number}", 63 | "pulls_url":"https://api.github.com/repos/svenfuchs/test/pulls{/number}", 64 | "milestones_url":"https://api.github.com/repos/svenfuchs/test/milestones{/number}", 65 | "notifications_url":"https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 66 | "labels_url":"https://api.github.com/repos/svenfuchs/test/labels{/name}", 67 | "releases_url":"https://api.github.com/repos/svenfuchs/test/releases{/id}", 68 | "deployments_url":"https://api.github.com/repos/svenfuchs/test/deployments", 69 | "created_at":"2015-10-14T15:42:48Z", 70 | "updated_at":"2016-01-27T10:04:29Z", 71 | "pushed_at":"2016-08-06T19:23:26Z", 72 | "git_url":"git://github.com/svenfuchs/test.git", 73 | "ssh_url":"git@github.com:svenfuchs/test.git", 74 | "clone_url":"https://github.com/svenfuchs/test.git", 75 | "svn_url":"https://github.com/svenfuchs/test", 76 | "homepage":null, 77 | "size":47, 78 | "stargazers_count":0, 79 | "watchers_count":0, 80 | "language":null, 81 | "has_issues":true, 82 | "has_downloads":true, 83 | "has_wiki":true, 84 | "has_pages":true, 85 | "forks_count":0, 86 | "mirror_url":null, 87 | "open_issues_count":2, 88 | "forks":0, 89 | "open_issues":2, 90 | "watchers":0, 91 | "default_branch":"master" 92 | }, 93 | "sender":{ 94 | "login":"svenfuchs", 95 | "id":2208, 96 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 97 | "gravatar_id":"", 98 | "url":"https://api.github.com/users/svenfuchs", 99 | "html_url":"https://github.com/svenfuchs", 100 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 101 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 102 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 103 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 104 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 105 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 106 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 107 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 108 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 109 | "type":"User", 110 | "site_admin":false 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /spec/payloads/repo_created.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "created", 3 | "repository": { 4 | "id": 1, 5 | "name": "test", 6 | "full_name": "svenfuchs/test", 7 | "owner": { 8 | "login": "svenfuchs", 9 | "id": 2208, 10 | "avatar_url": "https://avatars.githubusercontent.com/u/2208?v=3", 11 | "gravatar_id": "", 12 | "url": "https://api.github.com/users/svenfuchs", 13 | "html_url": "https://github.com/svenfuchs", 14 | "followers_url": "https://api.github.com/users/svenfuchs/followers", 15 | "following_url": "https://api.github.com/users/svenfuchs/following{/other_user}", 16 | "gists_url": "https://api.github.com/users/svenfuchs/gists{/gist_id}", 17 | "starred_url": "https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 18 | "subscriptions_url": "https://api.github.com/users/svenfuchs/subscriptions", 19 | "organizations_url": "https://api.github.com/users/svenfuchs/orgs", 20 | "repos_url": "https://api.github.com/users/svenfuchs/repos", 21 | "events_url": "https://api.github.com/users/svenfuchs/events{/privacy}", 22 | "received_events_url": "https://api.github.com/users/svenfuchs/received_events", 23 | "type": "User", 24 | "site_admin": false 25 | }, 26 | "private": true, 27 | "html_url": "https://github.com/svenfuchs/test", 28 | "description": "", 29 | "fork": false, 30 | "url": "https://api.github.com/repos/svenfuchs/test", 31 | "forks_url": "https://api.github.com/repos/svenfuchs/test/forks", 32 | "keys_url": "https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 33 | "collaborators_url": "https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 34 | "teams_url": "https://api.github.com/repos/svenfuchs/test/teams", 35 | "hooks_url": "https://api.github.com/repos/svenfuchs/test/hooks", 36 | "issue_events_url": "https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 37 | "events_url": "https://api.github.com/repos/svenfuchs/test/events", 38 | "assignees_url": "https://api.github.com/repos/svenfuchs/test/assignees{/user}", 39 | "branches_url": "https://api.github.com/repos/svenfuchs/test/branches{/branch}", 40 | "tags_url": "https://api.github.com/repos/svenfuchs/test/tags", 41 | "blobs_url": "https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 42 | "git_tags_url": "https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 43 | "git_refs_url": "https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 44 | "trees_url": "https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 45 | "statuses_url": "https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 46 | "languages_url": "https://api.github.com/repos/svenfuchs/test/languages", 47 | "stargazers_url": "https://api.github.com/repos/svenfuchs/test/stargazers", 48 | "contributors_url": "https://api.github.com/repos/svenfuchs/test/contributors", 49 | "subscribers_url": "https://api.github.com/repos/svenfuchs/test/subscribers", 50 | "subscription_url": "https://api.github.com/repos/svenfuchs/test/subscription", 51 | "commits_url": "https://api.github.com/repos/svenfuchs/test/commits{/sha}", 52 | "git_commits_url": "https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 53 | "comments_url": "https://api.github.com/repos/svenfuchs/test/comments{/number}", 54 | "issue_comment_url": "https://api.github.com/repos/svenfuchs/test/issues/comments/{number}", 55 | "contents_url": "https://api.github.com/repos/svenfuchs/test/contents/{+path}", 56 | "compare_url": "https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 57 | "merges_url": "https://api.github.com/repos/svenfuchs/test/merges", 58 | "archive_url": "https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 59 | "downloads_url": "https://api.github.com/repos/svenfuchs/test/downloads", 60 | "issues_url": "https://api.github.com/repos/svenfuchs/test/issues{/number}", 61 | "pulls_url": "https://api.github.com/repos/svenfuchs/test/pulls{/number}", 62 | "milestones_url": "https://api.github.com/repos/svenfuchs/test/milestones{/number}", 63 | "notifications_url": "https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 64 | "labels_url": "https://api.github.com/repos/svenfuchs/test/labels{/name}", 65 | "releases_url": "https://api.github.com/repos/svenfuchs/test/releases{/id}", 66 | "created_at": "2014-12-03T16:39:25Z", 67 | "updated_at": "2014-12-03T16:39:25Z", 68 | "pushed_at": "2014-12-03T16:39:25Z", 69 | "git_url": "git://github.com/svenfuchs/test.git", 70 | "ssh_url": "git@github.com:svenfuchs/test.git", 71 | "clone_url": "https://github.com/svenfuchs/test.git", 72 | "svn_url": "https://github.com/svenfuchs/test", 73 | "homepage": null, 74 | "size": 0, 75 | "stargazers_count": 0, 76 | "watchers_count": 0, 77 | "language": null, 78 | "has_issues": true, 79 | "has_downloads": true, 80 | "has_wiki": true, 81 | "has_pages": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "open_issues_count": 0, 85 | "forks": 0, 86 | "open_issues": 0, 87 | "watchers": 0, 88 | "default_branch": "master" 89 | }, 90 | "sender": { 91 | "login": "baxterthehacker", 92 | "id": 6752317, 93 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", 94 | "gravatar_id": "", 95 | "url": "https://api.github.com/users/baxterthehacker", 96 | "html_url": "https://github.com/baxterthehacker", 97 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 98 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 99 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 100 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 101 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 102 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 103 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 104 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 105 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 106 | "type": "User", 107 | "site_admin": false 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /spec/payloads/repo_deleted.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "deleted", 3 | "repository": { 4 | "id": 1, 5 | "name": "test", 6 | "full_name": "svenfuchs/test", 7 | "owner": { 8 | "login": "svenfuchs", 9 | "id": 2208, 10 | "avatar_url": "https://avatars.githubusercontent.com/u/2208?v=3", 11 | "gravatar_id": "", 12 | "url": "https://api.github.com/users/svenfuchs", 13 | "html_url": "https://github.com/svenfuchs", 14 | "followers_url": "https://api.github.com/users/svenfuchs/followers", 15 | "following_url": "https://api.github.com/users/svenfuchs/following{/other_user}", 16 | "gists_url": "https://api.github.com/users/svenfuchs/gists{/gist_id}", 17 | "starred_url": "https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 18 | "subscriptions_url": "https://api.github.com/users/svenfuchs/subscriptions", 19 | "organizations_url": "https://api.github.com/users/svenfuchs/orgs", 20 | "repos_url": "https://api.github.com/users/svenfuchs/repos", 21 | "events_url": "https://api.github.com/users/svenfuchs/events{/privacy}", 22 | "received_events_url": "https://api.github.com/users/svenfuchs/received_events", 23 | "type": "User", 24 | "site_admin": false 25 | }, 26 | "private": true, 27 | "html_url": "https://github.com/svenfuchs/test", 28 | "description": "", 29 | "fork": false, 30 | "url": "https://api.github.com/repos/svenfuchs/test", 31 | "forks_url": "https://api.github.com/repos/svenfuchs/test/forks", 32 | "keys_url": "https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 33 | "collaborators_url": "https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 34 | "teams_url": "https://api.github.com/repos/svenfuchs/test/teams", 35 | "hooks_url": "https://api.github.com/repos/svenfuchs/test/hooks", 36 | "issue_events_url": "https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 37 | "events_url": "https://api.github.com/repos/svenfuchs/test/events", 38 | "assignees_url": "https://api.github.com/repos/svenfuchs/test/assignees{/user}", 39 | "branches_url": "https://api.github.com/repos/svenfuchs/test/branches{/branch}", 40 | "tags_url": "https://api.github.com/repos/svenfuchs/test/tags", 41 | "blobs_url": "https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 42 | "git_tags_url": "https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 43 | "git_refs_url": "https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 44 | "trees_url": "https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 45 | "statuses_url": "https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 46 | "languages_url": "https://api.github.com/repos/svenfuchs/test/languages", 47 | "stargazers_url": "https://api.github.com/repos/svenfuchs/test/stargazers", 48 | "contributors_url": "https://api.github.com/repos/svenfuchs/test/contributors", 49 | "subscribers_url": "https://api.github.com/repos/svenfuchs/test/subscribers", 50 | "subscription_url": "https://api.github.com/repos/svenfuchs/test/subscription", 51 | "commits_url": "https://api.github.com/repos/svenfuchs/test/commits{/sha}", 52 | "git_commits_url": "https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 53 | "comments_url": "https://api.github.com/repos/svenfuchs/test/comments{/number}", 54 | "issue_comment_url": "https://api.github.com/repos/svenfuchs/test/issues/comments/{number}", 55 | "contents_url": "https://api.github.com/repos/svenfuchs/test/contents/{+path}", 56 | "compare_url": "https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 57 | "merges_url": "https://api.github.com/repos/svenfuchs/test/merges", 58 | "archive_url": "https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 59 | "downloads_url": "https://api.github.com/repos/svenfuchs/test/downloads", 60 | "issues_url": "https://api.github.com/repos/svenfuchs/test/issues{/number}", 61 | "pulls_url": "https://api.github.com/repos/svenfuchs/test/pulls{/number}", 62 | "milestones_url": "https://api.github.com/repos/svenfuchs/test/milestones{/number}", 63 | "notifications_url": "https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 64 | "labels_url": "https://api.github.com/repos/svenfuchs/test/labels{/name}", 65 | "releases_url": "https://api.github.com/repos/svenfuchs/test/releases{/id}", 66 | "created_at": "2014-12-03T16:39:25Z", 67 | "updated_at": "2014-12-03T16:39:25Z", 68 | "pushed_at": "2014-12-03T16:39:25Z", 69 | "git_url": "git://github.com/svenfuchs/test.git", 70 | "ssh_url": "git@github.com:svenfuchs/test.git", 71 | "clone_url": "https://github.com/svenfuchs/test.git", 72 | "svn_url": "https://github.com/svenfuchs/test", 73 | "homepage": null, 74 | "size": 0, 75 | "stargazers_count": 0, 76 | "watchers_count": 0, 77 | "language": null, 78 | "has_issues": true, 79 | "has_downloads": true, 80 | "has_wiki": true, 81 | "has_pages": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "open_issues_count": 0, 85 | "forks": 0, 86 | "open_issues": 0, 87 | "watchers": 0, 88 | "default_branch": "master" 89 | }, 90 | "sender": { 91 | "login": "baxterthehacker", 92 | "id": 6752317, 93 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", 94 | "gravatar_id": "", 95 | "url": "https://api.github.com/users/baxterthehacker", 96 | "html_url": "https://github.com/baxterthehacker", 97 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 98 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 99 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 100 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 101 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 102 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 103 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 104 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 105 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 106 | "type": "User", 107 | "site_admin": false 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /spec/payloads/repo_privatized.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "privatized", 3 | "repository": { 4 | "id": 1, 5 | "name": "test", 6 | "full_name": "svenfuchs/test", 7 | "owner": { 8 | "login": "svenfuchs", 9 | "id": 2208, 10 | "avatar_url": "https://avatars.githubusercontent.com/u/2208?v=3", 11 | "gravatar_id": "", 12 | "url": "https://api.github.com/users/svenfuchs", 13 | "html_url": "https://github.com/svenfuchs", 14 | "followers_url": "https://api.github.com/users/svenfuchs/followers", 15 | "following_url": "https://api.github.com/users/svenfuchs/following{/other_user}", 16 | "gists_url": "https://api.github.com/users/svenfuchs/gists{/gist_id}", 17 | "starred_url": "https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 18 | "subscriptions_url": "https://api.github.com/users/svenfuchs/subscriptions", 19 | "organizations_url": "https://api.github.com/users/svenfuchs/orgs", 20 | "repos_url": "https://api.github.com/users/svenfuchs/repos", 21 | "events_url": "https://api.github.com/users/svenfuchs/events{/privacy}", 22 | "received_events_url": "https://api.github.com/users/svenfuchs/received_events", 23 | "type": "User", 24 | "site_admin": false 25 | }, 26 | "private": true, 27 | "html_url": "https://github.com/svenfuchs/test", 28 | "description": "", 29 | "fork": false, 30 | "url": "https://api.github.com/repos/svenfuchs/test", 31 | "forks_url": "https://api.github.com/repos/svenfuchs/test/forks", 32 | "keys_url": "https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 33 | "collaborators_url": "https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 34 | "teams_url": "https://api.github.com/repos/svenfuchs/test/teams", 35 | "hooks_url": "https://api.github.com/repos/svenfuchs/test/hooks", 36 | "issue_events_url": "https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 37 | "events_url": "https://api.github.com/repos/svenfuchs/test/events", 38 | "assignees_url": "https://api.github.com/repos/svenfuchs/test/assignees{/user}", 39 | "branches_url": "https://api.github.com/repos/svenfuchs/test/branches{/branch}", 40 | "tags_url": "https://api.github.com/repos/svenfuchs/test/tags", 41 | "blobs_url": "https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 42 | "git_tags_url": "https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 43 | "git_refs_url": "https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 44 | "trees_url": "https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 45 | "statuses_url": "https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 46 | "languages_url": "https://api.github.com/repos/svenfuchs/test/languages", 47 | "stargazers_url": "https://api.github.com/repos/svenfuchs/test/stargazers", 48 | "contributors_url": "https://api.github.com/repos/svenfuchs/test/contributors", 49 | "subscribers_url": "https://api.github.com/repos/svenfuchs/test/subscribers", 50 | "subscription_url": "https://api.github.com/repos/svenfuchs/test/subscription", 51 | "commits_url": "https://api.github.com/repos/svenfuchs/test/commits{/sha}", 52 | "git_commits_url": "https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 53 | "comments_url": "https://api.github.com/repos/svenfuchs/test/comments{/number}", 54 | "issue_comment_url": "https://api.github.com/repos/svenfuchs/test/issues/comments/{number}", 55 | "contents_url": "https://api.github.com/repos/svenfuchs/test/contents/{+path}", 56 | "compare_url": "https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 57 | "merges_url": "https://api.github.com/repos/svenfuchs/test/merges", 58 | "archive_url": "https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 59 | "downloads_url": "https://api.github.com/repos/svenfuchs/test/downloads", 60 | "issues_url": "https://api.github.com/repos/svenfuchs/test/issues{/number}", 61 | "pulls_url": "https://api.github.com/repos/svenfuchs/test/pulls{/number}", 62 | "milestones_url": "https://api.github.com/repos/svenfuchs/test/milestones{/number}", 63 | "notifications_url": "https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 64 | "labels_url": "https://api.github.com/repos/svenfuchs/test/labels{/name}", 65 | "releases_url": "https://api.github.com/repos/svenfuchs/test/releases{/id}", 66 | "created_at": "2014-12-03T16:39:25Z", 67 | "updated_at": "2014-12-03T16:39:25Z", 68 | "pushed_at": "2014-12-03T16:39:25Z", 69 | "git_url": "git://github.com/svenfuchs/test.git", 70 | "ssh_url": "git@github.com:svenfuchs/test.git", 71 | "clone_url": "https://github.com/svenfuchs/test.git", 72 | "svn_url": "https://github.com/svenfuchs/test", 73 | "homepage": null, 74 | "size": 0, 75 | "stargazers_count": 0, 76 | "watchers_count": 0, 77 | "language": null, 78 | "has_issues": true, 79 | "has_downloads": true, 80 | "has_wiki": true, 81 | "has_pages": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "open_issues_count": 0, 85 | "forks": 0, 86 | "open_issues": 0, 87 | "watchers": 0, 88 | "default_branch": "master" 89 | }, 90 | "sender": { 91 | "login": "baxterthehacker", 92 | "id": 6752317, 93 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", 94 | "gravatar_id": "", 95 | "url": "https://api.github.com/users/baxterthehacker", 96 | "html_url": "https://github.com/baxterthehacker", 97 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 98 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 99 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 100 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 101 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 102 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 103 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 104 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 105 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 106 | "type": "User", 107 | "site_admin": false 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /spec/payloads/repo_publicized.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "publicized", 3 | "repository": { 4 | "id": 1, 5 | "name": "test", 6 | "full_name": "svenfuchs/test", 7 | "owner": { 8 | "login": "svenfuchs", 9 | "id": 2208, 10 | "avatar_url": "https://avatars.githubusercontent.com/u/2208?v=3", 11 | "gravatar_id": "", 12 | "url": "https://api.github.com/users/svenfuchs", 13 | "html_url": "https://github.com/svenfuchs", 14 | "followers_url": "https://api.github.com/users/svenfuchs/followers", 15 | "following_url": "https://api.github.com/users/svenfuchs/following{/other_user}", 16 | "gists_url": "https://api.github.com/users/svenfuchs/gists{/gist_id}", 17 | "starred_url": "https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 18 | "subscriptions_url": "https://api.github.com/users/svenfuchs/subscriptions", 19 | "organizations_url": "https://api.github.com/users/svenfuchs/orgs", 20 | "repos_url": "https://api.github.com/users/svenfuchs/repos", 21 | "events_url": "https://api.github.com/users/svenfuchs/events{/privacy}", 22 | "received_events_url": "https://api.github.com/users/svenfuchs/received_events", 23 | "type": "User", 24 | "site_admin": false 25 | }, 26 | "private": true, 27 | "html_url": "https://github.com/svenfuchs/test", 28 | "description": "", 29 | "fork": false, 30 | "url": "https://api.github.com/repos/svenfuchs/test", 31 | "forks_url": "https://api.github.com/repos/svenfuchs/test/forks", 32 | "keys_url": "https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 33 | "collaborators_url": "https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 34 | "teams_url": "https://api.github.com/repos/svenfuchs/test/teams", 35 | "hooks_url": "https://api.github.com/repos/svenfuchs/test/hooks", 36 | "issue_events_url": "https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 37 | "events_url": "https://api.github.com/repos/svenfuchs/test/events", 38 | "assignees_url": "https://api.github.com/repos/svenfuchs/test/assignees{/user}", 39 | "branches_url": "https://api.github.com/repos/svenfuchs/test/branches{/branch}", 40 | "tags_url": "https://api.github.com/repos/svenfuchs/test/tags", 41 | "blobs_url": "https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 42 | "git_tags_url": "https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 43 | "git_refs_url": "https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 44 | "trees_url": "https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 45 | "statuses_url": "https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 46 | "languages_url": "https://api.github.com/repos/svenfuchs/test/languages", 47 | "stargazers_url": "https://api.github.com/repos/svenfuchs/test/stargazers", 48 | "contributors_url": "https://api.github.com/repos/svenfuchs/test/contributors", 49 | "subscribers_url": "https://api.github.com/repos/svenfuchs/test/subscribers", 50 | "subscription_url": "https://api.github.com/repos/svenfuchs/test/subscription", 51 | "commits_url": "https://api.github.com/repos/svenfuchs/test/commits{/sha}", 52 | "git_commits_url": "https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 53 | "comments_url": "https://api.github.com/repos/svenfuchs/test/comments{/number}", 54 | "issue_comment_url": "https://api.github.com/repos/svenfuchs/test/issues/comments/{number}", 55 | "contents_url": "https://api.github.com/repos/svenfuchs/test/contents/{+path}", 56 | "compare_url": "https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 57 | "merges_url": "https://api.github.com/repos/svenfuchs/test/merges", 58 | "archive_url": "https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 59 | "downloads_url": "https://api.github.com/repos/svenfuchs/test/downloads", 60 | "issues_url": "https://api.github.com/repos/svenfuchs/test/issues{/number}", 61 | "pulls_url": "https://api.github.com/repos/svenfuchs/test/pulls{/number}", 62 | "milestones_url": "https://api.github.com/repos/svenfuchs/test/milestones{/number}", 63 | "notifications_url": "https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 64 | "labels_url": "https://api.github.com/repos/svenfuchs/test/labels{/name}", 65 | "releases_url": "https://api.github.com/repos/svenfuchs/test/releases{/id}", 66 | "created_at": "2014-12-03T16:39:25Z", 67 | "updated_at": "2014-12-03T16:39:25Z", 68 | "pushed_at": "2014-12-03T16:39:25Z", 69 | "git_url": "git://github.com/svenfuchs/test.git", 70 | "ssh_url": "git@github.com:svenfuchs/test.git", 71 | "clone_url": "https://github.com/svenfuchs/test.git", 72 | "svn_url": "https://github.com/svenfuchs/test", 73 | "homepage": null, 74 | "size": 0, 75 | "stargazers_count": 0, 76 | "watchers_count": 0, 77 | "language": null, 78 | "has_issues": true, 79 | "has_downloads": true, 80 | "has_wiki": true, 81 | "has_pages": false, 82 | "forks_count": 0, 83 | "mirror_url": null, 84 | "open_issues_count": 0, 85 | "forks": 0, 86 | "open_issues": 0, 87 | "watchers": 0, 88 | "default_branch": "master" 89 | }, 90 | "sender": { 91 | "login": "baxterthehacker", 92 | "id": 6752317, 93 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=2", 94 | "gravatar_id": "", 95 | "url": "https://api.github.com/users/baxterthehacker", 96 | "html_url": "https://github.com/baxterthehacker", 97 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 98 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 99 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 100 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 101 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 102 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 103 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 104 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 105 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 106 | "type": "User", 107 | "site_admin": false 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /spec/payloads/tag_created.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref":"v1.0.0", 3 | "ref_type":"tag", 4 | "master_branch":"master", 5 | "description":"", 6 | "pusher_type":"user", 7 | "repository":{ 8 | "id":1, 9 | "name":"test", 10 | "full_name":"svenfuchs/test", 11 | "owner":{ 12 | "login":"svenfuchs", 13 | "id":2208, 14 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 15 | "gravatar_id":"", 16 | "url":"https://api.github.com/users/svenfuchs", 17 | "html_url":"https://github.com/svenfuchs", 18 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 19 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 20 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 21 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 22 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 23 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 24 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 25 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 26 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 27 | "type":"User", 28 | "site_admin":false 29 | }, 30 | "private":false, 31 | "html_url":"https://github.com/svenfuchs/test", 32 | "description":"", 33 | "fork":false, 34 | "url":"https://api.github.com/repos/svenfuchs/test", 35 | "forks_url":"https://api.github.com/repos/svenfuchs/test/forks", 36 | "keys_url":"https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 37 | "collaborators_url":"https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 38 | "teams_url":"https://api.github.com/repos/svenfuchs/test/teams", 39 | "hooks_url":"https://api.github.com/repos/svenfuchs/test/hooks", 40 | "issue_events_url":"https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 41 | "events_url":"https://api.github.com/repos/svenfuchs/test/events", 42 | "assignees_url":"https://api.github.com/repos/svenfuchs/test/assignees{/user}", 43 | "branches_url":"https://api.github.com/repos/svenfuchs/test/branches{/branch}", 44 | "tags_url":"https://api.github.com/repos/svenfuchs/test/tags", 45 | "blobs_url":"https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 46 | "git_tags_url":"https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 47 | "git_refs_url":"https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 48 | "trees_url":"https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 49 | "statuses_url":"https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 50 | "languages_url":"https://api.github.com/repos/svenfuchs/test/languages", 51 | "stargazers_url":"https://api.github.com/repos/svenfuchs/test/stargazers", 52 | "contributors_url":"https://api.github.com/repos/svenfuchs/test/contributors", 53 | "subscribers_url":"https://api.github.com/repos/svenfuchs/test/subscribers", 54 | "subscription_url":"https://api.github.com/repos/svenfuchs/test/subscription", 55 | "commits_url":"https://api.github.com/repos/svenfuchs/test/commits{/sha}", 56 | "git_commits_url":"https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 57 | "comments_url":"https://api.github.com/repos/svenfuchs/test/comments{/number}", 58 | "issue_comment_url":"https://api.github.com/repos/svenfuchs/test/issues/comments{/number}", 59 | "contents_url":"https://api.github.com/repos/svenfuchs/test/contents/{+path}", 60 | "compare_url":"https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 61 | "merges_url":"https://api.github.com/repos/svenfuchs/test/merges", 62 | "archive_url":"https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 63 | "downloads_url":"https://api.github.com/repos/svenfuchs/test/downloads", 64 | "issues_url":"https://api.github.com/repos/svenfuchs/test/issues{/number}", 65 | "pulls_url":"https://api.github.com/repos/svenfuchs/test/pulls{/number}", 66 | "milestones_url":"https://api.github.com/repos/svenfuchs/test/milestones{/number}", 67 | "notifications_url":"https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 68 | "labels_url":"https://api.github.com/repos/svenfuchs/test/labels{/name}", 69 | "releases_url":"https://api.github.com/repos/svenfuchs/test/releases{/id}", 70 | "deployments_url":"https://api.github.com/repos/svenfuchs/test/deployments", 71 | "created_at":"2015-10-14T15:42:48Z", 72 | "updated_at":"2016-01-27T10:04:29Z", 73 | "pushed_at":"2016-08-06T19:23:26Z", 74 | "git_url":"git://github.com/svenfuchs/test.git", 75 | "ssh_url":"git@github.com:svenfuchs/test.git", 76 | "clone_url":"https://github.com/svenfuchs/test.git", 77 | "svn_url":"https://github.com/svenfuchs/test", 78 | "homepage":null, 79 | "size":47, 80 | "stargazers_count":0, 81 | "watchers_count":0, 82 | "language":null, 83 | "has_issues":true, 84 | "has_downloads":true, 85 | "has_wiki":true, 86 | "has_pages":true, 87 | "forks_count":0, 88 | "mirror_url":null, 89 | "open_issues_count":2, 90 | "forks":0, 91 | "open_issues":2, 92 | "watchers":0, 93 | "default_branch":"master" 94 | }, 95 | "sender":{ 96 | "login":"svenfuchs", 97 | "id":2208, 98 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 99 | "gravatar_id":"", 100 | "url":"https://api.github.com/users/svenfuchs", 101 | "html_url":"https://github.com/svenfuchs", 102 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 103 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 104 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 105 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 106 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 107 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 108 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 109 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 110 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 111 | "type":"User", 112 | "site_admin":false 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /spec/payloads/tag_deleted.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref":"v1.0.0", 3 | "ref_type":"tag", 4 | "master_branch":"master", 5 | "description":"", 6 | "pusher_type":"user", 7 | "repository":{ 8 | "id":1, 9 | "name":"test", 10 | "full_name":"svenfuchs/test", 11 | "owner":{ 12 | "login":"svenfuchs", 13 | "id":2208, 14 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 15 | "gravatar_id":"", 16 | "url":"https://api.github.com/users/svenfuchs", 17 | "html_url":"https://github.com/svenfuchs", 18 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 19 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 20 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 21 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 22 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 23 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 24 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 25 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 26 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 27 | "type":"User", 28 | "site_admin":false 29 | }, 30 | "private":false, 31 | "html_url":"https://github.com/svenfuchs/test", 32 | "description":"", 33 | "fork":false, 34 | "url":"https://api.github.com/repos/svenfuchs/test", 35 | "forks_url":"https://api.github.com/repos/svenfuchs/test/forks", 36 | "keys_url":"https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 37 | "collaborators_url":"https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 38 | "teams_url":"https://api.github.com/repos/svenfuchs/test/teams", 39 | "hooks_url":"https://api.github.com/repos/svenfuchs/test/hooks", 40 | "issue_events_url":"https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 41 | "events_url":"https://api.github.com/repos/svenfuchs/test/events", 42 | "assignees_url":"https://api.github.com/repos/svenfuchs/test/assignees{/user}", 43 | "branches_url":"https://api.github.com/repos/svenfuchs/test/branches{/branch}", 44 | "tags_url":"https://api.github.com/repos/svenfuchs/test/tags", 45 | "blobs_url":"https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 46 | "git_tags_url":"https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 47 | "git_refs_url":"https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 48 | "trees_url":"https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 49 | "statuses_url":"https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 50 | "languages_url":"https://api.github.com/repos/svenfuchs/test/languages", 51 | "stargazers_url":"https://api.github.com/repos/svenfuchs/test/stargazers", 52 | "contributors_url":"https://api.github.com/repos/svenfuchs/test/contributors", 53 | "subscribers_url":"https://api.github.com/repos/svenfuchs/test/subscribers", 54 | "subscription_url":"https://api.github.com/repos/svenfuchs/test/subscription", 55 | "commits_url":"https://api.github.com/repos/svenfuchs/test/commits{/sha}", 56 | "git_commits_url":"https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 57 | "comments_url":"https://api.github.com/repos/svenfuchs/test/comments{/number}", 58 | "issue_comment_url":"https://api.github.com/repos/svenfuchs/test/issues/comments{/number}", 59 | "contents_url":"https://api.github.com/repos/svenfuchs/test/contents/{+path}", 60 | "compare_url":"https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 61 | "merges_url":"https://api.github.com/repos/svenfuchs/test/merges", 62 | "archive_url":"https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 63 | "downloads_url":"https://api.github.com/repos/svenfuchs/test/downloads", 64 | "issues_url":"https://api.github.com/repos/svenfuchs/test/issues{/number}", 65 | "pulls_url":"https://api.github.com/repos/svenfuchs/test/pulls{/number}", 66 | "milestones_url":"https://api.github.com/repos/svenfuchs/test/milestones{/number}", 67 | "notifications_url":"https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 68 | "labels_url":"https://api.github.com/repos/svenfuchs/test/labels{/name}", 69 | "releases_url":"https://api.github.com/repos/svenfuchs/test/releases{/id}", 70 | "deployments_url":"https://api.github.com/repos/svenfuchs/test/deployments", 71 | "created_at":"2015-10-14T15:42:48Z", 72 | "updated_at":"2016-01-27T10:04:29Z", 73 | "pushed_at":"2016-08-06T19:23:26Z", 74 | "git_url":"git://github.com/svenfuchs/test.git", 75 | "ssh_url":"git@github.com:svenfuchs/test.git", 76 | "clone_url":"https://github.com/svenfuchs/test.git", 77 | "svn_url":"https://github.com/svenfuchs/test", 78 | "homepage":null, 79 | "size":47, 80 | "stargazers_count":0, 81 | "watchers_count":0, 82 | "language":null, 83 | "has_issues":true, 84 | "has_downloads":true, 85 | "has_wiki":true, 86 | "has_pages":true, 87 | "forks_count":0, 88 | "mirror_url":null, 89 | "open_issues_count":2, 90 | "forks":0, 91 | "open_issues":2, 92 | "watchers":0, 93 | "default_branch":"master" 94 | }, 95 | "sender":{ 96 | "login":"svenfuchs", 97 | "id":2208, 98 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 99 | "gravatar_id":"", 100 | "url":"https://api.github.com/users/svenfuchs", 101 | "html_url":"https://github.com/svenfuchs", 102 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 103 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 104 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 105 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 106 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 107 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 108 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 109 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 110 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 111 | "type":"User", 112 | "site_admin":false 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /spec/payloads/branch_created.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref":"test-branch", 3 | "ref_type":"branch", 4 | "master_branch":"master", 5 | "description":"", 6 | "pusher_type":"user", 7 | "repository":{ 8 | "id":1, 9 | "name":"test", 10 | "full_name":"svenfuchs/test", 11 | "owner":{ 12 | "login":"svenfuchs", 13 | "id":2208, 14 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 15 | "gravatar_id":"", 16 | "url":"https://api.github.com/users/svenfuchs", 17 | "html_url":"https://github.com/svenfuchs", 18 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 19 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 20 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 21 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 22 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 23 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 24 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 25 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 26 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 27 | "type":"User", 28 | "site_admin":false 29 | }, 30 | "private":false, 31 | "html_url":"https://github.com/svenfuchs/test", 32 | "description":"", 33 | "fork":false, 34 | "url":"https://api.github.com/repos/svenfuchs/test", 35 | "forks_url":"https://api.github.com/repos/svenfuchs/test/forks", 36 | "keys_url":"https://api.github.com/repos/svenfuchs/test/keys{/key_id}", 37 | "collaborators_url":"https://api.github.com/repos/svenfuchs/test/collaborators{/collaborator}", 38 | "teams_url":"https://api.github.com/repos/svenfuchs/test/teams", 39 | "hooks_url":"https://api.github.com/repos/svenfuchs/test/hooks", 40 | "issue_events_url":"https://api.github.com/repos/svenfuchs/test/issues/events{/number}", 41 | "events_url":"https://api.github.com/repos/svenfuchs/test/events", 42 | "assignees_url":"https://api.github.com/repos/svenfuchs/test/assignees{/user}", 43 | "branches_url":"https://api.github.com/repos/svenfuchs/test/branches{/branch}", 44 | "tags_url":"https://api.github.com/repos/svenfuchs/test/tags", 45 | "blobs_url":"https://api.github.com/repos/svenfuchs/test/git/blobs{/sha}", 46 | "git_tags_url":"https://api.github.com/repos/svenfuchs/test/git/tags{/sha}", 47 | "git_refs_url":"https://api.github.com/repos/svenfuchs/test/git/refs{/sha}", 48 | "trees_url":"https://api.github.com/repos/svenfuchs/test/git/trees{/sha}", 49 | "statuses_url":"https://api.github.com/repos/svenfuchs/test/statuses/{sha}", 50 | "languages_url":"https://api.github.com/repos/svenfuchs/test/languages", 51 | "stargazers_url":"https://api.github.com/repos/svenfuchs/test/stargazers", 52 | "contributors_url":"https://api.github.com/repos/svenfuchs/test/contributors", 53 | "subscribers_url":"https://api.github.com/repos/svenfuchs/test/subscribers", 54 | "subscription_url":"https://api.github.com/repos/svenfuchs/test/subscription", 55 | "commits_url":"https://api.github.com/repos/svenfuchs/test/commits{/sha}", 56 | "git_commits_url":"https://api.github.com/repos/svenfuchs/test/git/commits{/sha}", 57 | "comments_url":"https://api.github.com/repos/svenfuchs/test/comments{/number}", 58 | "issue_comment_url":"https://api.github.com/repos/svenfuchs/test/issues/comments{/number}", 59 | "contents_url":"https://api.github.com/repos/svenfuchs/test/contents/{+path}", 60 | "compare_url":"https://api.github.com/repos/svenfuchs/test/compare/{base}...{head}", 61 | "merges_url":"https://api.github.com/repos/svenfuchs/test/merges", 62 | "archive_url":"https://api.github.com/repos/svenfuchs/test/{archive_format}{/ref}", 63 | "downloads_url":"https://api.github.com/repos/svenfuchs/test/downloads", 64 | "issues_url":"https://api.github.com/repos/svenfuchs/test/issues{/number}", 65 | "pulls_url":"https://api.github.com/repos/svenfuchs/test/pulls{/number}", 66 | "milestones_url":"https://api.github.com/repos/svenfuchs/test/milestones{/number}", 67 | "notifications_url":"https://api.github.com/repos/svenfuchs/test/notifications{?since,all,participating}", 68 | "labels_url":"https://api.github.com/repos/svenfuchs/test/labels{/name}", 69 | "releases_url":"https://api.github.com/repos/svenfuchs/test/releases{/id}", 70 | "deployments_url":"https://api.github.com/repos/svenfuchs/test/deployments", 71 | "created_at":"2015-10-14T15:42:48Z", 72 | "updated_at":"2016-01-27T10:04:29Z", 73 | "pushed_at":"2016-08-06T19:23:26Z", 74 | "git_url":"git://github.com/svenfuchs/test.git", 75 | "ssh_url":"git@github.com:svenfuchs/test.git", 76 | "clone_url":"https://github.com/svenfuchs/test.git", 77 | "svn_url":"https://github.com/svenfuchs/test", 78 | "homepage":null, 79 | "size":47, 80 | "stargazers_count":0, 81 | "watchers_count":0, 82 | "language":null, 83 | "has_issues":true, 84 | "has_downloads":true, 85 | "has_wiki":true, 86 | "has_pages":true, 87 | "forks_count":0, 88 | "mirror_url":null, 89 | "open_issues_count":2, 90 | "forks":0, 91 | "open_issues":2, 92 | "watchers":0, 93 | "default_branch":"master" 94 | }, 95 | "sender":{ 96 | "login":"svenfuchs", 97 | "id":2208, 98 | "avatar_url":"https://avatars.githubusercontent.com/u/2208?v=3", 99 | "gravatar_id":"", 100 | "url":"https://api.github.com/users/svenfuchs", 101 | "html_url":"https://github.com/svenfuchs", 102 | "followers_url":"https://api.github.com/users/svenfuchs/followers", 103 | "following_url":"https://api.github.com/users/svenfuchs/following{/other_user}", 104 | "gists_url":"https://api.github.com/users/svenfuchs/gists{/gist_id}", 105 | "starred_url":"https://api.github.com/users/svenfuchs/starred{/owner}{/repo}", 106 | "subscriptions_url":"https://api.github.com/users/svenfuchs/subscriptions", 107 | "organizations_url":"https://api.github.com/users/svenfuchs/orgs", 108 | "repos_url":"https://api.github.com/users/svenfuchs/repos", 109 | "events_url":"https://api.github.com/users/svenfuchs/events{/privacy}", 110 | "received_events_url":"https://api.github.com/users/svenfuchs/received_events", 111 | "type":"User", 112 | "site_admin":false 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/travis/listener/schemas.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Travis 4 | module Listener 5 | module Schemas 6 | PUSH = { 7 | 'ref' => nil, 8 | 'head_commit' => { 9 | 'id' => nil 10 | }, 11 | 'commits' => { 12 | 'id' => nil 13 | }, 14 | 'repository' => { 15 | 'id' => nil, 16 | 'name' => nil, 17 | 'full_name' => nil, 18 | 'owner' => { 19 | 'login' => nil 20 | }, 21 | 'private' => nil 22 | }, 23 | 'sender' => { 24 | 'id' => nil, 25 | 'login' => nil, 26 | 'type' => nil 27 | } 28 | }.freeze 29 | 30 | PULL_REQUEST = { 31 | 'action' => nil, 32 | 'number' => nil, 33 | 'pull_request' => { 34 | 'head' => { 35 | 'repo' => { 36 | 'full_name' => nil 37 | }, 38 | 'sha' => nil, 39 | 'ref' => nil, 40 | 'user' => { 41 | 'login' => nil 42 | } 43 | } 44 | }, 45 | 'repository' => { 46 | 'id' => nil, 47 | 'name' => nil, 48 | 'full_name' => nil, 49 | 'owner' => { 50 | 'login' => nil 51 | }, 52 | 'private' => nil 53 | }, 54 | 'sender' => { 55 | 'id' => nil, 56 | 'login' => nil, 57 | 'type' => nil 58 | } 59 | }.freeze 60 | 61 | INSTALLATION = { 62 | 'action' => nil, 63 | 'installation' => { 64 | 'id' => nil, 65 | 'account' => { 66 | 'login' => nil 67 | } 68 | }, 69 | 'sender' => { 70 | 'login' => nil 71 | } 72 | }.freeze 73 | 74 | CHECK_SUITE = { 75 | 'action' => nil, 76 | 'check_suite' => { 77 | 'ref_type' => nil 78 | }, 79 | 'repository' => { 80 | 'id' => nil, 81 | 'name' => nil, 82 | 'full_name' => nil, 83 | 'owner' => { 84 | 'login' => nil 85 | }, 86 | 'private' => nil 87 | }, 88 | 'sender' => { 89 | 'id' => nil, 90 | 'login' => nil 91 | } 92 | }.freeze 93 | 94 | REPOSITORY = { 95 | 'action' => nil, 96 | 'repository' => { 97 | 'id' => nil, 98 | 'name' => nil, 99 | 'full_name' => nil, 100 | 'owner' => { 101 | 'login' => nil 102 | }, 103 | 'private' => nil 104 | }, 105 | 'sender' => { 106 | 'id' => nil, 107 | 'login' => nil 108 | } 109 | }.freeze 110 | 111 | # For MemberEvents 112 | # (https://developer.github.com/v3/activity/events/types/#memberevent) 113 | # 114 | MEMBER = { 115 | 'action' => nil, 116 | 'member' => { 117 | 'login' => nil, 118 | 'id' => nil 119 | }, 120 | 'changes' => { 121 | 'permission' => { 122 | 'from' => nil 123 | } 124 | }, 125 | 'repository' => { 126 | 'id' => nil, 127 | 'name' => nil, 128 | 'full_name' => nil 129 | } 130 | }.freeze 131 | 132 | RELEASE = { 133 | 'action' => nil, 134 | 'release' => { 135 | 'tag_name' => nil, 136 | 'target_commitish' => nil 137 | }, 138 | 'repository' => { 139 | 'id' => nil, 140 | 'name' => nil, 141 | 'full_name' => nil, 142 | 'owner' => { 143 | 'login' => nil 144 | }, 145 | 'private' => nil 146 | }, 147 | 'sender' => { 148 | 'id' => nil, 149 | 'login' => nil, 150 | 'type' => nil 151 | } 152 | }.freeze 153 | 154 | FALLBACK = { 155 | 'sender' => { 156 | 'id' => nil, 157 | 'login' => nil 158 | } 159 | }.freeze 160 | 161 | def self.event_details(event_type, payload) 162 | case event_type 163 | when 'pull_request' 164 | { 165 | repository: payload['repository']['full_name'], 166 | number: payload['number'], 167 | action: payload['action'], 168 | source: payload['pull_request']['head']['repo'] && payload['pull_request']['head']['repo']['full_name'], 169 | head: payload['pull_request']['head']['sha'][0..6], 170 | ref: payload['pull_request']['head']['ref'], 171 | user: payload['pull_request']['head'].fetch('user', {}).fetch('login', ''), 172 | sender: payload['sender'].fetch('login', ''), 173 | sender_type: payload['sender'].fetch('type', '') 174 | } 175 | when 'push' 176 | { 177 | repository: payload['repository']['full_name'], 178 | ref: payload['ref'], 179 | head: payload['head_commit'] && payload['head_commit']['id'][0..6], 180 | commits: (payload['commits'] || []).map { |c| c['id'][0..6] }.join(','), 181 | sender: payload['sender'].fetch('login', ''), 182 | sender_type: payload['sender'].fetch('type', '') 183 | } 184 | when 'check_suite' 185 | { 186 | action: payload['action'], 187 | ref_type: payload['check_suite']['ref_type'], 188 | repository: payload['repository']['full_name'], 189 | sender: payload['sender'].fetch('login', '') 190 | } 191 | when 'create', 'delete', 'repository', 'check_run' 192 | { 193 | action: payload['action'], 194 | repository: payload['repository']['full_name'], 195 | sender: payload['sender'].fetch('login', '') 196 | } 197 | when 'installation', 'installation_repositories' 198 | { 199 | action: payload['action'], 200 | installation: payload['installation']['account']['login'], 201 | sender: payload['sender'].fetch('login', '') 202 | } 203 | when 'release' 204 | { 205 | name: payload['release']['name'], 206 | repository: payload['repository']['full_name'], 207 | action: payload['action'], 208 | tag: payload['release']['tag_name'], 209 | target_commitish: payload['release']['target_commitish'], 210 | sender: payload['sender'].fetch('login', ''), 211 | sender_type: payload['sender'].fetch('type', '') 212 | } 213 | else 214 | {} 215 | end 216 | end 217 | end 218 | end 219 | end 220 | -------------------------------------------------------------------------------- /spec/payloads/member.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "added", 3 | "member": { 4 | "login": "octocat", 5 | "id": 583231, 6 | "avatar_url": "https://avatars.githubusercontent.com/u/583231?v=3", 7 | "gravatar_id": "", 8 | "url": "https://api.github.com/users/octocat", 9 | "html_url": "https://github.com/octocat", 10 | "followers_url": "https://api.github.com/users/octocat/followers", 11 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 12 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 13 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 14 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 15 | "organizations_url": "https://api.github.com/users/octocat/orgs", 16 | "repos_url": "https://api.github.com/users/octocat/repos", 17 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 18 | "received_events_url": "https://api.github.com/users/octocat/received_events", 19 | "type": "User", 20 | "site_admin": false 21 | }, 22 | "repository": { 23 | "id": 35129377, 24 | "name": "public-repo", 25 | "full_name": "baxterthehacker/public-repo", 26 | "owner": { 27 | "login": "baxterthehacker", 28 | "id": 6752317, 29 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", 30 | "gravatar_id": "", 31 | "url": "https://api.github.com/users/baxterthehacker", 32 | "html_url": "https://github.com/baxterthehacker", 33 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 34 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 35 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 36 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 37 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 38 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 39 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 40 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 41 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 42 | "type": "User", 43 | "site_admin": false 44 | }, 45 | "private": false, 46 | "html_url": "https://github.com/baxterthehacker/public-repo", 47 | "description": "", 48 | "fork": false, 49 | "url": "https://api.github.com/repos/baxterthehacker/public-repo", 50 | "forks_url": "https://api.github.com/repos/baxterthehacker/public-repo/forks", 51 | "keys_url": "https://api.github.com/repos/baxterthehacker/public-repo/keys{/key_id}", 52 | "collaborators_url": "https://api.github.com/repos/baxterthehacker/public-repo/collaborators{/collaborator}", 53 | "teams_url": "https://api.github.com/repos/baxterthehacker/public-repo/teams", 54 | "hooks_url": "https://api.github.com/repos/baxterthehacker/public-repo/hooks", 55 | "issue_events_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/events{/number}", 56 | "events_url": "https://api.github.com/repos/baxterthehacker/public-repo/events", 57 | "assignees_url": "https://api.github.com/repos/baxterthehacker/public-repo/assignees{/user}", 58 | "branches_url": "https://api.github.com/repos/baxterthehacker/public-repo/branches{/branch}", 59 | "tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/tags", 60 | "blobs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/blobs{/sha}", 61 | "git_tags_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/tags{/sha}", 62 | "git_refs_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/refs{/sha}", 63 | "trees_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/trees{/sha}", 64 | "statuses_url": "https://api.github.com/repos/baxterthehacker/public-repo/statuses/{sha}", 65 | "languages_url": "https://api.github.com/repos/baxterthehacker/public-repo/languages", 66 | "stargazers_url": "https://api.github.com/repos/baxterthehacker/public-repo/stargazers", 67 | "contributors_url": "https://api.github.com/repos/baxterthehacker/public-repo/contributors", 68 | "subscribers_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscribers", 69 | "subscription_url": "https://api.github.com/repos/baxterthehacker/public-repo/subscription", 70 | "commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/commits{/sha}", 71 | "git_commits_url": "https://api.github.com/repos/baxterthehacker/public-repo/git/commits{/sha}", 72 | "comments_url": "https://api.github.com/repos/baxterthehacker/public-repo/comments{/number}", 73 | "issue_comment_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues/comments{/number}", 74 | "contents_url": "https://api.github.com/repos/baxterthehacker/public-repo/contents/{+path}", 75 | "compare_url": "https://api.github.com/repos/baxterthehacker/public-repo/compare/{base}...{head}", 76 | "merges_url": "https://api.github.com/repos/baxterthehacker/public-repo/merges", 77 | "archive_url": "https://api.github.com/repos/baxterthehacker/public-repo/{archive_format}{/ref}", 78 | "downloads_url": "https://api.github.com/repos/baxterthehacker/public-repo/downloads", 79 | "issues_url": "https://api.github.com/repos/baxterthehacker/public-repo/issues{/number}", 80 | "pulls_url": "https://api.github.com/repos/baxterthehacker/public-repo/pulls{/number}", 81 | "milestones_url": "https://api.github.com/repos/baxterthehacker/public-repo/milestones{/number}", 82 | "notifications_url": "https://api.github.com/repos/baxterthehacker/public-repo/notifications{?since,all,participating}", 83 | "labels_url": "https://api.github.com/repos/baxterthehacker/public-repo/labels{/name}", 84 | "releases_url": "https://api.github.com/repos/baxterthehacker/public-repo/releases{/id}", 85 | "created_at": "2015-05-05T23:40:12Z", 86 | "updated_at": "2015-05-05T23:40:30Z", 87 | "pushed_at": "2015-05-05T23:40:40Z", 88 | "git_url": "git://github.com/baxterthehacker/public-repo.git", 89 | "ssh_url": "git@github.com:baxterthehacker/public-repo.git", 90 | "clone_url": "https://github.com/baxterthehacker/public-repo.git", 91 | "svn_url": "https://github.com/baxterthehacker/public-repo", 92 | "homepage": null, 93 | "size": 0, 94 | "stargazers_count": 0, 95 | "watchers_count": 0, 96 | "language": null, 97 | "has_issues": true, 98 | "has_downloads": true, 99 | "has_wiki": true, 100 | "has_pages": true, 101 | "forks_count": 0, 102 | "mirror_url": null, 103 | "open_issues_count": 2, 104 | "forks": 0, 105 | "open_issues": 2, 106 | "watchers": 0, 107 | "default_branch": "master" 108 | }, 109 | "sender": { 110 | "login": "baxterthehacker", 111 | "id": 6752317, 112 | "avatar_url": "https://avatars.githubusercontent.com/u/6752317?v=3", 113 | "gravatar_id": "", 114 | "url": "https://api.github.com/users/baxterthehacker", 115 | "html_url": "https://github.com/baxterthehacker", 116 | "followers_url": "https://api.github.com/users/baxterthehacker/followers", 117 | "following_url": "https://api.github.com/users/baxterthehacker/following{/other_user}", 118 | "gists_url": "https://api.github.com/users/baxterthehacker/gists{/gist_id}", 119 | "starred_url": "https://api.github.com/users/baxterthehacker/starred{/owner}{/repo}", 120 | "subscriptions_url": "https://api.github.com/users/baxterthehacker/subscriptions", 121 | "organizations_url": "https://api.github.com/users/baxterthehacker/orgs", 122 | "repos_url": "https://api.github.com/users/baxterthehacker/repos", 123 | "events_url": "https://api.github.com/users/baxterthehacker/events{/privacy}", 124 | "received_events_url": "https://api.github.com/users/baxterthehacker/received_events", 125 | "type": "User", 126 | "site_admin": false 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /lib/travis/listener/app.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'travis/listener/schemas' 4 | require 'sinatra' 5 | require 'travis/support/logging' 6 | require 'sidekiq' 7 | require 'travis/sidekiq' 8 | require 'yajl' 9 | require 'ipaddr' 10 | require 'metriks' 11 | 12 | module Travis 13 | module Listener 14 | class App < Sinatra::Base 15 | include Logging 16 | 17 | # use Rack::CommonLogger for request logging 18 | enable :logging, :dump_errors 19 | 20 | # https://developer.github.com/v3/activity/events/types 21 | set :events, %w[ 22 | check_run 23 | check_suite 24 | create 25 | delete 26 | installation 27 | installation_repositories 28 | member 29 | organization 30 | pull_request 31 | push 32 | repository 33 | release 34 | ] 35 | 36 | before do 37 | logger.level = 1 38 | end 39 | 40 | get '/' do 41 | redirect 'http://travis-ci.com' 42 | end 43 | 44 | # Used for new relic uptime monitoring 45 | get '/uptime' do 46 | 200 47 | end 48 | 49 | # the main endpoint for scm services 50 | post '/' do 51 | report_memory_usage 52 | report_ip_validity 53 | replace_bot_sender 54 | 55 | if !ip_validation? || valid_ip? 56 | if valid_request? 57 | dispatch_event 58 | 59 | 204 60 | else 61 | Metriks.meter('listener.request.no_payload').mark 62 | 63 | 422 64 | end 65 | else 66 | 403 67 | end 68 | end 69 | 70 | protected 71 | 72 | def valid_request? 73 | payload 74 | end 75 | 76 | def ip_validation? 77 | Travis.config.listener&.ip_validation 78 | end 79 | 80 | def replace_bot_sender 81 | return unless payload && decoded_payload.dig('sender', 'type')&.downcase == 'bot' 82 | 83 | payload_data = JSON.parse(payload) 84 | payload_data['sender'] = { 85 | type: 'User', 86 | github_id: 0, 87 | vcs_id: '0', 88 | login: 'bot' 89 | } 90 | params[:payload] = JSON.dump(payload_data) 91 | end 92 | 93 | def report_ip_validity 94 | if valid_ip? 95 | Metriks.meter('listener.ip.valid').mark 96 | else 97 | Metriks.meter('listener.ip.invalid').mark 98 | logger.info "Payload to travis-listener sent from an invalid IP(#{request.ip})" 99 | end 100 | end 101 | 102 | def valid_ip? 103 | return true if valid_ips.empty? 104 | 105 | valid_ips.any? { |ip| IPAddr.new(ip).include? request.ip } 106 | end 107 | 108 | def valid_ips 109 | Travis.config.listener&.valid_ips || [] 110 | end 111 | 112 | def dispatch_event 113 | Metriks.meter("listener.event.#{event_type}").mark 114 | Metriks.meter("listener.integration.#{integration_type}").mark 115 | 116 | return unless handle_event? 117 | 118 | return if release_event_skip_action? 119 | 120 | # According to GitHub every webhook payload should have this 121 | # If it is not present, assume payload is malformed 122 | return unless payload['sender'] 123 | 124 | debug "Event payload for #{uuid}: #{payload.inspect}" 125 | 126 | log_event 127 | 128 | case event_type 129 | when 'installation' 130 | Travis::Sidekiq::GithubSync.gh_app_install(data) 131 | when 'installation_repositories' 132 | Travis::Sidekiq::GithubSync.gh_app_repos(data) 133 | when 'member' 134 | Travis::Sidekiq::GithubSync.gh_app_member(data) 135 | when 'organization' 136 | Travis::Sidekiq::GithubSync.organization(data) 137 | else 138 | Travis::Sidekiq::Gatekeeper.push(Travis.config.gator.queue, data) 139 | end 140 | end 141 | 142 | def handle_event? 143 | if accepted_event_excluding_checks? || rerequested_check? 144 | Metriks.meter('listener.handle.accept').mark 145 | true 146 | else 147 | Metriks.meter('listener.handle.reject').mark 148 | false 149 | end 150 | end 151 | 152 | def accepted_event_excluding_checks? 153 | settings.events.include?(event_type) && !checks_event? 154 | end 155 | 156 | # there are two types of rerequested events 157 | # 1. for branches 158 | # 2. for tags (when tags are created) 159 | # we ignore the tag events because we also receive individual 160 | # tag created events. 161 | def rerequested_check? 162 | checks_event? && 163 | decoded_payload['action'] == 'rerequested' && 164 | !tag_created_check_suite? 165 | end 166 | 167 | def checks_event? 168 | %w[check_run check_suite].include?(event_type) 169 | end 170 | 171 | def tag_created_check_suite? 172 | event_type == 'check_suite' && 173 | decoded_payload['check_suite']['ref_type'] == 'tag' 174 | end 175 | 176 | def release_event_skip_action? 177 | event_type == 'release' && 178 | decoded_payload['action'] != 'released' 179 | end 180 | 181 | def log_event 182 | details = { 183 | uuid:, 184 | delivery_guid:, 185 | type: event_type 186 | } 187 | 188 | info(details.merge(event_details).map { |k, v| "#{k}=#{v}" }.join(' ')) 189 | end 190 | 191 | def data 192 | { 193 | type: event_type, 194 | payload:, 195 | uuid:, 196 | github_guid: delivery_guid, 197 | github_event: event_type, 198 | received_at: Time.now 199 | } 200 | end 201 | 202 | def uuid 203 | env['HTTP_X_REQUEST_ID'] || Travis.uuid 204 | end 205 | 206 | def event_type 207 | env['HTTP_X_GITHUB_EVENT'] || 'push' 208 | end 209 | 210 | def delivery_guid 211 | env['HTTP_X_GITHUB_DELIVERY'] || env['HTTP_X_GITHUB_GUID'] 212 | end 213 | 214 | def integration_type 215 | if params[:payload].blank? 216 | 'github_apps' 217 | else 218 | 'webhook' 219 | end 220 | end 221 | 222 | def event_details 223 | Schemas.event_details(event_type, decoded_payload) 224 | rescue StandardError => e 225 | error("Error logging payload: #{e.message}") 226 | error("Payload causing error: #{decoded_payload}") 227 | Sentry.capture_exception(e) 228 | {} 229 | end 230 | 231 | def decoded_payload 232 | @decoded_payload ||= begin 233 | schema = 234 | case event_type 235 | when 'push' 236 | Schemas::PUSH 237 | when 'pull_request' 238 | Schemas::PULL_REQUEST 239 | when 'installation', 'installation_repositories' 240 | Schemas::INSTALLATION 241 | when 'check_suite' 242 | Schemas::CHECK_SUITE 243 | when 'create', 'delete', 'repository', 'check_run' 244 | Schemas::REPOSITORY 245 | when 'member' 246 | Schemas::MEMBER 247 | when 'release' 248 | Schemas::RELEASE 249 | else 250 | Schemas::FALLBACK 251 | end 252 | 253 | stream = StringIO.new(payload) 254 | Yajl::Projector.new(stream).project(schema) 255 | end 256 | end 257 | 258 | def payload 259 | if !params[:payload].blank? 260 | params[:payload] 261 | elsif !request_body.blank? 262 | request_body 263 | end 264 | end 265 | 266 | def request_body 267 | @request_body ||= begin 268 | request.body.rewind 269 | request.body.read.force_encoding('utf-8') 270 | end 271 | end 272 | 273 | def report_memory_usage 274 | Metriks.gauge('listener.gc.heap_live_slots').set(GC.stat[:heap_live_slots]) 275 | end 276 | end 277 | end 278 | end 279 | -------------------------------------------------------------------------------- /spec/payloads/member_removed.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "removed", 3 | "member": { 4 | "login": "AndriiMyskoTest", 5 | "id": 88183964, 6 | "node_id": "MDQ6VXNlcjg4MTgzOTY0", 7 | "avatar_url": "https://avatars.githubusercontent.com/u/88183964?v=4", 8 | "gravatar_id": "", 9 | "url": "https://api.github.com/users/AndriiMyskoTest", 10 | "html_url": "https://github.com/AndriiMyskoTest", 11 | "followers_url": "https://api.github.com/users/AndriiMyskoTest/followers", 12 | "following_url": "https://api.github.com/users/AndriiMyskoTest/following{/other_user}", 13 | "gists_url": "https://api.github.com/users/AndriiMyskoTest/gists{/gist_id}", 14 | "starred_url": "https://api.github.com/users/AndriiMyskoTest/starred{/owner}{/repo}", 15 | "subscriptions_url": "https://api.github.com/users/AndriiMyskoTest/subscriptions", 16 | "organizations_url": "https://api.github.com/users/AndriiMyskoTest/orgs", 17 | "repos_url": "https://api.github.com/users/AndriiMyskoTest/repos", 18 | "events_url": "https://api.github.com/users/AndriiMyskoTest/events{/privacy}", 19 | "received_events_url": "https://api.github.com/users/AndriiMyskoTest/received_events", 20 | "type": "User", 21 | "site_admin": false 22 | }, 23 | "repository": { 24 | "id": 373785375, 25 | "node_id": "MDEwOlJlcG9zaXRvcnkzNzM3ODUzNzU=", 26 | "name": "TestRepoPPC", 27 | "full_name": "AndriiMysko/TestRepoPPC", 28 | "private": false, 29 | "owner": { 30 | "login": "AndriiMysko", 31 | "id": 69478317, 32 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 33 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 34 | "gravatar_id": "", 35 | "url": "https://api.github.com/users/AndriiMysko", 36 | "html_url": "https://github.com/AndriiMysko", 37 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 38 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 39 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 40 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 41 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 42 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 43 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 44 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 45 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 46 | "type": "User", 47 | "site_admin": false 48 | }, 49 | "html_url": "https://github.com/AndriiMysko/TestRepoPPC", 50 | "description": null, 51 | "fork": false, 52 | "url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC", 53 | "forks_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/forks", 54 | "keys_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/keys{/key_id}", 55 | "collaborators_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/collaborators{/collaborator}", 56 | "teams_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/teams", 57 | "hooks_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/hooks", 58 | "issue_events_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/issues/events{/number}", 59 | "events_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/events", 60 | "assignees_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/assignees{/user}", 61 | "branches_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/branches{/branch}", 62 | "tags_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/tags", 63 | "blobs_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/git/blobs{/sha}", 64 | "git_tags_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/git/tags{/sha}", 65 | "git_refs_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/git/refs{/sha}", 66 | "trees_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/git/trees{/sha}", 67 | "statuses_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/statuses/{sha}", 68 | "languages_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/languages", 69 | "stargazers_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/stargazers", 70 | "contributors_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/contributors", 71 | "subscribers_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/subscribers", 72 | "subscription_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/subscription", 73 | "commits_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/commits{/sha}", 74 | "git_commits_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/git/commits{/sha}", 75 | "comments_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/comments{/number}", 76 | "issue_comment_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/issues/comments{/number}", 77 | "contents_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/contents/{+path}", 78 | "compare_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/compare/{base}...{head}", 79 | "merges_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/merges", 80 | "archive_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/{archive_format}{/ref}", 81 | "downloads_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/downloads", 82 | "issues_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/issues{/number}", 83 | "pulls_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/pulls{/number}", 84 | "milestones_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/milestones{/number}", 85 | "notifications_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/notifications{?since,all,participating}", 86 | "labels_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/labels{/name}", 87 | "releases_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/releases{/id}", 88 | "deployments_url": "https://api.github.com/repos/AndriiMysko/TestRepoPPC/deployments", 89 | "created_at": "2021-06-04T09:12:09Z", 90 | "updated_at": "2021-10-11T08:25:17Z", 91 | "pushed_at": "2024-03-01T12:48:38Z", 92 | "git_url": "git://github.com/AndriiMysko/TestRepoPPC.git", 93 | "ssh_url": "git@github.com:AndriiMysko/TestRepoPPC.git", 94 | "clone_url": "https://github.com/AndriiMysko/TestRepoPPC.git", 95 | "svn_url": "https://github.com/AndriiMysko/TestRepoPPC", 96 | "homepage": null, 97 | "size": 47, 98 | "stargazers_count": 0, 99 | "watchers_count": 0, 100 | "language": null, 101 | "has_issues": true, 102 | "has_projects": true, 103 | "has_downloads": true, 104 | "has_wiki": true, 105 | "has_pages": false, 106 | "has_discussions": false, 107 | "forks_count": 0, 108 | "mirror_url": null, 109 | "archived": false, 110 | "disabled": false, 111 | "open_issues_count": 0, 112 | "license": null, 113 | "allow_forking": true, 114 | "is_template": false, 115 | "web_commit_signoff_required": false, 116 | "topics": [], 117 | "visibility": "public", 118 | "forks": 0, 119 | "open_issues": 0, 120 | "watchers": 0, 121 | "default_branch": "main" 122 | }, 123 | "sender": { 124 | "login": "AndriiMysko", 125 | "id": 69478317, 126 | "node_id": "MDQ6VXNlcjY5NDc4MzE3", 127 | "avatar_url": "https://avatars.githubusercontent.com/u/69478317?v=4", 128 | "gravatar_id": "", 129 | "url": "https://api.github.com/users/AndriiMysko", 130 | "html_url": "https://github.com/AndriiMysko", 131 | "followers_url": "https://api.github.com/users/AndriiMysko/followers", 132 | "following_url": "https://api.github.com/users/AndriiMysko/following{/other_user}", 133 | "gists_url": "https://api.github.com/users/AndriiMysko/gists{/gist_id}", 134 | "starred_url": "https://api.github.com/users/AndriiMysko/starred{/owner}{/repo}", 135 | "subscriptions_url": "https://api.github.com/users/AndriiMysko/subscriptions", 136 | "organizations_url": "https://api.github.com/users/AndriiMysko/orgs", 137 | "repos_url": "https://api.github.com/users/AndriiMysko/repos", 138 | "events_url": "https://api.github.com/users/AndriiMysko/events{/privacy}", 139 | "received_events_url": "https://api.github.com/users/AndriiMysko/received_events", 140 | "type": "User", 141 | "site_admin": false 142 | } 143 | } -------------------------------------------------------------------------------- /spec/payloads/push.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "refs/heads/master", 3 | "before": "f968cca6b2a1cc561424ad3b93d63438b0d7a9d8", 4 | "after": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 5 | "created": false, 6 | "deleted": false, 7 | "forced": false, 8 | "base_ref": null, 9 | "compare": "https://github.com/joshk/sportsmaps.co.nz/compare/f968cca6b2a1...902ac3c75527", 10 | "commits": [ 11 | { 12 | "id": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 13 | "tree_id": "2a5e394af3e29803ffae0e45da1237bc4fb76e9c", 14 | "distinct": true, 15 | "message": "moar ###", 16 | "timestamp": "2018-05-03T18:49:57-07:00", 17 | "url": "https://github.com/joshk/sportsmaps.co.nz/commit/902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 18 | "author": { 19 | "name": "Josh Kalderimis", 20 | "email": "josh.kalderimis@gmail.com", 21 | "username": "joshk" 22 | }, 23 | "committer": { 24 | "name": "GitHub", 25 | "email": "noreply@github.com", 26 | "username": "web-flow" 27 | }, 28 | "added": [ 29 | 30 | ], 31 | "removed": [ 32 | 33 | ], 34 | "modified": [ 35 | "README.textile" 36 | ] 37 | } 38 | ], 39 | "head_commit": { 40 | "id": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 41 | "tree_id": "2a5e394af3e29803ffae0e45da1237bc4fb76e9c", 42 | "distinct": true, 43 | "message": "moar ###", 44 | "timestamp": "2018-05-03T18:49:57-07:00", 45 | "url": "https://github.com/joshk/sportsmaps.co.nz/commit/902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 46 | "author": { 47 | "name": "Josh Kalderimis", 48 | "email": "josh.kalderimis@gmail.com", 49 | "username": "joshk" 50 | }, 51 | "committer": { 52 | "name": "GitHub", 53 | "email": "noreply@github.com", 54 | "username": "web-flow" 55 | }, 56 | "added": [ 57 | 58 | ], 59 | "removed": [ 60 | 61 | ], 62 | "modified": [ 63 | "README.textile" 64 | ] 65 | }, 66 | "repository": { 67 | "id": 149532, 68 | "name": "sportsmaps.co.nz", 69 | "full_name": "joshk/sportsmaps.co.nz", 70 | "owner": { 71 | "name": "joshk", 72 | "email": "josh.kalderimis@gmail.com", 73 | "login": "joshk", 74 | "id": 8701, 75 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 76 | "gravatar_id": "", 77 | "url": "https://api.github.com/users/joshk", 78 | "html_url": "https://github.com/joshk", 79 | "followers_url": "https://api.github.com/users/joshk/followers", 80 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 81 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 82 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 83 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 84 | "organizations_url": "https://api.github.com/users/joshk/orgs", 85 | "repos_url": "https://api.github.com/users/joshk/repos", 86 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 87 | "received_events_url": "https://api.github.com/users/joshk/received_events", 88 | "type": "User", 89 | "site_admin": false 90 | }, 91 | "private": true, 92 | "html_url": "https://github.com/joshk/sportsmaps.co.nz", 93 | "description": "SportsMaps central repo", 94 | "fork": false, 95 | "url": "https://github.com/joshk/sportsmaps.co.nz", 96 | "forks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/forks", 97 | "keys_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/keys{/key_id}", 98 | "collaborators_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/collaborators{/collaborator}", 99 | "teams_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/teams", 100 | "hooks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/hooks", 101 | "issue_events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/events{/number}", 102 | "events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/events", 103 | "assignees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/assignees{/user}", 104 | "branches_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/branches{/branch}", 105 | "tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/tags", 106 | "blobs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/blobs{/sha}", 107 | "git_tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/tags{/sha}", 108 | "git_refs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/refs{/sha}", 109 | "trees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/trees{/sha}", 110 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/{sha}", 111 | "languages_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/languages", 112 | "stargazers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/stargazers", 113 | "contributors_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contributors", 114 | "subscribers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscribers", 115 | "subscription_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscription", 116 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/commits{/sha}", 117 | "git_commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/commits{/sha}", 118 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/comments{/number}", 119 | "issue_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/comments{/number}", 120 | "contents_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contents/{+path}", 121 | "compare_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/compare/{base}...{head}", 122 | "merges_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/merges", 123 | "archive_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/{archive_format}{/ref}", 124 | "downloads_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/downloads", 125 | "issues_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues{/number}", 126 | "pulls_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls{/number}", 127 | "milestones_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/milestones{/number}", 128 | "notifications_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/notifications{?since,all,participating}", 129 | "labels_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/labels{/name}", 130 | "releases_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/releases{/id}", 131 | "deployments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/deployments", 132 | "created_at": 1236890990, 133 | "updated_at": "2015-05-21T23:06:01Z", 134 | "pushed_at": 1525398598, 135 | "git_url": "git://github.com/joshk/sportsmaps.co.nz.git", 136 | "ssh_url": "git@github.com:joshk/sportsmaps.co.nz.git", 137 | "clone_url": "https://github.com/joshk/sportsmaps.co.nz.git", 138 | "svn_url": "https://github.com/joshk/sportsmaps.co.nz", 139 | "homepage": "www.sportsmaps.co.nz", 140 | "size": 6724, 141 | "stargazers_count": 2, 142 | "watchers_count": 2, 143 | "language": "Ruby", 144 | "has_issues": true, 145 | "has_projects": true, 146 | "has_downloads": true, 147 | "has_wiki": true, 148 | "has_pages": false, 149 | "forks_count": 0, 150 | "mirror_url": null, 151 | "archived": false, 152 | "open_issues_count": 0, 153 | "license": null, 154 | "forks": 0, 155 | "open_issues": 0, 156 | "watchers": 2, 157 | "default_branch": "master", 158 | "stargazers": 2, 159 | "master_branch": "master" 160 | }, 161 | "pusher": { 162 | "name": "joshk", 163 | "email": "josh.kalderimis@gmail.com" 164 | }, 165 | "sender": { 166 | "login": "joshk", 167 | "id": 8701, 168 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 169 | "gravatar_id": "", 170 | "url": "https://api.github.com/users/joshk", 171 | "html_url": "https://github.com/joshk", 172 | "followers_url": "https://api.github.com/users/joshk/followers", 173 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 174 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 175 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 176 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 177 | "organizations_url": "https://api.github.com/users/joshk/orgs", 178 | "repos_url": "https://api.github.com/users/joshk/repos", 179 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 180 | "received_events_url": "https://api.github.com/users/joshk/received_events", 181 | "type": "User", 182 | "site_admin": false 183 | }, 184 | "installation": { 185 | "id": 151888 186 | } 187 | } -------------------------------------------------------------------------------- /spec/payloads/bot_push.json: -------------------------------------------------------------------------------- 1 | { 2 | "ref": "refs/heads/master", 3 | "before": "f968cca6b2a1cc561424ad3b93d63438b0d7a9d8", 4 | "after": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 5 | "created": false, 6 | "deleted": false, 7 | "forced": false, 8 | "base_ref": null, 9 | "compare": "https://github.com/joshk/sportsmaps.co.nz/compare/f968cca6b2a1...902ac3c75527", 10 | "commits": [ 11 | { 12 | "id": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 13 | "tree_id": "2a5e394af3e29803ffae0e45da1237bc4fb76e9c", 14 | "distinct": true, 15 | "message": "moar ###", 16 | "timestamp": "2018-05-03T18:49:57-07:00", 17 | "url": "https://github.com/joshk/sportsmaps.co.nz/commit/902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 18 | "author": { 19 | "name": "Josh Kalderimis", 20 | "email": "josh.kalderimis@gmail.com", 21 | "username": "joshk" 22 | }, 23 | "committer": { 24 | "name": "GitHub", 25 | "email": "noreply@github.com", 26 | "username": "web-flow" 27 | }, 28 | "added": [ 29 | 30 | ], 31 | "removed": [ 32 | 33 | ], 34 | "modified": [ 35 | "README.textile" 36 | ] 37 | } 38 | ], 39 | "head_commit": { 40 | "id": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 41 | "tree_id": "2a5e394af3e29803ffae0e45da1237bc4fb76e9c", 42 | "distinct": true, 43 | "message": "moar ###", 44 | "timestamp": "2018-05-03T18:49:57-07:00", 45 | "url": "https://github.com/joshk/sportsmaps.co.nz/commit/902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 46 | "author": { 47 | "name": "Josh Kalderimis", 48 | "email": "josh.kalderimis@gmail.com", 49 | "username": "joshk" 50 | }, 51 | "committer": { 52 | "name": "GitHub", 53 | "email": "noreply@github.com", 54 | "username": "web-flow" 55 | }, 56 | "added": [ 57 | 58 | ], 59 | "removed": [ 60 | 61 | ], 62 | "modified": [ 63 | "README.textile" 64 | ] 65 | }, 66 | "repository": { 67 | "id": 149532, 68 | "name": "sportsmaps.co.nz", 69 | "full_name": "joshk/sportsmaps.co.nz", 70 | "owner": { 71 | "name": "joshk", 72 | "email": "josh.kalderimis@gmail.com", 73 | "login": "joshk", 74 | "id": 8701, 75 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 76 | "gravatar_id": "", 77 | "url": "https://api.github.com/users/joshk", 78 | "html_url": "https://github.com/joshk", 79 | "followers_url": "https://api.github.com/users/joshk/followers", 80 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 81 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 82 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 83 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 84 | "organizations_url": "https://api.github.com/users/joshk/orgs", 85 | "repos_url": "https://api.github.com/users/joshk/repos", 86 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 87 | "received_events_url": "https://api.github.com/users/joshk/received_events", 88 | "type": "User", 89 | "site_admin": false 90 | }, 91 | "private": true, 92 | "html_url": "https://github.com/joshk/sportsmaps.co.nz", 93 | "description": "SportsMaps central repo", 94 | "fork": false, 95 | "url": "https://github.com/joshk/sportsmaps.co.nz", 96 | "forks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/forks", 97 | "keys_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/keys{/key_id}", 98 | "collaborators_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/collaborators{/collaborator}", 99 | "teams_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/teams", 100 | "hooks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/hooks", 101 | "issue_events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/events{/number}", 102 | "events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/events", 103 | "assignees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/assignees{/user}", 104 | "branches_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/branches{/branch}", 105 | "tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/tags", 106 | "blobs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/blobs{/sha}", 107 | "git_tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/tags{/sha}", 108 | "git_refs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/refs{/sha}", 109 | "trees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/trees{/sha}", 110 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/{sha}", 111 | "languages_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/languages", 112 | "stargazers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/stargazers", 113 | "contributors_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contributors", 114 | "subscribers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscribers", 115 | "subscription_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscription", 116 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/commits{/sha}", 117 | "git_commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/commits{/sha}", 118 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/comments{/number}", 119 | "issue_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/comments{/number}", 120 | "contents_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contents/{+path}", 121 | "compare_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/compare/{base}...{head}", 122 | "merges_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/merges", 123 | "archive_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/{archive_format}{/ref}", 124 | "downloads_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/downloads", 125 | "issues_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues{/number}", 126 | "pulls_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls{/number}", 127 | "milestones_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/milestones{/number}", 128 | "notifications_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/notifications{?since,all,participating}", 129 | "labels_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/labels{/name}", 130 | "releases_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/releases{/id}", 131 | "deployments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/deployments", 132 | "created_at": 1236890990, 133 | "updated_at": "2015-05-21T23:06:01Z", 134 | "pushed_at": 1525398598, 135 | "git_url": "git://github.com/joshk/sportsmaps.co.nz.git", 136 | "ssh_url": "git@github.com:joshk/sportsmaps.co.nz.git", 137 | "clone_url": "https://github.com/joshk/sportsmaps.co.nz.git", 138 | "svn_url": "https://github.com/joshk/sportsmaps.co.nz", 139 | "homepage": "www.sportsmaps.co.nz", 140 | "size": 6724, 141 | "stargazers_count": 2, 142 | "watchers_count": 2, 143 | "language": "Ruby", 144 | "has_issues": true, 145 | "has_projects": true, 146 | "has_downloads": true, 147 | "has_wiki": true, 148 | "has_pages": false, 149 | "forks_count": 0, 150 | "mirror_url": null, 151 | "archived": false, 152 | "open_issues_count": 0, 153 | "license": null, 154 | "forks": 0, 155 | "open_issues": 0, 156 | "watchers": 2, 157 | "default_branch": "master", 158 | "stargazers": 2, 159 | "master_branch": "master" 160 | }, 161 | "pusher": { 162 | "name": "joshk", 163 | "email": "josh.kalderimis@gmail.com" 164 | }, 165 | "sender": { 166 | "login": "joshk", 167 | "id": 8701, 168 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 169 | "gravatar_id": "", 170 | "url": "https://api.github.com/users/joshk", 171 | "html_url": "https://github.com/joshk", 172 | "followers_url": "https://api.github.com/users/joshk/followers", 173 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 174 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 175 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 176 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 177 | "organizations_url": "https://api.github.com/users/joshk/orgs", 178 | "repos_url": "https://api.github.com/users/joshk/repos", 179 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 180 | "received_events_url": "https://api.github.com/users/joshk/received_events", 181 | "type": "Bot", 182 | "site_admin": false 183 | }, 184 | "installation": { 185 | "id": 151888 186 | } 187 | } -------------------------------------------------------------------------------- /spec/payloads/rerequested_check_suite_tag_ref_type.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "requested", 3 | "check_suite": { 4 | "id": 5, 5 | "ref_type": "tag", 6 | "head_branch": "master", 7 | "head_sha": "d6fde92930d4715a2b49857d24b940956b26d2d3", 8 | "status": "completed", 9 | "conclusion": "neutral", 10 | "url": "https://api.github.com/repos/github/hello-world/check-suites/5", 11 | "before": "146e867f55c26428e5f9fade55a9bbf5e95a7912", 12 | "after": "d6fde92930d4715a2b49857d24b940956b26d2d3", 13 | "pull_requests": [ 14 | 15 | ], 16 | "app": { 17 | "id": 2, 18 | "node_id": "MDExOkludGVncmF0aW9uMQ==", 19 | "owner": { 20 | "login": "github", 21 | "id": 340, 22 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjE=", 23 | "avatar_url": "http://alambic.github.com/avatars/u/340?", 24 | "gravatar_id": "", 25 | "url": "https://api.github.com/users/github", 26 | "html_url": "http://github.com/github", 27 | "followers_url": "https://api.github.com/users/github/followers", 28 | "following_url": "https://api.github.com/users/github/following{/other_user}", 29 | "gists_url": "https://api.github.com/users/github/gists{/gist_id}", 30 | "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", 31 | "subscriptions_url": "https://api.github.com/users/github/subscriptions", 32 | "organizations_url": "https://api.github.com/users/github/orgs", 33 | "repos_url": "https://api.github.com/users/github/repos", 34 | "events_url": "https://api.github.com/users/github/events{/privacy}", 35 | "received_events_url": "https://api.github.com/users/github/received_events", 36 | "type": "Organization", 37 | "site_admin": false 38 | }, 39 | "name": "Super Duper", 40 | "description": null, 41 | "external_url": "http://super-duper.example.com", 42 | "html_url": "http://github.com/apps/super-duper", 43 | "created_at": "2018-04-25 20:42:10", 44 | "updated_at": "2018-04-25 20:42:10" 45 | }, 46 | "created_at": "2018-05-04T01:14:52Z", 47 | "updated_at": "2018-05-04T01:14:52Z", 48 | "latest_check_runs_count": 1, 49 | "check_runs_url": "https://api.github.com/repos/github/hello-world/check-suites/5/check-runs", 50 | "head_commit": { 51 | "id": "d6fde92930d4715a2b49857d24b940956b26d2d3", 52 | "tree_id": "41a846c7d878d279f11355e23b348e1bb63b89a8", 53 | "message": "Say hello (again) to everybody", 54 | "timestamp": "2018-05-04T01:14:46Z", 55 | "author": { 56 | "name": "octocat", 57 | "email": "octocat@github.com" 58 | }, 59 | "committer": { 60 | "name": "octocat", 61 | "email": "octocat@github.com" 62 | } 63 | } 64 | }, 65 | "repository": { 66 | "id": 526, 67 | "node_id": "MDEwOlJlcG9zaXRvcnkxMzU0OTMyMzM=", 68 | "name": "hello-world", 69 | "full_name": "github/hello-world", 70 | "owner": { 71 | "login": "github", 72 | "id": 340, 73 | "node_id": "MDQ6VXNlcjIxMDMxMDY3", 74 | "avatar_url": "http://alambic.github.com/avatars/u/340?", 75 | "gravatar_id": "", 76 | "url": "https://api.github.com/users/github", 77 | "html_url": "http://github.com/github", 78 | "followers_url": "https://api.github.com/users/github/followers", 79 | "following_url": "https://api.github.com/users/github/following{/other_user}", 80 | "gists_url": "https://api.github.com/users/github/gists{/gist_id}", 81 | "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", 82 | "subscriptions_url": "https://api.github.com/users/github/subscriptions", 83 | "organizations_url": "https://api.github.com/users/github/orgs", 84 | "repos_url": "https://api.github.com/users/github/repos", 85 | "events_url": "https://api.github.com/users/github/events{/privacy}", 86 | "received_events_url": "https://api.github.com/users/github/received_events", 87 | "type": "Organization", 88 | "site_admin": false 89 | }, 90 | "private": false, 91 | "html_url": "http://github.com/github/hello-world", 92 | "description": null, 93 | "fork": false, 94 | "url": "https://api.github.com/repos/github/hello-world", 95 | "forks_url": "https://api.github.com/repos/github/hello-world/forks", 96 | "keys_url": "https://api.github.com/repos/github/hello-world/keys{/key_id}", 97 | "collaborators_url": "https://api.github.com/repos/github/hello-world/collaborators{/collaborator}", 98 | "teams_url": "https://api.github.com/repos/github/hello-world/teams", 99 | "hooks_url": "https://api.github.com/repos/github/hello-world/hooks", 100 | "issue_events_url": "https://api.github.com/repos/github/hello-world/issues/events{/number}", 101 | "events_url": "https://api.github.com/repos/github/hello-world/events", 102 | "assignees_url": "https://api.github.com/repos/github/hello-world/assignees{/user}", 103 | "branches_url": "https://api.github.com/repos/github/hello-world/branches{/branch}", 104 | "tags_url": "https://api.github.com/repos/github/hello-world/tags", 105 | "blobs_url": "https://api.github.com/repos/github/hello-world/git/blobs{/sha}", 106 | "git_tags_url": "https://api.github.com/repos/github/hello-world/git/tags{/sha}", 107 | "git_refs_url": "https://api.github.com/repos/github/hello-world/git/refs{/sha}", 108 | "trees_url": "https://api.github.com/repos/github/hello-world/git/trees{/sha}", 109 | "statuses_url": "https://api.github.com/repos/github/hello-world/statuses/{sha}", 110 | "languages_url": "https://api.github.com/repos/github/hello-world/languages", 111 | "stargazers_url": "https://api.github.com/repos/github/hello-world/stargazers", 112 | "contributors_url": "https://api.github.com/repos/github/hello-world/contributors", 113 | "subscribers_url": "https://api.github.com/repos/github/hello-world/subscribers", 114 | "subscription_url": "https://api.github.com/repos/github/hello-world/subscription", 115 | "commits_url": "https://api.github.com/repos/github/hello-world/commits{/sha}", 116 | "git_commits_url": "https://api.github.com/repos/github/hello-world/git/commits{/sha}", 117 | "comments_url": "https://api.github.com/repos/github/hello-world/comments{/number}", 118 | "issue_comment_url": "https://api.github.com/repos/github/hello-world/issues/comments{/number}", 119 | "contents_url": "https://api.github.com/repos/github/hello-world/contents/{+path}", 120 | "compare_url": "https://api.github.com/repos/github/hello-world/compare/{base}...{head}", 121 | "merges_url": "https://api.github.com/repos/github/hello-world/merges", 122 | "archive_url": "https://api.github.com/repos/github/hello-world/{archive_format}{/ref}", 123 | "downloads_url": "https://api.github.com/repos/github/hello-world/downloads", 124 | "issues_url": "https://api.github.com/repos/github/hello-world/issues{/number}", 125 | "pulls_url": "https://api.github.com/repos/github/hello-world/pulls{/number}", 126 | "milestones_url": "https://api.github.com/repos/github/hello-world/milestones{/number}", 127 | "notifications_url": "https://api.github.com/repos/github/hello-world/notifications{?since,all,participating}", 128 | "labels_url": "https://api.github.com/repos/github/hello-world/labels{/name}", 129 | "releases_url": "https://api.github.com/repos/github/hello-world/releases{/id}", 130 | "deployments_url": "https://api.github.com/repos/github/hello-world/deployments", 131 | "created_at": "2018-04-25T20:42:10Z", 132 | "updated_at": "2018-04-25T20:43:34Z", 133 | "pushed_at": "2018-05-04T01:14:47Z", 134 | "git_url": "git://github.com/github/hello-world.git", 135 | "ssh_url": "ssh://git@localhost:3035/github/hello-world.git", 136 | "clone_url": "http://github.com/github/hello-world.git", 137 | "svn_url": "http://github.com/github/hello-world", 138 | "homepage": null, 139 | "size": 0, 140 | "stargazers_count": 0, 141 | "watchers_count": 0, 142 | "language": null, 143 | "has_issues": true, 144 | "has_projects": true, 145 | "has_downloads": true, 146 | "has_wiki": true, 147 | "has_pages": false, 148 | "forks_count": 0, 149 | "mirror_url": null, 150 | "archived": false, 151 | "open_issues_count": 3, 152 | "license": null, 153 | "forks": 0, 154 | "open_issues": 3, 155 | "watchers": 0, 156 | "default_branch": "master" 157 | }, 158 | "organization": { 159 | "login": "github", 160 | "id": 340, 161 | "node_id": "MDEyOk9yZ2FuaXphdGlvbjM4MzAyODk5", 162 | "url": "https://api.github.com/orgs/github", 163 | "repos_url": "https://api.github.com/orgs/github/repos", 164 | "events_url": "https://api.github.com/orgs/github/events", 165 | "hooks_url": "https://api.github.com/orgs/github/hooks", 166 | "issues_url": "https://api.github.com/orgs/github/issues", 167 | "members_url": "https://api.github.com/orgs/github/members{/member}", 168 | "public_members_url": "https://api.github.com/orgs/github/public_members{/member}", 169 | "avatar_url": "http://alambic.github.com/avatars/u/340?", 170 | "description": "How people build software." 171 | }, 172 | "sender": { 173 | "login": "octocat", 174 | "id": 5346, 175 | "node_id": "MDQ6VXNlcjIxMDMxMDY3", 176 | "avatar_url": "http://alambic.github.com/avatars/u/5346?", 177 | "gravatar_id": "", 178 | "url": "https://api.github.com/users/octocat", 179 | "html_url": "http://github.com/octocat", 180 | "followers_url": "https://api.github.com/users/octocat/followers", 181 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 182 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 183 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 184 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 185 | "organizations_url": "https://api.github.com/users/octocat/orgs", 186 | "repos_url": "https://api.github.com/users/octocat/repos", 187 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 188 | "received_events_url": "https://api.github.com/users/octocat/received_events", 189 | "type": "User", 190 | "site_admin": false 191 | }, 192 | "installation": { 193 | "id": 1 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /spec/payloads/rerequested_check_suite.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "rerequested", 3 | "check_suite": { 4 | "id": 55, 5 | "ref_type": "branch", 6 | "branch": "master", 7 | "sha": "3dca65fa3e8d4b3da3f3d056c59aee1c50f41390", 8 | "status": "completed", 9 | "conclusion": "neutral", 10 | "url": "https://api.github.com/repos/github/hello-world/check-suites/55", 11 | "before": "e6a8776dca057e538c800aaa7ff8fe2a08f35ef6", 12 | "after": "3dca65fa3e8d4b3da3f3d056c59aee1c50f41390", 13 | "pull_requests": [{ 14 | "url": "https://api.github.com/repos/github/hello-world/pulls/1", 15 | "id": 1934, 16 | "head": { 17 | "ref": "say-hello", 18 | "sha": "3dca65fa3e8d4b3da3f3d056c59aee1c50f41390", 19 | "repo": { 20 | "id": 526, 21 | "url": "https://api.github.com/repos/github/hello-world", 22 | "name": "hello-world" 23 | } 24 | }, 25 | "base": { 26 | "ref": "master", 27 | "sha": "e7fdf7640066d71ad16a86fbcbb9c6a10a18af4f", 28 | "repo": { 29 | "id": 526, 30 | "url": "https://api.github.com/repos/github/hello-world", 31 | "name": "hello-world" 32 | } 33 | } 34 | }], 35 | "app": { 36 | "id": 3, 37 | "owner": { 38 | "login": "github", 39 | "id": 340, 40 | "avatar_url": "http://alambic.github.localhost/avatars/u/340?", 41 | "gravatar_id": "", 42 | "url": "https://api.github.com/users/github", 43 | "html_url": "http://github.localhost/github", 44 | "followers_url": "https://api.github.com/users/github/followers", 45 | "following_url": "https://api.github.com/users/github/following{/other_user}", 46 | "gists_url": "https://api.github.com/users/github/gists{/gist_id}", 47 | "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", 48 | "subscriptions_url": "https://api.github.com/users/github/subscriptions", 49 | "organizations_url": "https://api.github.com/users/github/orgs", 50 | "repos_url": "https://api.github.com/users/github/repos", 51 | "events_url": "https://api.github.com/users/github/events{/privacy}", 52 | "received_events_url": "https://api.github.com/users/github/received_events", 53 | "type": "Organization", 54 | "site_admin": false 55 | }, 56 | "name": "Super Duper", 57 | "description": null, 58 | "external_url": "http://super-duper.example.com", 59 | "html_url": "http://github.localhost/apps/super-duper", 60 | "created_at": "2018-04-05 17:13:50 UTC", 61 | "updated_at": "2018-04-05 17:13:50 UTC" 62 | }, 63 | "created_at": "2018-04-06T18:32:21Z", 64 | "updated_at": "2018-04-06T18:32:21Z", 65 | "unique_check_runs_count": 1, 66 | "check_runs_url": "https://api.github.com/repos/github/hello-world/check-suites/55/check-runs", 67 | "head_commit": { 68 | "id": "3dca65fa3e8d4b3da3f3d056c59aee1c50f41390", 69 | "tree_id": "f2eeeb75e48a014b6b379b0f47b612a93f85dd44", 70 | "message": "Say hello (again) to everybody", 71 | "timestamp": "2018-04-06T18:32:05Z", 72 | "author": { 73 | "name": "octocat", 74 | "email": "octocat@github.com" 75 | }, 76 | "committer": { 77 | "name": "octocat", 78 | "email": "octocat@github.com" 79 | } 80 | } 81 | }, 82 | "repository": { 83 | "id": 526, 84 | "name": "hello-world", 85 | "full_name": "github/hello-world", 86 | "owner": { 87 | "login": "github", 88 | "id": 340, 89 | "avatar_url": "http://alambic.github.localhost/avatars/u/340?", 90 | "gravatar_id": "", 91 | "url": "https://api.github.com/users/github", 92 | "html_url": "http://github.localhost/github", 93 | "followers_url": "https://api.github.com/users/github/followers", 94 | "following_url": "https://api.github.com/users/github/following{/other_user}", 95 | "gists_url": "https://api.github.com/users/github/gists{/gist_id}", 96 | "starred_url": "https://api.github.com/users/github/starred{/owner}{/repo}", 97 | "subscriptions_url": "https://api.github.com/users/github/subscriptions", 98 | "organizations_url": "https://api.github.com/users/github/orgs", 99 | "repos_url": "https://api.github.com/users/github/repos", 100 | "events_url": "https://api.github.com/users/github/events{/privacy}", 101 | "received_events_url": "https://api.github.com/users/github/received_events", 102 | "type": "Organization", 103 | "site_admin": false 104 | }, 105 | "private": false, 106 | "html_url": "http://github.localhost/github/hello-world", 107 | "description": null, 108 | "fork": false, 109 | "url": "https://api.github.com/repos/github/hello-world", 110 | "forks_url": "https://api.github.com/repos/github/hello-world/forks", 111 | "keys_url": "https://api.github.com/repos/github/hello-world/keys{/key_id}", 112 | "collaborators_url": "https://api.github.com/repos/github/hello-world/collaborators{/collaborator}", 113 | "teams_url": "https://api.github.com/repos/github/hello-world/teams", 114 | "hooks_url": "https://api.github.com/repos/github/hello-world/hooks", 115 | "issue_events_url": "https://api.github.com/repos/github/hello-world/issues/events{/number}", 116 | "events_url": "https://api.github.com/repos/github/hello-world/events", 117 | "assignees_url": "https://api.github.com/repos/github/hello-world/assignees{/user}", 118 | "branches_url": "https://api.github.com/repos/github/hello-world/branches{/branch}", 119 | "tags_url": "https://api.github.com/repos/github/hello-world/tags", 120 | "blobs_url": "https://api.github.com/repos/github/hello-world/git/blobs{/sha}", 121 | "git_tags_url": "https://api.github.com/repos/github/hello-world/git/tags{/sha}", 122 | "git_refs_url": "https://api.github.com/repos/github/hello-world/git/refs{/sha}", 123 | "trees_url": "https://api.github.com/repos/github/hello-world/git/trees{/sha}", 124 | "statuses_url": "https://api.github.com/repos/github/hello-world/statuses/{sha}", 125 | "languages_url": "https://api.github.com/repos/github/hello-world/languages", 126 | "stargazers_url": "https://api.github.com/repos/github/hello-world/stargazers", 127 | "contributors_url": "https://api.github.com/repos/github/hello-world/contributors", 128 | "subscribers_url": "https://api.github.com/repos/github/hello-world/subscribers", 129 | "subscription_url": "https://api.github.com/repos/github/hello-world/subscription", 130 | "commits_url": "https://api.github.com/repos/github/hello-world/commits{/sha}", 131 | "git_commits_url": "https://api.github.com/repos/github/hello-world/git/commits{/sha}", 132 | "comments_url": "https://api.github.com/repos/github/hello-world/comments{/number}", 133 | "issue_comment_url": "https://api.github.com/repos/github/hello-world/issues/comments{/number}", 134 | "contents_url": "https://api.github.com/repos/github/hello-world/contents/{+path}", 135 | "compare_url": "https://api.github.com/repos/github/hello-world/compare/{base}...{head}", 136 | "merges_url": "https://api.github.com/repos/github/hello-world/merges", 137 | "archive_url": "https://api.github.com/repos/github/hello-world/{archive_format}{/ref}", 138 | "downloads_url": "https://api.github.com/repos/github/hello-world/downloads", 139 | "issues_url": "https://api.github.com/repos/github/hello-world/issues{/number}", 140 | "pulls_url": "https://api.github.com/repos/github/hello-world/pulls{/number}", 141 | "milestones_url": "https://api.github.com/repos/github/hello-world/milestones{/number}", 142 | "notifications_url": "https://api.github.com/repos/github/hello-world/notifications{?since,all,participating}", 143 | "labels_url": "https://api.github.com/repos/github/hello-world/labels{/name}", 144 | "releases_url": "https://api.github.com/repos/github/hello-world/releases{/id}", 145 | "deployments_url": "https://api.github.com/repos/github/hello-world/deployments", 146 | "created_at": "2018-04-05T17:13:50Z", 147 | "updated_at": "2018-04-06T17:57:34Z", 148 | "pushed_at": "2018-04-06T18:32:09Z", 149 | "git_url": "git://github.localhost/github/hello-world.git", 150 | "ssh_url": "ssh://git@localhost:3035/github/hello-world.git", 151 | "clone_url": "http://github.localhost/github/hello-world.git", 152 | "svn_url": "http://github.localhost/github/hello-world", 153 | "homepage": null, 154 | "size": 0, 155 | "stargazers_count": 0, 156 | "watchers_count": 0, 157 | "language": null, 158 | "has_issues": true, 159 | "has_projects": true, 160 | "has_downloads": true, 161 | "has_wiki": true, 162 | "has_pages": false, 163 | "forks_count": 0, 164 | "mirror_url": null, 165 | "archived": false, 166 | "open_issues_count": 1, 167 | "license": null, 168 | "forks": 0, 169 | "open_issues": 1, 170 | "watchers": 0, 171 | "default_branch": "master" 172 | }, 173 | "organization": { 174 | "login": "github", 175 | "id": 340, 176 | "url": "https://api.github.com/orgs/github", 177 | "repos_url": "https://api.github.com/orgs/github/repos", 178 | "events_url": "https://api.github.com/orgs/github/events", 179 | "hooks_url": "https://api.github.com/orgs/github/hooks", 180 | "issues_url": "https://api.github.com/orgs/github/issues", 181 | "members_url": "https://api.github.com/orgs/github/members{/member}", 182 | "public_members_url": "https://api.github.com/orgs/github/public_members{/member}", 183 | "avatar_url": "http://alambic.github.localhost/avatars/u/340?", 184 | "description": "How people build software." 185 | }, 186 | "sender": { 187 | "login": "octocat", 188 | "id": 5347, 189 | "avatar_url": "http://alambic.github.localhost/avatars/u/5347?", 190 | "gravatar_id": "", 191 | "url": "https://api.github.com/users/octocat", 192 | "html_url": "http://github.localhost/octocat", 193 | "followers_url": "https://api.github.com/users/octocat/followers", 194 | "following_url": "https://api.github.com/users/octocat/following{/other_user}", 195 | "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", 196 | "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", 197 | "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", 198 | "organizations_url": "https://api.github.com/users/octocat/orgs", 199 | "repos_url": "https://api.github.com/users/octocat/repos", 200 | "events_url": "https://api.github.com/users/octocat/events{/privacy}", 201 | "received_events_url": "https://api.github.com/users/octocat/received_events", 202 | "type": "User", 203 | "site_admin": false 204 | }, 205 | "installation": { 206 | "id": 2 207 | } 208 | } -------------------------------------------------------------------------------- /spec/payloads/rerequested_check_run.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "rerequested", 3 | "check_run": { 4 | "id": 164649, 5 | "sha": "868ffc0979839e69a50f3fded9955bfd66d6edb4", 6 | "head_sha": "868ffc0979839e69a50f3fded9955bfd66d6edb4", 7 | "external_id": "186584", 8 | "url": "https://api.github.com/repos/travis-ci/check-api-test/check-runs/164649", 9 | "html_url": "https://github.com/travis-ci/check-api-test/runs/164649", 10 | "status": "completed", 11 | "conclusion": "success", 12 | "started_at": "2018-04-30T20:30:38Z", 13 | "completed_at": "2018-04-30T20:31:14Z", 14 | "output": { 15 | "title": "Build Passed", 16 | "summary": " The build **passed**, just like the previous build.", 17 | "text": "This is a [pull request build](https://docs.travis-ci.com/user/pull-requests/).\n\nIt is running a build against the merge commit, after merging [#36 Update .travis.yml](https://github.com/travis-ci/check-api-test/pull/36).\nAny changes that have been made to the master branch before the build ran are also included.\n\n## Jobs and Stages\nThis build only has a single job.\nYou can use jobs to [test against multiple versions](https://docs.travis-ci.com/user/customizing-the-build/#Build-Matrix) of your runtime or dependencies, or to [speed up your build](https://docs.travis-ci.com/user/speeding-up-the-build/).\n\n## Build Configuration\n\nBuild Option | Setting\n-----------------|--------------\nLanguage | Ruby\nOperating System | Linux (Trusty)\nSudo Access | not required\n\n\nTests are run via the following build script:\n\n
\nskip\n
\n\n
\nBuild Configuration\n
\n{\n  \"language\": \"ruby\",\n  \"os\": [\n    \"linux\"\n  ],\n  \"dist\": \"trusty\",\n  \"sudo\": false,\n  \"install\": [\n    \"skip\"\n  ],\n  \"script\": [\n    \"skip\"\n  ],\n  \".result\": \"configured\",\n  \"group\": \"stable\"\n}\n
\n
", 18 | "annotations_count": 0, 19 | "annotations_url": "https://api.github.com/repos/travis-ci/check-api-test/check-runs/164649/annotations" 20 | }, 21 | "name": "Travis CI - Pull Request", 22 | "check_suite": { 23 | "id": 42296, 24 | "branch": "BanzaiMan-patch-1", 25 | "head_branch": "BanzaiMan-patch-1", 26 | "sha": "868ffc0979839e69a50f3fded9955bfd66d6edb4", 27 | "head_sha": "868ffc0979839e69a50f3fded9955bfd66d6edb4", 28 | "status": "queued", 29 | "conclusion": null, 30 | "url": "https://api.github.com/repos/travis-ci/check-api-test/check-suites/42296", 31 | "before": "0000000000000000000000000000000000000000", 32 | "after": "868ffc0979839e69a50f3fded9955bfd66d6edb4", 33 | "pull_requests": [ 34 | 35 | ], 36 | "app": { 37 | "id": 10131, 38 | "owner": { 39 | "login": "travis-ci", 40 | "id": 639823, 41 | "avatar_url": "https://avatars2.githubusercontent.com/u/639823?v=4", 42 | "gravatar_id": "", 43 | "url": "https://api.github.com/users/travis-ci", 44 | "html_url": "https://github.com/travis-ci", 45 | "followers_url": "https://api.github.com/users/travis-ci/followers", 46 | "following_url": "https://api.github.com/users/travis-ci/following{/other_user}", 47 | "gists_url": "https://api.github.com/users/travis-ci/gists{/gist_id}", 48 | "starred_url": "https://api.github.com/users/travis-ci/starred{/owner}{/repo}", 49 | "subscriptions_url": "https://api.github.com/users/travis-ci/subscriptions", 50 | "organizations_url": "https://api.github.com/users/travis-ci/orgs", 51 | "repos_url": "https://api.github.com/users/travis-ci/repos", 52 | "events_url": "https://api.github.com/users/travis-ci/events{/privacy}", 53 | "received_events_url": "https://api.github.com/users/travis-ci/received_events", 54 | "type": "Organization", 55 | "site_admin": false 56 | }, 57 | "name": "Travis CI / Staging", 58 | "description": "Test and deploy with confidence. Trusted by over 800,000 users, Travis CI is the leading hosted continuous integration system.\r\n\r\nSupporting over 20 different languages, including Ruby, Mac/iOS, and Docker, Travis CI is built for everyone.\r\n\r\nFree for open source, and with a 100 build trial for private projects, getting setup takes just 2 minutes.", 59 | "external_url": "https://staging.travis-ci.com", 60 | "html_url": "https://github.com/apps/travis-ci-staging", 61 | "created_at": 1521256098, 62 | "updated_at": 1524515279 63 | }, 64 | "created_at": "2018-04-30T20:29:34Z", 65 | "updated_at": "2018-05-01T18:52:56Z" 66 | }, 67 | "app": { 68 | "id": 10131, 69 | "owner": { 70 | "login": "travis-ci", 71 | "id": 639823, 72 | "avatar_url": "https://avatars2.githubusercontent.com/u/639823?v=4", 73 | "gravatar_id": "", 74 | "url": "https://api.github.com/users/travis-ci", 75 | "html_url": "https://github.com/travis-ci", 76 | "followers_url": "https://api.github.com/users/travis-ci/followers", 77 | "following_url": "https://api.github.com/users/travis-ci/following{/other_user}", 78 | "gists_url": "https://api.github.com/users/travis-ci/gists{/gist_id}", 79 | "starred_url": "https://api.github.com/users/travis-ci/starred{/owner}{/repo}", 80 | "subscriptions_url": "https://api.github.com/users/travis-ci/subscriptions", 81 | "organizations_url": "https://api.github.com/users/travis-ci/orgs", 82 | "repos_url": "https://api.github.com/users/travis-ci/repos", 83 | "events_url": "https://api.github.com/users/travis-ci/events{/privacy}", 84 | "received_events_url": "https://api.github.com/users/travis-ci/received_events", 85 | "type": "Organization", 86 | "site_admin": false 87 | }, 88 | "name": "Travis CI / Staging", 89 | "description": "Test and deploy with confidence. Trusted by over 800,000 users, Travis CI is the leading hosted continuous integration system.\r\n\r\nSupporting over 20 different languages, including Ruby, Mac/iOS, and Docker, Travis CI is built for everyone.\r\n\r\nFree for open source, and with a 100 build trial for private projects, getting setup takes just 2 minutes.", 90 | "external_url": "https://staging.travis-ci.com", 91 | "html_url": "https://github.com/apps/travis-ci-staging", 92 | "created_at": 1521256098, 93 | "updated_at": 1524515279 94 | }, 95 | "pull_requests": [ 96 | 97 | ] 98 | }, 99 | "repository": { 100 | "id": 129795855, 101 | "name": "check-api-test", 102 | "full_name": "travis-ci/check-api-test", 103 | "owner": { 104 | "login": "travis-ci", 105 | "id": 639823, 106 | "avatar_url": "https://avatars2.githubusercontent.com/u/639823?v=4", 107 | "gravatar_id": "", 108 | "url": "https://api.github.com/users/travis-ci", 109 | "html_url": "https://github.com/travis-ci", 110 | "followers_url": "https://api.github.com/users/travis-ci/followers", 111 | "following_url": "https://api.github.com/users/travis-ci/following{/other_user}", 112 | "gists_url": "https://api.github.com/users/travis-ci/gists{/gist_id}", 113 | "starred_url": "https://api.github.com/users/travis-ci/starred{/owner}{/repo}", 114 | "subscriptions_url": "https://api.github.com/users/travis-ci/subscriptions", 115 | "organizations_url": "https://api.github.com/users/travis-ci/orgs", 116 | "repos_url": "https://api.github.com/users/travis-ci/repos", 117 | "events_url": "https://api.github.com/users/travis-ci/events{/privacy}", 118 | "received_events_url": "https://api.github.com/users/travis-ci/received_events", 119 | "type": "Organization", 120 | "site_admin": false 121 | }, 122 | "private": true, 123 | "html_url": "https://github.com/travis-ci/check-api-test", 124 | "description": "For testing all aspects of Check* API", 125 | "fork": false, 126 | "url": "https://api.github.com/repos/travis-ci/check-api-test", 127 | "forks_url": "https://api.github.com/repos/travis-ci/check-api-test/forks", 128 | "keys_url": "https://api.github.com/repos/travis-ci/check-api-test/keys{/key_id}", 129 | "collaborators_url": "https://api.github.com/repos/travis-ci/check-api-test/collaborators{/collaborator}", 130 | "teams_url": "https://api.github.com/repos/travis-ci/check-api-test/teams", 131 | "hooks_url": "https://api.github.com/repos/travis-ci/check-api-test/hooks", 132 | "issue_events_url": "https://api.github.com/repos/travis-ci/check-api-test/issues/events{/number}", 133 | "events_url": "https://api.github.com/repos/travis-ci/check-api-test/events", 134 | "assignees_url": "https://api.github.com/repos/travis-ci/check-api-test/assignees{/user}", 135 | "branches_url": "https://api.github.com/repos/travis-ci/check-api-test/branches{/branch}", 136 | "tags_url": "https://api.github.com/repos/travis-ci/check-api-test/tags", 137 | "blobs_url": "https://api.github.com/repos/travis-ci/check-api-test/git/blobs{/sha}", 138 | "git_tags_url": "https://api.github.com/repos/travis-ci/check-api-test/git/tags{/sha}", 139 | "git_refs_url": "https://api.github.com/repos/travis-ci/check-api-test/git/refs{/sha}", 140 | "trees_url": "https://api.github.com/repos/travis-ci/check-api-test/git/trees{/sha}", 141 | "statuses_url": "https://api.github.com/repos/travis-ci/check-api-test/statuses/{sha}", 142 | "languages_url": "https://api.github.com/repos/travis-ci/check-api-test/languages", 143 | "stargazers_url": "https://api.github.com/repos/travis-ci/check-api-test/stargazers", 144 | "contributors_url": "https://api.github.com/repos/travis-ci/check-api-test/contributors", 145 | "subscribers_url": "https://api.github.com/repos/travis-ci/check-api-test/subscribers", 146 | "subscription_url": "https://api.github.com/repos/travis-ci/check-api-test/subscription", 147 | "commits_url": "https://api.github.com/repos/travis-ci/check-api-test/commits{/sha}", 148 | "git_commits_url": "https://api.github.com/repos/travis-ci/check-api-test/git/commits{/sha}", 149 | "comments_url": "https://api.github.com/repos/travis-ci/check-api-test/comments{/number}", 150 | "issue_comment_url": "https://api.github.com/repos/travis-ci/check-api-test/issues/comments{/number}", 151 | "contents_url": "https://api.github.com/repos/travis-ci/check-api-test/contents/{+path}", 152 | "compare_url": "https://api.github.com/repos/travis-ci/check-api-test/compare/{base}...{head}", 153 | "merges_url": "https://api.github.com/repos/travis-ci/check-api-test/merges", 154 | "archive_url": "https://api.github.com/repos/travis-ci/check-api-test/{archive_format}{/ref}", 155 | "downloads_url": "https://api.github.com/repos/travis-ci/check-api-test/downloads", 156 | "issues_url": "https://api.github.com/repos/travis-ci/check-api-test/issues{/number}", 157 | "pulls_url": "https://api.github.com/repos/travis-ci/check-api-test/pulls{/number}", 158 | "milestones_url": "https://api.github.com/repos/travis-ci/check-api-test/milestones{/number}", 159 | "notifications_url": "https://api.github.com/repos/travis-ci/check-api-test/notifications{?since,all,participating}", 160 | "labels_url": "https://api.github.com/repos/travis-ci/check-api-test/labels{/name}", 161 | "releases_url": "https://api.github.com/repos/travis-ci/check-api-test/releases{/id}", 162 | "deployments_url": "https://api.github.com/repos/travis-ci/check-api-test/deployments", 163 | "created_at": "2018-04-16T19:36:48Z", 164 | "updated_at": "2018-04-30T20:29:02Z", 165 | "pushed_at": "2018-04-30T20:58:18Z", 166 | "git_url": "git://github.com/travis-ci/check-api-test.git", 167 | "ssh_url": "git@github.com:travis-ci/check-api-test.git", 168 | "clone_url": "https://github.com/travis-ci/check-api-test.git", 169 | "svn_url": "https://github.com/travis-ci/check-api-test", 170 | "homepage": null, 171 | "size": 14, 172 | "stargazers_count": 0, 173 | "watchers_count": 0, 174 | "language": null, 175 | "has_issues": true, 176 | "has_projects": true, 177 | "has_downloads": true, 178 | "has_wiki": true, 179 | "has_pages": false, 180 | "forks_count": 0, 181 | "mirror_url": null, 182 | "archived": false, 183 | "open_issues_count": 0, 184 | "license": { 185 | "key": "mit", 186 | "name": "MIT License", 187 | "spdx_id": "MIT", 188 | "url": "https://api.github.com/licenses/mit" 189 | }, 190 | "forks": 0, 191 | "open_issues": 0, 192 | "watchers": 0, 193 | "default_branch": "master" 194 | }, 195 | "organization": { 196 | "login": "travis-ci", 197 | "id": 639823, 198 | "url": "https://api.github.com/orgs/travis-ci", 199 | "repos_url": "https://api.github.com/orgs/travis-ci/repos", 200 | "events_url": "https://api.github.com/orgs/travis-ci/events", 201 | "hooks_url": "https://api.github.com/orgs/travis-ci/hooks", 202 | "issues_url": "https://api.github.com/orgs/travis-ci/issues", 203 | "members_url": "https://api.github.com/orgs/travis-ci/members{/member}", 204 | "public_members_url": "https://api.github.com/orgs/travis-ci/public_members{/member}", 205 | "avatar_url": "https://avatars2.githubusercontent.com/u/639823?v=4", 206 | "description": null 207 | }, 208 | "sender": { 209 | "login": "kerrizor", 210 | "id": 257689, 211 | "avatar_url": "https://avatars2.githubusercontent.com/u/257689?v=4", 212 | "gravatar_id": "", 213 | "url": "https://api.github.com/users/kerrizor", 214 | "html_url": "https://github.com/kerrizor", 215 | "followers_url": "https://api.github.com/users/kerrizor/followers", 216 | "following_url": "https://api.github.com/users/kerrizor/following{/other_user}", 217 | "gists_url": "https://api.github.com/users/kerrizor/gists{/gist_id}", 218 | "starred_url": "https://api.github.com/users/kerrizor/starred{/owner}{/repo}", 219 | "subscriptions_url": "https://api.github.com/users/kerrizor/subscriptions", 220 | "organizations_url": "https://api.github.com/users/kerrizor/orgs", 221 | "repos_url": "https://api.github.com/users/kerrizor/repos", 222 | "events_url": "https://api.github.com/users/kerrizor/events{/privacy}", 223 | "received_events_url": "https://api.github.com/users/kerrizor/received_events", 224 | "type": "User", 225 | "site_admin": false 226 | }, 227 | "installation": { 228 | "id": 132556 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /spec/payloads/pull_request.json: -------------------------------------------------------------------------------- 1 | { 2 | "action": "opened", 3 | "number": 1, 4 | "pull_request": { 5 | "url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1", 6 | "id": 185877784, 7 | "html_url": "https://github.com/joshk/sportsmaps.co.nz/pull/1", 8 | "diff_url": "https://github.com/joshk/sportsmaps.co.nz/pull/1.diff", 9 | "patch_url": "https://github.com/joshk/sportsmaps.co.nz/pull/1.patch", 10 | "issue_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/1", 11 | "number": 1, 12 | "state": "open", 13 | "locked": false, 14 | "title": "less ###", 15 | "user": { 16 | "login": "joshk", 17 | "id": 8701, 18 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 19 | "gravatar_id": "", 20 | "url": "https://api.github.com/users/joshk", 21 | "html_url": "https://github.com/joshk", 22 | "followers_url": "https://api.github.com/users/joshk/followers", 23 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 24 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 25 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 26 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 27 | "organizations_url": "https://api.github.com/users/joshk/orgs", 28 | "repos_url": "https://api.github.com/users/joshk/repos", 29 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 30 | "received_events_url": "https://api.github.com/users/joshk/received_events", 31 | "type": "User", 32 | "site_admin": false 33 | }, 34 | "body": "", 35 | "created_at": "2018-05-04T01:51:53Z", 36 | "updated_at": "2018-05-04T01:51:53Z", 37 | "closed_at": null, 38 | "merged_at": null, 39 | "merge_commit_sha": null, 40 | "assignee": null, 41 | "assignees": [ 42 | 43 | ], 44 | "requested_reviewers": [ 45 | 46 | ], 47 | "requested_teams": [ 48 | 49 | ], 50 | "labels": [ 51 | 52 | ], 53 | "milestone": null, 54 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1/commits", 55 | "review_comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1/comments", 56 | "review_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/comments{/number}", 57 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/1/comments", 58 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/0dffd35ee23e49a93166095583eb52906245bd71", 59 | "head": { 60 | "label": "joshk:joshk-less-hashes", 61 | "ref": "joshk-less-hashes", 62 | "sha": "0dffd35ee23e49a93166095583eb52906245bd71", 63 | "user": { 64 | "login": "joshk", 65 | "id": 8701, 66 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 67 | "gravatar_id": "", 68 | "url": "https://api.github.com/users/joshk", 69 | "html_url": "https://github.com/joshk", 70 | "followers_url": "https://api.github.com/users/joshk/followers", 71 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 72 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 73 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 74 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 75 | "organizations_url": "https://api.github.com/users/joshk/orgs", 76 | "repos_url": "https://api.github.com/users/joshk/repos", 77 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 78 | "received_events_url": "https://api.github.com/users/joshk/received_events", 79 | "type": "User", 80 | "site_admin": false 81 | }, 82 | "repo": { 83 | "id": 149532, 84 | "name": "sportsmaps.co.nz", 85 | "full_name": "joshk/sportsmaps.co.nz", 86 | "owner": { 87 | "login": "joshk", 88 | "id": 8701, 89 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 90 | "gravatar_id": "", 91 | "url": "https://api.github.com/users/joshk", 92 | "html_url": "https://github.com/joshk", 93 | "followers_url": "https://api.github.com/users/joshk/followers", 94 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 95 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 96 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 97 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 98 | "organizations_url": "https://api.github.com/users/joshk/orgs", 99 | "repos_url": "https://api.github.com/users/joshk/repos", 100 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 101 | "received_events_url": "https://api.github.com/users/joshk/received_events", 102 | "type": "User", 103 | "site_admin": false 104 | }, 105 | "private": true, 106 | "html_url": "https://github.com/joshk/sportsmaps.co.nz", 107 | "description": "SportsMaps central repo", 108 | "fork": false, 109 | "url": "https://api.github.com/repos/joshk/sportsmaps.co.nz", 110 | "forks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/forks", 111 | "keys_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/keys{/key_id}", 112 | "collaborators_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/collaborators{/collaborator}", 113 | "teams_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/teams", 114 | "hooks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/hooks", 115 | "issue_events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/events{/number}", 116 | "events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/events", 117 | "assignees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/assignees{/user}", 118 | "branches_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/branches{/branch}", 119 | "tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/tags", 120 | "blobs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/blobs{/sha}", 121 | "git_tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/tags{/sha}", 122 | "git_refs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/refs{/sha}", 123 | "trees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/trees{/sha}", 124 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/{sha}", 125 | "languages_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/languages", 126 | "stargazers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/stargazers", 127 | "contributors_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contributors", 128 | "subscribers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscribers", 129 | "subscription_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscription", 130 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/commits{/sha}", 131 | "git_commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/commits{/sha}", 132 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/comments{/number}", 133 | "issue_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/comments{/number}", 134 | "contents_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contents/{+path}", 135 | "compare_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/compare/{base}...{head}", 136 | "merges_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/merges", 137 | "archive_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/{archive_format}{/ref}", 138 | "downloads_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/downloads", 139 | "issues_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues{/number}", 140 | "pulls_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls{/number}", 141 | "milestones_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/milestones{/number}", 142 | "notifications_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/notifications{?since,all,participating}", 143 | "labels_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/labels{/name}", 144 | "releases_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/releases{/id}", 145 | "deployments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/deployments", 146 | "created_at": "2009-03-12T20:49:50Z", 147 | "updated_at": "2018-05-04T01:50:00Z", 148 | "pushed_at": "2018-05-04T01:51:51Z", 149 | "git_url": "git://github.com/joshk/sportsmaps.co.nz.git", 150 | "ssh_url": "git@github.com:joshk/sportsmaps.co.nz.git", 151 | "clone_url": "https://github.com/joshk/sportsmaps.co.nz.git", 152 | "svn_url": "https://github.com/joshk/sportsmaps.co.nz", 153 | "homepage": "www.sportsmaps.co.nz", 154 | "size": 6724, 155 | "stargazers_count": 2, 156 | "watchers_count": 2, 157 | "language": "Ruby", 158 | "has_issues": true, 159 | "has_projects": true, 160 | "has_downloads": true, 161 | "has_wiki": true, 162 | "has_pages": false, 163 | "forks_count": 0, 164 | "mirror_url": null, 165 | "archived": false, 166 | "open_issues_count": 1, 167 | "license": null, 168 | "forks": 0, 169 | "open_issues": 1, 170 | "watchers": 2, 171 | "default_branch": "master" 172 | } 173 | }, 174 | "base": { 175 | "label": "joshk:master", 176 | "ref": "master", 177 | "sha": "902ac3c7552760b548e8d1d0f9e4fbfd3a3ea5a5", 178 | "user": { 179 | "login": "joshk", 180 | "id": 8701, 181 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 182 | "gravatar_id": "", 183 | "url": "https://api.github.com/users/joshk", 184 | "html_url": "https://github.com/joshk", 185 | "followers_url": "https://api.github.com/users/joshk/followers", 186 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 187 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 188 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 189 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 190 | "organizations_url": "https://api.github.com/users/joshk/orgs", 191 | "repos_url": "https://api.github.com/users/joshk/repos", 192 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 193 | "received_events_url": "https://api.github.com/users/joshk/received_events", 194 | "type": "User", 195 | "site_admin": false 196 | }, 197 | "repo": { 198 | "id": 149532, 199 | "name": "sportsmaps.co.nz", 200 | "full_name": "joshk/sportsmaps.co.nz", 201 | "owner": { 202 | "login": "joshk", 203 | "id": 8701, 204 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 205 | "gravatar_id": "", 206 | "url": "https://api.github.com/users/joshk", 207 | "html_url": "https://github.com/joshk", 208 | "followers_url": "https://api.github.com/users/joshk/followers", 209 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 210 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 211 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 212 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 213 | "organizations_url": "https://api.github.com/users/joshk/orgs", 214 | "repos_url": "https://api.github.com/users/joshk/repos", 215 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 216 | "received_events_url": "https://api.github.com/users/joshk/received_events", 217 | "type": "User", 218 | "site_admin": false 219 | }, 220 | "private": true, 221 | "html_url": "https://github.com/joshk/sportsmaps.co.nz", 222 | "description": "SportsMaps central repo", 223 | "fork": false, 224 | "url": "https://api.github.com/repos/joshk/sportsmaps.co.nz", 225 | "forks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/forks", 226 | "keys_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/keys{/key_id}", 227 | "collaborators_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/collaborators{/collaborator}", 228 | "teams_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/teams", 229 | "hooks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/hooks", 230 | "issue_events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/events{/number}", 231 | "events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/events", 232 | "assignees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/assignees{/user}", 233 | "branches_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/branches{/branch}", 234 | "tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/tags", 235 | "blobs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/blobs{/sha}", 236 | "git_tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/tags{/sha}", 237 | "git_refs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/refs{/sha}", 238 | "trees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/trees{/sha}", 239 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/{sha}", 240 | "languages_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/languages", 241 | "stargazers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/stargazers", 242 | "contributors_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contributors", 243 | "subscribers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscribers", 244 | "subscription_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscription", 245 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/commits{/sha}", 246 | "git_commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/commits{/sha}", 247 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/comments{/number}", 248 | "issue_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/comments{/number}", 249 | "contents_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contents/{+path}", 250 | "compare_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/compare/{base}...{head}", 251 | "merges_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/merges", 252 | "archive_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/{archive_format}{/ref}", 253 | "downloads_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/downloads", 254 | "issues_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues{/number}", 255 | "pulls_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls{/number}", 256 | "milestones_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/milestones{/number}", 257 | "notifications_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/notifications{?since,all,participating}", 258 | "labels_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/labels{/name}", 259 | "releases_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/releases{/id}", 260 | "deployments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/deployments", 261 | "created_at": "2009-03-12T20:49:50Z", 262 | "updated_at": "2018-05-04T01:50:00Z", 263 | "pushed_at": "2018-05-04T01:51:51Z", 264 | "git_url": "git://github.com/joshk/sportsmaps.co.nz.git", 265 | "ssh_url": "git@github.com:joshk/sportsmaps.co.nz.git", 266 | "clone_url": "https://github.com/joshk/sportsmaps.co.nz.git", 267 | "svn_url": "https://github.com/joshk/sportsmaps.co.nz", 268 | "homepage": "www.sportsmaps.co.nz", 269 | "size": 6724, 270 | "stargazers_count": 2, 271 | "watchers_count": 2, 272 | "language": "Ruby", 273 | "has_issues": true, 274 | "has_projects": true, 275 | "has_downloads": true, 276 | "has_wiki": true, 277 | "has_pages": false, 278 | "forks_count": 0, 279 | "mirror_url": null, 280 | "archived": false, 281 | "open_issues_count": 1, 282 | "license": null, 283 | "forks": 0, 284 | "open_issues": 1, 285 | "watchers": 2, 286 | "default_branch": "master" 287 | } 288 | }, 289 | "_links": { 290 | "self": { 291 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1" 292 | }, 293 | "html": { 294 | "href": "https://github.com/joshk/sportsmaps.co.nz/pull/1" 295 | }, 296 | "issue": { 297 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/1" 298 | }, 299 | "comments": { 300 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/1/comments" 301 | }, 302 | "review_comments": { 303 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1/comments" 304 | }, 305 | "review_comment": { 306 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/comments{/number}" 307 | }, 308 | "commits": { 309 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls/1/commits" 310 | }, 311 | "statuses": { 312 | "href": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/0dffd35ee23e49a93166095583eb52906245bd71" 313 | } 314 | }, 315 | "author_association": "OWNER", 316 | "merged": false, 317 | "mergeable": null, 318 | "rebaseable": null, 319 | "mergeable_state": "unknown", 320 | "merged_by": null, 321 | "comments": 0, 322 | "review_comments": 0, 323 | "maintainer_can_modify": false, 324 | "commits": 1, 325 | "additions": 1, 326 | "deletions": 1, 327 | "changed_files": 1 328 | }, 329 | "repository": { 330 | "id": 149532, 331 | "name": "sportsmaps.co.nz", 332 | "full_name": "joshk/sportsmaps.co.nz", 333 | "owner": { 334 | "login": "joshk", 335 | "id": 8701, 336 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 337 | "gravatar_id": "", 338 | "url": "https://api.github.com/users/joshk", 339 | "html_url": "https://github.com/joshk", 340 | "followers_url": "https://api.github.com/users/joshk/followers", 341 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 342 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 343 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 344 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 345 | "organizations_url": "https://api.github.com/users/joshk/orgs", 346 | "repos_url": "https://api.github.com/users/joshk/repos", 347 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 348 | "received_events_url": "https://api.github.com/users/joshk/received_events", 349 | "type": "User", 350 | "site_admin": false 351 | }, 352 | "private": true, 353 | "html_url": "https://github.com/joshk/sportsmaps.co.nz", 354 | "description": "SportsMaps central repo", 355 | "fork": false, 356 | "url": "https://api.github.com/repos/joshk/sportsmaps.co.nz", 357 | "forks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/forks", 358 | "keys_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/keys{/key_id}", 359 | "collaborators_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/collaborators{/collaborator}", 360 | "teams_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/teams", 361 | "hooks_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/hooks", 362 | "issue_events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/events{/number}", 363 | "events_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/events", 364 | "assignees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/assignees{/user}", 365 | "branches_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/branches{/branch}", 366 | "tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/tags", 367 | "blobs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/blobs{/sha}", 368 | "git_tags_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/tags{/sha}", 369 | "git_refs_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/refs{/sha}", 370 | "trees_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/trees{/sha}", 371 | "statuses_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/statuses/{sha}", 372 | "languages_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/languages", 373 | "stargazers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/stargazers", 374 | "contributors_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contributors", 375 | "subscribers_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscribers", 376 | "subscription_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/subscription", 377 | "commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/commits{/sha}", 378 | "git_commits_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/git/commits{/sha}", 379 | "comments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/comments{/number}", 380 | "issue_comment_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues/comments{/number}", 381 | "contents_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/contents/{+path}", 382 | "compare_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/compare/{base}...{head}", 383 | "merges_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/merges", 384 | "archive_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/{archive_format}{/ref}", 385 | "downloads_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/downloads", 386 | "issues_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/issues{/number}", 387 | "pulls_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/pulls{/number}", 388 | "milestones_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/milestones{/number}", 389 | "notifications_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/notifications{?since,all,participating}", 390 | "labels_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/labels{/name}", 391 | "releases_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/releases{/id}", 392 | "deployments_url": "https://api.github.com/repos/joshk/sportsmaps.co.nz/deployments", 393 | "created_at": "2009-03-12T20:49:50Z", 394 | "updated_at": "2018-05-04T01:50:00Z", 395 | "pushed_at": "2018-05-04T01:51:51Z", 396 | "git_url": "git://github.com/joshk/sportsmaps.co.nz.git", 397 | "ssh_url": "git@github.com:joshk/sportsmaps.co.nz.git", 398 | "clone_url": "https://github.com/joshk/sportsmaps.co.nz.git", 399 | "svn_url": "https://github.com/joshk/sportsmaps.co.nz", 400 | "homepage": "www.sportsmaps.co.nz", 401 | "size": 6724, 402 | "stargazers_count": 2, 403 | "watchers_count": 2, 404 | "language": "Ruby", 405 | "has_issues": true, 406 | "has_projects": true, 407 | "has_downloads": true, 408 | "has_wiki": true, 409 | "has_pages": false, 410 | "forks_count": 0, 411 | "mirror_url": null, 412 | "archived": false, 413 | "open_issues_count": 1, 414 | "license": null, 415 | "forks": 0, 416 | "open_issues": 1, 417 | "watchers": 2, 418 | "default_branch": "master" 419 | }, 420 | "sender": { 421 | "login": "joshk", 422 | "id": 8701, 423 | "avatar_url": "https://avatars2.githubusercontent.com/u/8701?v=4", 424 | "gravatar_id": "", 425 | "url": "https://api.github.com/users/joshk", 426 | "html_url": "https://github.com/joshk", 427 | "followers_url": "https://api.github.com/users/joshk/followers", 428 | "following_url": "https://api.github.com/users/joshk/following{/other_user}", 429 | "gists_url": "https://api.github.com/users/joshk/gists{/gist_id}", 430 | "starred_url": "https://api.github.com/users/joshk/starred{/owner}{/repo}", 431 | "subscriptions_url": "https://api.github.com/users/joshk/subscriptions", 432 | "organizations_url": "https://api.github.com/users/joshk/orgs", 433 | "repos_url": "https://api.github.com/users/joshk/repos", 434 | "events_url": "https://api.github.com/users/joshk/events{/privacy}", 435 | "received_events_url": "https://api.github.com/users/joshk/received_events", 436 | "type": "User", 437 | "site_admin": false 438 | }, 439 | "installation": { 440 | "id": 151888 441 | } 442 | } --------------------------------------------------------------------------------