Code Monkey home page Code Monkey logo

travis-yml's Introduction

This is a replacement for, and rewrite of travis-yaml.

Travis CI build config processing

This library is used for parsing, normalizing, and validating Travis CI build configuration (.travis.yml).

It serves these main functions:

  • Defining and producing a specification for our build configuration format in the form of JSON Schema.
  • Merging actual build configuration parts (such as .travis.yml)
  • Applying the spec to a merged build configuration in order to normalize and validate it.
  • Expanding a build config to job matrix configs.
  • Generating reference documentation from the spec.

The specification (schema) produced by the library is being used for both normalizing and validating build configs, and for generating reference documentation. I.e. these two parts of the code base are clients to the schema.

Applying the specification to a build configuration produces structured messages on the levels info, warn, and error. Such messages include a message code (e.g. unknown_key, deprecated_key etc.) and arguments (e.g. the given key, value) so they can be translated to human readable messages by clients. These can be used in the UI, and links to the documentation, suggesting fixes.

For example:

yaml = 'rvm: 2.3'
config = Travis::Yml.load(yaml)

config.serialize
# {
#   language: 'ruby',
#   os: ['linux'],
#   rvm: ['2.3']
# }

config.msgs
# [
#   [:info, :language, :default, key: :language, default: 'ruby'],
#   [:info, :language, :default, key: :os, default: 'linux'],
# ]

config.msgs.map { |msg| Travis::Yml.msg(msg) }
# [
#   '[info] on root: missing :language, using the default: "ruby"',
#   '[info] on root: missing :os, using the default: "linux"',
# ]

YAML

The library uses a custom YAML parser based on Psych, using its safe YAML parsing features.

Diverging from the YAML specification this library does not:

  • convert the strings yes or on to the boolean true, or the strings no or off to the boolean false
  • convert YAML integers or floats to Ruby integers or floats
  • convert symbol keys to symbols

For the following reasons:

  • Deployment config uses the key on. This being converted to true as a hash key does not make sense for us.
  • Version numbers like 1.10 used to be truncated to 1.1 by the YAML parser, causing confusion, and requiring users to specify these as strings ("1.10") instead.
  • Keys need to be strings so they can carry additional meta information (such as the source name of the build config, and the line number for messages).

The parser uses the classes Key, Map, and Seq for representing Ruby strings that are hash keys, hashes, and arrays, in order to be able to carry additional meta information. This is then used while merging config parts, and normalizing and validating the resulting config.

Integers and floats are not converted by the YAML parser, but they are casted later by the build config normalization, so they can be casted only if the respective node wants an integer or float.

Types

Borrowing from YAML's terminology the library uses:

  • map for hashes (key value mappings)
  • seq for arrays (sequence)

It also uses the following scalar types:

  • str for strings
  • num for numbers
  • bool for booleans
  • secure for secure strings

Scalars can be enums, as defined by JSON Schema, i.e. they can have a number of known and allowed values. Examples for keys that hold enums are: language, os, dist etc.

A map can be strict or not strict. Maps are strict by default. A strict map disallows keys that are not known.

A secure resembles our build config format for encrypted key/value pairs. Secures also can be strict or not strict, and they are strict by default. A not strict secure would accept a plain string without producing a warning (e.g. on keys like username or email).

Build config specification

The spec is included to the repository as schema.json.

The spec is defined in Schema::Def, and can be produced by:

Travis::Yml.schema

Classes in Schema::Def use classes in Schema::Type to build a tree of nodes that define allowed keys, types, and various options in a readable and succinct way (using a DSL for describing the schema).

Nodes on this tree that match certain well-known patterns are then transformed according to these patterns using classes in Schema::Type::Form. E.g. a sequence of strings always also accepts a single string, which will then automatically be wrapped into a sequence during the config normalization process. Therefore the JSON Schema needs to accept both forms.

The resulting tree is then serialized by classes in Schema::Json to a large Hash which serves as a specification in the form of a JSON Schema.

A good starting point for exploring the schema definition is the root node.

Examples for various nodes on this specification can be found in the tests, e.g. for the git, heroku, or os nodes.

Most nodes can be sufficiently specified by mapping known keys (e.g. language) to types (str, bool, map, seq etc.) with certain options, such as:

  • values: known values on a scalar type
  • default: default value
  • required: the node has to have a value
  • edge: the node represents an experimental feature
  • only: the node is valid only if the given value matches the current language or os
  • except: the node is valid only if the given value does not match the current language or os
  • expand: the node represents a matrix key for matrix expansion

In order to keep the JSON payload reasonably small the library uses JSON Schema's mechanism for defining and referencing shared sub schemas. All nodes that have a registered definition class are exported as such a defined sub schema, and then referenced on the respective nodes that use them.

TBD: mention JSON Schema limitations, and how travis-yml interprets particular types (all, any) in a specific way that is not defined by JSON Schema.

Loading the spec

Before the tree representing the schema can be applied to an actual build configuration it will be turned into another object oriented representation optimized for this purpose, so non-parametrized methods can be memoized for better performance.

The method Travis::Yml.expand returns this object oriented tree, using classes in Doc::Schema.

Applying the spec to a build config

This representation of the schema can be applied to a build configuration by:

# given a YAML string
Travis::Yml.load(yaml)

# given a Ruby hash
Travis::Yml.apply(config)

Both methods also accept an optional options hash. Please see here for a list of known options.

When the schema is applied to a build configuration three things happen:

  • The config is turned into an object oriented representation as well by the way of calling Doc::Value.build. This method uses classes in Doc::Value in order to build a tree of nodes that maps to the given build config hash.

  • The config structure is normalized by the way of calling Doc::Change.apply. This method applies various strategies in order to attempt to fix potential problems with the given structure, such as typos, misplaced keys, wrong section types. In some cases it will store messages on the resulting tree. Change strategies are determined based on the type of the given node. Some strategies can be required by the schema for certain sections that need very specific normalizations, such as cache, env_vars, enable.

  • The resulting config is validated by the way of calling Doc::Validate.apply. This method applies various validations, and sets default values. It also stores (most of the) messages on the resulting tree. Sections also can require specific validations. The only section specific validation currently is template (which validates used var names in notification templates).

Examples of type specific change strategies:

  • downcase: downcase a string if required by the spec
  • keys: add required keys, and attempt to fix an unknown key by removing special chars and finding typos (uses a dictionary, as well levenshtein and similar simple strategies)
  • prefix: turn the given value into a hash with a prefix key (e.g. turning env: ["FOO=bar"] into env: { matrix: ["FOO=foo"] })
  • pick: pick the first value of a given sequence for a scalar node
  • value: de-alias fixed node values, and try fixing typos in unknown values
  • wrap: wrap the given node into a sequence if required by the spec (e.g. os needs to result in an array)

Section specific change strategies:

  • env_vars: normalize env vars according to our build config format, parse env vars in order to validate them
  • enable: normalize enabled and disabled values, set enabled if missing (used by, for example, notifications)
  • inherit: inherit certain keys from the parent node if present (used by, for example, notifications)

Examples of the validations:

  • alert: add an alert level message if a node that expects a secure string accepts a plain string
  • default: use a default value as required by the spec if the node does not have a value
  • empty: warn about an empty section
  • format: unset the value and if the given value does not conform with the format as required by the spec
  • invalid_type: unset the value if the given value's type is not compatible with the spec's node type
  • required: add an error level message if the given map is missing a required key
  • template: drop the value if the given template string uses unknown variables
  • unknown_keys: add an error level message for an unknown key
  • unknown_value: add an error level message for an unknown value

Env vars given as strings will be parsed into hashes using the library sh_vars. Conditions will be parsed using the library travis-conditions.

Summary

There are three sets of classes that are used to build trees:

  • Travis::Yml::Spec builds the static, unexpanded Ruby hash that can be served as JSON.
  • Travis::Yml::Doc::Spec is used to build an object oriented tree of nodes from the expanded spec.
  • Travis::Yml::Doc::Value is used to build an object oriented tree of nodes that represent the given build config.

Only the last one, Doc::Value, is re-used at runtime, i.e. only for the given build configs we build new trees. The Doc::Spec representation is kept in memory, is static, and remains unchanged.

For each build config we then apply all relevant changes (Doc::Change) and all relevant validations (Doc::Validate) to each node.

Expanding a build matrix

A given build configuration can be expanded to job matrix configurations by:

Travis::Yml.matrix(config)

E.g. a build config like:

{
  language: 'ruby',
  ruby: ['2.2', '2.3'],
  env: ['FOO=foo', 'BAR=bar']
}

will be expanded to:

[
  { language: 'ruby', ruby: '2.2', env: { FOO: 'foo' } },
  { language: 'ruby', ruby: '2.2', env: { BAR: 'bar' } },
  { language: 'ruby', ruby: '2.3', env: { FOO: 'foo' } },
  { language: 'ruby', ruby: '2.3', env: { BAR: 'bar' } },
]

Web API

This gem also contains a web API for parsing and expanding a build config, which is used by travis-gatekeeper when processing a build request.

To start the server:

$ bundle exec rackup

The API contains three endpoints:

Home

$ curl -X GET /v1 | jq .
{
  "version": "v1"
}

Parse

The body of the request should be raw YAML. The response contains parsing messages and the validated and normalised config.

$ curl -X POST --data-binary @travis.yml /v1/parse | jq .
{
  "version": "v1",
  "messages": [
    {
      "level": "info",
      "key": "language",
      "code": "default",
      "args": {
        "key": "language",
        "default": "ruby"
      }
    }
  ],
  "full_messages": [
    "[info] on language: missing :language, defaulting to: ruby"
  ],
  "config": {
    "language": "ruby",
    "os": [
      "linux"
    ],
    "dist": "trusty",
    "sudo": false
  }
}

Expand

The body of the request should be the JSON config found in the response from /v1/parse. The response will contain the expanded matrix of jobs.

$ curl -X POST --data-binary @config.json /v1/expand | jq .
{
  "version": "v1",
  "matrix": [
    {
      "os": "linux",
      "language": "ruby",
      "dist": "trusty",
      "sudo": false
    }
  ]
}

travis-yml's People

Contributors

andriimysko avatar banzaiman avatar carlad avatar damianszymanski avatar dependabot[bot] avatar eugene-travis avatar fsamin avatar gbarc avatar gbarc-dt avatar gbarc80 avatar igorwwwwwwwwwwwwwwwwwwww avatar joecorcoran avatar joepvd avatar joshk avatar link-ny avatar linuxmadness avatar mboudreau avatar meatballhat avatar mjm avatar muizzk avatar murtaza-swati avatar pavel-d avatar pezi777 avatar piotrmilcarz avatar r-arek avatar speedywizard avatar svenfuchs avatar tahsin-travis-ci avatar vitalied avatar weban-pl avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

travis-yml's Issues

Move stages expansion to travis-yml?

Gatekeeper currently handles the expansion and normalization of stages. I think it might be worth moving this to travis-yml, so we can offer a preview to users.

Improve UI messages

  • don't display info level messages

  • make messages more human (eg sequence)

  • link to documentation (dependent on #34)

group should be accepted without the feature

The feature allows the matrix expansion of it:

group:
  - edge
  - stable

At the moment, when there is no expansion required (eg group: edge) travis-yml is creating this message:

[info] on group: your repository must be feature flagged for :group to be used

Reintroduce validation of group

At the moment, any arbitrary value for group is accepted. We might want to bring back some strictness here.

Values like the following should be accepted for group (no guarantees for completeness or accuracy):

stable
edge
dev
lts
latest
deprecated-<year><quartal>
deprecated-date

Maybe the values can be queried from job-board?

config parser ignores matrix.exclude

Bug report

matrix.exclude doesn't seem to have an effect when used together with matrix.include and regular matrix expansion with the new config parser.

Description

I was using matrix.exclude to exclude 3 mac jobs, together with regular matrix expansion and an extra deploy stage. Ideally, this configuration would end up running 10 jobs (6 Linux jobs + 4 Mac ) ones and a deploy one (rather than 13 jobs (6 Linux + 7 Mac) and the deploy one.

Ideally, 3 mac OS jobs, the default ones for Ruby 1.9.2, 1.9.3 and jruby should have been excluded.

Steps to reproduce

Use a travis.yml file like the following: https://github.com/travis-ci/travis.rb/blob/7b6f2ec82ed6c23a72bf60fee4cbc420554b2601/.travis.yml

Parse it with http://config.travis-ci.org/ :)

Expected behavior

matrix.exclude is taken into account and we end up generating 10 jobs, 6 Linux jobs + 4 Mac jobs

The same travis.yml configuration with the old parser: https://travis-ci.com/MariadeAnton/travis.rb/builds/81158133 results in the expected behaviour

Actual behavior

When using the new config parser, seems that matrix.exclude is not properly taken into account, resulting in 13 jobs in total, (6 Linux + 7 Mac)

See: https://travis-ci.org/travis-ci/travis.rb/builds/413047457

Let `sudo: required` pass without emitting "info"

Currently, sudo: required results in this information text:

casting value required(str) to true(bool)

While this is entirely correct technically, this would be a source of possible confusion, as through all our documentation and historical communications in the past we always refer to this setting as sudo: required.

We should be lenient in this case.

Rolling out

  • approach embassy customers
  • early Alpha
  • collect issues

Improve "version" error message

This YAML snippet

version: "=0"

results in this error message

dropping invalid format: =0

It would be instructive to display (or give hints as to) what valid format is.

Travis does't recognize branches with slash

I have this piece of code in my travis.yml file:

deploy:
  provider: script
  script: bash $TRAVIS_BUILD_DIR/deploy-to-gae.sh
  on: 
    branch: Makeroid/BETA
  skip_cleanup: true

However, the deploy script is not being executed in that branch. Travis returns this:

image

Global python version setting no longer respected

At the top of my .travis.yml I set python: "3.6" globally, so that Python 3.6 will be used for the jobs that don't override it, rather than Travis's default of Python 2.7.

This has been working fine. But when I try adding version: "= 0" to the top of my .travis.yml to opt into the new yml parser, the global Python 3.6 setting gets ignored, and Python 2.7 gets used for jobs that don't specify a Python version, resulting in build failures.

deep_merge_prepend is not working on our builds as of 24 Apr 2020

We have an import section in our .travis.yml and then 1 install statement in the .travis.yml and the resulting config has only the install statement from the .travis.yml

.travis.yml
image

fs-webdev/fs-common-build-scripts:travis/install_with_bower.yml
image

Build Config
image

"Camelcase" warning is picking up only the hyphenated keys

Problem

This snippet with a hyphenated key

deploy:
  skip-cleanup: true
  

results in warning:

key skip-cleanup is camelcased, using skip_cleanup

while a real camel cased key

deploy:
  SkipCleanup: true
  

is silently ignored.

The message should read "X is hyphenated; using X snake_cased".

(Incidentally, I don't recall we ever supported camel cased keys.)

Deprecation message signature changed?

From here:

image

The relevant message:

    {
      "@type": "message",
      "@representation": "standard",
      "id": 44173,
      "level": "warn",
      "key": "language",
      "code": "deprecated",
      "args": {
        "given": "__sardonyx__",
        "info": true
      }

I’m making note of this without significant digging, sorry if it’s a duplicate etc

Handle merge_mode

Gatekeeper is able to merge config from API requests into the repo config. This is curently broken when opting into travis-yml, because it returns env vars as FOO=bar strings, which can't be merged/deep-merged. We could potentially handle this by producing env var hashes.

The :bool type coerces every string into a bool

It's not currently possible to combine the :bool type with other types. The use case for this is to be able to have a value be a boolean if the user puts true or false or a string version of them, but have the value be a string if they specify some other string value.

Currently, if you use [:bool, :scalar] as the type, you will always get a boolean, regardless of the string given. It is as though you just specified :bool.

Feature Request: Allow using multiple distributions for build matrix expansion

Hi,
I would like to use the build matrix feature to run jobs on multiple Linux distributions like Bionic, Focal, etc. Currently, each job needs to specified individually, since matrix expansion doesn't work with dist.

Please see https://travis-ci.community/t/using-build-matrix-for-multiple-ubuntu-distributions/9187 for detailed description and discussion.

An example of final config file, expecting to get 2 x 5 jobs -

language: python
os: linux
dist:
  - bionic
  - focal

env:
  - CIINSTALL=yes SCRIPT=12   # BasicSetup + GenSoftware
  - CIINSTALL=yes SCRIPT=3    # ML-Basic
  - CIINSTALL=yes SCRIPT=4    # Build-OpenCV
  - CIINSTALL=yes SCRIPT=14   # BasicSetup + OpenCV (Conda OpenCV)
  - CIINSTALL=yes SCRIPT=5    # BuildML

Current travis.yml - https://github.com/rsnk96/Ubuntu-Setup-Scripts/blob/master/.travis.yml

This is my first time creating an issue here, so sorry for any details missing, etc. I would love to contribute this myself as well, any direction on how to proceed will be very much appreciated!

[BUG] `secure:` values decryption seems broken

Hi @svenfuchs,

it looks like current version of yaml parser is somehow omitting secure values decryption, only reproducible under one repo (partial feature rollout?).

See log: https://travis-ci.com/patron-it/opencanary/builds/89310413#L432-L434

I suspect that this is somehow related to this test change where the list of one secure item is turned into two:
bdfeb2f...master#diff-7579c6b61703c78685c80a644a34666eR37

I think this requires a test for a mapping with a secure value nested... Haven't confirmed it though.

remove default values for `sudo`

with single linux, we need default values for sudo to go to sudo: required. however, based on my testing with travis-api vs. my personal account it looks like we're setting sudo: false as default here.

given that we're managing defaults for sudo: in the keychain right now, and that this will be going away fully as a configurable option soon, I'd recommend we remove the behavior here that sets a default for sudo.

Non-hash input should not raise errors

Problem

Non-hash input such as

n

should not throw errors (in the library, or 400's/500's in HTTP).

Current behavior

HTTP requests throw 500
$ curl -vs -X POST -d 'n' http://localhost:9292/v1/parse
*   Trying ::1:9292...
* TCP_NODELAY set
* Connected to localhost (::1) port 9292 (#0)
> POST /v1/parse HTTP/1.1
> Host: localhost:9292
> User-Agent: curl/7.65.3
> Accept: */*
> Content-Length: 1
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 1 out of 1 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Content-Type: text/plain
< X-Content-Type-Options: nosniff
< Vary: Origin
< X-Rack-CORS: miss; no-origin
< Content-Length: 13548
<
NoMethodError: undefined method `opts' for "n":String
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml/parts/part.rb:25:in `to_h'
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml/parts.rb:10:in `load'
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml.rb:108:in `load'
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml/web/parse.rb:33:in `load'
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml/web/parse.rb:26:in `handle'
        /Users/asari/Development/src/travis-ci/travis-yml/lib/travis/yml/web/parse.rb:19:in `block in '
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1636:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1636:in `block in compile!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:987:in `block (3 levels) in route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1006:in `route_eval'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:987:in `block (2 levels) in route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1035:in `block in process_route'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1033:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1033:in `process_route'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:985:in `block in route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:984:in `each'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:984:in `route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1098:in `block in dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1095:in `dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `block in call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:908:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/xss_header.rb:18:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/path_traversal.rb:16:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/json_csrf.rb:26:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/frame_options.rb:31:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/null_logger.rb:11:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/show_exceptions.rb:22:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:194:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1951:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:966:in `forward'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1052:in `route_missing'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1001:in `route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:997:in `route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1098:in `block in dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1095:in `dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `block in call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:908:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/xss_header.rb:18:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/path_traversal.rb:16:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/json_csrf.rb:26:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/frame_options.rb:31:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/null_logger.rb:11:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/show_exceptions.rb:22:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:194:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1951:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:966:in `forward'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1052:in `route_missing'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1001:in `route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:997:in `route!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1098:in `block in dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1095:in `dispatch!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `block in call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `block in invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `catch'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1072:in `invoke'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:919:in `call!'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:908:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/xss_header.rb:18:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/path_traversal.rb:16:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/json_csrf.rb:26:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/frame_options.rb:31:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/null_logger.rb:11:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/show_exceptions.rb:22:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:194:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1951:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-cors-1.1.1/lib/rack/cors.rb:100:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/xss_header.rb:18:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/path_traversal.rb:16:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/json_csrf.rb:26:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/base.rb:50:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-protection-2.0.8.1/lib/rack/protection/frame_options.rb:31:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/null_logger.rb:11:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/head.rb:12:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/show_exceptions.rb:22:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:194:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:1951:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/tempfile_reaper.rb:15:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/lint.rb:50:in `_call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/lint.rb:38:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/show_exceptions.rb:23:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/common_logger.rb:38:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/sinatra-2.0.8.1/lib/sinatra/base.rb:231:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/rack-2.2.3/lib/rack/content_length.rb:17:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.5/lib/puma/configuration.rb:228:in `call'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.5/lib/puma/server.rb:713:in `handle_request'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.5/lib/puma/server.rb:472:in `process_client'
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.5/lib/puma/server.rb:328:in `block in run'
* Connection #0 to host localhost left intact
        /Users/asari/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/puma-4.3.5/lib/puma/thread_pool.rb:134:in `block in spawn_thread'

Expected behavior

Return a data structure indicating an error in the input, e.g.,

$ curl -s -X POST -d 'n' http://localhost:9292/v1/parse | jq .
{
  "version": "v1",
  "messages": [
    {
      "type": "config",
      "level": "warn",
      "key": "root",
      "code": "unprocessable_data",
      "args": {
        "key": "n",
        "value": nil
      },
      "line": 0
    },
    {
      "type": "config",
      "level": "info",
      "key": "root",
      "code": "default",
      "args": {
        "key": "language",
        "default": "ruby"
      }
    },
    {
      "type": "config",
      "level": "info",
      "key": "root",
      "code": "default",
      "args": {
        "key": "os",
        "default": "linux"
      }
    },
    {
      "type": "config",
      "level": "info",
      "key": "root",
      "code": "default",
      "args": {
        "key": "dist",
        "default": "xenial"
      }
    }
  ],
  "full_messages": [
    "[warn] on root: unprocessable data \"n\"",
    "[info] on root: missing language, using the default \"ruby\"",
    "[info] on root: missing os, using the default \"linux\"",
    "[info] on root: missing dist, using the default \"xenial\""
  ],
  "config": {
    "a": "b",
    "language": "ruby",
    "os": [
      "linux"
    ],
    "dist": "xenial"
  }
}

`dist: xenial` is not recognized

While we are experimenting with Xenial images, it is important to have this value recognized, so that it can be used (while users completely assume the responsibility) to build language runtimes for seeding the supported images.

travis-lint vs travis-yaml vs travis-yml

The travis-lint says it's deprecated and replaced with travis-yaml.
The travis-yaml readme has no links to travis-yml (this repo), but this travis-yml readme says that it's a replacement for travis-yaml.

What's the story behind this? I'm so confused.

Also, the readme says nothing about linting the .travis.yml file.
There are no examples on how to use it as a drop-in replacement for travis-lint.

As far as I understand, travis-yaml is a library, so installing gem install travis-yaml doesn't give anything that replace travis-lint executable/script right away. I don't understand how to use it instead of travis-lint, honestly. :)

Travis deploy provider "script" should support sequences (gives weird error if you try)

I need to do this in order to deploy with Maven:

...
      deploy:
        - provider: script
          script:
            - openssl aes-256-cbc -K $encrypted_dc2adf587a89_key -iv $encrypted_dc2adf587a89_iv -in .travis.gpg.enc -out .travis.gpg -d
            - openssl aes-256-cbc -K $encrypted_dc2adf587a89_key -iv $encrypted_dc2adf587a89_iv -in .travis.settings.xml.enc -out .travis.settings.xml -d
            - gpg --import .travis.gpg
            - cp .travis.settings.xml $HOME/.m2/settings.xml
            - mvn clean deploy -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -P sign -B -V -e
...

The worst bit is that, if you try this, you get a very strange error that doesn't actually indicate what you've done wrong:

Installing deploy dependencies
Successfully installed dpl-script-1.10.6
Parsing documentation for dpl-script-1.10.6
Installing ri documentation for dpl-script-1.10.6
Done installing documentation for dpl-script after 0 seconds
1 gem installed
/home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/cli.rb:54:in `system': wrong first argument (ArgumentError)
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/cli.rb:54:in `shell'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-script-1.10.6/lib/dpl/provider/script.rb:19:in `push_app'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/provider.rb:199:in `block in deploy'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/cli.rb:41:in `fold'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/provider.rb:199:in `deploy'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/cli.rb:32:in `run'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/lib/dpl/cli.rb:7:in `run'
	from /home/travis/.rvm/gems/ruby-2.4.1/gems/dpl-1.10.6/bin/dpl:5:in `<top (required)>'
	from /home/travis/.rvm/gems/ruby-2.4.1/bin/dpl:23:in `load'
	from /home/travis/.rvm/gems/ruby-2.4.1/bin/dpl:23:in `<main>'

I figured it out by browsing through the travis-ci/travis-yml source code and finding this:

...
          class Script < Deploy
            register :script

            def define
              super
              map :script, to: :str # TODO should be a seq?
            end
...

# TODO should be a seq? ... Yes, it should definitely be a sequence. Particularly important here, the top-level script directive supports sequences, so this directive's not supporting sequences, with no documentation saying it doesn't, and with a weird error message that doesn't indicate the problem, is a bug.

For now, I think I can get around it with this (I'm about to test it), but this is not the correct way to do this, especially since I'm using multiple providers, and before_deploy runs before each provider (unnecessary here).

...
      before_deploy:
        - openssl aes-256-cbc -K $encrypted_dc2adf587a89_key -iv $encrypted_dc2adf587a89_iv -in .travis.gpg.enc -out .travis.gpg -d
        - openssl aes-256-cbc -K $encrypted_dc2adf587a89_key -iv $encrypted_dc2adf587a89_iv -in .travis.settings.xml.enc -out .travis.settings.xml -d
        - gpg --import .travis.gpg
        - cp .travis.settings.xml $HOME/.m2/settings.xml
      deploy:
        - provider: script
          script: "mvn clean deploy -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -P sign -B -V -e"
...

Arabic text gets gobbled up

Given:

language: python
script:
  - cat ضروریاں.txt

travis-yml returns:

{
  "language": "python",
  "os": [
    "linux"
  ],
  "dist": "xenial",
  "script": [
    "cat .txt"
  ],
}

Config Explorer fails to parse unevenly spaced YAML

Using the config explorer here:
https://config.travis-ci.com/explore

It parses this:

install:
 - foo
 # baz
 - bar

But fails with this:

install:
 - foo
 # baz
- bar

Or this:

install:
- foo
 # baz
 - bar

And this (although seemingly only when you make an edit in the text box):

install:
 - foo
# baz
 - bar

Reporting undefined: undefined

But equivalent more complicated config works fine on Travis proper.

Nothing is logged in Firefox browser console.

This configuration is not expanded into matrix

Add support for top-level "arch"

Near-future work on hosted Travis and some current work on at least one Travis Enterprise installation is raising the topic of supporting the concept of architecture, designated via an arch top-level key, e.g.:

language: ruby
os: linux
arch: x86_64
language: python
os: linux
arch:
- amd64
- arm64
- ppc64

Valid values, at the time of this writing, are:

  • x86_64 / amd64 (currently supported)
  • ppc64 / ppc64le (currently supported in closed beta)
  • arm64 (proposed future)

Parsing Yaml-Like Bash Strings

The current "live" parser on org and the linter can not parse files containing strings such as:

language: cpp
sudo: false
dist: trusty

install:
- echo -e "config:\n  build_jobs: 2"

But allow the modified versions

install:
- echo -e "config:\n  build_jobs:"" 2"

and

install:
- |
  echo -e "config:\n  build_jobs: 2"

.

Maybe you want to add such a yaml file to your test coverage for the new parser? Unfortunately I am an absolute ruby novice and can not provide a PR :)

Broader Build Config UI Improvement

The UI approach to how we show information about a build's config needs some re-thinking.

  • Currently there's confusion about the fact that the config relates to the build but is displayed as a tab on the job page.
  • There's confusion about the fact that the config displayed in web is parsed config, and not necessarily what is in the build's .travis.yml file (the parsing step renames things, removes things, creates a matrix etc).
  • The messages that are created by travis-yml relate to the whole build (not individual jobs) and to the travis.yml file, not to the parsed config currently displayed on the config tab

Please note conversation in this issue, which has already started discussing a new approach:
https://github.com/travis-pro/team-teal/issues/2175#issuecomment-362094386

Slack notifications to different channels

Right now, we have travis slack notifications send status messages to one channel (say #builds), but I want to separate out the notification message stream into different audience developer builds vs dependencies upgrade(#builds, #dep-upgrade). I wonder if and how I can achieve it.

Let me know if that makes sense. Thanks!

Test script in README is broken

Actually, I'm not 100% on this, but it seems something in the test script provided in the README is either broken or missing.

WebLint tool

We are working on a new yml parsing library, travis-yml, which is slowly being rolled out on the Travis CI hosted platform. We are also working on a new WebLint tool.

Copied from https://yaml.travis-ci.org/
What's the progress here as the page/tool is not available currently.

Use env vars in import ref

Hi,

I'm using the build configuration import for a while now and I wanted to test something.
I tried to import configuration with an environment variable as an import ref but it doesn't seem to work (File portapps/portapps:.travis/configs/install.yml not found on GitHub):

version: ~> 1.0

os: windows
language: shell

before_install:
  - export PORTAPPS_VERSION=$(cat go.mod | grep github.com/portapps/portapps | awk '{print $2}')

import:
  - portapps/portapps:.travis/configs/install.yml@$PORTAPPS_VERSION
  - portapps/portapps:.travis/configs/build.yml@$PORTAPPS_VERSION
  - portapps/portapps:.travis/configs/set-version.yml@$PORTAPPS_VERSION
  - portapps/portapps:.travis/configs/git-config.yml@$PORTAPPS_VERSION
  - portapps/portapps:.travis/configs/deploy.yml@$PORTAPPS_VERSION
  - portapps/portapps:.travis/configs/notifs.yml@$PORTAPPS_VERSION

Is there a way to do this?

Thanks!

Do not pick the first value from matrix expansion keys into listed jobs

With this config:

          env:
            global:
              - FOO=bar
            matrix:
              - BAR=foo
              - BAR=baz
          matrix:
            include:
              - stage: foo
                if: env(BAR) = foo
              - stage: bar
                if: env(BAR) = bar

Gatekeeper currently creates jobs with these configs:

{:env=>"BAR=foo", :global_env=>["FOO=bar"], :language=>"ruby", :group=>"stable", :dist=>"trusty", :os=>"linux"}
{:env=>"BAR=baz", :global_env=>["FOO=bar"], :language=>"ruby", :group=>"stable", :dist=>"trusty", :os=>"linux"}
{:env=>"BAR=foo", :global_env=>["FOO=bar"], :language=>"ruby", :group=>"stable", :dist=>"trusty", :if=>"env(BAR) = foo", :stage=>"foo", :os=>"linux"}

In the last one, which was generated out of matrix.include it should not have :env=>"BAR=foo" set.

I believe for all matrix expansion keys Gatekeeper currently picks the first element out of an array, unless the key is already given on the job. @BanzaiMan and i think we should stop doing that in travis-yml.

Matrix is not expanded for the jobs alias

An example:

# yaml from https://docs.travis-ci.com/user/build-stages/
pp Travis::Yaml.matrix(YAML.load(<<-'EOF'
jobs:
  include:
    - stage: test
      script: ./test 1
    - # stage name not required, will continue to use `test`
      script: ./test 2
    - stage: deploy
      script: ./deploy
EOF
).deep_symbolize_keys!).rows

This expands to:

[{:jobs=>
   {:include=>
     [{:stage=>"test", :script=>"./test 1"},
      {:script=>"./test 2"},
      {:stage=>"deploy", :script=>"./deploy"}]}}]

Changing jobs to matrix correctly expands it:

[{:stage=>"test", :script=>"./test 1"},
 {:script=>"./test 2"},
 {:stage=>"deploy", :script=>"./deploy"}]

My understanding is that jobs and matrix are currently equivalent, so it seems that jobs ought to end up normalized to matrix (or the reverse). Either way I would expect the matrix to expand equivalently here.

Side note: I also wonder if :stage=>"test" should be automatically added for the middle entry above, but maybe it's outside the scope of this lib.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.