coderifts 1.7.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/cli.js +496 -48
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -3003,7 +3003,7 @@ var require_package = __commonJS({
3003
3003
  "package.json"(exports2, module2) {
3004
3004
  module2.exports = {
3005
3005
  name: "coderifts",
3006
- version: "1.7.1",
3006
+ version: "1.8.0",
3007
3007
  description: "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
3008
3008
  author: "CodeRifts <hello@coderifts.com>",
3009
3009
  license: "MIT",
@@ -3058,7 +3058,7 @@ var require_package = __commonJS({
3058
3058
  "json-schema-ref-parser": "npm:@apidevtools/json-schema-ref-parser@^11.7.3"
3059
3059
  },
3060
3060
  devDependencies: {
3061
- esbuild: "^0.27.3"
3061
+ esbuild: "^0.27.4"
3062
3062
  }
3063
3063
  };
3064
3064
  }
@@ -61466,14 +61466,438 @@ var require_proxy_from_env = __commonJS({
61466
61466
  }
61467
61467
  });
61468
61468
 
61469
- // node_modules/follow-redirects/debug.js
61469
+ // ../../node_modules/ms/index.js
61470
+ var require_ms = __commonJS({
61471
+ "../../node_modules/ms/index.js"(exports2, module2) {
61472
+ var s = 1e3;
61473
+ var m = s * 60;
61474
+ var h = m * 60;
61475
+ var d = h * 24;
61476
+ var y = d * 365.25;
61477
+ module2.exports = function(val, options) {
61478
+ options = options || {};
61479
+ var type = typeof val;
61480
+ if (type === "string" && val.length > 0) {
61481
+ return parse(val);
61482
+ } else if (type === "number" && isNaN(val) === false) {
61483
+ return options.long ? fmtLong(val) : fmtShort(val);
61484
+ }
61485
+ throw new Error(
61486
+ "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
61487
+ );
61488
+ };
61489
+ function parse(str) {
61490
+ str = String(str);
61491
+ if (str.length > 100) {
61492
+ return;
61493
+ }
61494
+ var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
61495
+ str
61496
+ );
61497
+ if (!match) {
61498
+ return;
61499
+ }
61500
+ var n = parseFloat(match[1]);
61501
+ var type = (match[2] || "ms").toLowerCase();
61502
+ switch (type) {
61503
+ case "years":
61504
+ case "year":
61505
+ case "yrs":
61506
+ case "yr":
61507
+ case "y":
61508
+ return n * y;
61509
+ case "days":
61510
+ case "day":
61511
+ case "d":
61512
+ return n * d;
61513
+ case "hours":
61514
+ case "hour":
61515
+ case "hrs":
61516
+ case "hr":
61517
+ case "h":
61518
+ return n * h;
61519
+ case "minutes":
61520
+ case "minute":
61521
+ case "mins":
61522
+ case "min":
61523
+ case "m":
61524
+ return n * m;
61525
+ case "seconds":
61526
+ case "second":
61527
+ case "secs":
61528
+ case "sec":
61529
+ case "s":
61530
+ return n * s;
61531
+ case "milliseconds":
61532
+ case "millisecond":
61533
+ case "msecs":
61534
+ case "msec":
61535
+ case "ms":
61536
+ return n;
61537
+ default:
61538
+ return void 0;
61539
+ }
61540
+ }
61541
+ function fmtShort(ms) {
61542
+ if (ms >= d) {
61543
+ return Math.round(ms / d) + "d";
61544
+ }
61545
+ if (ms >= h) {
61546
+ return Math.round(ms / h) + "h";
61547
+ }
61548
+ if (ms >= m) {
61549
+ return Math.round(ms / m) + "m";
61550
+ }
61551
+ if (ms >= s) {
61552
+ return Math.round(ms / s) + "s";
61553
+ }
61554
+ return ms + "ms";
61555
+ }
61556
+ function fmtLong(ms) {
61557
+ return plural(ms, d, "day") || plural(ms, h, "hour") || plural(ms, m, "minute") || plural(ms, s, "second") || ms + " ms";
61558
+ }
61559
+ function plural(ms, n, name) {
61560
+ if (ms < n) {
61561
+ return;
61562
+ }
61563
+ if (ms < n * 1.5) {
61564
+ return Math.floor(ms / n) + " " + name;
61565
+ }
61566
+ return Math.ceil(ms / n) + " " + name + "s";
61567
+ }
61568
+ }
61569
+ });
61570
+
61571
+ // ../../node_modules/debug/src/debug.js
61470
61572
  var require_debug2 = __commonJS({
61573
+ "../../node_modules/debug/src/debug.js"(exports2, module2) {
61574
+ exports2 = module2.exports = createDebug.debug = createDebug["default"] = createDebug;
61575
+ exports2.coerce = coerce;
61576
+ exports2.disable = disable;
61577
+ exports2.enable = enable;
61578
+ exports2.enabled = enabled;
61579
+ exports2.humanize = require_ms();
61580
+ exports2.names = [];
61581
+ exports2.skips = [];
61582
+ exports2.formatters = {};
61583
+ var prevTime;
61584
+ function selectColor(namespace) {
61585
+ var hash = 0, i;
61586
+ for (i in namespace) {
61587
+ hash = (hash << 5) - hash + namespace.charCodeAt(i);
61588
+ hash |= 0;
61589
+ }
61590
+ return exports2.colors[Math.abs(hash) % exports2.colors.length];
61591
+ }
61592
+ function createDebug(namespace) {
61593
+ function debug() {
61594
+ if (!debug.enabled) return;
61595
+ var self2 = debug;
61596
+ var curr = +/* @__PURE__ */ new Date();
61597
+ var ms = curr - (prevTime || curr);
61598
+ self2.diff = ms;
61599
+ self2.prev = prevTime;
61600
+ self2.curr = curr;
61601
+ prevTime = curr;
61602
+ var args = new Array(arguments.length);
61603
+ for (var i = 0; i < args.length; i++) {
61604
+ args[i] = arguments[i];
61605
+ }
61606
+ args[0] = exports2.coerce(args[0]);
61607
+ if ("string" !== typeof args[0]) {
61608
+ args.unshift("%O");
61609
+ }
61610
+ var index = 0;
61611
+ args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
61612
+ if (match === "%%") return match;
61613
+ index++;
61614
+ var formatter = exports2.formatters[format];
61615
+ if ("function" === typeof formatter) {
61616
+ var val = args[index];
61617
+ match = formatter.call(self2, val);
61618
+ args.splice(index, 1);
61619
+ index--;
61620
+ }
61621
+ return match;
61622
+ });
61623
+ exports2.formatArgs.call(self2, args);
61624
+ var logFn = debug.log || exports2.log || console.log.bind(console);
61625
+ logFn.apply(self2, args);
61626
+ }
61627
+ debug.namespace = namespace;
61628
+ debug.enabled = exports2.enabled(namespace);
61629
+ debug.useColors = exports2.useColors();
61630
+ debug.color = selectColor(namespace);
61631
+ if ("function" === typeof exports2.init) {
61632
+ exports2.init(debug);
61633
+ }
61634
+ return debug;
61635
+ }
61636
+ function enable(namespaces) {
61637
+ exports2.save(namespaces);
61638
+ exports2.names = [];
61639
+ exports2.skips = [];
61640
+ var split = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/);
61641
+ var len = split.length;
61642
+ for (var i = 0; i < len; i++) {
61643
+ if (!split[i]) continue;
61644
+ namespaces = split[i].replace(/\*/g, ".*?");
61645
+ if (namespaces[0] === "-") {
61646
+ exports2.skips.push(new RegExp("^" + namespaces.substr(1) + "$"));
61647
+ } else {
61648
+ exports2.names.push(new RegExp("^" + namespaces + "$"));
61649
+ }
61650
+ }
61651
+ }
61652
+ function disable() {
61653
+ exports2.enable("");
61654
+ }
61655
+ function enabled(name) {
61656
+ var i, len;
61657
+ for (i = 0, len = exports2.skips.length; i < len; i++) {
61658
+ if (exports2.skips[i].test(name)) {
61659
+ return false;
61660
+ }
61661
+ }
61662
+ for (i = 0, len = exports2.names.length; i < len; i++) {
61663
+ if (exports2.names[i].test(name)) {
61664
+ return true;
61665
+ }
61666
+ }
61667
+ return false;
61668
+ }
61669
+ function coerce(val) {
61670
+ if (val instanceof Error) return val.stack || val.message;
61671
+ return val;
61672
+ }
61673
+ }
61674
+ });
61675
+
61676
+ // ../../node_modules/debug/src/browser.js
61677
+ var require_browser = __commonJS({
61678
+ "../../node_modules/debug/src/browser.js"(exports2, module2) {
61679
+ exports2 = module2.exports = require_debug2();
61680
+ exports2.log = log;
61681
+ exports2.formatArgs = formatArgs;
61682
+ exports2.save = save;
61683
+ exports2.load = load;
61684
+ exports2.useColors = useColors;
61685
+ exports2.storage = "undefined" != typeof chrome && "undefined" != typeof chrome.storage ? chrome.storage.local : localstorage();
61686
+ exports2.colors = [
61687
+ "lightseagreen",
61688
+ "forestgreen",
61689
+ "goldenrod",
61690
+ "dodgerblue",
61691
+ "darkorchid",
61692
+ "crimson"
61693
+ ];
61694
+ function useColors() {
61695
+ if (typeof window !== "undefined" && window.process && window.process.type === "renderer") {
61696
+ return true;
61697
+ }
61698
+ return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // is firebug? http://stackoverflow.com/a/398120/376773
61699
+ typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // is firefox >= v31?
61700
+ // https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
61701
+ typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // double check webkit in userAgent just in case we are in a worker
61702
+ typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
61703
+ }
61704
+ exports2.formatters.j = function(v) {
61705
+ try {
61706
+ return JSON.stringify(v);
61707
+ } catch (err) {
61708
+ return "[UnexpectedJSONParseError]: " + err.message;
61709
+ }
61710
+ };
61711
+ function formatArgs(args) {
61712
+ var useColors2 = this.useColors;
61713
+ args[0] = (useColors2 ? "%c" : "") + this.namespace + (useColors2 ? " %c" : " ") + args[0] + (useColors2 ? "%c " : " ") + "+" + exports2.humanize(this.diff);
61714
+ if (!useColors2) return;
61715
+ var c = "color: " + this.color;
61716
+ args.splice(1, 0, c, "color: inherit");
61717
+ var index = 0;
61718
+ var lastC = 0;
61719
+ args[0].replace(/%[a-zA-Z%]/g, function(match) {
61720
+ if ("%%" === match) return;
61721
+ index++;
61722
+ if ("%c" === match) {
61723
+ lastC = index;
61724
+ }
61725
+ });
61726
+ args.splice(lastC, 0, c);
61727
+ }
61728
+ function log() {
61729
+ return "object" === typeof console && console.log && Function.prototype.apply.call(console.log, console, arguments);
61730
+ }
61731
+ function save(namespaces) {
61732
+ try {
61733
+ if (null == namespaces) {
61734
+ exports2.storage.removeItem("debug");
61735
+ } else {
61736
+ exports2.storage.debug = namespaces;
61737
+ }
61738
+ } catch (e) {
61739
+ }
61740
+ }
61741
+ function load() {
61742
+ var r;
61743
+ try {
61744
+ r = exports2.storage.debug;
61745
+ } catch (e) {
61746
+ }
61747
+ if (!r && typeof process !== "undefined" && "env" in process) {
61748
+ r = process.env.DEBUG;
61749
+ }
61750
+ return r;
61751
+ }
61752
+ exports2.enable(load());
61753
+ function localstorage() {
61754
+ try {
61755
+ return window.localStorage;
61756
+ } catch (e) {
61757
+ }
61758
+ }
61759
+ }
61760
+ });
61761
+
61762
+ // ../../node_modules/debug/src/node.js
61763
+ var require_node2 = __commonJS({
61764
+ "../../node_modules/debug/src/node.js"(exports2, module2) {
61765
+ var tty = require("tty");
61766
+ var util = require("util");
61767
+ exports2 = module2.exports = require_debug2();
61768
+ exports2.init = init;
61769
+ exports2.log = log;
61770
+ exports2.formatArgs = formatArgs;
61771
+ exports2.save = save;
61772
+ exports2.load = load;
61773
+ exports2.useColors = useColors;
61774
+ exports2.colors = [6, 2, 3, 4, 5, 1];
61775
+ exports2.inspectOpts = Object.keys(process.env).filter(function(key) {
61776
+ return /^debug_/i.test(key);
61777
+ }).reduce(function(obj, key) {
61778
+ var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function(_, k) {
61779
+ return k.toUpperCase();
61780
+ });
61781
+ var val = process.env[key];
61782
+ if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
61783
+ else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
61784
+ else if (val === "null") val = null;
61785
+ else val = Number(val);
61786
+ obj[prop] = val;
61787
+ return obj;
61788
+ }, {});
61789
+ var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
61790
+ if (1 !== fd && 2 !== fd) {
61791
+ util.deprecate(function() {
61792
+ }, "except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)")();
61793
+ }
61794
+ var stream = 1 === fd ? process.stdout : 2 === fd ? process.stderr : createWritableStdioStream(fd);
61795
+ function useColors() {
61796
+ return "colors" in exports2.inspectOpts ? Boolean(exports2.inspectOpts.colors) : tty.isatty(fd);
61797
+ }
61798
+ exports2.formatters.o = function(v) {
61799
+ this.inspectOpts.colors = this.useColors;
61800
+ return util.inspect(v, this.inspectOpts).split("\n").map(function(str) {
61801
+ return str.trim();
61802
+ }).join(" ");
61803
+ };
61804
+ exports2.formatters.O = function(v) {
61805
+ this.inspectOpts.colors = this.useColors;
61806
+ return util.inspect(v, this.inspectOpts);
61807
+ };
61808
+ function formatArgs(args) {
61809
+ var name = this.namespace;
61810
+ var useColors2 = this.useColors;
61811
+ if (useColors2) {
61812
+ var c = this.color;
61813
+ var prefix = " \x1B[3" + c + ";1m" + name + " \x1B[0m";
61814
+ args[0] = prefix + args[0].split("\n").join("\n" + prefix);
61815
+ args.push("\x1B[3" + c + "m+" + exports2.humanize(this.diff) + "\x1B[0m");
61816
+ } else {
61817
+ args[0] = (/* @__PURE__ */ new Date()).toUTCString() + " " + name + " " + args[0];
61818
+ }
61819
+ }
61820
+ function log() {
61821
+ return stream.write(util.format.apply(util, arguments) + "\n");
61822
+ }
61823
+ function save(namespaces) {
61824
+ if (null == namespaces) {
61825
+ delete process.env.DEBUG;
61826
+ } else {
61827
+ process.env.DEBUG = namespaces;
61828
+ }
61829
+ }
61830
+ function load() {
61831
+ return process.env.DEBUG;
61832
+ }
61833
+ function createWritableStdioStream(fd2) {
61834
+ var stream2;
61835
+ var tty_wrap = process.binding("tty_wrap");
61836
+ switch (tty_wrap.guessHandleType(fd2)) {
61837
+ case "TTY":
61838
+ stream2 = new tty.WriteStream(fd2);
61839
+ stream2._type = "tty";
61840
+ if (stream2._handle && stream2._handle.unref) {
61841
+ stream2._handle.unref();
61842
+ }
61843
+ break;
61844
+ case "FILE":
61845
+ var fs = require("fs");
61846
+ stream2 = new fs.SyncWriteStream(fd2, { autoClose: false });
61847
+ stream2._type = "fs";
61848
+ break;
61849
+ case "PIPE":
61850
+ case "TCP":
61851
+ var net = require("net");
61852
+ stream2 = new net.Socket({
61853
+ fd: fd2,
61854
+ readable: false,
61855
+ writable: true
61856
+ });
61857
+ stream2.readable = false;
61858
+ stream2.read = null;
61859
+ stream2._type = "pipe";
61860
+ if (stream2._handle && stream2._handle.unref) {
61861
+ stream2._handle.unref();
61862
+ }
61863
+ break;
61864
+ default:
61865
+ throw new Error("Implement me. Unknown stream file type!");
61866
+ }
61867
+ stream2.fd = fd2;
61868
+ stream2._isStdio = true;
61869
+ return stream2;
61870
+ }
61871
+ function init(debug) {
61872
+ debug.inspectOpts = {};
61873
+ var keys = Object.keys(exports2.inspectOpts);
61874
+ for (var i = 0; i < keys.length; i++) {
61875
+ debug.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
61876
+ }
61877
+ }
61878
+ exports2.enable(load());
61879
+ }
61880
+ });
61881
+
61882
+ // ../../node_modules/debug/src/index.js
61883
+ var require_src = __commonJS({
61884
+ "../../node_modules/debug/src/index.js"(exports2, module2) {
61885
+ if (typeof process !== "undefined" && process.type === "renderer") {
61886
+ module2.exports = require_browser();
61887
+ } else {
61888
+ module2.exports = require_node2();
61889
+ }
61890
+ }
61891
+ });
61892
+
61893
+ // node_modules/follow-redirects/debug.js
61894
+ var require_debug3 = __commonJS({
61471
61895
  "node_modules/follow-redirects/debug.js"(exports2, module2) {
61472
61896
  var debug;
61473
61897
  module2.exports = function() {
61474
61898
  if (!debug) {
61475
61899
  try {
61476
- debug = require("debug")("follow-redirects");
61900
+ debug = require_src()("follow-redirects");
61477
61901
  } catch (error) {
61478
61902
  }
61479
61903
  if (typeof debug !== "function") {
@@ -61495,7 +61919,7 @@ var require_follow_redirects = __commonJS({
61495
61919
  var https = require("https");
61496
61920
  var Writable = require("stream").Writable;
61497
61921
  var assert = require("assert");
61498
- var debug = require_debug2();
61922
+ var debug = require_debug3();
61499
61923
  (function detectUnsupportedEnvironment() {
61500
61924
  var looksLikeNode = typeof process !== "undefined";
61501
61925
  var looksLikeBrowser = typeof window !== "undefined" && typeof document !== "undefined";
@@ -81785,7 +82209,7 @@ var require_password = __commonJS({
81785
82209
  });
81786
82210
 
81787
82211
  // node_modules/chardet/lib/fs/node.js
81788
- var require_node2 = __commonJS({
82212
+ var require_node3 = __commonJS({
81789
82213
  "node_modules/chardet/lib/fs/node.js"(exports2, module2) {
81790
82214
  "use strict";
81791
82215
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -87287,7 +87711,7 @@ var require_lib6 = __commonJS({
87287
87711
  };
87288
87712
  Object.defineProperty(exports2, "__esModule", { value: true });
87289
87713
  exports2.detectFileSync = exports2.detectFile = exports2.analyse = exports2.detect = void 0;
87290
- var node_1 = __importDefault(require_node2());
87714
+ var node_1 = __importDefault(require_node3());
87291
87715
  var ascii_1 = __importDefault(require_ascii());
87292
87716
  var utf8_1 = __importDefault(require_utf8());
87293
87717
  var unicode = __importStar(require_unicode());
@@ -91640,56 +92064,80 @@ var require_hook = __commonJS({
91640
92064
  var HOOK_MARKER = "# CodeRifts pre-push hook";
91641
92065
  var PRE_PUSH_SCRIPT = `#!/bin/sh
91642
92066
  ${HOOK_MARKER}
91643
- # Checks API spec changes before pushing
92067
+ # Checks API spec changes before pushing.
92068
+ # The pre-push hook receives lines on stdin:
92069
+ # <local ref> <local sha> <remote ref> <remote sha>
91644
92070
 
91645
92071
  CODERIFTS_API_KEY=$(git config coderifts.apiKey)
91646
92072
  SPEC_PATH=$(git config coderifts.specPath || echo "api/openapi.yaml")
92073
+ ZERO="0000000000000000000000000000000000000000"
91647
92074
 
91648
92075
  if [ -z "$CODERIFTS_API_KEY" ]; then
91649
92076
  echo "CodeRifts: No API key configured. Run: git config coderifts.apiKey <your-key>"
91650
92077
  exit 0 # Don't block if not configured
91651
92078
  fi
91652
92079
 
91653
- # Get the base and head specs
91654
- BASE_SPEC=$(git show HEAD:$SPEC_PATH 2>/dev/null)
91655
- HEAD_SPEC=$(cat $SPEC_PATH 2>/dev/null)
91656
-
91657
- if [ -z "$BASE_SPEC" ] || [ -z "$HEAD_SPEC" ]; then
91658
- exit 0 # No spec found, skip
91659
- fi
91660
-
91661
- if [ "$BASE_SPEC" = "$HEAD_SPEC" ]; then
91662
- exit 0 # No changes, skip
91663
- fi
91664
-
91665
- echo "CodeRifts: Checking API spec changes..."
91666
-
91667
- RESULT=$(curl -s -X POST https://app.coderifts.com/api/v1/diff \\
91668
- -H "Authorization: Bearer $CODERIFTS_API_KEY" \\
91669
- -H "Content-Type: application/json" \\
91670
- -d "{\\"before\\": $(echo "$BASE_SPEC" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))'), \\"after\\": $(echo "$HEAD_SPEC" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}")
91671
-
91672
- DECISION=$(echo $RESULT | python3 -c "import sys,json; print(json.load(sys.stdin).get('omega_decision','ALLOW'))" 2>/dev/null)
91673
- OMEGA=$(echo $RESULT | python3 -c "import sys,json; print(json.load(sys.stdin).get('omega_api',0))" 2>/dev/null)
91674
- BREAKING=$(echo $RESULT | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('breaking_changes',[])))" 2>/dev/null)
91675
-
91676
- if [ "$DECISION" = "BLOCK" ]; then
91677
- echo ""
91678
- echo "\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"
91679
- echo "\u2551 CodeRifts: PUSH BLOCKED \u2551"
91680
- echo "\u2560\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563"
91681
- echo "\u2551 Risk score: $OMEGA/100"
91682
- echo "\u2551 Breaking changes: $BREAKING"
91683
- echo "\u2551 Decision: BLOCK"
91684
- echo "\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"
91685
- echo ""
91686
- echo "Fix breaking changes or use --no-verify to bypass."
91687
- exit 1
91688
- fi
91689
-
91690
- if [ "$DECISION" = "REQUIRE_APPROVAL" ] || [ "$DECISION" = "WARN" ]; then
91691
- echo "CodeRifts: \u26A0 $DECISION \u2014 Risk: $OMEGA/100, Breaking: $BREAKING"
91692
- fi
92080
+ # Read stdin lines provided by git pre-push
92081
+ while read LOCAL_REF LOCAL_SHA REMOTE_REF REMOTE_SHA; do
92082
+ # Skip delete pushes
92083
+ if [ "$LOCAL_SHA" = "$ZERO" ]; then
92084
+ continue
92085
+ fi
92086
+
92087
+ # Get the spec at the local (about-to-be-pushed) commit
92088
+ HEAD_SPEC=$(git show "$LOCAL_SHA:$SPEC_PATH" 2>/dev/null)
92089
+ if [ -z "$HEAD_SPEC" ]; then
92090
+ continue # Spec doesn't exist in local commit, skip
92091
+ fi
92092
+
92093
+ # Get the spec at the remote (already-pushed) commit
92094
+ if [ "$REMOTE_SHA" = "$ZERO" ]; then
92095
+ # New branch \u2014 no remote baseline, use empty spec
92096
+ BASE_SPEC=""
92097
+ else
92098
+ BASE_SPEC=$(git show "$REMOTE_SHA:$SPEC_PATH" 2>/dev/null || echo "")
92099
+ fi
92100
+
92101
+ # If base is empty (new spec or new branch), allow
92102
+ if [ -z "$BASE_SPEC" ]; then
92103
+ echo "CodeRifts: New spec detected, allowing push."
92104
+ continue
92105
+ fi
92106
+
92107
+ # If specs are identical, nothing to check
92108
+ if [ "$BASE_SPEC" = "$HEAD_SPEC" ]; then
92109
+ continue
92110
+ fi
92111
+
92112
+ echo "CodeRifts: Checking API spec changes..."
92113
+
92114
+ RESULT=$(curl -s -X POST https://app.coderifts.com/api/v1/diff \\
92115
+ -H "Authorization: Bearer $CODERIFTS_API_KEY" \\
92116
+ -H "Content-Type: application/json" \\
92117
+ -d "{\\"before\\": $(echo "$BASE_SPEC" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))'), \\"after\\": $(echo "$HEAD_SPEC" | python3 -c 'import sys,json; print(json.dumps(sys.stdin.read()))')}")
92118
+
92119
+ DECISION=$(echo $RESULT | python3 -c "import sys,json; print(json.load(sys.stdin).get('omega_decision','ALLOW'))" 2>/dev/null)
92120
+ OMEGA=$(echo $RESULT | python3 -c "import sys,json; print(json.load(sys.stdin).get('omega_api',0))" 2>/dev/null)
92121
+ BREAKING=$(echo $RESULT | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('breaking_changes',[])))" 2>/dev/null)
92122
+
92123
+ if [ "$DECISION" = "BLOCK" ]; then
92124
+ echo ""
92125
+ echo "========================================"
92126
+ echo " CodeRifts: PUSH BLOCKED"
92127
+ echo "========================================"
92128
+ echo " Risk score: $OMEGA/100"
92129
+ echo " Breaking changes: $BREAKING"
92130
+ echo " Decision: BLOCK"
92131
+ echo "========================================"
92132
+ echo ""
92133
+ echo "Fix breaking changes or use --no-verify to bypass."
92134
+ exit 1
92135
+ fi
92136
+
92137
+ if [ "$DECISION" = "REQUIRE_APPROVAL" ] || [ "$DECISION" = "WARN" ]; then
92138
+ echo "CodeRifts: WARNING \u2014 $DECISION \u2014 Risk: $OMEGA/100, Breaking: $BREAKING"
92139
+ fi
92140
+ done
91693
92141
 
91694
92142
  exit 0
91695
92143
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coderifts",
3
- "version": "1.7.1",
3
+ "version": "1.8.0",
4
4
  "description": "Detect breaking API changes from the command line. Works locally or with the CodeRifts cloud API.",
5
5
  "author": "CodeRifts <hello@coderifts.com>",
6
6
  "license": "MIT",
@@ -55,6 +55,6 @@
55
55
  "json-schema-ref-parser": "npm:@apidevtools/json-schema-ref-parser@^11.7.3"
56
56
  },
57
57
  "devDependencies": {
58
- "esbuild": "^0.27.3"
58
+ "esbuild": "^0.27.4"
59
59
  }
60
60
  }