|
| 1 | +--- |
| 2 | +name: validate-rebase-rules |
| 3 | +description: Validates that .rebase/ rules (replace, add, override) are still current against upstream VS Code. Generates a rebase-rules-validation.md report with mismatches and proposed fixes. Use when asked to check, validate, or audit rebase rules, or before a rebase. |
| 4 | +--- |
| 5 | + |
| 6 | +# Validate Rebase Rules |
| 7 | + |
| 8 | +Check whether `.rebase/` rules are still applicable to the current upstream VS Code version and the current che-code branch. Produce a `rebase-rules-validation.md` report listing any problems found. |
| 9 | + |
| 10 | +## Prerequisites |
| 11 | + |
| 12 | +Ensure the `upstream-code` remote exists and is fetched: |
| 13 | + |
| 14 | +```bash |
| 15 | +git remote get-url upstream-code || git remote add upstream-code https://github.com/microsoft/vscode |
| 16 | +git fetch upstream-code |
| 17 | +``` |
| 18 | + |
| 19 | +## Step 1 — Resolve versions from rebase.sh |
| 20 | + |
| 21 | +Read `rebase.sh` and extract two variables: |
| 22 | + |
| 23 | +- `CURRENT_UPSTREAM_VERSION` — e.g. `release/1.108` |
| 24 | +- `PREVIOUS_UPSTREAM_VERSION` — e.g. `release/1.104` |
| 25 | + |
| 26 | +These are defined near the top of `rebase.sh` as shell variable assignments. |
| 27 | + |
| 28 | +Use the upstream git ref `upstream-code/<version>` when fetching file content: |
| 29 | + |
| 30 | +```bash |
| 31 | +git show upstream-code/<version>:<path> |
| 32 | +``` |
| 33 | + |
| 34 | +Where `<path>` is **without** the `code/` prefix (upstream stores VS Code sources at repo root). |
| 35 | + |
| 36 | +## Step 2 — Validate `.rebase/replace/` rules |
| 37 | + |
| 38 | +Each file under `.rebase/replace/` has the form `.rebase/replace/<code-path>.json` and contains a JSON array of `{ "from": "...", "by": "..." }` objects. |
| 39 | + |
| 40 | +**Path mapping:** |
| 41 | + |
| 42 | +| Context | Path | |
| 43 | +|---------|------| |
| 44 | +| Rule file | `.rebase/replace/<code-path>.json` | |
| 45 | +| Upstream file | `<code-path>` with leading `code/` stripped → use as path in `git show upstream-code/CURRENT_UPSTREAM_VERSION:<stripped-path>` | |
| 46 | +| che-code file | `<code-path>` in the current working tree | |
| 47 | + |
| 48 | +**For each rule entry:** |
| 49 | + |
| 50 | +1. **Check `from` in upstream.** Fetch the upstream file at `CURRENT_UPSTREAM_VERSION`. Verify the `from` string exists verbatim in that file content. Handle escape sequences in the JSON: `\n` → newline, `\t` → tab, `\\` → backslash. The actual file content must contain the **decoded** string. |
| 51 | + |
| 52 | +2. **Check `by` in che-code.** Read the che-code file from the current working tree. Verify the decoded `by` string exists in it. Again, decode JSON escapes before matching. |
| 53 | + |
| 54 | +3. **On mismatch — propose a fix.** |
| 55 | + - Fetch the same file at `PREVIOUS_UPSTREAM_VERSION`. |
| 56 | + - Compare the `PREVIOUS_UPSTREAM_VERSION` content with the `CURRENT_UPSTREAM_VERSION` content around the area where `from` was expected. |
| 57 | + - Identify what changed and propose the corrected `from` or `by` value. |
| 58 | + |
| 59 | +**Important note on escape handling in replace rules:** |
| 60 | +The replace rules use a custom escaping convention (not standard JSON escapes). For example `\\\n` means literal newline, `\\\t` means literal tab. When reading the JSON with `jq -r`, these are automatically decoded to actual newline/tab characters. Always use `jq -r '.from'` and `jq -r '.by'` to get the real strings for comparison. |
| 61 | + |
| 62 | +## Step 3 — Validate `.rebase/add/` rules |
| 63 | + |
| 64 | +Files under `.rebase/add/` are JSON fragments that get **merged into** upstream files using jq: `jq -s '.[1] * .[0]' <add-file> <upstream-file>` — the add-rule values take priority for conflicting keys. By convention, add rules are intended for keys absent in upstream, so conflicts should not occur. |
| 65 | + |
| 66 | +### 3a — Check upstream for conflicts |
| 67 | + |
| 68 | +The purpose of `add` rules is to add keys that **do not exist** in upstream. If a key now exists in upstream, the rule may be redundant or causing a silent override. |
| 69 | + |
| 70 | +**For each file in `.rebase/add/`:** |
| 71 | + |
| 72 | +1. Identify the upstream file path (strip `code/` prefix). |
| 73 | +2. Read the add rule JSON. |
| 74 | +3. Fetch the upstream file at `CURRENT_UPSTREAM_VERSION`. |
| 75 | +4. For every leaf key/value in the add rule, check if that key exists in the upstream file: |
| 76 | + - **Key absent in upstream** → OK, the add rule is still needed. |
| 77 | + - **Key exists with the same value** → WARNING: add rule is redundant, upstream already has this value. Consider removing it. |
| 78 | + - **Key exists with a different value** → WARNING: the add rule silently overrides the upstream value. This is a potential conflict. |
| 79 | + - For version-like values (semver): if upstream version ≥ add-rule version → the add rule may be downgrading. Report as WARNING. |
| 80 | + - For non-version values: report the upstream value vs add-rule value for manual review. |
| 81 | + |
| 82 | +### 3b — Check che-code for correct application |
| 83 | + |
| 84 | +Verify that the add rule values are actually present in the current che-code working tree. |
| 85 | + |
| 86 | +**For each file in `.rebase/add/`:** |
| 87 | + |
| 88 | +1. Identify the corresponding che-code file (same path, e.g. `.rebase/add/code/package.json` → `code/package.json`). |
| 89 | +2. Read the che-code file from the working tree. |
| 90 | +3. Read the add rule JSON. |
| 91 | +4. For every leaf key/value in the add rule, verify it is present in the che-code file: |
| 92 | + - For flat key-value pairs, check exact key and value presence. |
| 93 | + - For nested objects (e.g. `dependencies`, `devDependencies`, `overrides`), check that each leaf key-value from the add rule appears in the corresponding section of the che-code file. |
| 94 | +5. If a value from the add rule is **not** found in the che-code file, report it as ERROR: rule was not applied or was overwritten. |
| 95 | + |
| 96 | +**Note:** For `product.json` add rules, check nested arrays and objects similarly — verify each element/key is present. |
| 97 | + |
| 98 | +## Step 4 — Validate `.rebase/override/` rules |
| 99 | + |
| 100 | +Files under `.rebase/override/` are JSON fragments merged **over** upstream files using jq: `jq -s '.[0] * .[1]' <upstream-file> <override-file>` — override values take priority. |
| 101 | + |
| 102 | +**For each file in `.rebase/override/`:** |
| 103 | + |
| 104 | +1. Identify the upstream file path (strip `code/` prefix). |
| 105 | +2. Read the override rule JSON. |
| 106 | +3. Fetch the upstream file at `CURRENT_UPSTREAM_VERSION`. |
| 107 | +4. For every leaf key in the override rule: |
| 108 | + a. **Check key still exists in upstream.** If the key no longer exists in the upstream file at `CURRENT_UPSTREAM_VERSION`, report a warning: the override may be unnecessary or the upstream structure changed. |
| 109 | + b. **For version-like values (semver patterns like `^X.Y.Z`):** Compare the upstream value with the override value. Use semver logic: |
| 110 | + - If upstream version ≥ override version → report a warning (override may no longer be needed because upstream already meets or exceeds the required version). |
| 111 | + - If upstream version < override version → OK, override is still needed. |
| 112 | + c. **For non-version values:** If the upstream value already equals the override value, report a warning (override is redundant). |
| 113 | + |
| 114 | +**Semver comparison guidance:** |
| 115 | +Strip leading `^`, `~`, `>=` etc. before comparing. Compare major.minor.patch numerically. For example, `^5.1.9` override vs `^5.1.0` upstream → upstream `5.1.0 < 5.1.9` → OK. But `^5.1.9` override vs `^5.2.0` upstream → upstream `5.2.0 > 5.1.9` → warn. |
| 116 | + |
| 117 | +## Step 5 — Generate the report |
| 118 | + |
| 119 | +Create `rebase-rules-validation.md` in the repository root. Only create this file if there are findings to report. If all rules are valid, inform the user and do not create the file. |
| 120 | + |
| 121 | +### Report format |
| 122 | + |
| 123 | +```markdown |
| 124 | +# Rebase Rules Validation Report |
| 125 | + |
| 126 | +> Generated against upstream `<CURRENT_UPSTREAM_VERSION>` (previous: `<PREVIOUS_UPSTREAM_VERSION>`) |
| 127 | +
|
| 128 | +## Critical findings |
| 129 | + |
| 130 | +<!-- Numbered list of the most important actionable items, e.g.: --> |
| 131 | +1. **Short description** — Why it matters and what to do. |
| 132 | +2. ... |
| 133 | + |
| 134 | +--- |
| 135 | + |
| 136 | +## Replace Rules |
| 137 | + |
| 138 | +| Rule file | Problematic value | Proposed fix | |
| 139 | +|-----------|-------------------|--------------| |
| 140 | +| `.rebase/replace/code/src/server-main.js.json` | `"from": "const product = ..."` not found in upstream | `"from": "const product = <new value>"` | |
| 141 | + |
| 142 | +## Add Rules |
| 143 | + |
| 144 | +| Rule file | Issue | |
| 145 | +|-----------|-------| |
| 146 | +| `.rebase/add/code/package.json` | Key `dependencies.ws` with value `8.2.3` not found in `code/package.json` | |
| 147 | + |
| 148 | +## Override Rules |
| 149 | + |
| 150 | +| Rule file | Key | Issue | |
| 151 | +|-----------|-----|-------| |
| 152 | +| `.rebase/override/code/extensions/npm/package.json` | `dependencies.minimatch` | Upstream already at `^5.2.0` which is ≥ override `^5.1.9` — override may be unnecessary | |
| 153 | +``` |
| 154 | + |
| 155 | +### Severity indicators |
| 156 | + |
| 157 | +Use these prefixes in the Issue/Proposed fix column: |
| 158 | + |
| 159 | +- **ERROR** — `from` or `by` value not found; rule will fail during rebase |
| 160 | +- **WARNING** — override may be unnecessary or redundant |
| 161 | +- **INFO** — value changed but rule still works |
| 162 | + |
| 163 | +## Workflow summary |
| 164 | + |
| 165 | +1. Fetch upstream remote. |
| 166 | +2. Extract versions from `rebase.sh`. |
| 167 | +3. Enumerate all files under `.rebase/replace/`, `.rebase/add/`, `.rebase/override/`. |
| 168 | +4. For each rule, perform the checks described above. |
| 169 | +5. Collect all findings. |
| 170 | +6. Generate `rebase-rules-validation.md` if there are findings. Otherwise report success. |
| 171 | + |
| 172 | +## Parallelization guidance |
| 173 | + |
| 174 | +When checking rules, launch parallel subagents or batch operations where possible: |
| 175 | + |
| 176 | +- All `.rebase/replace/` rule files can be checked independently. |
| 177 | +- All `.rebase/add/` rule files can be checked independently. |
| 178 | +- All `.rebase/override/` rule files can be checked independently. |
| 179 | +- Upstream file fetches (`git show`) can be batched. |
| 180 | + |
| 181 | +## Missing file handling |
| 182 | + |
| 183 | +Apply these rules across all steps when a target file cannot be found: |
| 184 | + |
| 185 | +| File missing | Behavior | |
| 186 | +|--------------|----------| |
| 187 | +| **Upstream file not found** (`git show` fails) | Report as ERROR: the file was likely removed or renamed in VS Code. The entire rule file is suspect and should be reviewed. | |
| 188 | +| **Che-code file not found** in working tree | Report as ERROR: the file is missing. The rule targets a file that does not exist in che-code. | |
| 189 | + |
| 190 | +## Edge cases |
| 191 | + |
| 192 | +- Some replace rules use multiline `from`/`by` values with `\\\n` and `\\\t` escapes. Always decode before matching. |
| 193 | +- `code/package.json` can have both replace, add, and override rules simultaneously. Check each independently. |
| 194 | +- `product.json` uses tab indentation (see `override_json_file` call with `"tab"` parameter in `rebase.sh`). |
0 commit comments