From c7561ee13eff407340cb9f015860685ca39e60ef Mon Sep 17 00:00:00 2001
From: Piotr Sarnacki <drogus@gmail.com>
Date: Sat, 6 Apr 2013 01:48:32 +0200
Subject: [PATCH] Properly display matrix keys when build does not have all
 keys

When additional items are included into matrix via 'matrix.include' key
in .travis.yml they may contain config keys, which are not available on
build.

For example build can contain only 'rvm' key, but we may add the
following include:

    matrix:
      include:
        - rvm: '2.0.0'
          env: 'FOO=bar'

In such case, we need to take into account also keys from additional
job, not only from the build.

(closes #172)
---
 assets/scripts/app/helpers/helpers.coffee  |  3 +++
 assets/scripts/app/models/branch.coffee    |  2 +-
 assets/scripts/app/models/build.coffee     | 15 ++++++++++++---
 assets/scripts/app/models/job.coffee       | 10 +++++-----
 assets/scripts/spec/unit/build_spec.coffee | 14 ++++++++++++++
 assets/scripts/spec/unit/job_spec.coffee   | 17 +++++++++++++++++
 6 files changed, 52 insertions(+), 9 deletions(-)

diff --git a/assets/scripts/app/helpers/helpers.coffee b/assets/scripts/app/helpers/helpers.coffee
index a0f28ec5..1268ff15 100644
--- a/assets/scripts/app/helpers/helpers.coffee
+++ b/assets/scripts/app/helpers/helpers.coffee
@@ -91,3 +91,6 @@ require 'config/emoij'
   _escape: (text) ->
     text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace />/g, '&gt;'
 
+  configKeys: (config) ->
+    return [] unless config
+    $.intersect($.keys(config), Travis.CONFIG_KEYS)
diff --git a/assets/scripts/app/models/branch.coffee b/assets/scripts/app/models/branch.coffee
index 4b7ce750..3d45d52d 100644
--- a/assets/scripts/app/models/branch.coffee
+++ b/assets/scripts/app/models/branch.coffee
@@ -1,6 +1,6 @@
 require 'travis/model'
 
-@Travis.Branch = Travis.Model.extend Travis.Helpers,
+@Travis.Branch = Travis.Model.extend
   repoId:       DS.attr('number', key: 'repository_id')
   commitId:     DS.attr('number')
   state:        DS.attr('string')
diff --git a/assets/scripts/app/models/build.coffee b/assets/scripts/app/models/build.coffee
index ca3bb292..9906e770 100644
--- a/assets/scripts/app/models/build.coffee
+++ b/assets/scripts/app/models/build.coffee
@@ -45,12 +45,21 @@ require 'travis/model'
     @get('jobs').filter (data) -> data.get('allowFailure')
   ).property('jobs.@each.allowFailure')
 
+  rawConfigKeys: (->
+    keys = Travis.Helpers.configKeys(@get('config'))
+
+    @get('jobs').forEach (job) ->
+      Travis.Helpers.configKeys(job.get('config')).forEach (key) ->
+        keys.pushObject key unless keys.contains key
+
+    keys
+  ).property('config', 'jobs.@each.config')
+
   configKeys: (->
-    return [] unless config = @get('config')
-    keys = $.intersect($.keys(config), Travis.CONFIG_KEYS)
+    keys = @get('rawConfigKeys')
     headers = (I18n.t(key) for key in ['build.job', 'build.duration', 'build.finished_at'])
     $.map(headers.concat(keys), (key) -> return $.camelize(key))
-  ).property('config')
+  ).property('rawConfigKeys.length')
 
   canCancel: (->
     @get('state') == 'created' # TODO
diff --git a/assets/scripts/app/models/job.coffee b/assets/scripts/app/models/job.coffee
index e54a717c..30251213 100644
--- a/assets/scripts/app/models/job.coffee
+++ b/assets/scripts/app/models/job.coffee
@@ -61,14 +61,14 @@ require 'travis/model'
   ).property('log.workerName')
 
   configValues: (->
-    config      = @get('config')
-    buildConfig = @get('build.config')
-    if config && buildConfig
-      keys = $.intersect($.keys(buildConfig), Travis.CONFIG_KEYS)
+    config = @get('config')
+    keys   = @get('build.rawConfigKeys')
+
+    if config && keys
       keys.map (key) -> config[key]
     else
       []
-  ).property('config')
+  ).property('config', 'build.rawConfigKeys.length')
 
   canCancel: (->
     @get('state') == 'created' || @get('state') == 'queued' # TODO
diff --git a/assets/scripts/spec/unit/build_spec.coffee b/assets/scripts/spec/unit/build_spec.coffee
index f7374224..10d3fd9f 100644
--- a/assets/scripts/spec/unit/build_spec.coffee
+++ b/assets/scripts/spec/unit/build_spec.coffee
@@ -30,3 +30,17 @@ describe 'Travis.Build', ->
       waits 50
       runs ->
         expect( record.get('incomplete') ).toBeFalsy()
+
+  describe 'configKeys', ->
+    it 'takes into account all the jobs when getting config keys', ->
+      buildConfig = { rvm: ['1.9.3', '2.0.0'] }
+      store.load Travis.Build, { id: '1', job_ids: ['1', '2', '3'], config: buildConfig }, { id: '1' }
+
+      store.load Travis.Job, { id: '1', config: { rvm: '1.9.3', env: 'FOO=foo'       } }, { id: '1' }
+      store.load Travis.Job, { id: '2', config: { rvm: '2.0.0', gemfile: 'Gemfile.1' } }, { id: '2' }
+      store.load Travis.Job, { id: '3', config: { rvm: '1.9.3', jdk: 'OpenJDK'       } }, { id: '3' }
+
+      build = store.find(Travis.Build, '1')
+
+      expect( build.get('rawConfigKeys') ).toEqual( ['rvm', 'env', 'gemfile', 'jdk' ] )
+      expect( build.get('configKeys') ).toEqual( [ 'Job', 'Duration', 'Finished', 'Rvm', 'Env', 'Gemfile', 'Jdk' ] )
diff --git a/assets/scripts/spec/unit/job_spec.coffee b/assets/scripts/spec/unit/job_spec.coffee
index 42efff80..26fb35a9 100644
--- a/assets/scripts/spec/unit/job_spec.coffee
+++ b/assets/scripts/spec/unit/job_spec.coffee
@@ -8,6 +8,23 @@ describe 'Travis.Job', ->
   afterEach ->
     store.destroy()
 
+  describe 'configKeys', ->
+    it 'takes into account the keys of other jobs', ->
+      buildConfig = { rvm: ['1.9.3', '2.0.0'] }
+      store.load Travis.Build, { id: '1', job_ids: ['1', '2', '3'], config: buildConfig }, { id: '1' }
+
+      store.load Travis.Job, { id: '1', config: { rvm: '1.9.3', env: 'FOO=foo'       }, build_id: '1' }, { id: '1' }
+      store.load Travis.Job, { id: '2', config: { rvm: '2.0.0', gemfile: 'Gemfile.1' },  build_id: '1' }, { id: '2' }
+      store.load Travis.Job, { id: '3', config: { rvm: '1.9.3', jdk: 'OpenJDK'       },  build_id: '1' }, { id: '3' }
+
+      job1 = store.find(Travis.Job, '1')
+      job2 = store.find(Travis.Job, '2')
+      job3 = store.find(Travis.Job, '3')
+
+      expect( job1.get('configValues') ).toEqual( [ '1.9.3', 'FOO=foo', undefined, undefined ] )
+      expect( job2.get('configValues') ).toEqual( [ '2.0.0', undefined, 'Gemfile.1', undefined ] )
+      expect( job3.get('configValues') ).toEqual( [ '1.9.3', undefined, undefined, 'OpenJDK' ] )
+
   describe 'incomplete attributes', ->
     beforeEach ->
       store.loadIncomplete Travis.Job, { id: 1, state: 'started' }