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

circle-config-creator

v0.2.0

Published

> A simple helper to create CircleCI configs

Downloads

13

Readme

circle-config-creator

A simple helper to create CircleCI configs

Overview

I noticed that a lot of my CircleCI config was repetitive. I had written a small lib to help generate the config, but it got messy quickly. So I thought it through a little more and wrote a decent config generation tool. This is the result of that.

It allows the generation of workflows and jobs for CircleCI 2.0, and the sharing of parts of config.

Installation

This lib is written in JS. I'd recommend adding it to your devDependencies so that everyone on your team can use it.

yarn add -D circle-config-creator

Usage

  • create a file to generate your config. I use .circleci/config.js.
  • create a Config, Workflow and Job to get started
    • see API for details
import Config, { Workflow, Job, executors } from 'circle-config-creator';

const buildContainer = new executors.Docker('circleci/node:latest');
const config = new Config();

const build = new Job('build')
  .executor(buildContainer)
  .checkout()
  .run('./my-build-script.sh')
  .saveCache('v1-repo-{{ .Revision }}', '~/project');

const test = new Job('test')
  .executor(buildContainer)
  .restoreCache('v1-repo-{{ .Revision }}')
  .run({ command: './tests.sh', workingDirectory: '~/project/test' });

const workflow = new Workflow('build-and-test')
  .job(build)
  .job(test, [build]);

config
  .workflow(workflow)
  .writeSync();
  • Ensure you add Config#write or Config#writeSync to put your config into .circleci/config.yml

API

Methods are designed to build out configs in a chain. All chainable methods return a copy (operations are immutable).

Config

constructor() => Config;

workflow(workflow: Workflow) => Config

Add a workflow to the config

location(directory: string) => Config

Params

| Name | Type | Default | Description | |-----------|--------|------------|----------------------------------------------------------------------------------------------| | directory | string | (required) | The project directory this config is for. Saves to .circleci/config.yml of that directory. |

Change the location that the config will be saved to. This will always save to the directory you pass in, in the .circleci/config.yml file. Defaults to __dirname (the current directory)

compose() => Object

Generate a JavaScript object based on the Jobs and Workflows added

dump() => string

Generate yaml from the Jobs and Workflows added

write(disclaimer: boolean, callback: ?((?ErrnoError) => mixed)) => Promise<void>

Write the config to .circleci/config.yml

Params

| Name | Type | Default | Description | |------------|---------------------------------|-----------|----------------------------------------------------------------------------------------------| | disclaimer | boolean | true | Add a disclaimer to the top of the generated file, warning that changes will be overwritten. | | callback | (optional) (?ErrnoError) => any | undefined | Node-style callback for write completion |

writeSync(disclaimer: boolean) => void

Write the config synchronously to .circleci/config.yml

Params

| Name | Type | Default | Description | |------------|---------------------------------|-----------|----------------------------------------------------------------------------------------------| | disclaimer | boolean | true | Add a disclaimer to the top of the generated file, warning that changes will be overwritten. |

Workflow

constructor(name: string) => Workflow

job(
  job: Job,
  requires: ?Array<Job>,
  filter: ?Branches,
  type: ?'approval', // Deprecated - use [Job](#job)#type
  context: ?string,
) => Workflow

Add a job to this workflow

Params

| Name | Type | Default | Description | |----------|----------------------------------|------------|-------------------------------------------------------------------------------------| | job | Job | (required) | The job to add to the workflow | | requires | (optional) Array<Job> | [] | Any jobs that this job requires | | filter | (optional) Branches | undefined | Filter the branches that this job runs for | | type | (optional) oneOf('approval') | undefined | The job type. See CircleCI config docs for more (Deprecated - use Job#type) | | context | (optional) string | undefined | The context of the job. See CircleCI config docs for more |

schedule(cron: string, filter: Branches) => Workflow

Add a schedule to run this job against (see triggers on CircleCI docs)

Params

| Name | Type | Default | Description | |--------|-----------------------|------------|-------------------------------------------| | cron | string | (required) | The cron string to run this job on | | filter | Branches | (required) | The branches to run this schedule against |

Job

constructor(name: string) => Job

updateName(name: string) => Job

Update the name of a job. Useful if you want to take an existing job and modify it slightly to create a new job from it.

Params

| Name | Type | Default | Description | |------|--------|------------|------------------------------| | name | string | (required) | The shell to run this job in |

shell(shell: string) => Job

CircleCI Docs

Change the shell this job runs with

Params

| Name | Type | Default | Description | |-------|--------|------------|------------------------------| | shell | string | (required) | The shell to run this job in |

workingDirectory(directory: string) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |-----------|--------|------------|--------------------------------| | directory | string | (required) | The directory this job runs in |

parallelism(p: number) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |------|--------|------------|-------------------------------| | p | number | (required) | The number to run in parallel |

executor(executor: Executor) => Job

CircleCI Docs

The executor to run the job in. This must be set.

Params

| Name | Type | Default | Description | |----------|-----------------------|------------|---------------------------------| | executor | Executor | (required) | The executor to run this job in |

environment(environment: { [key: string]: string }) => Job
environment(key: string, value: string) => Job

CircleCI Docs

This will append to any environment you've already added. Callable multiple times.

Params

| Name | Type | Default | Description | |-------------|----------------------|------------|-------------------------------------------------------| | environment | { [string]: string } | (required) | A map of environment variables to inject into the job | | | | | | | key | string | (required) | The environment key | | value | string | (required) | The environment value |

branches(branches: Branches) => Job

CircleCI Docs

The branch filter config to apply to this job. Note that this will apply at the workflow level, not at the job level. See CircleCI Docs. You can take advantage of immutability by settings branches on a job as you pass it in to the workflow. This was, you have one Job, and can set branches differently per-workflow.

Params

| Name | Type | Default | Description | |----------|-----------------------|------------|-------------------------------------------------| | branches | Branches | (required) | The branch config for this job to run inside of |

resourceClass(resourceClass: 'small' | 'medium' | 'medium+' | 'large' | 'xlarge') => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |---------------|--------|------------|---------------------------------------------| | resourceClass | string | (required) | The resource class for this job's container |

run(command: string) => Job
run(config: {
  background?: boolean,
  command: string,
  environment?: { [string]: string },
  name?: string,
  noOutputTimeout?: string,
  shell?: string,
  when?: 'always' | 'on_success' | 'on_fail',
  workingDirectory?: string,
}) => Job

CircleCI Docs

See the docs for the param meanings

checkout(path: ?string) => Job

CircleCi Docs

Params

| Name | Type | Default | Description | |------|-------------------|-----------|----------------------------------| | path | (optional) string | ~/project | The path to checkout the code to |

setupRemoteDocker(dockerLayerCaching: boolean = false) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |--------------------|--------------------|---------|-----------------------------| | dockerLayerCaching | (optional) boolean | false | Enable docker layer caching |

saveCache(
  key: string,
  paths: string | Array<string>,
  name: string = 'Saving Cache',
  when: 'always' | 'on_success' | 'on_fail' = 'on_success',
) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |-------|------------------------------------------|----------------|------------------------------------------------------------------------| | key | string | (required) | The key to save the cache to | | paths | string | Array | (required) | The path (or paths) to save to that cache key | | name | string | 'Saving Cache' | The message to display when this step is running | | when | oneOf('always', 'on_success', 'on_fail') | 'on_success' | When to save this cache. Defaults to saving when the job is successful |

restoreCache(key: string | Array<string>, name: string = 'Restoring Cache') => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |------|--------|-------------------|--------------------------------------------------| | key | string | (required) | The keys to (attempt) to restore from | | name | string | 'Restoring Cache' | The message to display when this step is running |

progressiveRestoreCache(key: string, base: ?string) => Job

Experimental: This will likely not work for everyone's existing config. It works for most of my use-cases, and it's super handy.

It makes use the CircleCI ability to fallback on caches. It takes the key you pass in, and sets the restoreCache job with each key, falling back to base ( which defaults to two chunks). It only splits on -s.

Example: with a key of v1-dependencies-{{ checksum "yarn.lock" }}, this will result in attempting to restore the cache in the following order:

  • v1-dependencies-{{ checksum "yarn.lock" }}
  • v1-dependencies-

If you have a different base, you can specify it. For example, calling

job.progressiveRestoreCache(
  'v1-yarn-deps-{{ checksum "yarn.lock" }}-{{ .Revision }}',
  'v1-yarn-deps'
)

Will result in trying to restore the following

  • v1-yarn-deps-{{ checksum "yarn.lock" }}-{{ .Revision }}
  • v1-yarn-deps-{{ checksum "yarn.lock" }}-
  • v1-yarn-deps-

Params

| Name | Type | Default | Description | |------|-------------------|----------------|------------------------------------| | key | string | (required) | The full key to try restoring from | | base | (optional) string | (see examples) | The base key of the cache |

deploy(command: string) => Job
deploy(config: {
  background?: boolean,
  command: string,
  environment?: { [string]: string },
  name?: string,
  noOutputTimeout?: string,
  shell?: string,
  when?: 'always' | 'on_success' | 'on_fail',
  workingDirectory?: string,
}) => Job

CircleCI Docs

See Job#run and the related CircleCI docs for param information.

storeArtifacts(path: string, destination: ?string) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |-------------|-------------------|------------|---------------------------------------------------------| | path | string | (required) | The directory to save as build artifacts | | destination | (optional) string | undefined | Prefix added to the artifact paths in the artifacts API |

storeTestResults(path: string) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |------|--------|------------|------------------------------| | path | string | (required) | The path to the test results |

persistToWorkspace(root: string, paths: string | Array<string>) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |-------|------------------------|------------|-------------------------------------------------------------| | root | string | (required) | An absolute path or one relative to the working_directory | | paths | string | Array | (required) | Paths to add to the shared workspace |

attachWorkspace(at: string) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |------|--------|------------|------------------------------------------| | at | string | (required) | The directory to attach the workspace at |

addSSHKeys(fingerprints: ?(string | Array<string>)) => Job

CircleCI Docs

Params

| Name | Type | Default | Description | |--------------|-----------------------------------|----------------|-----------------------------------------------------| | fingerprints | (optional) string | Array | (all SSH keys) | the fingerprint (or fingerprints) to add to the job |

type(type: 'approval') => Job

CircleCI Docs

This is technically a configuration setting for a Workflow, but is used in the workflow config as a job. If you apply this setting to a job, it will not appear in your Job list (so it makes no sense to give it any other configuration options). Jobs with a type of approval also do not need to have an executor set.

At this point, there is only one type supported by CircleCI: approval.

Params

| Name | Type | Default | Description | |------|------------|------------|----------------------| | type | 'approval' | (required) | The type for the job |

Executors

Executors are the environment in which your job will run. Every job must be assigned exactly one environment. The generator will throw an error if none are specified. If you try and set more than one, the second will overwrite the first.

It is likely a good idea to create your standard executor as a variable, and pass the same one into all the jobs that need it.

You can access the executors in the following way:

import { executors } from 'circle-config-generator';

Docker

CircleCI Docs

constructor(): Docker

There is an alternative constructor, which is likely the one you'll use. It accepts an image string which is a convenient way to instantiate the executor if you don't need multiple images to run together.

constructor(image: string) => Docker

The remainder of the Docker API is adding an image, configuring that image, and finally calling .done() on the image to close it and add it to the Docker executor. You can add as many images as you like to the Docker container.

To add an image,

image(image: string) => Image

Params

| Name | Type | Default | Description | |-------|--------|------------|-----------------------------------------| | image | string | (required) | The name of the docker image to be used |

Image

See the non-required fields of the CircleCI Docker Docs for the meanings of the fields

auth(auth: { username: string, password: string }) => Image
awsAuth(auth: {
  aws_access_key_id: string,
  aws_secret_access_key: string,
}) => Image
command(...command: Array<string>) => Image
entrypoint(...entrypoint: Array<string>) => Image
environment(env: { [key: string]: string }) => Image
name(name: string) => Image
user(user: string) => Image
done() => Docker

This closes up the image and returns back the parent Docker container.

Machine

Creates the machine executor.

CircleCI Docs

constructor(enabled: ?boolean) => Machine

Params

| Name | Type | Default | Description | |---------|---------|---------|-------------------------| | enabled | boolean | true | Is the machine enabled? |

enabled(enabled: boolean) => Machine

Params

| Name | Type | Default | Description | |---------|---------|------------|-------------------------| | enabled | boolean | (required) | Is the machine enabled? |

image(image: string) => Machine

Params

| Name | Type | Default | Description | |-------|--------|------------|----------------------------------| | image | string | (required) | The image to use for the machine |

dockerLayerCaching(enabled: boolean) => Machine

Params

| Name | Type | Default | Description | |---------|---------|------------|-------------------------------------------------| | enabled | boolean | (required) | Should this machine enable Docker layer caching |

MacOS

Creates a macOS executor.

CircleCI Docs

constructor(version: string) => MacOS

Params

| Name | Type | Default | Description | |---------|--------|------------|---------------------------------------------------------------------------------------------------------------------------| | version | string | (required) | Version of macOS to run - check here for full list |

Branches

This is used to set which branches a particular Job or Workflow will run on.

constructor() => Branches

ignore(...branches: Array<string>) => Branches

Sets branches that should be ignored by the Job or Trigger using this instance Note: Setting this will override any Branches#only branches that have been set.

only(...branches: Array<string>) => Branches

Filter down to only run on the branches passed in.