Understand, Automate, Collaborate

Rod Johnson
The Composition
Published in
8 min readNov 7, 2016

In previous posts, we’ve seen how Atomist can understand and modify project source code. Today I’ll show how understanding and modification can extend beyond a single project and beyond source code, and how it can help teams be more productive.

Modern systems involve many moving parts. Many organizations have dozens, if not hundreds, of services in production. Each service is more than source code, with a wealth of surrounding context, such as who works on it, what endpoints it exposes and how it’s built.

Imagine if you could update all relevant projects to use a new version of a framework, introduce a new monitoring technology, change an important configuration option or modify how deployment takes place, in a single operation. Imagine if you could route a piece of information to precisely those developers who care about it: For example, developers who work on a particular service or on services that consume it.

An Atomist executor can do all this and more. While an editor enables us to automate changes to the source code of a single project, an executor works on the big picture.

Note: We now call this concept a command. For current information, see our docs.

Atomist editors automate changes to a single project; executors can act on multiple projects, with awareness of their context and reaching beyond source code. This enables teams to automate many common tasks.

Let’s consider a common requirement: Preparing services to run in a containerized environment via Docker. It’s straightforward to write Atomist editors to perform this change, and there’s value in performing it consistently across all projects, using the same conventions. For example, we can Dockerize a GoKit application like this:

Note the precondition, which ensures that this editor will not change projects it doesn’t understand. Many editors will have more complex predicates reflecting deeper understanding of project structure. The Dockerfile content comes from a template, which is merged and then updated by the editor using our Rug Docker type.

Note: for current information, see our docs — the Rug DSL has been deprecated

Executors can update multiple projects by invoking editors, after automatically collecting parameters on their behalf:

The “with” block invokes the editor on all services associated with the present context. The Dockerize executor builds on technology-specific editors such as our GoKit editor to handle multiple project types.

Bringing Functionality to Where It’s Needed

Such changes should be run in a collaborative environment. For example, the teams working on each service should be informed about proposed changes.

We believe that ChatOps is a particularly compelling way to bring functionality to where it’s needed. By providing a ChatOps interface to Atomist, and surfacing executors as commands, we enable actions and inform about their effects:

This results in pull requests like this:

More and more teams live in chat — often, but not always, Slack. Chat is compelling because — particularly in the case of microservices projects — collaboration happens in continually changing and overlapping groups. Channels facilitate that, allowing users to choose which notifications matter to them and where they want to be heard. As polyglot systems become the norm, chat becomes an increasingly valuable common reference point for everyone in the organization.

Chat is a great place to deliver developer capabilities, respecting the existing work flow and bringing functionality to where it is relevant and needed. Atomist can register new commands such as executors dynamically, teaching the bot new tricks in real time and providing a more extensible UI than a GUI. Like editors, executors have parameters, which are gathered from the user. Data gathering via Q&A is natural in a chat context.

Currently we see teams using chat for notifications more often than for issuing commands. This seems a wasted opportunity. A chat message is a natural way to initiate code updates or other actions via an editor or executor.

It’s better to make changes in public. For code changes, GitHub can tell you which bits were changed, but not necessarily what the committer was trying to do or what those changes mean. In cases when a code change can be automated, a chat command executed in the appropriate channel can do both.

A deployment command executed in a shell session or GUI may satisfy the person who issues it, but doesn’t inform others or help them react, and may not leave an audit trail.

Unlike an editor, which always acts on a single project in isolation, the projects that an executor acts on depend on where and how it’s invoked.

Chat channels provide a natural way of contextualizing notification, discussion and actions.

Typically we see teams creating chat channels on a per service or per activity model. In the former model (which we use at Atomist), a new channel is created for each service; in the latter, a channel corresponds to an issue or other activity. When you create a new service by invoking an Atomist generator via our bot, a new channel is created automatically.

Imagine that we invoke an executor in a channel specific to a particular microservice. This will result in a change to only that service. If we run the same executor command in #general, it will act on all services associated with the chat team, and the whole team will know about it.

Pulling it All Together

We wrote variants of our Docker editor for multiple technologies. But developers love to introduce new technologies. What if our executor encounters a repo it doesn’t understand? In this case, we want to do what a responsible developer would do: Record that there’s a problem that will need to be dealt with later. How would a responsible developer do that? It depends on the team’s preferences, but most likely through raising an issue. Our complete executor does just that:

Note the “onNoChange” command. In the event that the editor doesn’t make any change (because preconditions indicated that the project was not understood), the executor raises an issue which is sent to the project’s issue tracker:

Correlating projects, chat channels and issue trackers requires a connected service model extending beyond source code. While there are existing point-to-point integrations between Slack and other tools, a unified model can significantly improve communication flow and create many new possibilities, with benefits going beyond chat.

Backing Model

The model implied here can locate the issue tracker for a repository. However, the Atomist connected data model is much farther reaching. The following diagram shows part of it: How a person’s identity can be related in GitHub and Slack; how channels are associated with repositories; and how we can drill into the files and internal structure of files in repositories or commits.

The model that backs Atomist executors presently extends to and helps manage the following:

  • Project source code, backed by parsing of programming language artifacts and knowledge of common formats and frameworks. Projects consist of files; many file types break down into an recognizable AST or document structure.
  • The owning organization’s or individual’s repositories (or a subset of them). What is the universe of source code available?
  • GitHub team membership and activity: Who has commit rights? Who has been active recently?
  • Chat team membership and structure. How do chat channels map to services?
  • Issue trackers. Where are issues kept for each project?
  • Build tools and process: What’s the build status? How long did the build take?

User code in executors can navigate these relationships to work with correlated information to automate tasks. Atomist’s understanding of source code is a unique and crucial element in tying everything together and making it possible to make changes safely.

This model will gradually extend to other areas, including:

  • Dependencies between projects, whether binary or over the wire or via message formats. This rests on Atomist’s understanding of source code.
  • Third party libraries used by projects, inferred from analysis of build files
  • Additional ways to interact with users, such as email, which is still used extensively in many teams.
  • Deployment. When did a service last deploy? What’s the structure of the Kubernetes specification or Cloud Formation template?
  • Alerts from monitoring tools. For example, an exception trace could be related to the source file and the most recent committer notified.

What This Enables

Activities that would otherwise require a lot of coordination can now be automated. For example:

  • Running project reviewers across multiple projects to help ensure consistency, raising issues when problems are found. (Unlike editors, reviewers don’t change code: They merely read it.)
  • Upgrading library or framework versions across multiple projects.
  • Changing deployment parameters in a consistent way.
  • Introducing new non-functional capabilities such as New Relic monitoring across multiple services.
  • Merging related pull requests in a single operation.
  • Notifying a team when a deprecated version of an endpoint is no longer used by any deployed service

Some operations will be generic— such as upgrading the version of a popular framework — while others will be authored in-house.

The model also enables users to pose and answer questions that are difficult or impossible to answer without a unified view, such as:

  • Which projects depend on a given version of a third party library?
  • What percentage of our services are dockerized?
  • How many different logging formats do we currently use in our distributed logging?
  • Do all our Java services listen on port 8080?
  • How many of our services don’t expose HTTP endpoints?
  • How many of our services use a particular library class?
  • How many of our services depend on local EBS volumes?
  • Which files that are modified most often?
  • How long does it take on average from push to deployment?
  • How close is our staging environment to production?
  • Which services make calls to my service’s API?

Again, such queries may be generic or authored in-house.

Where Next?

This is an ambitious vision, which will take time to deliver in full.

We’ve released the first phase of our ChatOps functionality — the ability to create and edit projects via Slack — in the Atomist Community Slack.

In the next few weeks you can expect to see more ChatOps features, as well as the open sourcing of our editor infrastructure and additional editors.

We’re building out the overall system model I’ve described and I look forward to sharing more details in future posts.

Please join us in our community Slack to try the ChatOps features and discuss!

--

--

Rod Johnson
The Composition

Cofounder and CEO, Atomist. Creator of Spring, Cofounder/CEO at SpringSource (acq by VMW)