npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

buildkite-graph

v6.1.0

Published

A graph-based generator for Buildkite pipelines

Downloads

61

Readme

buildkite-graph

A graph-based generator for Buildkite pipelines

This module allows you to generate Buildkite pipelines by defining their dependencies via a graph. This graph gets then serialized into the Buildkite-specific YAML format. All standard Buildkite features are supported.

The main advantage of using this module is:

  • Easy reuse and recombination of steps
  • Defining dependencies between steps explicitly
  • Wait steps are not defined explicitly and manually managed but derived from the graph, always providing the most optimized graph
  • Steps can be defined conditionally via an acceptor function, allowing for completely dynamic pipelines
  • The graph can be serialzed into dot format, allowing you to see the whole of the pipeline in one glance. Clusters denote which parts of the graph are dependendent.
  • Timeouts can be defined on a per-command basis, the step will then accumulate the timeouts accordingly

Example in a nutshell

const install = new Command('yarn', 2);

const lint = new CommandStep([install, new Command('yarn lint', 1)]).withKey(
  'lint',
);
const test = new CommandStep([install, new Command('yarn test', 2)])
  .withKey('test')
  .dependsOn(lint);
const build = new CommandStep([install, new Command('yarn build', 5)])
  .withKey('build')
  .dependsOn(lint);
const integration = new CommandStep([
  install,
  new Command('yarn integration', 10),
])
  .withKey('integration-test')
  .dependsOn(build);

const pipeline = new Pipeline('My pipeline').add(test).add(integration);

Do you see how we don't have to add the lint or buildstep? Because other steps depend on them, they will become part of the graph automatically in the right place. This allows you to define graphs with complex dependencies and only add the steps which have an important signal - no more manually adding auxiliary steps.

will serialize to:

steps:
  - command:
      - yarn
      - yarn lint
    timeout_in_minutes: 3
  - wait: ~
  - command:
      - yarn
      - yarn build
    timeout_in_minutes: 7
  - command:
      - yarn
      - yarn test
    timeout_in_minutes: 4
  - wait: ~
  - command:
      - yarn
      - yarn integration
    timeout_in_minutes: 12

Did you see how the wait step got added for you? How cool is that, hey :)

And did you also see how the timeouts for the steps are derived from the commands?

Since version 5 we also support the new depends_on syntax:

steps:
  - key: lint
    command:
      - yarn
      - yarn lint
    timeout_in_minutes: 3
  - key: build
    depends_on:
      - step: lint
    command:
      - yarn
      - yarn build
    timeout_in_minutes: 7
  - key: test
    depends_on:
      - step: lint
    command:
      - yarn
      - yarn test
    timeout_in_minutes: 4
  - key: integration-test
    depends_on:
      - step: build
    command:
      - yarn
      - yarn integration
    timeout_in_minutes: 12

you can get this format by using a flag on the yaml serializer:

console.log(
  await new YamlSerializer({ explicitDependencies: true }).serialize(pipeline),
);

The same with graphviz:

digraph "My pipeline" {
  graph [ compound =true ];
subgraph cluster_0 {
  graph [ color = "black" ];
  "<yarn && yarn lint>" [ color = "grey" ];
}

subgraph cluster_1 {
  graph [ color = "black" ];
  "<yarn && yarn build>" [ color = "grey" ];
  "<yarn && yarn test>" [ color = "grey" ];
}

subgraph cluster_2 {
  graph [ color = "black" ];
  "<yarn && yarn integration>" [ color = "grey" ];
}

  "<yarn && yarn lint>";
  "<yarn && yarn build>";
  "<yarn && yarn test>";
  "<yarn && yarn integration>";
  "<yarn && yarn lint>" -> "<yarn && yarn build>" [ ltail = "cluster_0", lhead = "cluster_1" ];
  "<yarn && yarn lint>" -> "<yarn && yarn test>" [ ltail = "cluster_0", lhead = "cluster_1" ];
  "<yarn && yarn build>" -> "<yarn && yarn integration>" [ ltail = "cluster_1", lhead = "cluster_2" ];
}

which will visualize to:

See the clusters (the square boxes)? The are legs of multiple steps in your pipeline, each separated by a wait step.

...but wait there's more; you can use the structural serializer to produce a textual output of the pipeline:

* Build Editor
* Test Editor
* [wait; continues on failure]
* Annotate failures
* Upload coverage
* [wait]
* Integration tests [x 8]
* [wait]
* :saucelabs: Integration tests [x 8]
* Visreg baseline update
* [wait; continues on failure]
* Annotate cucumber failures
* [wait]
* Copy to deploy bucket
* [wait]
* Update checkpoint
* Deploy to tech
* Deploy to usertesting
* [wait]
* [block for 'Release editor']

just by calling:

console.log(await new StructuralSerializer().serialize(pipeline));

This will allow you to create snapshot tests for your dynamic pipelines which represent the step composition and order.

Side-effects (Weak dependencies)

Sometimes a dependency is not a strong one, e.g. if you have a unit test you probably want to deploy the coverage, but adding the deploy coverage step should not trigger the unit tests unless they need to. In that case you can use .isEffectOf() instead of .dependsOn():

deploCoverageStep.isEffectOf(conditionalUnitTestStep);