https://github.com/deecewan/circle-config-creator
🔘 Generate composable, shareable CircleCI configs
https://github.com/deecewan/circle-config-creator
circleci circleci2 config config-management javascript javascript-library
Last synced: 3 months ago
JSON representation
🔘 Generate composable, shareable CircleCI configs
- Host: GitHub
- URL: https://github.com/deecewan/circle-config-creator
- Owner: deecewan
- Created: 2018-06-19T23:38:00.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-07-25T00:20:12.000Z (about 7 years ago)
- Last Synced: 2025-06-28T06:02:42.644Z (3 months ago)
- Topics: circleci, circleci2, config, config-management, javascript, javascript-library
- Language: JavaScript
- Size: 156 KB
- Stars: 6
- Watchers: 2
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
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](#api) for details```js
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 `Job`s and `Workflow`s added
```
dump() => string
```Generate `yaml` from the `Job`s and `Workflow`s added
```
write(disclaimer: boolean, callback: ?((?ErrnoError) => mixed)) => Promise
```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,
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](#job) | (required) | The job to add to the workflow |
| requires | (optional) Array<[Job](#job)> | [] | Any jobs that this job requires |
| filter | (optional) [Branches](#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](#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](#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](https://circleci.com/docs/2.0/configuration-reference/#jobs)
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](https://circleci.com/docs/2.0/configuration-reference/#jobs)
**Params**
| Name | Type | Default | Description |
|-----------|--------|------------|--------------------------------|
| directory | string | (required) | The directory this job runs in |
```
parallelism(p: number) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#parallelism)
**Params**
| Name | Type | Default | Description |
|------|--------|------------|-------------------------------|
| p | number | (required) | The number to run in parallel |
```
executor(executor: Executor) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#docker--machine--macosexecutor)
The executor to run the job in. This *must* be set.
**Params**
| Name | Type | Default | Description |
|----------|-----------------------|------------|---------------------------------|
| executor | [Executor](#executor) | (required) | The executor to run this job in |
```
environment(environment: { [key: string]: string }) => Job
environment(key: string, value: string) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#environment)
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](https://circleci.com/docs/2.0/configuration-reference/#branches)
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](https://circleci.com/docs/2.0/configuration-reference/#branches-1).
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](#branches) | (required) | The branch config for this job to run inside of |
```
resourceClass(resourceClass: 'small' | 'medium' | 'medium+' | 'large' | 'xlarge') => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#resource_class)
**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](https://circleci.com/docs/2.0/configuration-reference/#run)
See [the docs](https://circleci.com/docs/2.0/configuration-reference/#run) for
the param meanings
```
checkout(path: ?string) => Job
```[CircleCi Docs](https://circleci.com/docs/2.0/configuration-reference/#checkout)
**Params**
| Name | Type | Default | Description |
|------|-------------------|-----------|----------------------------------|
| path | (optional) string | ~/project | The path to checkout the code to |
```
setupRemoteDocker(dockerLayerCaching: boolean = false) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#setup_remote_docker)
**Params**
| Name | Type | Default | Description |
|--------------------|--------------------|---------|-----------------------------|
| dockerLayerCaching | (optional) boolean | false | Enable docker layer caching |
```
saveCache(
key: string,
paths: string | Array,
name: string = 'Saving Cache',
when: 'always' | 'on_success' | 'on_fail' = 'on_success',
) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#save_cache)
**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, name: string = 'Restoring Cache') => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#restore_cache)
**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](https://circleci.com/docs/2.0/configuration-reference/#deploy)
[See Job#run](#run) and [the related CircleCI docs](https://circleci.com/docs/2.0/configuration-reference/#run)
for param information.
```
storeArtifacts(path: string, destination: ?string) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#store_artifacts)
**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](https://circleci.com/docs/2.0/configuration-reference/#store_test_results)
**Params**
| Name | Type | Default | Description |
|------|--------|------------|------------------------------|
| path | string | (required) | The path to the test results |
```
persistToWorkspace(root: string, paths: string | Array) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#persist_to_workspace)
**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](https://circleci.com/docs/2.0/configuration-reference/#attach_workspace)
**Params**
| Name | Type | Default | Description |
|------|--------|------------|------------------------------------------|
| at | string | (required) | The directory to attach the workspace at |
```
addSSHKeys(fingerprints: ?(string | Array)) => Job
```[CircleCI Docs](https://circleci.com/docs/2.0/configuration-reference/#add_ssh_keys)
**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](https://circleci.com/docs/2.0/configuration-reference/#type)
This is technically a configuration setting for a [Workflow](#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](https://circleci.com/docs/2.0/configuration-reference/#docker)
`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](https://circleci.com/docs/2.0/configuration-reference/#docker) 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) => Image
```
```
entrypoint(...entrypoint: Array) => 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](https://circleci.com/docs/2.0/configuration-reference/#machine)
`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](https://circleci.com/docs/2.0/configuration-reference/#macos)
`constructor(version: string) => MacOS`
**Params**
| Name | Type | Default | Description |
|---------|--------|------------|---------------------------------------------------------------------------------------------------------------------------|
| version | string | (required) | Version of macOS to run - check [here](https://circleci.com/docs/2.0/testing-ios/#supported-xcode-versions) for full list |### Branches
This is used to set which branches a particular `Job` or `Workflow` will run on.
`constructor() => Branches`
```
ignore(...branches: Array) => 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) => Branches
```Filter down to only run on the branches passed in.