|
| 1 | +# qDup 0.11 Migration Guide |
| 2 | + |
| 3 | +## Breaking Changes in qDup 0.11 |
| 4 | + |
| 5 | +qDup 0.11 introduces a breaking change in how commands handle their output and pass it to subsequent actions. This document explains the change and provides examples to help you migrate your scripts. |
| 6 | + |
| 7 | +## The Key Change: Input Flow in `then` Blocks |
| 8 | + |
| 9 | +In qDup 0.11, **actions nested under a command's `then` block receive their input from that command**, not from previous sibling commands. |
| 10 | + |
| 11 | +### Rule Summary |
| 12 | + |
| 13 | +✅ **Works in both 0.10 and 0.11:** |
| 14 | +```yaml |
| 15 | +- sh: command |
| 16 | + then: |
| 17 | + - set-state: RESULT |
| 18 | +``` |
| 19 | +The `set-state` gets its input from the `sh` command because it's nested under the `sh`'s `then` block. |
| 20 | + |
| 21 | +❌ **Does NOT work in 0.11 (but worked in 0.10):** |
| 22 | +```yaml |
| 23 | +- regex: something |
| 24 | + then: |
| 25 | + - sh: command |
| 26 | + - set-state: RESULT |
| 27 | +``` |
| 28 | +The `set-state` will get its input from the `regex`, NOT from the `sh` command, because they are siblings under the same `then` block. |
| 29 | + |
| 30 | +## Migration Examples |
| 31 | + |
| 32 | +### Example 1: Sequential Commands Under a `then` Block |
| 33 | + |
| 34 | +**Old Pattern (qDup < 0.11):** |
| 35 | +```yaml |
| 36 | +- sh: scp ./file.war ${{SCP_PATH}}/file.war |
| 37 | +- regex: No such file or directory |
| 38 | + then: |
| 39 | + - abort: failed to build file.war |
| 40 | +``` |
| 41 | + |
| 42 | +**New Pattern (qDup 0.11+):** |
| 43 | +```yaml |
| 44 | +- sh: scp ./file.war ${{SCP_PATH}}/file.war |
| 45 | + then: |
| 46 | + - regex: No such file or directory |
| 47 | + then: |
| 48 | + - abort: failed to build file.war |
| 49 | +``` |
| 50 | + |
| 51 | +**Why?** In 0.11, the `regex` must be nested under the `sh`'s `then` block to receive the `sh` command's output. |
| 52 | + |
| 53 | +### Example 2: Multiple Sequential Commands |
| 54 | + |
| 55 | +**Old Pattern (qDup < 0.11):** |
| 56 | +```yaml |
| 57 | +- read-state: ${{SCP_PATH}} |
| 58 | + then: |
| 59 | + - sh: scp ./file1.war ${{SCP_PATH}}/file1.war |
| 60 | + - regex: No such file or directory |
| 61 | + then: |
| 62 | + - abort: failed to build file1.war |
| 63 | + - sh: scp ./file2.war ${{SCP_PATH}}/file2.war |
| 64 | + - regex: No such file or directory |
| 65 | + then: |
| 66 | + - abort: failed to build file2.war |
| 67 | +``` |
| 68 | + |
| 69 | +**New Pattern (qDup 0.11+):** |
| 70 | +```yaml |
| 71 | +- read-state: ${{SCP_PATH}} |
| 72 | + then: |
| 73 | + - sh: scp ./file1.war ${{SCP_PATH}}/file1.war |
| 74 | + then: |
| 75 | + - regex: No such file or directory |
| 76 | + then: |
| 77 | + - abort: failed to build file1.war |
| 78 | + - sh: scp ./file2.war ${{SCP_PATH}}/file2.war |
| 79 | + then: |
| 80 | + - regex: No such file or directory |
| 81 | + then: |
| 82 | + - abort: failed to build file2.war |
| 83 | +``` |
| 84 | + |
| 85 | +**Why?** Each `regex` must be nested under its corresponding `sh` command's `then` block to receive that command's output. |
| 86 | + |
| 87 | +### Example 3: Command with State Setting |
| 88 | + |
| 89 | +**Works in both 0.10 and 0.11:** |
| 90 | +```yaml |
| 91 | +- sh: echo $(($(date "+%s%N" -d "$(head -1 /tmp/first_response.txt)")/1000000)) |
| 92 | + then: |
| 93 | + - set-state: RUN.LOOP_SERVICE_FIRST_RESP_TIMESTAMP |
| 94 | +``` |
| 95 | + |
| 96 | +**Why?** The `set-state` is nested under the `sh`'s `then` block, so it receives the `sh` command's output in both versions. |
| 97 | + |
| 98 | +### Example 4: Conditional Execution |
| 99 | + |
| 100 | +**Old Pattern (qDup < 0.11):** |
| 101 | +```yaml |
| 102 | +- sh: "[[ -f ${{RAPL_PATH}}/rapl-plot ]] || echo GETRAPL;" |
| 103 | +- regex: GET |
| 104 | + then: |
| 105 | + - sh: rm -Rf ${{RAPL_PATH}} |
| 106 | + - sh: mkdir -p ${{RAPL_PATH}} |
| 107 | + - sh: cd ${{RAPL_PATH}} |
| 108 | + - sh: git clone https://github.com/example/repo.git |
| 109 | +``` |
| 110 | + |
| 111 | +**New Pattern (qDup 0.11+):** |
| 112 | +```yaml |
| 113 | +- sh: "[[ -f ${{RAPL_PATH}}/rapl-plot ]] || echo GETRAPL;" |
| 114 | + then: |
| 115 | + - regex: GET |
| 116 | + then: |
| 117 | + - sh: rm -Rf ${{RAPL_PATH}} |
| 118 | + - sh: mkdir -p ${{RAPL_PATH}} |
| 119 | + - sh: cd ${{RAPL_PATH}} |
| 120 | + - sh: git clone https://github.com/example/repo.git |
| 121 | +``` |
| 122 | + |
| 123 | +**Why?** The `regex` must be nested under the first `sh`'s `then` block to check its output. The subsequent `sh` commands are sequential and don't need further nesting. |
| 124 | + |
| 125 | +## Key Principles |
| 126 | + |
| 127 | +1. **Nesting determines input flow**: An action receives input from its parent command, not from sibling commands. |
| 128 | + |
| 129 | +2. **Sequential commands at the same level**: Commands at the same indentation level are executed sequentially but don't pass output to each other. |
| 130 | + |
| 131 | +3. **Use `then` blocks for dependencies**: If an action needs to process a command's output, nest it under that command's `then` block. |
| 132 | + |
| 133 | +## Migration Checklist |
| 134 | + |
| 135 | +When migrating to qDup 0.11: |
| 136 | + |
| 137 | +- [ ] Identify all `- sh:` commands followed by `- regex:` at the same indentation level |
| 138 | +- [ ] Nest the `- regex:` under the `- sh:`'s `then:` block |
| 139 | +- [ ] Ensure any actions that depend on the `regex` are nested under the `regex`'s `then:` block |
| 140 | +- [ ] Test your scripts with qDup 0.11 to verify correct behavior |
| 141 | + |
| 142 | +## Finding Files to Update |
| 143 | + |
| 144 | +Use this command to find YAML files containing `- sh` commands: |
| 145 | + |
| 146 | +```bash |
| 147 | +find . -name "*.yaml" -type f -exec grep -l -- "- sh" {} \; |
| 148 | +``` |
0 commit comments