From 0f1e697abd2df93573b30aa95e3d7d811dc1545c Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 19 Jun 2016 15:04:39 +0200 Subject: [PATCH] delete github/services/sync_user and user_mailer, remove action_mailer --- Gemfile.lock | 1 - lib/travis/api/app/endpoint/authorization.rb | 3 +- spec/spec_helper.rb | 6 +- travis-api.gemspec | 1 - vendor/travis-core/lib/travis.rb | 3 +- vendor/travis-core/lib/travis/github.rb | 6 +- .../travis-core/lib/travis/github/services.rb | 1 - .../lib/travis/github/services/sync_user.rb | 74 -------- .../services/sync_user/organizations.rb | 143 --------------- .../github/services/sync_user/repositories.rb | 140 --------------- .../github/services/sync_user/repository.rb | 140 --------------- .../github/services/sync_user/reset_token.rb | 36 ---- .../github/services/sync_user/user_info.rb | 90 ---------- vendor/travis-core/lib/travis/mailer.rb | 26 --- .../lib/travis/mailer/user_mailer.rb | 18 -- .../views/layouts/contact_email.html.erb | 170 ------------------ .../views/user_mailer/welcome_email.html.erb | 54 ------ 17 files changed, 10 insertions(+), 902 deletions(-) delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user.rb delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user/organizations.rb delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user/repositories.rb delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user/repository.rb delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user/reset_token.rb delete mode 100644 vendor/travis-core/lib/travis/github/services/sync_user/user_info.rb delete mode 100644 vendor/travis-core/lib/travis/mailer.rb delete mode 100644 vendor/travis-core/lib/travis/mailer/user_mailer.rb delete mode 100644 vendor/travis-core/lib/travis/mailer/views/layouts/contact_email.html.erb delete mode 100644 vendor/travis-core/lib/travis/mailer/views/user_mailer/welcome_email.html.erb diff --git a/Gemfile.lock b/Gemfile.lock index abcb6d27..ec0958a1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -69,7 +69,6 @@ PATH remote: . specs: travis-api (0.0.1) - actionmailer (~> 3.2.19) activerecord (~> 3.2.19) coder (~> 0.4.0) composite_primary_keys (~> 5.0) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index 441032c0..bfc4f1e5 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -1,8 +1,9 @@ -require 'travis/api/app' require 'addressable/uri' require 'faraday' require 'securerandom' require 'customerio' +require 'travis/api/app' +require 'travis/github/education' class Travis::Api::App class Endpoint diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b414cfea..748561f5 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -38,6 +38,10 @@ RSpec.configure do |c| DatabaseCleaner.clean_with :truncation DatabaseCleaner.strategy = :transaction + # This sets up a scenario in the db as an initial state. The db will be + # rolled back to this state after each test. Several tests in ./spec depend + # on this scenario, so this gives a performance benefit, but also can be + # confusing. Scenario.default end @@ -45,7 +49,6 @@ RSpec.configure do |c| DatabaseCleaner.start Redis.new.flushall Travis.config.oauth2.scope = "user:email,public_repo" - # set_app Travis::Api::App.new end c.before :each, set_app: true do @@ -53,7 +56,6 @@ RSpec.configure do |c| end c.after :each do - # puts DatabaseCleaner.connections.map(&:strategy).map(&:class).map(&:name).join(', ') DatabaseCleaner.clean custom_endpoints.each do |endpoint| endpoint.superclass.direct_subclasses.delete(endpoint) diff --git a/travis-api.gemspec b/travis-api.gemspec index 6fce569d..e8c75eb2 100644 --- a/travis-api.gemspec +++ b/travis-api.gemspec @@ -25,7 +25,6 @@ Gem::Specification.new do |s| # from travis-core gemspec s.add_dependency 'activerecord', '~> 3.2.19' - s.add_dependency 'actionmailer', '~> 3.2.19' s.add_dependency 'railties', '~> 3.2.19' s.add_dependency 'rollout', '~> 1.1.0' s.add_dependency 'coder', '~> 0.4.0' diff --git a/vendor/travis-core/lib/travis.rb b/vendor/travis-core/lib/travis.rb index af73f92a..fbe09549 100644 --- a/vendor/travis-core/lib/travis.rb +++ b/vendor/travis-core/lib/travis.rb @@ -1,7 +1,7 @@ require 'pusher' require 'travis/support' require 'travis/support/database' -require 'travis_core/version' +require 'travis/version' require 'travis/redis_pool' require 'travis/errors' require 'travis/commit_command' @@ -46,7 +46,6 @@ module Travis require 'travis/config/defaults' require 'travis/features' require 'travis/github' - require 'travis/mailer' require 'travis/notification' require 'travis/services' diff --git a/vendor/travis-core/lib/travis/github.rb b/vendor/travis-core/lib/travis/github.rb index 95b5a0ad..78ea5050 100644 --- a/vendor/travis-core/lib/travis/github.rb +++ b/vendor/travis-core/lib/travis/github.rb @@ -1,16 +1,16 @@ require 'gh' require 'core_ext/hash/compact' +require 'travis/github/education' +require 'travis/github/services' module Travis module Github - require 'travis/github/services' - class << self def setup GH.set( client_id: Travis.config.oauth2.client_id, client_secret: Travis.config.oauth2.client_secret, - user_agent: "Travis-CI/#{TravisCore::VERSION} GH/#{GH::VERSION}", + user_agent: "Travis-CI/#{Travis::VERSION} GH/#{GH::VERSION}", origin: Travis.config.host, api_url: Travis.config.github.api_url, ssl: Travis.config.ssl.to_h.merge(Travis.config.github.ssl || {}).to_h.compact diff --git a/vendor/travis-core/lib/travis/github/services.rb b/vendor/travis-core/lib/travis/github/services.rb index bca56e28..4f2b028a 100644 --- a/vendor/travis-core/lib/travis/github/services.rb +++ b/vendor/travis-core/lib/travis/github/services.rb @@ -5,7 +5,6 @@ module Travis require 'travis/github/services/find_or_create_repo' require 'travis/github/services/find_or_create_user' require 'travis/github/services/set_hook' - require 'travis/github/services/sync_user' class << self def register diff --git a/vendor/travis-core/lib/travis/github/services/sync_user.rb b/vendor/travis-core/lib/travis/github/services/sync_user.rb deleted file mode 100644 index 1c5fda57..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'metriks' -require 'travis/mailer/user_mailer' -require 'travis/services/base' - -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - require 'travis/github/services/sync_user/organizations' - require 'travis/github/services/sync_user/repositories' - require 'travis/github/services/sync_user/repository' - require 'travis/github/services/sync_user/reset_token' - require 'travis/github/services/sync_user/user_info' - - register :github_sync_user - - def run - new_user? do - syncing do - # if Time.now.utc.tuesday? && Travis::Features.feature_active?("reset_token_in_sync") - # ResetToken.new(user).run - # end - UserInfo.new(user).run - Organizations.new(user).run - Repositories.new(user).run - end - end - ensure - user.update_column(:is_syncing, false) - end - - def user - # TODO check that clients are only passing the id - @user ||= current_user || User.find(params[:id]) - end - - def new_user? - new_user = user.synced_at.nil? && user.created_at > 48.hours.ago.utc - - yield if block_given? - - if new_user and Travis.config.welcome_email - send_welcome_email - end - end - - def send_welcome_email - return unless user.email.present? - UserMailer.welcome_email(user).deliver - logger.info("Sent welcome email to #{user.login}") - Metriks.meter('travis.welcome.email').mark - end - - private - - def syncing - unless user.github_oauth_token? - logger.warn "user sync for #{user.login} (id:#{user.id}) was cancelled as the user doesn't have a token" - return - end - user.update_column(:is_syncing, true) - result = yield - user.update_column(:synced_at, Time.now) - result - rescue GH::TokenInvalid => e - logger.warn "user sync for #{user.login} (id:#{user.id}) failed as the token was invalid, dropping the token" - user.update_column(:github_oauth_token, nil) - ensure - user.update_column(:is_syncing, false) - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/github/services/sync_user/organizations.rb b/vendor/travis-core/lib/travis/github/services/sync_user/organizations.rb deleted file mode 100644 index f04caf33..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user/organizations.rb +++ /dev/null @@ -1,143 +0,0 @@ -require 'gh' - -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - class Organizations - class Filter - attr_reader :data, :limit - def initialize(data, options = {}) - @data = data || {} - @limit = options[:repositories_limit] || 1000 - end - - def allow? - repositories_count < limit - end - - def repositories_count - # I was not sure how to handle the case where we don't get the - # sufficient amount of data here and this seems the best answer, - # that way we will not get orgs siltently ignored - data['public_repositories'] || 0 - end - end - - class << self - def cancel_memberships(user, orgs) - user.memberships.where(:organization_id => orgs.map(&:id)).delete_all - end - end - - extend Travis::Instrumentation - include Travis::Logging - - attr_reader :user, :data - - def initialize(user) - @user = user - end - - def run - with_github do - { :synced => create_or_update, :removed => remove } - end - end - instrument :run - - private - - def create_or_update - fetch_and_filter.map do |data| - org = create_or_update_org(data) - user.organizations << org unless user.organizations.include?(org) - org - end - end - - def remove - orgs = user.organizations.reject { |org| github_ids.include?(org.github_id) } - self.class.cancel_memberships(user, orgs) - orgs - end - - def fetch - @data ||= GH['user/orgs'].to_a - end - instrument :fetch, :level => :debug - - def github_ids - @github_ids ||= data.map { |org| org['id'] } - end - - def with_github(&block) - # TODO in_parallel should return the block's result in a future version - result = nil - GH.with(:token => user.github_oauth_token) do - # GH.in_parallel do - result = yield - # end - end - result - end - - def fetch_and_filter - fetch.map do |data| - fetch_resource("organizations/#{data['id']}") - end.find_all do |data| - options = Travis.config.sync.organizations || {} - Filter.new(data, options).allow? - end - end - - def fetch_resource(resource) - GH[resource] # TODO should be: ?type=#{self.class.type} but GitHub doesn't work as documented - rescue GH::Error => e - log_exception(e) - end - - def create_or_update_org(data) - org = Organization.find_or_create_by_github_id(data['id']) - org.update_attributes!({ - :name => data['name'], - :login => data['login'], - :email => data['email'], - :avatar_url => avatar_url(data['_links']['avatar']), - :location => data['location'], - :homepage => data['_links']['blog'].try(:fetch, 'href'), - :company => data['company'] - }) - org - end - - def avatar_url(github_data) - href = github_data.try(:fetch, 'href') - href ? href[/^(https:\/\/[\w\.\/]*)/, 1] : nil - end - - class Instrument < Notification::Instrument - def run_completed - format = lambda do |orgs| - orgs.map { |org| { id: org.id, login: org.login } } - end - - publish( - msg: %(for #), - result: { synced: format.call(result[:synced]), removed: format.call(result[:removed]) } - ) - end - - def fetch_completed - publish( - msg: %(for #), - result: result - ) - end - end - Instrument.attach_to(self) - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/github/services/sync_user/repositories.rb b/vendor/travis-core/lib/travis/github/services/sync_user/repositories.rb deleted file mode 100644 index 294f670e..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user/repositories.rb +++ /dev/null @@ -1,140 +0,0 @@ -require 'active_support/core_ext/class/attribute' - -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - # Fetches all repositories from Github which are in /user/repos or any of the user's - # orgs/[name]/repos. Creates or updates existing repositories on our side and adds - # it to the user's permissions. Also removes existing permissions for repositories - # which are not in the received Github data. NOTE that this does *not* delete any - # repositories because we do not know if the repository was deleted or renamed - # on Github's side. - class Repositories - extend Travis::Instrumentation - include Travis::Logging - - class_attribute :types - self.types = [:public] - - class << self - # TODO backwards compat, remove once all apps use `types=` - def type=(types) - self.types = Array.wrap(types).map(&:to_s).join(',').split(',').map(&:to_sym) - end - - def include?(type) - self.types.include?(type) - end - end - - attr_reader :user, :resources, :data - - def initialize(user) - @user = user - @resources = ['user/repos'] + user.organizations.map { |org| "orgs/#{org.login}/repos" } - end - - def run - with_github do - { :synced => create_or_update, :removed => remove } - end - end - instrument :run - - private - - def create_or_update - data.map do |repository| - Repository.new(user, repository).run - end - end - - def remove - repos = user.repositories.reject { |repo| slugs.include?(repo.slug) } - Repository.unpermit_all(user, repos) - repos - end - - # we have to filter these ourselves because the github api is broken for this - def data - @data ||= filter_duplicates(filter_based_on_repo_permission) - end - - def filter_based_on_repo_permission - fetch.select { |repo| self.class.include?(repo['private'] ? :private : :public) } - end - - def filter_duplicates(repositories) - repositories.each_with_object([]) do |repository, filtered_list| - unless in_filtered_list?(filtered_list, repository) - filtered_list.push(repository) - end - end - end - - def in_filtered_list?(filtered_list, other_repository) - filtered_list.any? do |existing_repository| - same_repository_with_admin?(existing_repository, other_repository) - end - end - - def same_repository_with_admin?(existing_repository, other_repository) - existing_repository['owner']['login'] == other_repository['owner']['login'] and - existing_repository['name'] == other_repository['name'] and - existing_repository['permissions']['admin'] == true - end - - def slugs - @slugs ||= data.map { |repo| "#{repo['owner']['login']}/#{repo['name']}" } - end - - def fetch - resources.map { |resource| fetch_resource(resource) }.map(&:to_a).flatten.compact - end - instrument :fetch, :level => :debug - - def fetch_resource(resource) - GH[resource] # TODO should be: ?type=#{self.class.type} but GitHub doesn't work as documented - rescue GH::Error => e - log_exception(e) - end - - def with_github(&block) - # TODO in_parallel should return the block's result in a future version - result = nil - GH.with(:token => user.github_oauth_token) do - # GH.in_parallel do - result = yield - # end - end - result - end - - class Instrument < Notification::Instrument - def run_completed - format = lambda do |repos| - repos.map { |repo| { id: repo.id, owner: repo.owner_name, name: repo.name } } - end - - publish( - msg: %(for #), - resources: target.resources, - result: { synced: format.call(result[:synced]), removed: format.call(result[:removed]) } - ) - end - - def fetch_completed - publish( - msg: %(for #), - resources: target.resources, - result: result - ) - end - end - Instrument.attach_to(self) - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/github/services/sync_user/repository.rb b/vendor/travis-core/lib/travis/github/services/sync_user/repository.rb deleted file mode 100644 index 1636d0f5..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user/repository.rb +++ /dev/null @@ -1,140 +0,0 @@ -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - class Repository - class << self - def unpermit_all(user, repositories) - user.permissions.where(:repository_id => repositories.map(&:id)).delete_all unless repositories.empty? - end - end - - attr_reader :user, :data, :repo - - def initialize(user, data) - @user = user - @data = data - end - - def run - @repo = find || create - update - if permission - sync_permissions - elsif permit? - permit - end - repo - end - - private - - def find - ::Repository.where(:github_id => github_id).first - end - - def create - if Travis::Features.enabled_for_all?(:sync_repo_owner) - ::Repository.create!(:owner => owner, :owner_name => owner_name, :name => name, github_id: github_id) - else - ::Repository.create!(:owner_name => owner_name, :name => name, github_id: github_id) - end - end - # instrument :create, :level => :debug - - def permission - @permission ||= user.permissions.where(:repository_id => repo.id).first - end - - def sync_permissions - if permit? - permission.update_attributes!(permission_data) - else - permission.destroy - end - end - - def permit? - push_access? || admin_access? || repo.private? - end - - def permit - user.permissions.create!({ - :user => user, - :repository => repo - }.merge(permission_data)) - end - # instrument :permit, :level => :debug - - def update - if Travis::Features.enabled_for_all?(:sync_repo_owner) - repo.update_attributes!({ - owner: owner, - github_id: data['id'], - private: data['private'], - description: data['description'], - url: data['homepage'], - default_branch: data['default_branch'], - github_language: data['language'], - name: name, - owner_name: owner_name - }) - else - repo.update_attributes!({ - github_id: data['id'], - private: data['private'], - description: data['description'], - url: data['homepage'], - default_branch: data['default_branch'], - github_language: data['language'], - name: name, - owner_name: owner_name - }) - end - rescue ActiveRecord::RecordInvalid - # ignore for now. this seems to happen when multiple syncs (i.e. user sign - # in requests are running in parallel? - rescue GH::Error(response_status: 404) => e - Travis.logger.warn "[github][services][user_sync] GitHub info was not available for #{repo.owner_name}/#{repo.name}: #{e.inspect}" - end - - def owner - @owner ||= owner_type.constantize.find_by_github_id(owner_id) - end - - def owner_id - data['owner']['id'] - end - - def owner_type - data['owner']['type'] - end - - def owner_name - data['owner']['login'] - end - - def name - data['name'] - end - - def github_id - data['id'] - end - - def permission_data - data['permissions'] - end - - def push_access? - permission_data['push'] - end - - def admin_access? - permission_data['admin'] - end - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/github/services/sync_user/reset_token.rb b/vendor/travis-core/lib/travis/github/services/sync_user/reset_token.rb deleted file mode 100644 index cc09ae26..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user/reset_token.rb +++ /dev/null @@ -1,36 +0,0 @@ -require "gh" - -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - class ResetToken - def initialize(user, config = Travis.config.oauth2.to_h, gh = nil) - @user = user - @config = config - @gh = gh || GH.with(username: @config.client_id, password: @config.client_secret) - end - - def run - token = new_token - @user.update_attributes!(github_oauth_token: token) if token - end - - private - - def new_token - @new_token ||= @gh.post("/applications/#{client_id}/tokens/#{@user.github_oauth_token}", {})["token"] - end - - def client_id - @config.client_id - end - - def client_secret - @config.client_secret - end - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/github/services/sync_user/user_info.rb b/vendor/travis-core/lib/travis/github/services/sync_user/user_info.rb deleted file mode 100644 index c3be5399..00000000 --- a/vendor/travis-core/lib/travis/github/services/sync_user/user_info.rb +++ /dev/null @@ -1,90 +0,0 @@ -require 'gh' -require 'travis/github/education' - -module Travis - module Github - module Services - class SyncUser < Travis::Services::Base - class UserInfo - attr_reader :user, :gh - - def initialize(user, gh = Github.authenticated(user)) - @user, @gh = user, gh - end - - def run - if user.github_id != user_info['id'].to_i - raise "Updating # failed, github_id differs. github_id on user: #{user.github_id}, github_id from data: #{user_info['id']}" - end - if user.login != login - Travis.logger.info("Changing # login: current=\"#{user.login}\", new=\"#{login}\" (UserInfo), data: #{user_info.inspect}") - end - if user.email != email - Travis.logger.info("Changing # email: current=\"#{user.email}\", new=\"#{email}\" (UserInfo)") - end - - user.update_attributes!(name: name, login: login, gravatar_id: gravatar_id, email: email, education: education) - emails = verified_emails - emails << email unless emails.include? email - emails.each { |e| user.emails.find_or_create_by_email!(e) } - end - - def education - if Travis::Features.feature_active?(:education_data_sync) || Travis::Features.owner_active?(:education_data_sync, user) - Education.new(user.github_oauth_token).student? - end - end - - def name - user_info['name'] - end - - def login - user_info.fetch('login') - end - - def gravatar_id - user_info['gravatar_id'] - end - - def email - user_info['email'].presence || primary_email || verified_email || user.email.presence || first_email - end - - def verified_emails - emails.select { |e| e["verified"] }.map { |e| e['email'] } - end - - private - - def emails - return [] unless user.github_scopes.include? 'user' or user.github_scopes.include? 'user:email' - @emails ||= gh['user/emails'].to_a - end - - def first_email - emails.first.try(:[], 'email') - end - - def primary_email - emails.detect { |e| e["primary"] }.try(:[], 'email') - end - - def verified_email - verified_emails.first - end - - def user_info - @user_info ||= begin - data = gh['user'].to_hash - if user.login != data['login'] - Travis.logger.info("Fetching data for github_id=#{user.github_id} (UserInfo), data: #{data.inspect}") - end - data - end - end - end - end - end - end -end diff --git a/vendor/travis-core/lib/travis/mailer.rb b/vendor/travis-core/lib/travis/mailer.rb deleted file mode 100644 index 8a19cf01..00000000 --- a/vendor/travis-core/lib/travis/mailer.rb +++ /dev/null @@ -1,26 +0,0 @@ -require 'action_mailer' -require 'i18n' - -module Travis - module Mailer - class << self - def config - config = Travis.config.smtp - config ? config.to_h : {} - end - - def setup - if config.present? - mailer = ActionMailer::Base - mailer[:delivery_method] = :smtp - mailer[:smtp_settings] = config - @setup = true - end - end - - def setup? - !!@setup - end - end - end -end diff --git a/vendor/travis-core/lib/travis/mailer/user_mailer.rb b/vendor/travis-core/lib/travis/mailer/user_mailer.rb deleted file mode 100644 index 3a352648..00000000 --- a/vendor/travis-core/lib/travis/mailer/user_mailer.rb +++ /dev/null @@ -1,18 +0,0 @@ -require 'action_mailer' - -class UserMailer < ActionMailer::Base - ActionMailer::Base.append_view_path("#{File.dirname(__FILE__)}/views") - - layout 'contact_email' - - def welcome_email(user) - @user = user - mail(subject: "Welcome to Travis CI!", from: from, to: user.email) do |format| - format.html - end - end - - def from - Travis.config.email.from - end -end diff --git a/vendor/travis-core/lib/travis/mailer/views/layouts/contact_email.html.erb b/vendor/travis-core/lib/travis/mailer/views/layouts/contact_email.html.erb deleted file mode 100644 index ceef3ba3..00000000 --- a/vendor/travis-core/lib/travis/mailer/views/layouts/contact_email.html.erb +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - -
- - -
- -
- <%= yield %> -
- - - - diff --git a/vendor/travis-core/lib/travis/mailer/views/user_mailer/welcome_email.html.erb b/vendor/travis-core/lib/travis/mailer/views/user_mailer/welcome_email.html.erb deleted file mode 100644 index 3f210a32..00000000 --- a/vendor/travis-core/lib/travis/mailer/views/user_mailer/welcome_email.html.erb +++ /dev/null @@ -1,54 +0,0 @@ -
-

Welcome to Travis CI!

- -

- Hey <%= @user.name.blank? ? @user.login : @user.name %>, -

- -

- We'd like to extend a warm welcome to you and provide with some links to help you get started. -

- -

- If you haven't set up your first project yet, head to your - accounts page and enable the project you'd like to test on Travis CI. Push some code, and your repository - will appear on <%= Travis.config.host -%>. -

- -

- Are you part of an organization that's already running builds on Travis CI? Great news, we've just finished - synchronizing your permissions from GitHub. You can see the projects you have access to and that have already - been built on Travis CI at <%= Travis.config.host %> so you can - dive in right away. -

- -

- Remember to add a .travis.yml file to your project to tell us what steps we should execute to set up your build - environment and run your build. We have sensible defaults, but you're free to customize everything to your - liking. -

- -

- You can find all details on how to setup specific languages, the - available configuration options for your - builds, and our build environment in our documentation. Don't forget to setup notifications if - you'd like to be kept up-to-date about your builds on Campfire, HipChat, IRC, and others. -

- -

- If you have any questions or issues, shoot us an email. -

- -

- Have an awesome day! -

- -

- Cheers, -

- -

- The Travis CI Team -

-