engineering

Ably Engineering Team: GitHub Standards and Best Practices

This document details how the we use GitHub at Ably. The goal is to conform, where possible, so that as developers move from repository to repository the experience is predictable and unsurprising.

The standards and best practices documented on this page are intended to be:

GitHub First

On first inspection, for those granted access to Ably’s internal systems, it can be a little bit confusing that we have two ticket / issue management systems in concurrent use for our client libraries (GitHub issues and Jira). They complement each other and this section aims to explain why.

One of our key company values is being open for all. Our client library codebases align with this value as they are open source, available to view in every detail in the public domain.

GitHub…

Allows external parties to contribute by:

Allows us to:

Jira…

Used for internal management.

GitHub issues are bidirectionally synchronised with Jira.

Jira allows us to add internal meta-information beyond what GitHub issues allow us to - this includes:

…GitHub first!

Generally the following operations should be performed from GitHub, not Jira (unless they are issues which solely exist in Jira):

The primary reason is that this uses your real GitHub identity to associate with the operation from a public domain perspective. Operations done from Jira sync over to GitHub using a bot account and that looks ugly and awkward for external viewers.

Repository Names

The convention at Ably is to name repositories in the ably GitHub org that contain the source code for a client library / SDK with an ably- prefix. For example, ably/ably-js, where ably is the org and ably-js is the repository name.

Pull Requests

See Pull Requests for guidance around how we work on PRs in open source.

Workflows

This section describes our ways of working with GitHub workflows.

GitHub documents them under the umbrella of GitHub Actions, which has resulted in ‘Actions’ somewhat incorrectly being adopted as the all-encompassing title for this technology. The reality is that an Action is just a component of this technology stack, a thing that is downloaded and invoked by workflows (see jobs.<job_id>.steps[*].uses in the syntax for workflows).

Filenames

This is the name of the file within the .github/workflows folder.

Names

Name vs Filename

The root name key, typically defined at the top of the workflow file, should match the file name with:

Examples:

Some History re Workflow Names

The name key, at the top of the workflow file, is defined as optional.

When we started using workflows, we took the decision to take advantage of this optionality and not define the root name for workflow files, due to the fact that it generally seemed to just repeat the name of the file. More recently, we’ve come to realise that the GitHub user interface will use this name to represent workflows in a much more concise and human readable form. When omitted, the full path to the workflow is used and this is ugly (for example: as .github/workflows/check.yaml in the ‘Actions’ tab of a repository).

Triggers (on:)

Unless there a good reason to deviate from this, workflows should always be configured to trigger as follows:

on:
  workflow_dispatch:
  pull_request:
  push:
    branches:
      - main

Job Names

This one’s a work in progress at the moment. If in doubt use check. We’re also using build in some places (e.g. Android Asset Tracking’s docs workflow), where the job’s purpose is generating built output that’s intended to be accessible beyond the lifespan of the workflow.

It’s important because when we create branch protection rules (typically for the default branch, main) we want to tick the box to “Require status checks to pass before merging”, which then presents us a list of job names under “Status checks found in the last week for this repository”.

Matrix Strategies

By default GitHub’s fail-fast property on strategies is set to true. While that might be kinder from GitHub’s perspective on their server resources, as jobs will get cancelled prematurely, it doesn’t help us debug when things go wrong. So, generally, our preference is to override the default and explicitly specify false for fail-fast.

It’s a growing trend across our org. :smiling_imp:

Actions

To support our workflows we’re developing our own Actions - the LEGO-like modules that allow us to build build ourselves bigger structures from proven components of functionality.

SDK Upload Action

ably/sdk-upload-action

Pushing artifacts to sdk.ably.com (see this internal page for more information on the S3 bucket that underlies this domain).

Deployments and Environments

The docs repository has been using these for a while, with its own naming convention for environments.

We are also evolving a naming convention for environments. Initially modelled in ably-flutter #92, tied in with the SDK Upload Action.

Labels

The following table canonically defines labels we use in common across our open source repositories:

Name Color Description Additional Notes
blocked-by-ably fbca04 We can’t proceed until something under our direct control, in a different codebase, happens. Comments should be added to indicate what the blockage is (e.g. another repository).
blocked-by-external fbca04 We can’t proceed until something outside of Ably’s direct control happens. Comments should be added to indicate what the blockage is.
breaking ec4b42 Backwards incompatible changes made to the public API. Implies a need to release related changes in a major version bump.
bug d73a4a Something isn’t working. It’s clear that this does need to be fixed. Usually implies that related changes can be released in a patch version bump.
build dcd0ff Relates to the tooling used to build or release the contents of this repository.  
code-quality ff88cc Affects the developer experience when working in our codebase. Relating to the maintainabily of the codebase, not affecting the public API, therefore unlikely to be customer facing.
documentation 0075ca Improvements or additions to public interface documentation (API reference or readme).  
enhancement a2eeef New feature or improved functionality. Implies a need to release related changes in a minor version bump.
example-app 70fc6b Relates to the example apps included in this repository. Not all repositories have embedded example apps.
failing-test ff8888 Where an automated test is failing either locally or in CI. Perhaps flakey, wrong or bug.  
investigate 9acd32 Requires further investigation to decide the most appropriate label(s).  
testing ff8888 Includes all kinds of automated tests, the way that we run them and the infrastructure around them.  

The Name, Color and Description values above should be used when creating the corresponding labels in repositories.

It is expected that some labels will be used together - for example enhancement and breaking, indicating a feature that’s been added in a way that introduces backwards incompatible changes into the public API, therefore implying the need to release in a major (not minor) version bump.

The breaking and enhancement labels must be applied to all pull requests to which they apply (see: Guidance on Releases: Version Bump). They can also be applied to linked issues, but this is less important than labelling the change itself (i.e. the pull request).

While GitHub does allow us to use mixed case and spaces in label names, we’ve restricted ourselves to all lowercase and dashes instead of spaces to separate words.

We do not have any labels that imply or otherwise infer importance or prioritisation of issues or pull requests because that information is internally managed using Jira (see GitHub First).

Flexibility

What things we’re flexible about

Things that the Ably Engineering Team, in the open source work that we facilitate, intentionally don’t require contributors to do:

Why we’re flexible about some things

So, why do we leave some things flexible and up to individual preference?

Primarily, as stated at the start of this page, we - as a team - learn from experience. This means that there are things we end up converging on, as best practices or standards, because they’ve been shown to be sensible things to do in order to enable our work to progress productively and predictably for everybody involved. We, therefore, feel it’s worthwhile sharing those things as standards and best practices on this page.

However, conversely, there are things that - again, based on our experience - haven’t been shown to matter that much. More often, it turns out that many of these things are somewhat subjective in nature. We don’t feel it’s necessary to mandate rules or policies around these things as, on balance, we would prefer to tip the balance in these areas to allow individuals to express themselves with the work that they do in the way that they feel most comfortable.

We’re not machines. We’re humans. Let’s keep this fun!

See Also