Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

circletron

build statusKnown VulnerabilitiesRenovate

circletron is a tool to simplify working with monorepos. Currently monorepos managed via lerna are supported.

With circletron the .circleci/config.yml is distributed across subproject directories within the monorepo. Each subproject can define its own commands, workflows and jobs. Jobs defined within subpackage specific workflows will be automatically skipped in branches where no changes were detected.

How to use

  1. Create a minimal .circleci/config.yml like this:
version: 2.1setup: trueorbs:
circletron: circletron/circletron@3.0.5workflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs
  1. Optionally create a circle.yml in the root of the monorepo. The jobs in this circle.yml will always run and any commands, executors and orbs defined in this circle.yml will be available in the circle.yml of all other subpackages. This is also where version should be defined, if not the version 2.1 will be assigned.

  2. Create a circle.yml in each subpackage within the monorepo which requires automation. The jobs in this circle configuration are run only when there are changes in the respective branch to a file within this subpackage or changes to one of the subpackages that it depends on. conditional: false may be added to a job to specify that it must always be run.

  3. Optionally create a .circleci/circletron.yml file to specify target branches e.g.

# this is the default value
targetBranches: ^(release/|main$|master$|develop$)

To determine the branchpoint of a PR, circletron finds the latest commit that belongs to a branch matching the targetBranches regex. All jobs are run for pushes to a branch matching targetBranches except when runOnlyChangedOnTargetBranches is specified.

  1. Optionally add dependencies to circle.yml files

project1/circle.yml:

dependencies:
-project2-project3
jobs:
test-project-1:
steps:
-checkout-npmruntest
workflows:
project-1-workflow:
jobs:
-test-project-1

This will cause jobs within project1 to run when changes are detected in either project1, project2 or project3.

Details

It is useful to set up branch protection rules to prevent code from being merged when a CI job does not pass. When jobs are omitted then the PR will never be mergeable since the job will remain in a pending state. For this reason circletron will never omit a job that was determined not to be run, instead the job will be replaced with a simple job that echos "Job is not required" and return a success exit status.

Advanced Configuration

circletron can be configured to only run workflows on target branches in the packages that have changed since the last successful build on that branch. This feature interacts with the Circle API v2 so requires an access token to be provided, via the CIRCLE_TOKEN environment variable. This feature can be turned on using runOnlyChangedOnTargetBranches:

runOnlyChangedOnTargetBranches: true

circletron can be configured to skip whole workflows and not just specific jobs. This feature can be turned on using skip. Skip defaults to 'jobs'.

skip: workflows

When circletron is set to skip: jobs, instead of omitting jobs for GitHub protection rules, we run a simple job that returns success. In cases where you share jobs across workflows it might be more relevant to create a simple workflow that will run a single skip job and returns success. That way if two packages share a job circletron will know to omit running it on packages that haven't changed.

Skipping via check runs

skip: check-runs avoids running anything at all for unaffected packages. Instead of generating a green skip workflow per skipped package, the setup job (trigger-jobs) posts a GitHub check run for each skipped workflow — named exactly like the check CircleCI would have reported, with conclusion skipped, which GitHub branch protection accepts as passing — and the skipped workflows are omitted from the generated configuration entirely. A pipeline with N unaffected packages costs N GitHub API calls instead of N workflow runs, cutting queue time and CI load.

# .circleci/circletron.ymlskip: check-runs# only needed when the required check name differs from the workflow name:checkNames:
my-workflow: 'ci/circleci: my-workflow'

Creating check runs requires the GITHUB_CHECKS_TOKEN environment variable on the setup job, typically injected via a CircleCI context:

# .circleci/config.ymlworkflows:
trigger-jobs:
jobs:
- circletron/trigger-jobs:
context: github-checks

Classic GitHub personal access tokens cannot create check runs: the token must be a GitHub App installation token or a fine-grained PAT with checks: write permission on the repository.

The mode is fully best-effort: when the token is missing or a check run cannot be posted, each affected workflow falls back to the plain green skip workflow (the skip: workflows behaviour), so merges are never blocked.

Before relying on this mode, verify on a test repository that a check run posted by your App/PAT satisfies your required checks: classic branch protection can pin a required check to the app that first reported it (e.g. the CircleCI Checks app), in which case a same-named check run from another source is ignored. Repository rulesets make the accepted source explicit.

Skips artifact

Whatever the skip mode, the setup job writes a machine-readable summary of every skipped workflow to /tmp/circletron/skips.json and uploads it as the circletron/skips.json artifact, so tooling can count real runs vs skips:

{
"skippedWorkflows": ["my-workflow"],
"pipelineId": "<pipeline id>",
"pipelineNumber": "<pipeline number>",
"commitSha": "<sha>",
"branch": "<branch>"
}

report-skip subcommand

Custom skip paths (e.g. jobs that circleci-agent step halt on certain branches) can post their own skip indication:

circletron report-skip --workflow my-workflow --reason halted-on-branch

Unlike skip: check-runs this variant never collides with required check names: the check run is named my-workflow (circletron: skipped — halted-on-branch) with conclusion skipped, and a per-job artifact with a status of skipped-halted-on-branch is written to /tmp/circletron/skip.json (register it with store_artifacts to upload it). Repository owner/name and commit SHA are read from the built-in CIRCLE_PROJECT_USERNAME, CIRCLE_PROJECT_REPONAME and CIRCLE_SHA1 environment variables; pipeline id/number are read from CIRCLETRON_PIPELINE_ID/CIRCLETRON_PIPELINE_NUMBER if set.

About

A circleci orb to make CI within monorepos a pleasure

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages