0.2.0 • Published 6 years ago

circle-config-creator v0.2.0

Weekly downloads
8
License
MIT
Repository
github
Last release
6 years ago

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

NameTypeDefaultDescription
directorystring(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

NameTypeDefaultDescription
disclaimerbooleantrueAdd a disclaimer to the top of the generated file, warning that changes will be overwritten.
callback(optional) (?ErrnoError) => anyundefinedNode-style callback for write completion
writeSync(disclaimer: boolean) => void

Write the config synchronously to .circleci/config.yml

Params

NameTypeDefaultDescription
disclaimerbooleantrueAdd 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

NameTypeDefaultDescription
jobJob(required)The job to add to the workflow
requires(optional) Array<Job>[]Any jobs that this job requires
filter(optional) BranchesundefinedFilter the branches that this job runs for
type(optional) oneOf('approval')undefinedThe job type. See CircleCI config docs for more (Deprecated - use Job#type)
context(optional) stringundefinedThe 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

NameTypeDefaultDescription
cronstring(required)The cron string to run this job on
filterBranches(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

NameTypeDefaultDescription
namestring(required)The shell to run this job in
shell(shell: string) => Job

CircleCI Docs

Change the shell this job runs with

Params

NameTypeDefaultDescription
shellstring(required)The shell to run this job in
workingDirectory(directory: string) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
directorystring(required)The directory this job runs in
parallelism(p: number) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
pnumber(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

NameTypeDefaultDescription
executorExecutor(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

NameTypeDefaultDescription
environment{ string: string }(required)A map of environment variables to inject into the job
keystring(required)The environment key
valuestring(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

NameTypeDefaultDescription
branchesBranches(required)The branch config for this job to run inside of
resourceClass(resourceClass: 'small' | 'medium' | 'medium+' | 'large' | 'xlarge') => Job

CircleCI Docs

Params

NameTypeDefaultDescription
resourceClassstring(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

NameTypeDefaultDescription
path(optional) string~/projectThe path to checkout the code to
setupRemoteDocker(dockerLayerCaching: boolean = false) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
dockerLayerCaching(optional) booleanfalseEnable 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

NameTypeDefaultDescription
keystring(required)The key to save the cache to
pathsstringArray(required)The path (or paths) to save to that cache key
namestring'Saving Cache'The message to display when this step is running
whenoneOf('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

NameTypeDefaultDescription
keystring(required)The keys to (attempt) to restore from
namestring'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

NameTypeDefaultDescription
keystring(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

NameTypeDefaultDescription
pathstring(required)The directory to save as build artifacts
destination(optional) stringundefinedPrefix added to the artifact paths in the artifacts API
storeTestResults(path: string) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
pathstring(required)The path to the test results
persistToWorkspace(root: string, paths: string | Array<string>) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
rootstring(required)An absolute path or one relative to the working_directory
pathsstringArray(required)Paths to add to the shared workspace
attachWorkspace(at: string) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
atstring(required)The directory to attach the workspace at
addSSHKeys(fingerprints: ?(string | Array<string>)) => Job

CircleCI Docs

Params

NameTypeDefaultDescription
fingerprints(optional) stringArray(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

NameTypeDefaultDescription
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

NameTypeDefaultDescription
imagestring(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

NameTypeDefaultDescription
enabledbooleantrueIs the machine enabled?
enabled(enabled: boolean) => Machine

Params

NameTypeDefaultDescription
enabledboolean(required)Is the machine enabled?
image(image: string) => Machine

Params

NameTypeDefaultDescription
imagestring(required)The image to use for the machine
dockerLayerCaching(enabled: boolean) => Machine

Params

NameTypeDefaultDescription
enabledboolean(required)Should this machine enable Docker layer caching

MacOS

Creates a macOS executor.

CircleCI Docs

constructor(version: string) => MacOS

Params

NameTypeDefaultDescription
versionstring(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.

0.2.0

6 years ago

0.1.3

6 years ago

0.1.2

6 years ago

0.1.1

6 years ago

0.1.0

6 years ago

0.0.2

6 years ago

0.0.1

6 years ago