• Stars
    star
    170
  • Rank 223,357 (Top 5 %)
  • Language
    Ruby
  • License
    MIT License
  • Created over 10 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

parses, normalizes, validates and serializes your .travis.yml

Travis Configuration Parser

What is this?

This project is a library for loading Travis CI build configuration.

It can create a configuration both from a normal Ruby Hash or a YAML string. These config objects generally behave like normal primitives (hashes, arrays, etc).

require 'travis/yaml'

config = Travis::Yaml.parse('language: ruby')
config = Travis::Yaml.parse(language: 'ruby')

config[:language] # ruby
config.language   # ruby

# using parse! instead of parse will print out warnings
Travis::Yaml.parse! deploy: []
# .travis.yml: missing key "language", defaulting to "ruby"
# .travis.yml: value for "deploy" section is empty, dropping

# have it generate the build matrix for you
Travis::Yaml.matrix('rvm: [jruby, 2.0.0]').each do |matrix_entry|
  puts matrix_entry.ruby
end

Why use it?

  • Prevents code execution. Instead of deserializing arbitrary Ruby objects, it only deserializes primitive objects. To go even further, in contrast to SafeYAML, it only deserializes primitive objects that are expected for a certain part of the configuration.
  • Prevents memory leaks. Internally, only expected values are stored in the data structure, discarding any additional data. No user input is converted to symbols (which would allow a memory based DoS attack).
  • Normalization is happening in one place. Travis CI currently does config normalization in many different parts of its infrastructure, making it tedious to determine supported input formats and the resulting internal structure.
  • Explicit structure. Due to the explicit configuration structure, exceptions throughout the system can be greatly reduced, since the configuration will not contain unexpected objects.
  • Forgiving about user input. The parser knows the expected structure and can therefore automatically map some malformed input onto that structure. For instance, node: 1.10 does not get converted to node: 1.1 internally, because travis-yaml knows to expect a string here rather than a float.
  • Built-in support for encrypted values, making it easier to support these in different parts of the system and never leak the decrypted form if configuration is being serialized.
  • Extensive warning and error handling, making it possible to use this library for linting and also to display such warnings when running a build.
  • Performance. Using travis-yaml to load a configuration from a YAML string is slightly faster than using psych directly and significantly faster than using safeyaml.
  • Compatibility. This library is written in a way to not only be fully compatible with the current .travis.yml format, but also with the configuration data in the current Travis database and with the code interacting with the configuration data (for instance in travis-build).
  • Extensibility. The configuration structure is easily extended.
  • Pluggable parser. It is easy to write a new parser. This would be useful for instance for the Travis CI command line client, where one could imagine a parser for the small subset of the YAML format that is commonly in use. This would for instance allow to write a parser and serializer able to preserve comments and indentation when modifying the contents of the .travis.yml.

What is missing?

  • Serialization

External API

Loading a config

config = Travis::Yaml.parse('language: ruby') # parse from a yaml string
config = Travis::Yaml.parse(language: "ruby") # parse from Ruby object

For Psych/YAML compatibility, parse is also aliased to load.

Convenience

Nodes generally behave like normal Ruby objects. Mappings accept both symbols and strings as keys. Known fields on mappings are exposed as methods.

puts config.language
puts config[:language]
puts config['language']

Warnings and errors

  • errors are actual parse errors, parent elements should discard elements with errors.
  • warnings are general warnings for an element, with the element still being usable. These do not include warnings for child elements (though an error in a child element becomes a warning for its immediate parent).
  • nested warnings include warnings for the whole tree, they also come with key prefix (array of strings) to identify the position the error occured at.
Travis::Yaml.parse("foo: bar").nested_warnings.each do |key, warning|
  puts "#{key.join('.')}: #{warning}"
end

# will print nested warnings to stderr, will raise on top level error
Travis::Yaml.parse! "foo: bar"

Secure Variables

Secure variables are stored as Travis::Yaml::SecureString internally. A secure string has at least an encrypted_string or a decrypted_string, or both.

You can use decrypt/encrypt with a block to generate the missing string:

secret = Travis::Yaml::SecureString.new("foo")

secret.encrypted_string # => "foo"
secret.decrypted_string # => nil
secret.encrypted?       # => true
secret.decrypted?       # => false

secret.decrypt { |string| string.upcase }

secret.encrypted_string # => "foo"
secret.decrypted_string # => "FOO"
secret.encrypted?       # => true
secret.decrypted?       # => true

To avoid having to walk the whole structure manually or hardcoding the values to decrypt, these methods are also exposed on any node:

config = Travis::Yaml.load 'env: { secure: foo }'
config.decrypted? # => false

config.decrypt { |string| string.upcase }
config.decrypted?                        # => true
config.env.matrix.first.decrypted_string # => "FOO"

This can even be done right with the parse step:

content = File.read('.travis.yml')
Travis::Yaml.parse! content do |config|
  config.decrypt { |string| string.upcase }
end

Serialization

A travis-yaml document can be serialized to a few other formats via the serialize method:

pp   config.serialize(:ruby)
puts config.serialize(:json, pretty: true)
Serializer Descriptions Options
ruby Corresponding Ruby objects, secure values will be SecureStrings secure, symbol_keys
legacy Format compatible with Travis CI's old fetch_config service secure, symbol_keys
json Serialize as JSON, parsable via Travis::Yaml.load secure, pretty
yaml Serialize as YAML, parsable via Travis::Yaml.load secure, symbol_keys, indentation, line_width, canonical, avoid_tags

The secure option can be set to :decrypted or :encrypted, enforcing the decrypted or encrypted form of secure strings to be serialized. In some serializations, this might lead to secure strings being mapped to normal strings if set to :decrypted.

Defining Structure

Good starting points for getting into the code are the root node and the language node.

A parsed configuration is very similar to a syntax tree. To create a new node type, you should inherit from one of the abstract types. Internal vocabulary is taken from the YAML spec rather than the Ruby names (ie, sequence vs array, mapping vs hash).

Scalar Values

Most of the time, scalar values are just strings. In fact, if you create a new scalar node class and don't specify and other supported type, it will treat everything as string.

module Travis::Yaml::Nodes
  class Example < Scalar
  end
end

This will parse foo to "foo" and 1.10 to 1.10. This will also generate a warning and discard values like !float 1.10.

Value Types

You can also allow other types and change the default type unsupported implicit types are cast to.

module Travis::Yaml::Nodes
  class Example < Scalar
    cast :str, :binary, :int
    default_type :int
  end
end

Available types are str, binary, bool, float, int, time, regexp, secure and null.

Default Value

It is also possible to give a scalar a default value.

module Travis::Yaml::Nodes
  class Example < Scalar
    default_value "example"
  end
end

This is handy when using it for a required entry in a mapping (for instance, language is required, but has a default).

Fixed Value Set

For entries that have a well defined set of values, you can inherit from FixedValue:

module Travis::Yaml::Nodes
  class Example < FixedValue
    ignore_case

    default_value :example
    value :foo, :bar, baz: :bar
  end
end

This will, for example, map FOO to "foo", baz to "bar", and blah to "example" (and generate a warning about blah being not supported).

Shorthands

There are shorthands for creating Scalar and FixedValue subclasses:

module Travis::Yaml::Nodes
  class Example < Map
    map :foo, to: Scalar[:int]
    map :bar, to: FixedValue[:foo, :bar]
  end
end

Sequences

Sequences correspond to Ruby arrays. If you pass in a scalar or mapping instead of a sequence, it will be treated as if it was a sequence with a single entry of that value.

module Travis::Yaml::Nodes
  class ExampleList < Sequence
    type ExampleValue # node type, defaults to Scalar
  end
end

Mappings

Mappings correspond to hashes in Ruby.

module Travis::Yaml::Nodes
  class ExampleMapping < Mapping
    # map the value for the "example" key to an Example node
    # map the value for the "other" key to an Other node
    map :example, :other

    # map the values for "foo" and "bar" to a Scalar
    map :foo, :bar, to: Scalar

    # map "list" to a Sequence, keep it even if it's empty
    map :list, to: Sequence, drop_empty: false

    # require "setting" to be present
    map :setting, required: true

    # make "option" an alias for "setting"
    map :option, to: :setting

    # if a scalar is passed in instead of a mapping, treat it as
    # the value of "setting" ("foo" becomes { setting: "foo" })
    prefix_scalar :setting
  end
end

Open Mappings

Sometimes it is not possible to define all available keys for a mapping. You can solve this by using an open mapping:

module Travis::Yaml::Nodes
  class ExampleMapping < OpenMapping
    # node type for entries not specified (defaults to Scalar)
    default_type ExampleValue

    # map "setting" to Setting node, make it a requirement
    map :setting, required: true
  end
end

You can also limit the possible keys by overriding accept_key?.

module Travis::Yaml::Nodes
  class ExampleMapping < OpenMapping
    default_type ExampleValue

    def accept_key?(key)
      key.start_with? "example_"
    end
  end
end

Additional Verification

Besides the generated warnings, validations and normalizations inherent to the structure, you can define your own checks and normalizations by overriding the verify method.

module Travis::Yaml::Nodes
  class Example < Scalar
    def verify
      if value == "foo"
        warning "foo is deprecated, using bar instead"
        self.value = "bar"
      end
      super
    end
  end
end

The warning method will generate track a warning, so it can be presented to the user later on. The error method will lead to the node being removed from its parent node. It will also propagate the error message as a warning in the parent node.

Nested Warnings

When reflecting upon a node, warnings and errors will only contain the messages for that specific node. To get all the warnings for the entire tree, use nested_warnings, which will also give you the path (as array of strings).

config.nested_warnings.each do |path, message|
  p path      # ["my", "example", "key"]
  p message   # "this is the warning"
end

Requirements

This project requires Ruby 1.9.3 or 2.0.0 and Psych ~> 2.0 (part of the stdlib).

More Repositories

1

travis-ci

Free continuous integration platform for GitHub projects.
8,353
star
2

travis.rb

Travis CI Client (CLI and Ruby library)
Ruby
1,583
star
3

dpl

Dpl (dee-pee-ell) is a deploy tool made for continuous deployment.
Ruby
1,284
star
4

gimme

Install go, yay!
Shell
690
star
5

travis-cookbooks

Chef cookbook monolithic repo 📖 💣
HTML
663
star
6

travis-build

.travis.yml => build.sh converter
Ruby
653
star
7

travis-web

The Ember web client for Travis CI
JavaScript
611
star
8

docs-travis-ci-com

The Travis CI Documentation
SCSS
570
star
9

travis-api

The Travis CI API
Ruby
295
star
10

worker

Worker runs your Travis CI jobs
Go
274
star
11

travis-core

[DEPRECATED] Models and classes shared by Travis CI api, hub and gatekeeper
Ruby
239
star
12

travis-ci.github.com

[DEPRECATED] The Travis CI blog & documentation website
CSS
154
star
13

travis-worker

[DEPRECATED] This project is deprecated in favor of travis-ci/worker
Ruby
141
star
14

terraform-config

Terraform bits and bytes
HCL
123
star
15

travis-yml

Travis CI build config processing
Ruby
113
star
16

travis-lint

[DEPRECATED] Use travis-ci/travis-yml instead
Ruby
113
star
17

apt-package-safelist

Safelist of apt packages approved for build environments with restricted sudo
Shell
108
star
18

packer-templates

Templates for Packer!
Ruby
102
star
19

travis-watcher-macosx

[DEPRECATED] A Travis CI client for Mac OS X.
Objective-C
95
star
20

artifacts

Travis CI Artifacts Uploader
Go
87
star
21

travis-boxes

[DEPRECATED] Travis Boxes makes provisioning and configuring Virtual Box machines simple and easy.
Ruby
78
star
22

apt-source-safelist

Safelist of apt sources approved for build environments with restricted sudo
Ruby
78
star
23

gh

Layered GitHub API client
Ruby
68
star
24

travis-hub

Job State Central Command
Ruby
67
star
25

beta-features

The perfect place to leave feedback and comments on newly released Beta Features.
58
star
26

pudding

[DEPRECATED] It's a thing for managing instances!
Go
58
star
27

travis-logs

Processes log updates from the job runner (worker), and streams them to the web client, aggregates them, and archives to S3.
Ruby
56
star
28

travis-crowd

[DEPRECATED] Travis' love campaign (replaced by https://github.com/travis-ci/travis-love-campaign)
Ruby
49
star
29

osx-image-bootstrap

DEPRECATED Bootstrap scripts for Travis CI OS X VMs
Shell
47
star
30

build-stages-demo

Demos for Travis CI build stages
Ruby
46
star
31

travis-listener

Receives and queues service hook notifications from GitHub for processing.
Ruby
44
star
32

travis-rubies

my rubies, let me show you them
Shell
43
star
33

casher

CH CHING
Ruby
42
star
34

moustached-hubot

Moustached ChatOps for your hubot.
CoffeeScript
42
star
35

kubernetes-config

Travis services running on Kubernetes!
Shell
38
star
36

travis-tasks

The Sidekiq based Travis background job processor.
Ruby
37
star
37

php-src-builder

Builds php/php-src with php-build and uploads artifacts to S3
Roff
31
star
38

travis-support

Support classes and extensions used in travis-ci
Ruby
30
star
39

travis-scheduler

Queues jobs to be run by the various workers
Ruby
28
star
40

travis-cli-gh

[DEPRECATED] Travis CLI plugin to interact with GitHub API
Ruby
24
star
41

travis-sso

Implements Travis CI Single Sign-On as a Rack middleware.
Ruby
22
star
42

travis-artifacts

[DEPRECATED] Upload artifacts after running your tests to S3 (Unmaintained. See https://github.com/travis-ci/artifacts)
Ruby
21
star
43

docker-sinatra

[DEMO] Sample project for running a sinatra application on Docker from within a Travis build
Ruby
21
star
44

sso

SSO in go, implemented as an HTTP proxy.
Go
21
star
45

travis-assets

[DEPRECATED] We are using a CDN now
JavaScript
21
star
46

travis-conditions

Boolean language for conditional builds, stages, jobs
Ruby
20
star
47

actions

The best of GitHub Actions!
JavaScript
19
star
48

travis-foundation

Travis Foundation website.
HTML
19
star
49

gcloud-cleanup

Clean That Cloud! ☁️ 🛀
Go
19
star
50

travis-ruby-client

Ruby client library for Travis CI API
Ruby
19
star
51

packer-templates-mac

Templates for building images for macOS for Travis with Packer!
Shell
17
star
52

travis-chat

[DEMO] example app demoing travis-sso usage
Ruby
15
star
53

jupiter-brain

Jupiter Brain manages servers
Go
14
star
54

cpython-builder

Clones and builds CPython
Shell
13
star
55

travis.js

[DEPRECATED]
CoffeeScript
12
star
56

travis-deploy

[DEPRECATED] Travis Deploy tool
Ruby
11
star
57

collectd-vsphere

vSphere metrics plugin for collectd
Go
11
star
58

travis-web-log

CoffeeScript
10
star
59

system-info

💁 Gathers and reports system information specific to the travis build environment.
Ruby
10
star
60

worker-operator

A Kubernetes operator for deploying worker
Go
10
star
61

enterprise-installation

Travis CI Enterprise Installation Instructions
10
star
62

job-board

have a job? need a job? no jobs? all the jobs!
Ruby
9
star
63

cloud-brain

It talks to the clouds
Go
9
star
64

travis-weblint

travis-lint meets teh Internet
Ruby
9
star
65

travis-images

[DEPRECATED] Used to created and manage Travis VMs IN THE CLOUD
Ruby
9
star
66

apt-whitelist-checker

Automation of https://github.com/travis-ci/apt-package-whitelist approval process
Shell
9
star
67

cyclist

AWS ASG lifecycle thing 🎉 🚴
Go
8
star
68

2fabot

Slack bot that sends reminders to people to enable two-factor authentication.
Go
8
star
69

travis-extension-chrome

[DEPRECATED] Chrome extension that displays build status in the toolbar
8
star
70

travis-cli-pr

[DEPRECATED] This plugin has been deprecated, please use the travis settings command and the GitHub plugin instead. https://github.com/travis-ci/travis-cli-gh
Ruby
8
star
71

unlimited-jce-policy-jdk7

It's JCE Unlimited Strength Jurisdiction Policy Files 7 in a gem!
Ruby
7
star
72

prompt_warn_env

Warn if sensitive env vars are present
Shell
7
star
73

travis-erlang-builder

📫
Shell
6
star
74

travis-become

Ruby
6
star
75

travis-config

How does one configure 💃
Ruby
6
star
76

travis-migrations

Skeleton app to allow migrations to be run for our infrastructures
Ruby
6
star
77

travis-nightly-builder

API + rake tasks to build "nightly" or on-demand stuff
JavaScript
6
star
78

encrypted-column

Go implementation of encrypted database column bits
Go
6
star
79

travis-cli-settings

[DEPRECATED] No longer in use.
Ruby
5
star
80

travis-styleguide

[DEPRECATED] ✨
CSS
5
star
81

hubot-pudding

Script for interacting with a pudding server
CoffeeScript
5
star
82

travis-redirect

Ruby
5
star
83

veewee-definitions

[DEPRECATED] Veewee definitions we use to build our base boxes
Shell
5
star
84

container-example

[DEMO] An example showing how to use Travis CIs container-based infrastructure
Protocol Buffer
5
star
85

webhook-signature-verifier

A small Sinatra app to verify the webhook payload signature
Ruby
4
star
86

travis-images-specs

[DEPRECATED] tests for Travis build images
Ruby
4
star
87

travis-sidekiqs

Async, baby!
Ruby
4
star
88

cat-party

[DEMO] CodeDeploy Demo
HTML
4
star
89

tfw

The Tiny Floating Whale of infrastructure at Travis CI ✨ 🐳
Shell
4
star
90

travis-caching

[DEPRECATED] A simple caching service with pluggable backends
Ruby
4
star
91

travis_migrate_to_apps

Migrate your GitHub organizations to use the Travis CI GitHub App integration
Ruby
4
star
92

macbot

Slack bot for managing vSphere and other Travis Mac infrastructure things
Go
4
star
93

build-email

[DEPRECATED] The up-to-date HTML for build emails is generated from this template: https://github.com/travis-ci/travis-tasks/blob/master/lib/travis/addons/email/mailer/views/build/finished_email.html.erb
4
star
94

openshift-travis-quickstart

[DEMO] A sample Rack application showing Travis CI and OpenShift integration
Ruby
4
star
95

travis-api-v3

Pulling out our V3 codebase to be a stand alone application.
Ruby
3
star
96

travis-packer-build

📦 🚧
Ruby
3
star
97

travis-logsearch

Pipeline to dump job execution logs into elasticsearch!
Ruby
3
star
98

apt-gpg-keys

List of keys installed by travis-build at run time
3
star
99

build-env-linux

[WIP] New and improved Travis build environments for Linux
3
star
100

travis-encrypt

Encryption support
Ruby
3
star