Telescope: a pants-off approach (🔭🚫👖)

During our last sprint—titled Goodbye Random Pants—the Telescope team largely focused on slimming down our back end, as well as beautifying our front. That disclosed, please allow me to unpackage my own contributions to these efforts.

No more dateless pin-ups

For quite a few weeks, Telescope was placing one particularly-broken post on a pedestal (atop all other posts) just because it refused to give us a date:

Issue #757 – Telescope was ‘pinning’ a post without a publication date

This infamous post in question was being ‘pinned’ to the top of the Telescope’s feed list due to it being provided with a new date of publication upon being processed. As such, this post was provided with a publication date more recent than any other processed posts, which consequently caused it to be hoisted to the top of Telescope.

The solution that I presented simply involved preventing posts without a publication date from being processed:

PR #823: reject posts without a publication date

Implementing a fix for this issue required adjusting the logic within post.js involving the handling of missing or invalid publication dates. I did this by writing a robust ensureDate() function, which now validates each the two dates associated with each blog post (dates of publication, and of last update):

An ensureDate() function is now used to validate post dates

This function ensures that posts with an invalid publication date do not get processed (via throwing an error), while all other posts do. Notably, this function allows posts that lack a valid date of last update to be processed if they possess a valid publication date to fall back on.

Never drop trou(bleshooting)

Within my last blog post, I described how I “ventured into [four] aspects of Telescope that I had previously had zero interaction”. During this last sprint, I continued my streak, touching three aspects of Telescope completely new to me: authentication (passport.js), GraphQL, and releasing.

Gatsby.js authentication: graphql-passport

As Telescope appears to drift closer toward a serverless future, the team has been slowly enabling our Gatsby.js GraphQL to perform duties that previously required sending a request to one of our many backend REST API routes.

One such key duty was authentication—more specifically, querying user information from our passport.js implementation:

Issue #701: Add authenticated user info to GraphQL via passport.js
The (very-necessary) background reading I was kindly suggested

Although I had previously zero experience with GraphQL, this issue seemed fairly straightforward to resolve: all that needed to be done was (do some reading and then) install an npm package… right?

Well, it so happened that those steps were just the beginning of a lengthy learning experience.


My initial installation/implementation of the graphql-passport module went fairly smoothly. This involved simply involved installing the module, importing the buildContext() function, and adding a context: ({ req, res }) => buildContext({ req, res }) property to the object used to construct our ApolloServer. The only challenge, here, was determining whether or not we needed to pass some User schema to buildContext(), as suggested by some of the author’s code examples (we do not).

Now, with the installation out of the way, a final, crucial step remained: testing it all; ensuring everything actually worked…

and, it did not (for quite some time).


Within the description of my penultimate pull request (#824), I detailed the exact method that I used to test our graphql-passport implementation:

PR #824: Add graphql-passport to Telescope

Again, in text, here was the method used to test this pull request:

  1. Check out this PR locally.
  2. Run npm install, installing the added graphql-passport module.
  3. Within src/backend/web/graphql/index.js, add context as the third parameter of a GraphQL resolver of your choice.
    • e.g. The parameters of getPosts would be updated as such: (parent, { filter, page, perPage }) -> (parent, { filter, page, perPage }, context)
    • (It is not necessary to make any changes to typeDefs)
  4. Within the function body of your chosen resolver, add a statement to log context.isAuthenticated() and/or context.getUser() to your console.
    • e.g. console.log(context.isAuthenticated(), '\n', context.getUser());
  5. Run docker-compose up redis login elasticsearch (Telescope’s SAML server needs to be running)
  6. Run npm start (the backend must be run locally)
    • (Ensure that API_URL is set to http://localhost:3000 within your .env file)
  7. Navigate to http://localhost:3000/auth/login and log in with the credentials user1/user1pass (as per our login documentation)
    • (You can confirm logged-in status by visiting http://localhost:3000/user/profile)
  8. Navigate to http://localhost:3000/graphql and write a query of choice corresponding to the updated resolver.
    • e.g. a query for getPosts: { getPosts(page: 0, perPage: 1) { id } }
  9. Execute the query.
  10. Observe the statement logged to Telescope’s console, which should look something like this: true, { ... email: 'user1@example.com' }

For quite a long time, Step #10 instead returned false, undefined for me—and I could not, for the life of me, figure out why.

Thankfully, from the start, I have been collaborating on this issue with the extremely-knowledgeable @manekenpix. Unlike the other mystifying issues I’ve dealt with in the past, I did not spend long dwelling on it alone, and soon reached out privately to @manekenpix for a sanity check as well as for “hints” that may push me towards a solution.

@manekenpix was extremely accommodating of my sporadic requests for “clues” in lieu of an outright answer to my issues over the course of a few days. Ultimately, he (and then I, eventually) discovered two problems with backend/web/app.js as it was:

An excerpt of backend/web/app.js, as of commit c1eb65d

The first problem can be observed within this code excerpt: passport.js was being initialized after our GraphQL middleware was being applied. Moving lines 50 to 52 up to before line 35 resolved this particular problem.

However, making this single change resulted in no different output than before: still false, undefined. This problem ended up being extremely difficult to track down, and was only resolved by @manekenpix and he delved past the author’s documentation and into two sample implementations.

Despite receiving a hint that these implementations held the key to resolving the remaining problem, I was still having difficulty singling out the remaining change I needed to make to backend/web/app.js. As such, I requested that @manekenpix publicly share his solution to our two problems:

A comment by @manekenpix within PR #824

As it turns out, the elusive ‘second problem’ that I was experiencing was not, per se, an issue with any of the code that we had added to backend/web/app.js (or its positioning). Rather, it was an issue stemming from how our GraphQL Playground is configured by default.

It turns out that GraphQL Playground, by default, omits cookies sent in response to cross-origin requests. (Of course, this ended up being yet another CORS issue… and, it is worth noting that this default behaviour is the exact opposite of what we may be are accustomed to.)


Configuring our GraphQL Playground to accept cookies (via the playground property shown in @manekenpix‘s comment, shown above) resolved the final problem, allowing me to finally confirm that graphql-passport was working.

With that, I marked my draft pull request as ready for review, adding testing/reviewing instructions to its origin post, and the rest is history.


Now that PR #824 has been merged into Telescope, I plan to utilize our new graphql-passport functionalities within my work during the current sprint (more details to follow within in a subsequent blog post!)

Now released: Telescope v0.8.0 v0.8.1 v0.8.2

“We don’t speak about 0.8

Well, perhaps, except right now.

I was fortunate enough to experience Telescope’s releasing workflow firsthand, volunteering to perform a GitHub release for Telescope v0.8.0, officially ending that sprint.

Our releasing process is made very simple thanks to release-it, essentially entailing running a script and answering a few questions. The end result of our release process should result in a fully-fledged GitHub release being added as Telescope’s current release (as was the case with our previous releases).

However, this was not the case for Release 0.8.0: it failed due to a history conflict between my local master branch and the upstream/master branch. Although this conflict was easily resolved by resetting my local master, this failed attempt added a v0.8.0 GitHub tag, necessitating that my subsequent second attempt at releasing specify a new tag, i.e. “0.8.1”.

My second release attempt (v0.8.1) also failed, but in a different and strange way: this time, the release ended up being fully performed on my fork of Telescope, but not on the upstream repository (as before, only the 0.8.1 release tag was added to the upstream).

This result was puzzling, and indicative of a bug with release-it. As such, @humphd opened an issue with release-it, which was very quickly confirmed and patched by their dev team. Not missing a beat, @humphd updated our release-it configuration, which enabled me to finally successfully release Telescope v0.8.2.

“Hold onto your butts…”

…as Samuel L. Jackson put it in Jurassic Park (1993). Telescope is currently experiencing a feature bombardment prior to a code freeze. It’s a rocky time, both here on Earth and up in the cloud.

During this current sprint, I plan to use utilize some of the tools I talked about within this blog post to finish implementing the ‘My Feeds’ page (which I discussed within my last blog post)… details to follow within a subsequent blog post. Stay tuned, and stay safe. 🔭