Cimas (“Continuous integration master”)
Purpose
Cimas handles synchronizing CI configuration across multiple repositories.
When there are many repositories that need to share identical or similar CI (continuous integration) configuration, it is not only cumbersome but error prone to keep these configuration files in sync.
For example, adding new value to the CI test matrix for multiple repositories should not itself be a chore.
|
Note
|
This problem can technically be mitigated if we can externalize and consolidate CI configuration outside of data repositories. However, most CI solutions don’t support external configuration (i.e. Travis, GitHub Actions, Appveyor). For GitHub, see: GHA external workflow, GHA calling another action |
History
Installation
Cimas (and its CLI command, cimas) relies on Git.
Please ensure git is installed on your system.
Installing is as easy as:
gem install cimasOr, by specifying it in your Gemfile if you’re using Bundler.
Concepts
- CI configuration file
-
file to configure CI behavior of a repository
- CI configuration master file
-
CI configuration file that applies to one or more target repositories
- CI configuration master directory
-
directory (or a repo) where master CI configuration files reside
- Cimas working area
-
local directory where Cimas works within
- Cimas managed repository
-
repository with CI configuration managed by Cimas
Demonstration
The metanorma-build-scripts
repository contains Cimas configuration under cimas-config/
for the Metanorma repositories.
-
cimas-config/: the CI master configuration directory -
cimas-config/cimas.yml: the Cimas configuration file
Have a look to see how it’s being used!
Prerequisites
Setting up the CI configuration master directory
You need to first create a “CI configuration master directory” to contain master files for CI configuration. It is advisable to store the directory in Git for better version management.
For example, with Metanorma repositories,
the CI master configuration directory is at
metanorma/ci under cimas-config/.
(Historical note: prior to 2024 this lived in
metanorma-build-scripts;
older documentation may still reference that location.)
Setting the GITHUB_TOKEN environment variable
Cimas needs a GitHub token to look up per-repo visibility (public vs.
private) when the CI configuration file uses visibility-driven template
selection (see the metanorma/metanorma-docker template selection in
metanorma/ci#347 Option B).
Without the token, cimas sync prints a warning per repo and defaults
to private template picks — safe (won’t clobber public repos with
private templates), but the sync is inaccurate for public repos.
Set the token before running any sub-command that touches remotes or inspects visibility:
export GITHUB_TOKEN=$(gh auth token)gh auth token reuses the token the local gh CLI is authenticated
with. Alternatively, export an explicit PAT with repo scope.
Usage
Command line
Cimas works through the cimas executable. cimas provides the following sub-commands.
-
setup -
sync -
diff -
push -
pull -
open-prs -
for-each -
lint(disabled right now)
Global options (must appear before the sub-command name)
-
--dry-run: Skips destructive/remote operations (branches, pushes, PR opens, deletes); prints what would be done instead. Applies tosync,pull,push,open-prs,cleanup-*. -
-v/--verbose(currently disabled).
|
Warning
|
|
|
Note
|
Do not confuse |
cimas setup
The setup sub-command sets up the Cimas working area/directory with
Git repos cloned as described in your Cimas configuration file
(default: cimas.yml).
This command must be run before any other sub-commands are run, and must be run when the repository addresses change within the Cimas configuration file (it will prompt you).
cimas setup -f {cimas-config-file} -r {cimas-working-area}
# e.g.
# cimas setup -f cimas.yml -r ~/src/cimas-wd|
Note
|
This sub-command is considered “safe” as it does not alter the state of existing Git repositories within the Cimas working area. |
cimas pull
The pull sub-command resets all the Git repositories to the
original branch key set per-repo.
This command should be run before the cimas sync command to
clean up state.
cimas pull -f {cimas-config-file} -r {cimas-working-area}
# e.g.
# cimas pull -f cimas.yml -r ~/src/cimas-wd|
Note
|
This sub-command is considered “destructive” as it resets states of all Git repositories in the Cimas working area. |
cimas sync
The sync sub-command places the necessary CI configuration files,
as described in the Cimas configuration file, into the desired
repositories.
After copying the files, Cimas will also stage the changed files to Git.
This command must be run before the cimas push command.
cimas sync -f {cimas-config-file} -r {cimas-working-area} \
-d {cimas-master-config-dir}
# e.g.
# cimas sync -f cimas.yml -r ~/src/cimas-wd \
# -d ~/src/cimas-config|
Note
|
This sub-command is considered “destructive” as it resets states of all Git repositories in the Cimas working area before adding CI configuration files. But you can pass -k argument to not 'drop' state of the repo before sync |
Proposed extension — drift-audit / opt-out detection (Gap 3, not yet implemented)
|
Note
|
This subsection documents a proposed drift-audit capability, not currently implemented. See metanorma/ci#300 (Gap 3) for the full design discussion. The naming question (separate cimas drift-audit subcommand vs. a cimas sync --drift-audit flag) is part of the open design.
|
cimas sync today applies templates blindly: if a cimas.yml entry maps a downstream file to a template, the file is overwritten on every sync — even when the downstream repo has deliberately opted out by replacing the template with custom content. The opt-out is silent; the maintainer rediscovers it only when their override gets clobbered.
Concrete example: metanorma/coradoc/.github/workflows/rake.yml was replaced in d91d06d ("fix(ci): replace metanorma reusable workflow with direct rake job") with a direct in-file matrix-test job. Until tonight’s metanorma/ci#318 (the cimas-config/cimas.yml one-liner removing coradoc’s rake.yml mapping), every cimas sync run silently planned to clobber that opt-out. There is no equivalent automation for the next opt-out that gets introduced.
The proposed drift-audit (subcommand or flag, naming TBD) runs before every cimas sync and classifies each planned diff into:
-
Gap 1 signal — diff removes
with:block lines absent from any template the repo maps to. Likely indicates a per-repowith:override that the schema extension (above) hasn’t yet been used to capture. -
Gap 2 signal — structural diff (full
jobs:block differs) AND the downstream file references a local./.github/workflows/path. Likely a monorepo or other structural fork. -
Gap 3 signal — downstream file lacks the
# Auto-generated by Cimas: Do not edit it manually!header AND the structural diff to the assigned template is large. Likely an opt-out. -
Category D (benign) — diff adds template-resident lines absent from the downstream file. Standard template-forward drift; no hazard.
The audit reports Gap 1, 2, and 3 signals to the maintainer with the proposed cimas.yml or template edit that would resolve each, and exits non-zero on Gap 1 or Gap 3 signals, blocking cimas push until the maintainer either applies the remediation or explicitly overrides the audit.
The drift-audit serves as a forcing function against the silent-overwrite class of failures — opt-outs and per-repo overrides surface as actionable signals rather than getting clobbered. Naming and exact integration point (separate subcommand vs. flag on cimas sync) are open per `#300’s discussion section.
Until either is implemented, opt-out hygiene is a manual diff-review burden on every sync run.
cimas diff
The diff sub-command provides a consolidated diff output between
the repositories in the Cimas working area and remote.
This is useful prior to running the cimas push command.
After copying the files, Cimas will also stage the changed files to Git.
This command must be run before the cimas push command.
cimas diff -f {cimas-config-file} -r {cimas-working-area} \
-d {cimas-master-config-dir}
# e.g.
# cimas diff -f cimas.yml -r ~/src/cimas-wd \
# -d ~/src/cimas-config|
Note
|
This sub-command is considered “safe” as it does not alter state of Git repositories. |
cimas push
The push sub-command:
-
commits the changes made by the
syncsub-command in a new branch; -
pushes the new branch to the first Git remote.
This command must be run before the cimas open-prs command
as the branches need to be pushed before pull-requests can be
opened against them.
cimas push -f {cimas-config-file} -r {cimas-working-area} \
-b {new-branch-for-commit} \
-m {commit-message} \
# e.g.
# cimas push -f cimas.yml -r ~/src/cimas-wd \
# -b my-new-ci-branch \
# -m 'My commit message' \
# [-g {group1,group2,...}]|
Note
|
This sub-command is considered “destructive” as it alters the state of all Git repositories in the Cimas working area by adding commits and branches. |
cimas open-prs
The open-prs sub-command:
-
opens Pull Requests for all the specified repositories of the given branch;
-
creates Pull Request Review Requests for the created Pull Requests (if
reviewersare set incimas.yaml:settingsor via the-woption); -
assigns the created Pull Requests to assignees (if
assigneesare set incimas.yaml:settingsor via the-aoption).
Since this command depends on GitHub privileged functionality,
you must supply your GitHub Personal Access Token (PAT)
via the GITHUB_TOKEN environment variable.
GITHUB_TOKEN=deadbeefdeadbeef; \
cimas open-prs -f {cimas-config-file} -r {cimas-working-area} \
-b {new-branch-to-pr} \
-m {pr-message} \
# e.g.
# cimas open-prs -f cimas.yml -r ~/src/cimas-wd \
# -b my-new-ci-branch \
# -m 'My pull-request message' \
# [-w {reviewer1,reviewer2...}] \
# [-a {assignee1,assignee2...}] \
# [-g {group1,group2,...}]|
Note
|
This sub-command is considered “destructive” as it alters the state of GitHub repositories by creating pull requests. |
--supersede-stale flag (Gap 4, implemented 2026-06-30 in cheaper form)
When cimas open-prs runs against a repo where an earlier cimas-sync wave’s PR is still open (i.e. unmerged from a previous wave), the result without intervention is stacked PRs on the same repo carrying overlapping changes, with no automated relationship between them. The previous wave’s PR (e.g. PR#5 on the cimas-sync-2026-06-15 branch) and the new wave’s PR (e.g. PR#10 on cimas-sync-2026-06-29) coexist independently; the reviewer either merges both (redundant churn, possible conflicts), merges only the latest (`PR#5’s review thread gets orphaned), or freezes (the most common outcome). The pattern bites most on inactive-maintainer repos where PRs can sit for weeks or months before notice.
The --supersede-stale flag (opt-in) implements the cheaper-variant design discussed in metanorma/ci#300 (Gap 4). For each target repo, when set:
-
Before opening the new PR, lists existing open PRs whose head branch starts with
cimas-sync-(i.e. previous wave PRs that never merged). -
Prepends a
Supersedes #X, #Y from prior cimas-sync waves.line to the new PR’s body, naming the superseded PRs. -
After the new PR is opened, labels each superseded PR with
superseded-by-#N(where N is the new PR’s number) and posts a comment linking the new PR. -
Does NOT auto-close the superseded PRs — the reviewer keeps authority over the close decision.
cimas open-prs --supersede-stale \
-r ~/src/cimas-wd-2026-06-29 \
-f cimas.yml \
-b cimas-sync-2026-06-29 \
-m "Cimas sync 2026-06-29: ..." \
--body-file /tmp/wave-body.md \
-g processorA future PR may layer a strict-superset diff gate on top (only supersede when the new wave’s diff strictly contains the old PR’s diff, so different-intent waves stay parallel). For now the simpler cheaper-variant is sufficient — the label and comment make the supersede relationship visible and let the reviewer make the final close call.
A more elegant single-branch-per-repo alternative (rebase the existing cimas-sync branch in-place rather than opening new PRs) is noted in metanorma/ci#300 as a possible Phase-B candidate — bigger mental-model shift, defer until the revival settles.
--flatten-stale flag (Gap 4 full, implemented 2026-07-04)
--flatten-stale is the full Gap 4 shape: same detection as --supersede-stale but also auto-closes the superseded PRs. Implies --supersede-stale (setting --flatten-stale alone activates both detection AND auto-close).
Use this when you’re confident the new wave’s content strictly supersedes the older waves' — which is the standard case for cimas-sync waves, since every wave regenerates the same file set from cimas.yml. If the older PR contained content that should be preserved (e.g. a mid-wave hand-edit), rebase that branch elsewhere and reopen before running the new wave.
Behavioural delta vs --supersede-stale:
-
Superseded PRs get labelled
superseded-closed-by-#N(instead ofsuperseded-by-#N). -
The comment on each superseded PR names auto-closure and points at the new PR.
-
Each superseded PR is closed via
github_client.close_pull_request.
cimas open-prs --flatten-stale \
-r ~/src/cimas-wd-2026-06-29 \
-f cimas.yml \
-b cimas-sync-2026-06-29 \
-m "Cimas sync 2026-06-29: ..." \
--body-file /tmp/wave-body.md \
-g processorThe strict-superset diff gate mentioned above for --supersede-stale’s follow-up is orthogonal to `--flatten-stale — the flatten variant assumes the wave-regeneration invariant rather than checking it per-PR. If the invariant is broken (e.g. a wave that intentionally covers a narrower subset of files), stick with --supersede-stale and close manually.
cimas for-each
The for-each sub-command allow to execute arbitrary shell command for each repo
There is no strict requirment to use this commant during CI configuration update. You can use it on demand, for example if some CI configuration files was removed
cimas sync -f {cimas-config-file} -r {cimas-working-area} \
-d {cimas-master-config-dir}
# e.g.
# cimas for-each -f cimas.yml -r ~/src/cimas-wd \
# -c "git rm .github/workflows/windows.yml"End-to-end workflow: drift audit → preview → push
The full sequence for a “sync + push a wave of drift corrections”
operation is setup → sync → diff → push. Each sub-command has
its own required flags, so the full sequence is worth banking in one
place.
Prerequisites for this workflow:
-
GITHUB_TOKENexported (see prerequisites above). -
A checkout of the CI configuration master directory (e.g.
metanorma/cifor Metanorma). Below assume it lives at../ci/cimas-config/. -
A fresh work-dir (e.g.
../cimas-wd-YYYY-MM-DD).
Step 1 — create the work-dir.
mkdir ../cimas-wd-2026-07-22Step 2 — setup: clone every mapped repo into the work-dir.
cimas setup \
-r ../cimas-wd-2026-07-22 \
-f ../ci/cimas-config/cimas.ymlSetup does not need -d (it only clones; it doesn’t apply templates).
Step 3 — sync: apply templates to each cloned repo locally.
cimas sync \
-r ../cimas-wd-2026-07-22 \
-f ../ci/cimas-config/cimas.yml \
-d ../ci/cimas-configBoth -r (work-dir), -f (cimas.yml), and -d (master path) are
required for sync. Missing -d produces
[ERROR] config_master_path not set, aborting.
Step 4 — cimas diff: preview the aggregated diff. This is the primary
preview mechanism.
cimas diff \
-r ../cimas-wd-2026-07-22 \
-f ../ci/cimas-config/cimas.yml \
-d ../ci/cimas-configSame three flags as sync. Prints git diff output per drifted repo.
This is the decision surface — read it and decide which classes to
propagate, and which should become opt-out entries in cimas.yml.
Repos with no drift show no diff at all.
Quick count of repos with actual drift (post-sync, pre-push):
cd ../cimas-wd-2026-07-22 && for d in */; do
[ -n "$(git -C "$d" status --porcelain 2>/dev/null)" ] && echo "${d%/}"
done | tee /tmp/drifted-repos.txt | wc -lUseful because cimas push (and cimas --dry-run push) will report
work against every mapped repo regardless of drift (see gotcha
below); this one-liner isolates the actually-drifted subset.
|
Note
|
The |
Step 5 — real push (only after diff review).
cimas push \
-r ../cimas-wd-2026-07-22 \
-f ../ci/cimas-config/cimas.yml \
-b cimas-sync-2026-07-22 \
-m "cimas: sync <date> drift-audit findings"Creates cimas-sync-2026-07-22 on each mapped repo and pushes it. Does
NOT open PRs — that’s cimas open-prs as a separate step.
|
Important
|
Mitigations for future waves:
|
Step 6 — open PRs (optional; only for the drift-having branches).
See the cimas open-prs section above for the full flag list.
| Sub-command | -r |
-f |
-d |
-b |
-m |
|---|---|---|---|---|---|
|
✅ |
✅ |
|||
|
✅ |
✅ |
✅ |
||
|
✅ |
✅ |
✅ |
||
|
✅ |
✅ |
✅ |
(recommended) |
|
|
✅ |
✅ |
✅ |
(recommended) |
| Gotcha | Symptom |
|---|---|
Missing |
|
Missing |
|
|
|
Missing |
|
|
Push count much larger than actual drift; use |
Configuration
General
Cimas relies on reading a Cimas configuration file (default: cimas.yml)
that specifies:
-
repository settings;
-
group settings; and
-
Cimas behavior
This YAML file needs to be in the following structure:
---
settings:
{option-key}: {option-value}
...
repositories:
{repo-name}:
remote: {remote-name}
branch: {branch-name}
files:
{CI-file-target-location}: {CI-configuration-master-file-location}
...
...
groups:
{group-name}:
- {repo-name}
- ...EXAMPLE: See metanorma/metanorma-build-scripts/cimas-config/cimas.yml for a working configuration.
settings
The settings object specifies run-time configuration. These options
are merged with the command-line options, which have higher priority.
Syntax:
settings:
{option-key}: {option-value}
...The following options are available:
-
reviewerstakes an array of GitHub user names as PR reviewers. This is only relevant to thecimas open-prssub-command. -
assigneestakes an array of GitHub user names as assignees to PRs. This is only relevant to thecimas open-prssub-command.
EXAMPLE: This example comes from metanorma/metanorma-build-scripts/cimas-config/cimas.yml.
settings:
reviewers:
- opoudjis
- ronaldtserepositories
The repositories object specifies all Git repositories
that are managed by Cimas under this configuration file.
For example, when the cimas setup command is run, all
of these repositories will be cloned under the
Cimas working area.
Each repository is represented by a key under the
repositories object.
{repo-name-1}:
remote: {remote-name}
branch: {branch-name}
files:
{CI-file-target-location-1}: {CI-configuration-master-file-location-1}
{CI-file-target-location-2}: {CI-configuration-master-file-location-2}These attributes are mandatory for each repository:
-
remote: the remote Git location of this repository (i.e. wheregit clonecan find this repository). SSH and HTTPS paths are supported. Single valued. -
branch: the source branch and eventual branch to commit to (where a PR should be created against). Single valued. -
files: composed of key value pairs of the “target file location within the repository” to the “master file location within the configuration master directory”. Multiple files are supported.
Syntax:
repositories:
{repo-name-1}:
remote: {remote-name}
branch: {branch-name}
files:
{CI-file-target-location-1}: {CI-configuration-master-file-location-1}
{CI-file-target-location-2}: {CI-configuration-master-file-location-2}
{repo-name-2}:
remote: {remote-name}
branch: {branch-name}
files:
{CI-file-target-location-3}: {CI-configuration-master-file-location-3}
...
...EXAMPLE: This example comes from metanorma/metanorma-build-scripts/cimas-config/cimas.yml.
repositories:
metanorma-model-gb:
remote: ssh://git@github.com/metanorma/metanorma-model-gb
branch: master
files:
.github/workflows/macos.yml: gh-actions/model/macos.yml
.github/workflows/ubuntu.yml: gh-actions/model/ubuntu.yml
.github/workflows/windows.yml: gh-actions/model/windows.ymlProposed schema extension — per-repo with: rendering (Gap 1, not yet implemented)
|
Note
|
This subsection documents a proposed extension to the files: schema, not currently implemented. See metanorma/ci#300 (Gap 1) for the full design discussion, including the concrete renderer change and the first intended user (private-fonts: true for metanorma).
|
The current files: schema maps a downstream-file path to a template path as a single string. This works for cases where the template is fully self-contained, but breaks when the synced file needs a per-repo value that the shared template can’t anticipate (e.g. metanorma’s `rake.yml needs private-fonts: true, but gh-actions/inkscape/rake.yml has no slot for it).
The proposed extension keeps the existing string form valid (fully backward compatible) and adds an optional map form for entries that need per-repo with: rendering:
metanorma:
remote: ssh://git@github.com/metanorma/metanorma
branch: main
files:
# Existing string form — kept verbatim, no per-repo with:
.rubocop.yml: gh-actions/master/.rubocop.yml
.github/workflows/release.yml: gh-actions/master/release.yml
# Proposed map form — template + per-repo with: values
.github/workflows/rake.yml:
template: gh-actions/master/rake.yml
with:
private-fonts: trueThe renderer would route on the value’s type: strings render as today; maps extract template: as the path-to-render and pass with: to ERB as a local variable for injection into the template’s with: block. Templates that wish to support per-repo with: rendering gain an ERB injection block such as:
jobs:
rake:
uses: metanorma/ci/.github/workflows/generic-rake.yml@main
<% if defined?(file_with) && file_with.any? -%>
with:
<% file_with.each do |k, v| -%>
<%= k %>: <%= v.inspect %>
<% end -%>
<% end -%>
secrets:
pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}Until this lands, per-repo with: overrides have to be either inlined in each downstream file (and clobbered by every cimas-sync) or kept out-of-band as documentation, neither of which is sustainable.
Proposed schema extension — monorepo sub-template family (Gap 2, not yet implemented)
|
Note
|
This subsection documents a proposed extension to support monorepo-shaped repositories, not currently implemented. See metanorma/ci#300 (Gap 2) for the full design discussion. The reusable-workflow side of the work — adding monorepo / gem_directory inputs to the relevant metanorma/ci/.github/workflows/*.yml reusable workflows — is a coupled dependency tracked separately and is part of the open design question.
|
The existing gh-actions/master/ and per-flavour template families (gh-actions/inkscape/, gh-actions/xml2rfc/, gh-actions/graphviz/, gh-actions/libreoffice/) all assume a one-repo-one-gem layout: a single .gemspec at the repo root, one Gemfile, one rakefile. Monorepos that have been adopted across the metanorma org since the templates were written break this assumption.
Concrete example: metanorma/pubid is a monorepo of pubid-* gems under gems/. Its .github/workflows/rake.yml has been forked structurally:
jobs:
rake:
uses: ./.github/workflows/generic-rake.yml # local path, not metanorma/ci
with:
monorepo: true
gem_directory: gems
secrets:
pat_token: ${{ secrets.METANORMA_CI_PAT_TOKEN }}Note the uses: points at a local copy of generic-rake.yml, not at metanorma/ci. That’s because the metanorma/ci reusable workflow doesn’t currently accept monorepo / gem_directory inputs, so the monorepo had to fork the workflow locally to extend it. The cimas template family then has no way to express either the inputs or the structural shape, so monorepos sit outside cimas-sync entirely.
The proposed remediation pairs a new template family with reusable-workflow extensions:
-
A new
cimas-config/gh-actions/monorepo/.ymlsub-template family inmetanorma/ci, paralleling the existinggh-actions/master/shape but emittingwith: { monorepo: true, gem_directory: <path> }blocks. -
Reusable-workflow extensions to
metanorma/ci/.github/workflows/generic-rake.yml(and siblings as needed) to acceptmonorepo/gem_directoryinputs and dispatch the matrix correctly per-gem rather than per-repo. -
Monorepo repos'
cimas.ymlentries reference the new template family and (per Gap 1’s proposed schema extension) declare the per-monorepowith:values.
The Gap 1 schema extension above is a prerequisite — without per-repo with: rendering, the new template family can’t express the variable gem_directory values across different monorepos. So Gap 2 layers on top of Gap 1, not independently.
Until this lands, monorepo repos remain outside cimas-sync’s scope and maintain their CI configuration by hand.
groups
Cimas offers “grouping” functionality to allow you to work with groups of repositories. This is useful if your repositories fall into different categories, e.g. repositories for Ruby code vs C code that have different build routines.
There is a default group of all which applies if no group is specified.
Groups under the groups key are collections of repository names.
Each group is represented by a key of the group’s name, with
names of its repositories as array content.
One repository may belong to multiple groups.
Groups have no bearing on what files to synchronize; the files
must be specified per repository in the configuration file
under the repositories section.
The -g switch in the various commands directly refer to the
{group-name} specified in the configuration file.
Syntax:
groups:
{group-name-1}:
- {repo-name-1}
- {repo-name-2}
...
...EXAMPLE: This example comes from metanorma/metanorma-build-scripts/cimas-config/cimas.yml.
groups:
model:
- metanorma-model-iso
- metanorma-model-gb
- metanorma-model-standocPatches
In addition to full-file sync via files:, cimas supports in-place
line-level edits via a top-level patches: section. A patch is a named
regex find/replace that is applied to files already present in each target
repo. Patches are typically used for values (like a minimum Ruby version)
that live inside per-repo unique files (like `.gemspec`s) and therefore
cannot be copied wholesale.
patches:
ruby_version:
files:
- "*.gemspec"
find: 'spec\.required_ruby_version\s*=.*'
replace: 'spec.required_ruby_version = Gem::Requirement.new(">= 3.1.0")'
groups: [processor, pubid, model]Each patch entry supports these keys:
-
files— array of glob patterns, evaluated from each target repo’s root. Use*/.extfor recursive matching. -
find— Ruby regex (as a string). Compiled withRegexp.new. -
replace— replacement string passed togsub. Backreferences (\\1, etc.) work. -
groups— whichgroups:(defined elsewhere in the config) the patch applies to. A repo receives the patch if it appears in any listed group.
Patches are applied during cimas sync, immediately after the file-copy
phase, and the resulting changes are staged via git add so they flow
through cimas push and cimas open-prs the same way as file-copy
changes.
If a patch’s files glob matches nothing, or the find regex matches no
content in a file, cimas logs a warning but does not fail — this makes it
safe to leave stale patches in config without blocking other repos.
Unlike file-copy sync, patches do not prepend the "Auto-generated by Cimas" header, since they modify existing files in place rather than replacing them.
Development
After checking out the repo, run bin/setup to install dependencies. Then, run rake spec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/metanorma/cimas. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
Code of Conduct
Everyone interacting in the Cimas project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.