Skip to content

Commit c7a30b2

Browse files
committed
490fa8
1 parent 94fbb72 commit c7a30b2

2 files changed

Lines changed: 81 additions & 2 deletions

File tree

COOKBOOK.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -689,7 +689,7 @@ target "local" local:
689689
- `phase "install" when "action == 'install'":` groups all install steps. Every step in the block gets `when "action == 'install'"` injected automatically.
690690
- `phase "rollback" when "action == 'rollback'":` groups rollback steps — they are completely skipped during an install run.
691691
- `set stateless = true` means the graph has no state file, so a previous install run can't cause rollback steps to be skipped on the next run.
692-
- `run:` multiline blocks join lines with `&&` — if any line fails, the rest do not run.
692+
- `run:` multiline blocks run under `set -e; set -o pipefail` — if any line fails, the rest do not run.
693693
- `skip if:` multiline blocks join conditions with `&&` — all must exit 0 to skip.
694694

695695
**Usage:**
@@ -698,10 +698,75 @@ sudo cgr apply service.cgr --set action=install
698698
sudo cgr apply service.cgr --set action=rollback
699699
```
700700

701+
**`phase` only gates the steps inside it.** Steps outside a `phase` block are not affected by its `when` condition. A skipped step counts as done for `first` purposes, so a step that depends on a phase step will still run even when the phase condition is false:
702+
703+
```
704+
phase "install" when "action == 'install'":
705+
[configure]:
706+
...
707+
708+
[post-configure]: # outside the phase — runs regardless of action
709+
first [configure]
710+
...
711+
```
712+
713+
If `[post-configure]` should also be gated, put it inside the `phase` block — it will inherit the `when` condition automatically. Or add an explicit `when "action == 'install'"` to it directly.
714+
701715
---
702716

703717
## Patterns (continued)
704718

719+
### Conditional branching by runtime value
720+
721+
When the branch to take depends on a fact discovered at runtime (which subnet the host is on, which OS family, etc.), use paired `skip if $` steps — each skips when the host doesn't match, and both converge to a shared downstream step:
722+
723+
```
724+
[configure for subnet X]:
725+
skip if $ ip addr show | grep -qv '10\.0\.1\.'
726+
run:
727+
...
728+
729+
[configure for subnet Y]:
730+
skip if $ ip addr show | grep -qv '10\.0\.2\.'
731+
run:
732+
...
733+
734+
[post-configure]:
735+
first [configure for subnet X], [configure for subnet Y]
736+
run:
737+
...
738+
```
739+
740+
On a subnet-X host, `[configure for subnet Y]` is skipped — a skip counts as done for `first` purposes, so `[post-configure]` runs after whichever branch actually executed.
741+
742+
**If the configure step fails:** the default `on_fail = stop` halts the graph, so `[post-configure]` never runs. If you use `if fails warn` to allow the graph to continue past a failure, add a sentinel guard to `[post-configure]`:
743+
744+
```
745+
[configure for subnet X]:
746+
skip if $ ip addr show | grep -qv '10\.0\.1\.'
747+
if fails warn
748+
run:
749+
...
750+
touch /tmp/.subnet-x-done
751+
752+
[configure for subnet Y]:
753+
skip if $ ip addr show | grep -qv '10\.0\.2\.'
754+
if fails warn
755+
run:
756+
...
757+
touch /tmp/.subnet-y-done
758+
759+
[post-configure]:
760+
first [configure for subnet X], [configure for subnet Y]
761+
skip if $ ! { test -f /tmp/.subnet-x-done || test -f /tmp/.subnet-y-done; }
762+
run:
763+
...
764+
```
765+
766+
The sentinel file is only written on success, so `[post-configure]` skips itself when neither configure step completed.
767+
768+
**When to use `phase` instead:** if the branch is driven by a variable known at invocation time (not discovered at runtime), `phase "name" when "COND":` is cleaner — pass `--set action=install` and let the phase block gate the whole group.
769+
705770
### Multiline commands without shell glue
706771

707772
Long one-liners are hard to review and error-prone to edit. Use `run:` to split them across lines:
@@ -719,7 +784,7 @@ Long one-liners are hard to review and error-prone to edit. Use `run:` to split
719784
chmod 600 /etc/nginx/certs/server.key
720785
```
721786

722-
Lines are joined with `&&` — if `openssl` fails, `chmod` does not run. To continue past a failure, append `|| true` to that line.
787+
Lines run under `set -e; set -o pipefail` — if `openssl` fails, `chmod` does not run. To continue past a failure, append `|| true` to that line.
723788

724789
### `always run:` for service restarts
725790

@@ -754,6 +819,7 @@ Quick lookup: which feature solves your problem?
754819
| Install/rollback modes | Phase blocks | `phase "name" when "COND":` | MANUAL.md |
755820
| Multi-line commands | Multiline run | `run:` block | MANUAL.md |
756821
| Conditional steps | When | `when VAR == "val"` | MANUAL.md |
822+
| Branch on runtime fact | Paired skip if | `skip if $ cmd` (see Patterns) | MANUAL.md |
757823
| Subset execution | Tags | `tags x, y` / `--tags` | MANUAL.md |
758824
| Collect output | Reporting | `collect "key"` / `cgr report` | MANUAL.md |
759825
| Store secrets | Encryption | `cgr secrets` / `secrets "file"` | MANUAL.md |

docs/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# CommandGraph Documentation
2+
3+
The main CommandGraph documentation lives in the repository root:
4+
5+
- [README](../README.md)
6+
- [Quickstart](../QUICKSTART.md)
7+
- [Manual](../MANUAL.md)
8+
- [Tutorial](../TUTORIAL.md)
9+
- [Cookbook](../COOKBOOK.md)
10+
- [CommandGraph specification](../COMMANDGRAPH_SPEC.md)
11+
- [Troubleshooting](../TROUBLESHOOTING.md)
12+
13+
This directory contains documentation assets and demos referenced by those root documents.

0 commit comments

Comments
 (0)