skip to content

A CI job enforces backup retention with a shell script that exits 1. What does restating it as a policy rule buy?

level: juniorimportance: must knowfreq 62%

answer

  1. both are code; shape is the difference
  2. what does exit 1 actually carry?
  3. one bit versus a result per rule
  4. can you list the rules without running them?
  5. same rule, a second enforcement point

basics

~20 s

A rule file states the condition as data, so the engine can report which rule failed on which resource, and the same rule can be listed, reviewed and reused elsewhere. An exit code carries one bit: pass or fail.

solid answer

~50 s

Both are code and both live in version control, so this is not code versus no code — it is shape. The shell check is a procedure whose only structured output is an exit status; which database failed and why is stranded in log text. As a rule, the condition (retention must be at least 35 days) becomes data the engine evaluates against an input document, and it returns a result per rule per resource with the rule's name and a message. Because the rule set is itself data, I can list every rule we enforce, diff a change to one, and hand the same retention rule to a second enforcement point without rewriting the check. What the rule form does not buy is expressiveness or easy debugging, and it does not make the threshold any more correct than the script's.

go deeper

for a junior

Be ready to say what an exit status carries — pass or fail, nothing more — and to name two things the rule form gives instead: a named result per rule and a rule set someone can read without running it.

for a middle

Explain the mechanics: the condition becomes data evaluated against an input document, results come back per rule and per resource, and the decision about what to do with a violation is made by the caller, not the rule.

for a senior

Show when the rewrite pays for itself — several enforcement points, a growing catalogue, readers outside the team — and be candid about the debuggability tax and the component you now have to operate.

for a principal

Own the framing that the rule set, not any individual check, is the artifact worth having, and be able to say which checks you would deliberately leave as scripts and what that split costs in maintenance.

## The comparison is not code versus no code A shell check in a CI job is already code: it is committed, reviewed and diffable. So the honest question is not "is this policy as code" — it is what shape the check is in, and what that shape lets a machine and a reader do with it *without running it*. Take one concrete guardrail: **a managed database must keep at least 35 days of backups**. Two ways to state it. **As a script.** A job step reads the configuration, pulls the retention field out with a text or JSON filter, compares it to 35, prints a message and calls `exit 1`. The condition exists only as a step inside a procedure. Its output is an exit status — one bit — plus whatever it happened to print. **As a rule.** The same condition is written as a named rule in a file the engine loads: an input document goes in, and a decision comes out that says *this rule*, *this resource*, *this message*. The rule does not decide what happens next; the thing that called the engine does. ## What the data shape actually buys **Inspectability.** The set of rules can be read as a list. Someone who does not write the check language can still see that there are forty rules, what each is called, and that retention is one of them. With a pile of scripts, the only way to know what is enforced is to read every script, including the branches that quietly `return 0` early. **A result per rule, per resource.** An exit code collapses everything. A script that exits on the first failure hides the other nine. A rule evaluation produces a decision for each rule against each object, so a caller can count them, group them, attach them to the resource that caused them, or report on the ones it does not intend to block on. That structure is what makes a report possible at all. **Reuse.** Because the rule is data over an input document rather than a procedure wired to one job, the same rule can be evaluated wherever that input can be produced — a pre-merge check on a proposed change and a periodic sweep of what is actually running. This is usually the argument that decides adoption, and it is a practical one, not an aesthetic one. It is not automatic: both places have to feed the rule the fact in the same shape. **Mechanical handling.** Rules as data can be counted, parameterised (35 days here, 7 in the sandbox), rendered into documentation, and exercised one at a time against a known input. The script's condition cannot be picked up and used by anything other than the script. ## What it costs **Expressiveness.** A rule language is deliberately small. Anything that has to walk a paginated listing, join two systems or retry a flaky call is awkward or impossible in it, and that work belongs outside the rule. **Debuggability.** This is the real tax. A script has print statements, a stack trace and a step-through. A declarative rule that stops matching does not go red — in most rule languages a body that does not hold simply produces *no result*, which the caller reads as "nothing to report". Rename a field in the input and the rule goes quiet rather than failing loudly. "Undefined" is not "false", and a rule that produces nothing is indistinguishable from a rule that found nothing wrong. **A new dependency.** The engine is a component the team now runs, upgrades and debugs, and a language most of the team does not yet write. ## The line to hold in an interview Moving a check from a script to a rule changes what you can *do with the check*, not what the check *knows*. A wrong threshold is wrong in either form. The rule form pays off when the rule set — not any single check — is the thing you need: readable by people outside the team, reusable at more than one enforcement point, and reportable per rule. When you have one check, running at one place, read by nobody but its author, the script is fine and saying so is the stronger answer.

  • The script prints a clear message before exiting. Is that not the same information?
    No. A printed line is text in a log: nothing downstream can reliably group it by resource, count it, filter it, or tell it apart from the script's other output. A rule result is a structured record naming the rule, the object and the message, which is what a report or a dashboard consumes.
  • Does moving the check into a rule file make it more secure?
    Not by itself. The same condition with the same threshold catches the same things. What changes is that the condition is visible without reading a procedure, produces per-rule results, and can be reused. If the threshold was wrong at 7 days, it is still wrong as a rule.
  • What is the first thing you give up when a check becomes a rule?
    Free-form procedure and easy debugging. There is no print statement mid-evaluation and no stack trace, and a rule whose condition never holds produces no result rather than an error — so a rule that has silently stopped matching looks exactly like a rule that found nothing wrong.

A script is a note that says "I checked, and it was fine." A rule set is the checklist itself — anyone can read it, tick items off one by one, and hand the same checklist to a second inspector.

saying these in an interview costs you the question

  • Says rules are better because declarative code is cleaner
  • Believes an exit code can identify which check failed
  • Claims shell checks cannot be reviewed or version controlled
  • Treats the rewrite as free and ignores the new dependency
  • Assumes the rule form makes the check itself more correct

context