From f22df5d180f4b965adec92b6010e3bf1110d5e11 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Mon, 18 Mar 2013 23:05:06 -0300 Subject: [PATCH 1/8] Added missing word "repo" --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 37eceb4e..fae03551 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,5 @@ # Contributing to Travis-CI -Issues for any Travis-CI should be submitted to https://github.com/travis-ci/travis-ci/issues +Issues for any Travis-CI repo should be submitted to https://github.com/travis-ci/travis-ci/issues ## Security Issues ***Any security issues should be submitted directly to [security@travis-ci.org](mailto:security@travis-ci.org)*** From 653bf3a568e73b89cc29f3fc390679f6278eed80 Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Tue, 19 Mar 2013 01:05:04 -0300 Subject: [PATCH 2/8] Add build badge Dog fooding --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index eac08eba..0ce25081 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## Travis CI ember web client - +[![Build Status](https://travis-ci.org/travis-ci/travis-web.png)](https://travis-ci.org/travis-ci/travis-web) ### Running the app In order to run the app you need to install dependencies with: From 65254b70da210897c6511849066942c13aba3c50 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 19 Mar 2013 16:07:21 +0100 Subject: [PATCH 3/8] Fix cutting too long logs --- assets/scripts/app/views/log.coffee | 4 +-- assets/scripts/lib/travis/ordered_log.coffee | 5 ++-- assets/scripts/spec/job_spec.coffee | 27 +++++++++++++++++++ assets/scripts/spec/support/conditions.coffee | 2 +- .../scripts/spec/support/expectations.coffee | 2 +- assets/styles/main/log.sass | 3 +++ 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index 1fab0507..d3aa63fe 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -154,8 +154,8 @@ Travis.OrderedLogEngineMixin = Ember.Mixin.create this.$('#log')[0].appendChild fragment if cut - url = Travis.Urls.plainTextLog(@get('log.id')) - this.$("#log").append $("

Log was too long to display. Download the the raw version to get the full log.

") + url = Travis.Urls.plainTextLog(@get('log.job.id')) + this.$("#log").append $("
Log was too long to display. Download the the raw version to get the full log.
") Travis.reopen LogView: Travis.View.extend diff --git a/assets/scripts/lib/travis/ordered_log.coffee b/assets/scripts/lib/travis/ordered_log.coffee index 65c33fcd..f2127204 100644 --- a/assets/scripts/lib/travis/ordered_log.coffee +++ b/assets/scripts/lib/travis/ordered_log.coffee @@ -6,6 +6,7 @@ FOLDS = [ ] @Travis.OrderedLog = Em.Object.extend + linesLimit: 5000 init: -> @set 'folds', [] @set 'line', 1 @@ -17,7 +18,7 @@ FOLDS = [ append: (lines) -> return unless lines - return if @get('lineNumber') > 5000 + return if @get('lineNumber') > @get('linesLimit') log = @join lines log = @escape log @@ -88,7 +89,7 @@ FOLDS = [ if currentFold @set 'foldContinuation', true - if @get('lineNumber') + index >= 5000 + if @get('lineNumber') + index >= @get('linesLimit') result.pushObject logWasCut: true break diff --git a/assets/scripts/spec/job_spec.coffee b/assets/scripts/spec/job_spec.coffee index ab2f5955..9246e308 100644 --- a/assets/scripts/spec/job_spec.coffee +++ b/assets/scripts/spec/job_spec.coffee @@ -43,3 +43,30 @@ describe 'on the "job" state', -> displaysLog [ 'log 1' ] + +describe 'too long log', -> + beforeEach -> + $.mockjax + url: '/jobs/2/log?cors_hax=true' + responseTime: 0 + responseText: '1\n2\n3\n4\n5\n6\n7\n8\n9\n10' + + Travis.OrderedLog.reopen + linesLimit: 5 + + app 'travis-ci/travis-core/jobs/2' + waitFor logRendered + + afterEach -> + Travis.OrderedLog.reopen + linesLimit: 5000 + + it 'is cut after given limit', -> + displaysLog [ + '12345' + ] + + expect( $('#log .cut').text() ).toEqual 'Log was too long to display. Download the the raw version to get the full log.' + expect( $('#log .cut a').attr('href') ).toEqual '/jobs/2/log.txt?deansi=true' + + diff --git a/assets/scripts/spec/support/conditions.coffee b/assets/scripts/spec/support/conditions.coffee index 67a60462..fbc74720 100644 --- a/assets/scripts/spec/support/conditions.coffee +++ b/assets/scripts/spec/support/conditions.coffee @@ -11,4 +11,4 @@ @jobsRendered = notEmpty('#jobs .number') @queuesRendered = notEmpty('#queue_linux li') @workersRendered = notEmpty('.worker') - +@logRendered = notEmpty('#log p') diff --git a/assets/scripts/spec/support/expectations.coffee b/assets/scripts/spec/support/expectations.coffee index edf80ddc..3cb12953 100644 --- a/assets/scripts/spec/support/expectations.coffee +++ b/assets/scripts/spec/support/expectations.coffee @@ -42,7 +42,7 @@ @displaysLog = (lines) -> log = lines.join() - expect($('#log').text().trim()).toEqual log + expect($('#log p').text().trim()).toEqual log @listsRepos = (items) -> listsItems('repo', items) diff --git a/assets/styles/main/log.sass b/assets/styles/main/log.sass index 2af0aa97..80a6914b 100644 --- a/assets/styles/main/log.sass +++ b/assets/styles/main/log.sass @@ -19,6 +19,9 @@ pre#log overflow-x: scroll counter-reset: line-numbering + .cut + padding: 20px 15px 0 55px + p padding: 0 15px 0 55px margin: 0 From c0d23f5579e67caa58a8b3017eeec843bf15d87c Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Tue, 19 Mar 2013 21:30:53 +0100 Subject: [PATCH 4/8] Be more specific when catching 'URL not found' error, also add test --- assets/scripts/app/routes.coffee | 2 +- assets/scripts/spec/routes_spec.coffee | 7 +++++++ assets/scripts/spec/support/conditions.coffee | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 assets/scripts/spec/routes_spec.coffee diff --git a/assets/scripts/app/routes.coffee b/assets/scripts/app/routes.coffee index c7cd5df0..ac4dc99c 100644 --- a/assets/scripts/app/routes.coffee +++ b/assets/scripts/app/routes.coffee @@ -9,7 +9,7 @@ Ember.Router.reopen try @_super(url) catch error - @_super('/not-found') + @_super('/not-found') if error.message.match(/No route matched the URL/) # TODO: don't reopen Ember.Route to add events, there should be # a better way (like "parent" resource for everything inside map) diff --git a/assets/scripts/spec/routes_spec.coffee b/assets/scripts/spec/routes_spec.coffee new file mode 100644 index 00000000..6f17472f --- /dev/null +++ b/assets/scripts/spec/routes_spec.coffee @@ -0,0 +1,7 @@ +describe 'router', -> + it 'renders notFound template when URL can\t be found', -> + app '/somehing/something/something/.../dark/side/..../something/something/something/.../complete' + waitFor appRendered + runs -> + expect( $('#main').text().trim() ).toEqual('The requested page was not found.') + diff --git a/assets/scripts/spec/support/conditions.coffee b/assets/scripts/spec/support/conditions.coffee index fbc74720..c490eee0 100644 --- a/assets/scripts/spec/support/conditions.coffee +++ b/assets/scripts/spec/support/conditions.coffee @@ -12,3 +12,4 @@ @queuesRendered = notEmpty('#queue_linux li') @workersRendered = notEmpty('.worker') @logRendered = notEmpty('#log p') +@appRendered = -> $('.ember-view.application').length From f87fe183e442015abf6554c5295ccec95e357762 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Mar 2013 00:00:03 +0100 Subject: [PATCH 5/8] Keep application class at TravisApplication and move it to separate file It helps when application class needs to be reopened before creating application --- assets/scripts/app/app.coffee | 70 +++++++++++++++++++++++++++++++++-- assets/scripts/travis.coffee | 67 +-------------------------------- 2 files changed, 68 insertions(+), 69 deletions(-) diff --git a/assets/scripts/app/app.coffee b/assets/scripts/app/app.coffee index 42641989..311fc067 100644 --- a/assets/scripts/app/app.coffee +++ b/assets/scripts/app/app.coffee @@ -1,4 +1,66 @@ -# $.mockjaxSettings.log = false -# Ember.LOG_BINDINGS = true -# Ember.ENV.RAISE_ON_DEPRECATION = true -# Pusher.log = -> console.log(arguments) +unless window.TravisApplication + window.TravisApplication = Em.Application.extend(Ember.Evented, + authStateBinding: 'auth.state' + signedIn: (-> @get('authState') == 'signed-in' ).property('authState') + + setup: -> + @store = Travis.Store.create( + adapter: Travis.RestAdapter.create() + ) + @store.loadMany(Travis.Sponsor, Travis.SPONSORS) + + @slider = new Travis.Slider() + @pusher = new Travis.Pusher(Travis.config.pusher_key) + @tailing = new Travis.Tailing() + + @set('auth', Travis.Auth.create(app: this, endpoint: Travis.config.api_endpoint)) + + reset: -> + @store.destroy() + @setup() + + @_super.apply(this, arguments); + + lookup: -> + @__container__.lookup.apply this, arguments + + storeAfterSignInPath: (path) -> + @get('auth').storeAfterSignInPath(path) + + autoSignIn: (path) -> + @get('auth').autoSignIn() + + signIn: -> + @get('auth').signIn() + + signOut: -> + @get('auth').signOut() + + receive: -> + @store.receive.apply(@store, arguments) + + toggleSidebar: -> + $('body').toggleClass('maximized') + # TODO gotta force redraws here :/ + element = $('') + $('#top .profile').append(element) + Em.run.later (-> element.remove()), 10 + element = $('') + $('#repo').append(element) + Em.run.later (-> element.remove()), 10 + + setLocale: (locale) -> + return unless locale + I18n.locale = locale + Travis.set('locale', locale) + + defaultLocale: 'en' + + ready: -> + location.href = location.href.replace('#!/', '') if location.hash.slice(0, 2) == '#!' + I18n.fallbacks = true + @setLocale 'locale', @get('defaultLocale') + + currentDate: -> + new Date() + ) diff --git a/assets/scripts/travis.coffee b/assets/scripts/travis.coffee index e30412a0..1f1dbbcd 100644 --- a/assets/scripts/travis.coffee +++ b/assets/scripts/travis.coffee @@ -1,5 +1,6 @@ require 'ext/jquery' require 'ext/ember/namespace' +require 'app' window.ENV ||= {} window.ENV.RAISE_ON_DEPRECATION = true @@ -31,71 +32,7 @@ Storage = Em.Object.extend clear: -> @set('storage', {}) -window.Travis = Em.Application.extend(Ember.Evented, - authStateBinding: 'auth.state' - signedIn: (-> @get('authState') == 'signed-in' ).property('authState') - - setup: -> - @store = Travis.Store.create( - adapter: Travis.RestAdapter.create() - ) - @store.loadMany(Travis.Sponsor, Travis.SPONSORS) - - @slider = new Travis.Slider() - @pusher = new Travis.Pusher(Travis.config.pusher_key) - @tailing = new Travis.Tailing() - - @set('auth', Travis.Auth.create(app: this, endpoint: Travis.config.api_endpoint)) - - reset: -> - @store.destroy() - @setup() - - @_super.apply(this, arguments); - - lookup: -> - @__container__.lookup.apply this, arguments - - storeAfterSignInPath: (path) -> - @get('auth').storeAfterSignInPath(path) - - autoSignIn: (path) -> - @get('auth').autoSignIn() - - signIn: -> - @get('auth').signIn() - - signOut: -> - @get('auth').signOut() - - receive: -> - @store.receive.apply(@store, arguments) - - toggleSidebar: -> - $('body').toggleClass('maximized') - # TODO gotta force redraws here :/ - element = $('') - $('#top .profile').append(element) - Em.run.later (-> element.remove()), 10 - element = $('') - $('#repo').append(element) - Em.run.later (-> element.remove()), 10 - - setLocale: (locale) -> - return unless locale - I18n.locale = locale - Travis.set('locale', locale) - - defaultLocale: 'en' - - ready: -> - location.href = location.href.replace('#!/', '') if location.hash.slice(0, 2) == '#!' - I18n.fallbacks = true - @setLocale 'locale', @get('defaultLocale') - - currentDate: -> - new Date() -).create() +window.Travis = TravisApplication.create() Travis.deferReadiness() From 010754da8aa1ce4d24e5993f427c3c5d70debc9e Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Wed, 20 Mar 2013 19:05:36 +0100 Subject: [PATCH 6/8] Use container as a context to lookup delegated call --- assets/scripts/app/app.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/scripts/app/app.coffee b/assets/scripts/app/app.coffee index 311fc067..c296f5eb 100644 --- a/assets/scripts/app/app.coffee +++ b/assets/scripts/app/app.coffee @@ -22,7 +22,7 @@ unless window.TravisApplication @_super.apply(this, arguments); lookup: -> - @__container__.lookup.apply this, arguments + @__container__.lookup.apply @__container__, arguments storeAfterSignInPath: (path) -> @get('auth').storeAfterSignInPath(path) From 5d049fd7debab5ae0d4a3819155eafa4536766aa Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Thu, 21 Mar 2013 23:46:27 +0100 Subject: [PATCH 7/8] Destroy groups in running jobs after they're emptied --- assets/scripts/app/controllers/running_jobs.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/scripts/app/controllers/running_jobs.coffee b/assets/scripts/app/controllers/running_jobs.coffee index 2a010233..4d81a0e8 100644 --- a/assets/scripts/app/controllers/running_jobs.coffee +++ b/assets/scripts/app/controllers/running_jobs.coffee @@ -10,6 +10,9 @@ Travis.RunningJobsController = Em.ArrayProxy.extend sortProperties: ['number'] ).create(content: @get('jobs')) + willDestroy: -> + @get('sortedJobs').destroy() + add: (job) -> @get('jobs').pushObject(job) unless @get('jobs').contains job @attach() @@ -97,3 +100,4 @@ Travis.RunningJobsController = Em.ArrayProxy.extend removeGroup: (group) -> @get('groups').removeObject group delete @groupsBySlug[group.get('slug')] + group.destroy() From f1adbf8f203203fb177376b42f764f693c8ceae3 Mon Sep 17 00:00:00 2001 From: Piotr Sarnacki Date: Fri, 22 Mar 2013 00:49:02 +0100 Subject: [PATCH 8/8] Improve log handling * don't fetch log content on Travis.Log init * use timeout in ChunkBuffer instead of Ember.run.later * remove timeout when log is finalized --- assets/scripts/app/models/log.coffee | 4 +--- assets/scripts/app/store.coffee | 2 +- assets/scripts/app/views/log.coffee | 4 +++- assets/scripts/lib/travis/chunk_buffer.coffee | 12 ++++++---- .../spec/unit/chunk_buffer_spec.coffee | 24 +++++++++++++++++-- 5 files changed, 35 insertions(+), 11 deletions(-) diff --git a/assets/scripts/app/models/log.coffee b/assets/scripts/app/models/log.coffee index de96b6f6..2c29f9d5 100644 --- a/assets/scripts/app/models/log.coffee +++ b/assets/scripts/app/models/log.coffee @@ -8,7 +8,6 @@ require 'travis/chunk_buffer' init: -> @setParts() - @fetch() setParts: -> #@set 'parts', Ember.ArrayProxy.create(content: []) @@ -35,8 +34,7 @@ require 'travis/chunk_buffer' loadText: (text) -> console.log 'log model: load text' if Log.DEBUG - number = -1 - @append(number: 1, content: text) + @append(number: 1, content: text, final: true) @set('isLoaded', true) Travis.Log.Request = Em.Object.extend diff --git a/assets/scripts/app/store.coffee b/assets/scripts/app/store.coffee index 92519e07..101b5ae5 100644 --- a/assets/scripts/app/store.coffee +++ b/assets/scripts/app/store.coffee @@ -81,7 +81,7 @@ Travis.Store = DS.Store.extend console.log 'store: received job:log event', data if Log.DEBUG data = data.job job = @find(Travis.Job, data.id) - job.appendLog(number: parseInt(data.number), content: data._log) + job.appendLog(number: parseInt(data.number), content: data._log, final: data.final) else if data[type.singularName()] @_loadOne(this, type, data) else if data[type.pluralName()] diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index d3aa63fe..cecae22c 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -165,7 +165,9 @@ Travis.reopen didInsertElement: -> job = @get('job') - job.subscribe() if job && !job.get('isFinished') + if job && !job.get('isFinished') + job.get('log').fetch() + job.subscribe() willDestroyElement: -> job = @get('job') diff --git a/assets/scripts/lib/travis/chunk_buffer.coffee b/assets/scripts/lib/travis/chunk_buffer.coffee index f2e6d8fc..e49a90f0 100644 --- a/assets/scripts/lib/travis/chunk_buffer.coffee +++ b/assets/scripts/lib/travis/chunk_buffer.coffee @@ -2,7 +2,7 @@ get = Ember.get Travis.ChunkBuffer = Em.ArrayProxy.extend timeout: 5000 - checkTimeoutFrequency: 1000 + checkTimeoutFrequency: 5000 start: 1 next: 1 @@ -48,7 +48,6 @@ Travis.ChunkBuffer = Em.ArrayProxy.extend console.log 'Added log parts with numbers:', addedObjects.map( (element) -> get(element, 'number') )+'', 'current', @get('next') queue.pushObjects addedObjects @check() - @inserted() check: -> queue = @get('queue') @@ -60,11 +59,13 @@ Travis.ChunkBuffer = Em.ArrayProxy.extend while queue.get('firstObject.number') <= next element = queue.shiftObject() if get(element, 'number') == next + @finalize() if get(element, 'final') toPush.pushObject get(element, 'content') next += 1 if toPush.length arrangedContent.pushObjects toPush + @inserted() @set('next', next) @@ -72,14 +73,17 @@ Travis.ChunkBuffer = Em.ArrayProxy.extend now = @now() @lastInsert = now + finalize: -> + clearTimeout @get('runLaterId') + checkTimeout: -> now = @now() if now - @lastInsert > @get('timeout') @giveUpOnMissingParts() - @set 'runLaterId', Ember.run.later(this, @checkTimeout, @get('checkTimeoutFrequency')) + @set 'runLaterId', setTimeout((=> @checkTimeout()), @get('checkTimeoutFrequency')) willDestroy: -> - Ember.run.cancel @get('runLaterId') + @finalize() @_super.apply this, arguments now: -> diff --git a/assets/scripts/spec/unit/chunk_buffer_spec.coffee b/assets/scripts/spec/unit/chunk_buffer_spec.coffee index 399dcbb3..a07a5d1d 100644 --- a/assets/scripts/spec/unit/chunk_buffer_spec.coffee +++ b/assets/scripts/spec/unit/chunk_buffer_spec.coffee @@ -1,5 +1,5 @@ -createChunk = (number, content) -> - Em.Object.create(number: number, content: content) +createChunk = (number, content, options) -> + Em.Object.create(number: number, content: content, final: options?.final) describe 'Travis.ChunkBuffer', -> it 'waits for parts to be in order before revealing them', -> @@ -91,3 +91,23 @@ describe 'Travis.ChunkBuffer', -> it 'sets next to start if start is given at init', -> buffer = Travis.ChunkBuffer.create(content: [], start: 5) expect(buffer.get('next')).toEqual(5) + + it 'runs finalize after getting final element', -> + finalizeRuns = 0 + buffer = Travis.ChunkBuffer.extend({ + finalize: -> + @_super.apply this, arguments + finalizeRuns += 1 + }).create(content: []) + + buffer.pushObject createChunk(1, "foo") + buffer.pushObject createChunk(2, "bar") + buffer.pushObject createChunk(3, "baz") + + expect(finalizeRuns).toEqual(0) + + buffer.pushObject createChunk(4, "qux", final: true) + + expect(buffer.get('length')).toEqual(4) + + expect(finalizeRuns).toEqual(1)