fetch method returns a promise instead of an actual object. We used find
before, because this was the way we did things before upgrade to Ember
Model. Returning a promise from a model hook pauses router rendering for
the time a resource is loading, which makes it much easier to deal with
asynchronous requests. Thanks to that we can remove parts of the code,
which dealt with it manually.
After update specs fail when there is an unexpected ajax query, because
the response is not an ajax response.
A long term solution is to remove mockjax from specs, because it makes
them brittle and they usually fail after small changes. A better
approach would be to use fixtures, which are available for ember model
When a lot of pusher events come with build updates, lastBuildDidChange
can run quite frequently. We can avoid that by using scheduleOnce, which
will ensure that only the last invocation of lastBuildDidChange will be
run for a given runloop run.
Don't successfully `githubify` strings prepended with an `@` symbol if
what's matched actually resembles an email address. @mentions should
only be githubified if there is a word boundary before it.
This fixestravis-ci/travis-ci#1591
Signed-off-by: David Celis <me@davidcel.is>
lastBuildHash uses information for last build, which is available on the
repo object, so it will not trigger an ajax request if we haven't
fetched a build yet.
When first sync template is displayed, user usually doesn't have any
repos, which also triggers rendering of getting started template. The
fix for this is to handle the action to render getting started page on
first sync and do nothing in such case.
I also added a test to ensure that it works correctly.
When user activates a repository in the profile page, we now will
display this repository on the 'My Repositories' list. When user chooses
this repository, she will see an explenation why there is no builds and
what could be done to fix this.
Conflicts:
assets/scripts/app/controllers.coffee
assets/scripts/app/models/repo.coffee
assets/scripts/app/templates/repos/list.hbs
Ember Model does not do it automatically. I had a patch, which was
changing that, but after giving it more thought, I think it's not a good
idea - this should be up to adapter if the records are going into
record arrays.
When the job is restart, we will not get any updates unless we're
subscribed to job updates - that's why we need to subscribe even if the
job is already finished.
The other option to fix this would be to subscribe and unsubscribe also
based on the status, but since subscribing to finished jobs does not
cost us anything, I prefer the simpler solution.
log property in Travis.Job does not change - we create Log instance
when it's accessed and don't refresh it on any occasion, that's why the
observer on log is not needed.
I changed it to be a Number along with Job's number, but it's wrong -
Build's number should be treated as an integer (to not screw up
ordering) and Job's number can be treated as a string (because it has a
format "\d.\d")
We observe last build on the repo in order to show the freshest build on
repo page. I moved it to router in order to keep such observers in the
same place, but this was not a wise move. To make it work properly
observer needs to be removed when moving to some other part (like
build's page). The problem is that deactivate function is not called
when we move to the other route in the same nesting. We have our own
'activate' function on repoController, which is better suited for
handling this task.
This change pushes the cog menu to the top, where it belongs, as it
now only includes repository-relevant actions. The icons now reflect
things relating to the build/job itself, and have replace the cog
meny.
The hack which is needed for wrong outlet behaviour renders a template
when outlet is not rendered automatically, but it was done immediately.
Because of that when changing routes from index to job route, sometimes
the hack was kicking in and rendering build instead of job template.
This commit fixes it to check if rendering is needed in "afterRender"
phase on runloop.
When adding records just after loading them, the elements in the UI
might have to be updated, which may trigger `get` on associations right
away. As an effect, even if we load a few records on an event (like
repository on build:started event), ember model may end up fetching the
record.
This commit fixes such occurrences by adding record to record arrays in
a run loop, so newly created records will be added at once, after the
event was served.
Hooks were sometimes not loaded, because user property on
ProfileController was not available. This commit tries one additional
way to get a login - Travis.lookup with controller:currentUser.
Rendering on firefox was broken due to the difference in time when DOM
loads - without deferReadiness it was sometimes failing to add
ember-application element to body
We use `allBuilds` to observe new incoming builds, so we can put new
builds into the lists (for example when build is started). We use it for
observing purposes only, so we actually don't need to get builds from
the server, we can just register record array and use it later on.
This piece of code was used in order to load repos associated to jobs
when the latter were loaded from pusher. This was needed because jobs
events do not have repository record passed in pusher payload, so when
job was added with pusher and link to the job was displayed in "Running
Jobs" or in workers on right sidebar, Ember was loading missing repos.
We don't need this code anymore as there is no right sidebar.
Additionally after changes in Ember.js, it's possible to pass primitives
to linkTo. Previously the link to record needed to be constructed as
following:
{{#linkTo "job" job.repo job}}Link to repo{{/linkTo}}
The drawback of such code is that repo would have been instantiated in
such case. Now, we can do something like this:
{{#linkTo "job" job.repositorySlug job}}Link to repo{{/linkTo}}
so as long as we have information about repository slug in the job data,
such hacks are not be needed.
When collections are loading as ajax requests, we may still get pusher
updates, which will try to add records to these collections. In order to
make it work nicely, we should wait until Ajax request finishes (ie.
content of record array is set) and only then add objects from pusher
Previousy I was using find to ensure that the record is materialized,
but the new version is much lighter - it uses Model#load to load the
record directly
After changing Ember Data to Ember Model, the default behavior is to
not return promise by default from `find` call. This is better in
general for our use case, because we don't block rendering the UI while
data loads, but we now have to handle cases where model is not yet
loaded in `setupController`
Previously we showed only accounts and repositories, to which you have
admin access. To improve usability, it's better to show all accounts and
all repositories, but explain why part of the repositories are not
manageable.
When router is not set up yet sending events to it will fail. If that's
the case, we can just swallow the error, because afterSignIn will take
effect only if we are already in some state in the router.
Previously we were checking if we should display an error message by
adding if statements in a template. This is not the best way to do
it, because it clutters a template and makes code harder to follow.
In this commit I move rendering error templates to the router. Code for
rendering error when there is no builds is not the best way to do it
either, but it can be improved when new router changes are merged to
Ember's master and a way Ember Data is handling promises is revised and
improved.
Till now, when switching between different views, we were switching
different bindings on repo controller. This was quite innefficient,
because then we needed to add bindings also from other controllers and
it's hard to manage such structure when we would like to add specialized
controllers (like LogController).
The new setup is more declarative, meaning that we do such things on the
router and set things on proper controllers. The only drawback is that
now we need to setup a few observers instead of bindings for "current"
views (ie. when viewing the newest repo or when viewing the last build
in current repo).
At this point it may not look like huge improvement, but it will open a
way to more refactorings.
When user has Travis CI's web page open in the background we should not
process pusher events immediately, because she will not see the changes
on a page anyway. During peak hours we can get several messages per
second, which requires some CPU work almost all the time. By using
visibility API we can detect if the tab with Travis CI is in the
background and if that's the case we will process pusher messages in
batches every 5 minutes. This is much better for the CPU, because it
means one bigger spike every few minutes and additionally some of the
updates don't have to be done (for example if we get several job:started
events, Ember's run loop will process only last one when it comes to
rendering 'current' build).
Visibility.js provides a thin wrapper over page visibility API, which
allows to detect if page is currently visible by user. This allows us to
stop live updates when it's not needed. This is especially easy in case
of timers, because Visibility.js provides setInterval replacement, which
runs given code only when page is visible.
A lot of ❤️ for @tchack, who showed me visibility.js!
It seems that running Ember.run.later periodically can cause CPU usage
to increase over time. Such increase adds up to already increasing CPU
usage because of data amount growing.
This commit tries to mitigate the issue by using setTimeout instead
This will make them look nicer on Retina screens. We may want to make
them even bigger if people are increasing the size of the page on
Travis, but doing that causes all kinds of alignment issues, so it's not
necessary to do now, I think.
When logging out and then logging back in, there is sometimes an error
when registering flash view, which says that it can't register 2 views
with the same id. We don't need to use id here, so I just changed id to
class