|
38 | 38 | mvn install -pl sandbox_common_core -DskipTests -q |
39 | 39 | mvn package -pl sandbox_mining_core -DskipTests -q |
40 | 40 |
|
| 41 | + - name: Snapshot known rules before mining |
| 42 | + run: | |
| 43 | + if [ -f docs/mining-report/known-rules.json ]; then |
| 44 | + cp docs/mining-report/known-rules.json "$RUNNER_TEMP/known-rules-before.json" |
| 45 | + else |
| 46 | + printf '{"version":1,"rules":[]}' > "$RUNNER_TEMP/known-rules-before.json" |
| 47 | + fi |
| 48 | +
|
41 | 49 | - name: Run Commit Mining |
42 | 50 | continue-on-error: true |
43 | 51 | env: |
|
64 | 72 | --output docs/mining-report/ \ |
65 | 73 | ${{ github.event.inputs.llm_provider != '' && format('--llm-provider {0}', github.event.inputs.llm_provider) || '' }} |
66 | 74 |
|
| 75 | + - name: Reconcile staged mining candidates |
| 76 | + if: always() |
| 77 | + run: | |
| 78 | + BEFORE_KNOWN="$RUNNER_TEMP/known-rules-before.json" |
| 79 | + CURRENT_KNOWN="docs/mining-report/known-rules.json" |
| 80 | + CANDIDATE_DIR="mining-candidates" |
| 81 | + if [ ! -f "$CURRENT_KNOWN" ]; then |
| 82 | + echo "No known-rules.json found after mining; skipping candidate reconciliation." |
| 83 | + exit 0 |
| 84 | + fi |
| 85 | + python3 - "$BEFORE_KNOWN" "$CURRENT_KNOWN" "$CANDIDATE_DIR" <<'PY' |
| 86 | + import json |
| 87 | + import pathlib |
| 88 | + import sys |
| 89 | +
|
| 90 | + before_path = pathlib.Path(sys.argv[1]) |
| 91 | + known_path = pathlib.Path(sys.argv[2]) |
| 92 | + candidate_dir = pathlib.Path(sys.argv[3]) |
| 93 | +
|
| 94 | + def load_rules(path): |
| 95 | + if not path.exists(): |
| 96 | + return {"version": 1, "rules": []} |
| 97 | + with path.open(encoding="utf-8") as handle: |
| 98 | + return json.load(handle) |
| 99 | +
|
| 100 | + before = load_rules(before_path) |
| 101 | + current = load_rules(known_path) |
| 102 | + before_commits = { |
| 103 | + rule.get("sourceCommit") |
| 104 | + for rule in before.get("rules", []) |
| 105 | + if rule.get("sourceCommit") |
| 106 | + } |
| 107 | +
|
| 108 | + candidate_commits = set() |
| 109 | + if candidate_dir.exists(): |
| 110 | + for candidate_path in candidate_dir.glob("*-candidate.json"): |
| 111 | + try: |
| 112 | + with candidate_path.open(encoding="utf-8") as handle: |
| 113 | + candidate = json.load(handle) |
| 114 | + commit = candidate.get("sourceCommit") |
| 115 | + if commit: |
| 116 | + candidate_commits.add(commit) |
| 117 | + except Exception as exc: |
| 118 | + print(f"Warning: could not read candidate {candidate_path}: {exc}", file=sys.stderr) |
| 119 | +
|
| 120 | + rules = current.get("rules", []) |
| 121 | + kept = [ |
| 122 | + rule for rule in rules |
| 123 | + if rule.get("sourceCommit") in before_commits |
| 124 | + or rule.get("sourceCommit") in candidate_commits |
| 125 | + ] |
| 126 | + removed = len(rules) - len(kept) |
| 127 | + if removed: |
| 128 | + current["rules"] = kept |
| 129 | + with known_path.open("w", encoding="utf-8") as handle: |
| 130 | + json.dump(current, handle, indent=2) |
| 131 | + handle.write("\n") |
| 132 | + print( |
| 133 | + "Candidate reconciliation: " |
| 134 | + f"kept {len(kept)} known rules, " |
| 135 | + f"removed {removed} non-staged new rules, " |
| 136 | + f"candidate commits {len(candidate_commits)}" |
| 137 | + ) |
| 138 | + PY |
| 139 | +
|
67 | 140 | - name: Post-run diagnostics |
68 | 141 | if: always() |
69 | 142 | run: | |
@@ -99,6 +172,11 @@ jobs: |
99 | 172 | if [ -f docs/mining-report/known-rules.json ]; then |
100 | 173 | git add docs/mining-report/known-rules.json |
101 | 174 | fi |
| 175 | + # Include staged mining candidates if they were created/updated |
| 176 | + CANDIDATE_DIR="mining-candidates" |
| 177 | + if [ -d "$CANDIDATE_DIR" ]; then |
| 178 | + git add "$CANDIDATE_DIR"/*.json 2>/dev/null || true |
| 179 | + fi |
102 | 180 | # Include auto-generated .sandbox-hint files from HintFileUpdater |
103 | 181 | HINT_DIR="sandbox_common_core/src/main/resources/org/sandbox/jdt/triggerpattern/internal" |
104 | 182 | if [ -d "$HINT_DIR" ]; then |
@@ -129,11 +207,15 @@ jobs: |
129 | 207 | if [ -f docs/mining-report/known-rules.json ]; then |
130 | 208 | git add docs/mining-report/known-rules.json |
131 | 209 | fi |
| 210 | + # Re-add staged mining candidates after stash pop |
| 211 | + if [ -d "$CANDIDATE_DIR" ]; then |
| 212 | + git add "$CANDIDATE_DIR"/*.json 2>/dev/null || true |
| 213 | + fi |
132 | 214 | # Re-add hint files after stash pop |
133 | 215 | if [ -d "$HINT_DIR" ]; then |
134 | 216 | git add $HINT_DIR/*.sandbox-hint 2>/dev/null || true |
135 | 217 | fi |
136 | | - git commit -m "mining: Update state + known rules + hints $(date +%Y-%m-%d)" |
| 218 | + git commit -m "mining: Update state + known rules + candidates $(date +%Y-%m-%d)" |
137 | 219 | git push origin "$BRANCH" --force |
138 | 220 | echo "state_updated=true" >> "$GITHUB_OUTPUT" |
139 | 221 |
|
@@ -298,4 +380,7 @@ jobs: |
298 | 380 | if: always() |
299 | 381 | with: |
300 | 382 | name: mining-report-${{ github.run_number }} |
301 | | - path: docs/mining-report/ |
| 383 | + path: | |
| 384 | + docs/mining-report/ |
| 385 | + mining-candidates/ |
| 386 | + if-no-files-found: ignore |
0 commit comments