All posts by Owen Buckley

Since it was created in 2007, GitHub has not only become the primary destination for open source development and distribution, but also one of the largest collaborative platforms on the internet. GitHub’s open source practices have established the platform as one to the most important tools for developers and gives coders of all levels a place to learn new skills, contribute to a vast number of projects and work alongside other programmers. Kenzan is a company that leverages the benefits of open source software by opening many of our  projects to the community and contributing to others in order to support the technology landscape at large.

More than just a GUI on top of Git, the GitHub platform  offers many powerful tools  and features that can help maintainers of OSS projects provide a more useful, transparent, and open experience for their project and their community. In this post, we will walk through some of the best practices that can help make an OSS project successful and inspire community participation and contribution.

Getting Organized

In order to ensure a consistent path to PR integrity, acceptance and delivery, it is important to make sure team permissions are setup appropriately.  At Kenzan, we identify maintainer and contributor teams for our projects.  The primary goal is to establish a protected branch (typically master) for a given repo and those who should have write access to it. Protected branches allow you to give read access to everyone else in the organization or an internal contributing team, but only permit a small team to actually be able to manage the main line of development. Roles can be defined as:

  • Maintainers – Act as the stewards of the project with sole access to protected branches like master
  • Contributors – Community team within the organization that are allowed to read and push branches within the repo

Below is an example of a sample configuration that protects the master branch with options like:

  1. Ensuring only the maintaining team can push to master
  2. Requiring PR approvers
  3. Requiring PRs pass a Continuous Integration build

Pro-Tip!
Always use teams for delegating repo access, for both maintainers and contributors. This will ensure easy addition and removal of members, as well as a simple and streamlined permissions strategy for your organization and repositories.

Welcoming Contributions

Great software is developed by many people contributing more than just code like testing, refactoring, documentation, and more.  However, each project is generally run in a particular way, and so clearly communicating these specific processes and workflows can help make a big difference in the growth and success of your project.  Guiding developers and contributors through the following recommendation will  help ensure understanding and onboarding from the start.

  • README.md – First impressions are everything, so a README that includes important information like an overview (your “elevator pitch”), installation/setup, usage and example, license, etc., will ensure first timers to your project know exactly what it is, what it does, and if it is right for them.
  • CONTRIBUTING.md – by including a CONTRIBUTING.md in your project’s root, you can define the Contributing Guidelines for your project. With this, GitHub can prompt all users who open an issue or PR to your project with a link to read it.
  • LICENSE – Having a LICENSE file is important to disclose to users how your project can be consumed, used, and distributed. In addition, be aware of the license expectations of any dependencies your project has.
  • Webhooks – Webhooks allow “push notification” integration with 3rd party services such as a Continuous Integration server like Jenkins.  Anything that can be automated in your project (linting, static analysis, style guide, tests, etc) should be scripted and run against every PR to provide fast turnaround and feedback to contributors (i.e. pass or fail).  Kenzan uses GitHub PR Builder.
  • Issues / PRs – GitHub has done a lot to improve the features around these workflows, in particular Pull Request Templates, fields for reviewers, assignees and labels, reactions and many others.  These are great features for identifying/establishing ownership and status.

Below is an example of a PR making use of some of the available PR fields like

  1. Contributing guidelines (the yellow banner)
  2. PR templates (the content inside the textarea)
  3. Reviewers / Assignees

Pro-Tip!
Always create an issue for any non-trivial change. This promotes discussion of the feature to happen independently of the code review itself.

Bonus!
If you link to the issue in the PR, using #XX (where XX is the issue number) GitHub will close the issue when the PR is merged.

Steering the Project

As a project grows and matures, planning out goals and improving documentation will naturally require some additional organization.  No worries, GitHub has you covered!

  • Project Management – Leverage features like milestones and projects to group issues into related buckets of work.  At Kenzan, we see projects as sprints (in agile terms with one or more projects making up a milestone. This allows a project’s mantainer to communicate their roadmap clearly and can help direct contributors to where help is most immediately needed.  It also helps establish feature / bug delivery expectations.
  • Release Management – Whenever a Git tag is pushed to your repository, GitHub will create a link to a page for that tag, thus enabling  the easy creation of release notes for every tag.  This is useful for tracking progress over time and to keep a record of features and bugs completed.
  • Wiki – The wiki is a great place to organize and manage supplemental information for consumers and developers. Rather than pack everything into the README, the wiki can be used to establish separate documentation for onboarding, migration guides, API docs and more.
  • GitHub PagesGitHub Pages are a simple way to generate web content from source code or even just markdown and deploy that to a domain. This is a simple way to create a nice product, marketing, or API documentation for users with minimal fuss and overhead.
  • GitterGitter is a chat platform that integrates with popular development/OSS tools like GitHub, Jenkins, Bitbucket, Trello, and others that can allow you to foster a real time community around your project, assist others or let the community jump in and help!


In the below screenshot, we can see an example of the project feature in action, tracking issues sourced from the issue tracker.

Closing Thoughts

Hopefully this has helped shine a light on some of the great features and workflows GitHub  offers to support the development of your own OSS project.  It is important to remember that Open Source is an inclusive process by nature, so make sure to be open to feedback and respectful of all contributions. OSS will undoubtedly attract contributors of all skills levels, so make sure to engage openly and without prejudice. Likewise, if there are small bugs or documentation tasks, you can recommend those to newcomers as part of your onboarding documentation. With robust documentation around your project and workflows, developers are more likely to contribute and newcomers can self-onboard, with minimal guidance from you.

Most importantly, developing software should be fun and rewarding.  When the right people get together with the right tools and in the right way, great things can happen. Happy coding!

While there is a plethora of amazing open source tools out there, recent advances in the EMCAScript language specification (ES6/ES2015) have brought amazing power and expressiveness to the web for JavaScript. Language features like import, module loading, and classes have made writing JavaScript cleaner, more consistent, and less reliant on opinionated tooling, thus making code written today in ES6 immune to churn and less likely to become “legacy,” even after a few years. While these claims are bold, they are, in fact, very realistic, well-reasoned, and do not prevent teams from using their preferred build tools or any of the popular frameworks/libraries available.

The main concepts covered are:

  • Language Specification – Embrace ES6 or, ideally, Typescript
  • Dependency Management – Consume your dependencies in a universal format, be it from NPM or Github, while still being standards compliant
  • Module Loading – Load not only your JavaScript, but also your CSS, in accordance with standards compliance.

ES6 and TypeScript
ES6/ES2015 is the current iteration of JavaScript, which brings with it a number of useful features like classes, import/export statements, fat arrow, and improved support for variable scoping. This is a direct acknowledgment by the standards committee to support the needs and experience of developers, as our JavaScript applications have gotten bigger and more complex over the past few years. However, there is also a need to incorporate tried and true conventions from mature, strictly typed languages like Java, where concrete types and values can be caught before the code even reaches the browser.

While an excellent tool like Babel will make sure that one can write the ECMAScript of tomorrow today, TypeScript will do the same but will also support interfaces, member/method privacy, and member/argument types. As applications grow and become more “distributed” (component libraries/micro ui’s), and client side data management, consistency, and durability becomes more mission critical, TypeScript will ensure continuity and compile time feedback to developers.

Below is an example of a React component written in ES6. Inline comments added here to highlight key language features:

'use strict';

//we can import all our dependencies explicitly per module / component
import React from 'react';
 
//we can even load our CSS!
import './user-details.css!';

import { GithubStore } from '../../stores/github/github-store';

//here we use ES6 classes and merely extend the React library.  This is the only usage of React in this entire file
//we now align our components with a concrete language feature.  Our components are just classes at the end of the day

class UserDetails extends React.Component {

  //no longer we have init, activate or IIFE to kick off our component.  There is now consistent standard provided by the language
  constructor() {
    super();

    this.state = {
      avatar: '',
      name: ''
    };

    this.getUserDetails();
  }

  getUserDetails() {
    let store = new GithubStore();

    store.getUserDetails().then(response => {
      this.setState(response.data);
    });
  }

  render() {
    return (
      <div className="user-details">
        <img className="user-avatar img-responsive" src={this.state.avatar}/>
        <h1><span className="user-name">{this.state.name}</span></h1>      </div>
    )
  }

}

//ES6 way to expose our class for others to consume
export default UserDetails;

Below are some TypeScript code samples, based on the Angular 2 Tour of Heroes guide. Inline comments added here to highlight key language features.

//we now have support for strictly typed language features like interfaces
export interface Hero {
  id: number;
  name: string;
}
 
//an example of an Angular 2 Component
import { Component, OnInit } from 'angular2/core';

import { Router } from 'angular2/router';

import { Hero } from './hero.interface';
import { HeroDetailComponent } from './hero-detail.component';
import { HeroService } from './hero.service';

//here we are using ES7 decorators (supported in TypeScript) to annotate our component

@Component({
  selector: 'heroes-list',
  templateUrl: 'src/components/heroes/heroes-list.component.html',
  styleUrls:  ['src/components/heroes/heroes-list.component.css'],
  directives: [HeroDetailComponent]

})

export class HeroesComponent implements OnInit {

  //with TypeScript, we are able to enforce member types, as defined by our Hero interface
  heroes: Hero[];

  selectedHero: Hero;

  //with TypeScript, we are able to enforce privacy and argument types

  constructor(private router: Router, private heroService: HeroService) {

  }

 getHeroes() {

    this.heroService.getHeroes().then(heroes => this.heroes = heroes);

  }

  ngOnInit() {

    this.getHeroes();

  }

  onSelect(hero: Hero) { this.selectedHero = hero; }

  gotoDetail() {

    this.router.navigate(['HeroDetail', {
      id: this.selectedHero.id 
    }]);
  }
}


Dependency Management
Dependency management for JavaScript applications have conventionally been managed through Bower, and more recently through just NPM itself alone. Either way, package management has relied on ultimately delivering all static assets (concatenated or not) to be included via  <script> and <link> tags in an HTML file.  But!  No more!  JSPM was specifically developed to support SystemJS (covered in the next section) as the de facto package manager for client side JavaScript.  It can:

  1. Install a package / module / library / etc from NPM or Github.
  2. Save a single configration file (js) that captures the entire dependency graph for an application, such that all dependencies can easily be loaded in the browser with just a single JS file in a <script> tag.
  3. Bundle all dependencies to be loaded into the browser; either for development or production (minified and concatenated).

Module Loading
Module loading and dependency management, although separate concerns, often go hand-in-hand in the build process and the runtime of an application.  Though it didn’t make the final cut of the current ES6 spec, a module loader specification called System, which can be polyfilled today using SystemJS will be coming in ES7.  This allows us to greatly reduce the overhead in our code by allowing us to use ES6 import today with all our client side static assets, in addition to be able to load all our third-party vendor dependencies and the underlying dependency graph needed to support them all with a single <script> include.

Although there are tools like Webpack or Browserify which aim to encapsulate the entire build and packaging lifecycle of an application, they are not specifically built around ES6 like SystemJS is. For that reason, the choice to use SystemJS over Webpack or Browserify is specifically because of its primary motivation to support ES6 / ES7 and forgoing any sort of “vendor lock-in”.  Both SystemJS and JSPM are also authored by the same developer, Guy Bedford.

Below is an example of what the index.html of a SPA looks like when using SystemJS / JSPM.  Inline comments added here to highlight certain features.

<!DOCTYPE html>

<html lang="en">
 <head>
    <title>Github Dashboard</title>    <base href="/">
    <meta charset="utf-8">
    <meta name="description" content="Github Dashboard"/>
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>

    <!-- single line to import the System polyfill -->

    <script src="./jspm_packages/system.js"></script>

    <!-- import our vendor dependencies, as generated for us by JSPM-->

    <script src="./config.js"></script>

    <!-- kick off our application, and that's it! -->
    <script>
      System.import('src/bootstrap.js');

    </script>

  </head>

  <body>

<div class="container-fluid">

       <div class="col-md-*">
        <section id="content"></section>
      </div>

    </div>

</body>


</
html>

Rounding Things Out
As mentioned, this guide is opinionated only as it relates to future-proofing of how one writes and maintains their JavaScript in order to be as accommodating to standards and specifications as possible. Intentionally left out of this article are two key layers of the stack:

  1. Build / task runners
  2. UI library / frameworks

While there is no opinion on these, there are of recommendations and considerations.  For your build it is recommended to use Gulp via Keystone, as it is fast, composable, and has a robust ecosystem of plugins and can be installed and managed with NPM.  For the UI, any library or framework that plays nicely with the underlying stack here, like ReactAngular 2, or Aurelia will work as long as it is the right one for your application’s needs. What matters is that whatever you substitute, the only requirement should be that it plays well with ES6 and SystemJS / JSPM, so as to make the next few years of your JavaScript development as frictionless as possible.

So putting it all together, here is our stack of the future, today!

frontend-stack

This post was written by Owen Buckley, a software engineer based out of Kenzan’s Rhode Island office.